This forum has been archived. All content is frozen. Please use KDE Discuss instead.

type of returned boolean matrix, and use of SIMD bool matrix

Tags: None
(comma "," separated)
graphicsMan
Registered Member
Posts
16
Karma
0
OS
Hi all -

I'm trying to write an isnan() function using Eigen3, and my attempt thus far looks like:

Code: Select all
template <typename Derived>
inline Derived isnan(Eigen::ArrayBase<Derived> const &x) {
    return (x != x).template cast<typename Derived::Scalar>();
}


This works okay, but I'd prefer not to cast, and to maintain the boolean type. For that, I need to be able to figure out the return type. So far I've been unable to determine that. Can anyone fill me in on how to do this generically?

Additionally, Once I know the concrete return type, I'd also like to know if it's possible/desirable to return an expression template here, and if someone could provide an example of how that would work.

Finally, do these boolean Array types behave "smartly" with respect to SIMD usage and select()? In other words, are the return types such that efficient selection can be performed in SSE4 via _mm_blendv_ps(b, a, MASK) or SSE via or(and(a, MASK), nand(MASK, b)))? And potentially equivalently with Altivec/Neon?

Thanks for any help.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
the following will return an expression suitable for a .select(...):

template <typename Derived> inline
Eigen::CwiseBinaryOp<std::not_equal_to<typename Derived::Scalar,Derived,Derived>
isnan(Eigen::ArrayBase<Derived> const &x) { return x!=x; }

regarding your last question, currently this is not the case but there is a plan to do so. This is not as easy as it looks like to implement that properly and in a general fashion.
graphicsMan
Registered Member
Posts
16
Karma
0
OS
Thanks ggael. Questions almost covered. There was the first question that I still don't know about: what is the concrete Array type that I could assign that expression to?

Again, much appreciated.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
if you evaluate the returned expression then you will get and Array of bool, e.g.:

Array<bool,Dynamic,Dynamic>
graphicsMan
Registered Member
Posts
16
Karma
0
OS
So I wound up with the following, which seem to work well in isolation:

template<typename Derived>
inline const Eigen::CwiseBinaryOp<std::not_equal_to<typename Derived::Scalar>,
Derived const, Derived const>
isnan(Eigen::ArrayBase<Derived> const &x) {
return (x != x);
}

template<typename Derived>
inline const Eigen::CwiseBinaryOp<std::less<typename Derived::Scalar>,
Derived const,
Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<typename Derived::Scalar>, Derived> const >
isneg(Eigen::ArrayBase<Derived> const &x) {
return (x < Eigen::ArrayBase<Derived>::Zero());
}


However, now I'd like to use them together:

Eigen::Array<bool, 31, 1> res = isnan(c) || isneg(c);

c = res.select(Eigen::Array<float, 3, 1>::Zero(), c);

This fails because the operator|| does not seem to exist for these types:

error: no match for ‘operator||’ in ‘rsut::gfx::isnan [with Derived = Eigen::Array<float, 3, 1>, typename Derived::Scalar = float](((const Eigen::ArrayBase<Eigen::Array<float, 3, 1> >&)((const Eigen::ArrayBase<Eigen::Array<float, 3, 1> >*)c))) || rsut::gfx::isneg(const Eigen::ArrayBase<Derived>&) [with Derived = Eigen::Array<float, 3, 1>, typename Derived::Scalar = float]()’
note: candidate is: operator||(bool, bool) <built-in>

How can I accomplish an "or"ing of the two expressions? Note that I tried both "||" and "|" as or operators.
graphicsMan
Registered Member
Posts
16
Karma
0
OS
I managed to write this via:

template <typename boolean_t>
struct or_functor {
bool operator() (boolean_t a, boolean_t b) const {
return a | b;
}
};

template<typename DerivedA, typename DerivedB>
inline const Eigen::CwiseBinaryOp<or_functor<bool>,
DerivedA const, DerivedB const>
operator | (DerivedA const &a, DerivedB const &b) {
return Eigen::CwiseBinaryOp<or_functor<bool>,
DerivedA const, DerivedB const>(a, b);
}

I templatized the or_functor so that if boolean arrays are later represented by masks (0 vs 0xffff or 0xffffffff or 0xffffffffffffffff for half, float, and double precision respectively), different versions could be implemented for neon, altivec, and SSEX (where half and double are applicable).
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
yes we are lacking for operators && and ||. I'll add them as soon as I can...

Note that you don't need a isneg, you can simply do, e.g:

(c<0).select(....);
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
done in default branch.
graphicsMan
Registered Member
Posts
16
Karma
0
OS
Fantastic. Thanks very much. Is it advisable to use the dev branch, or should I wait until the next release (presumably 3.2?)?
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
currently it is safe.


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], q.ignora, watchstar