Registered Member
|
Hi all -
I'm trying to write an isnan() function using Eigen3, and my attempt thus far looks like:
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. |
Moderator
|
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. |
Registered Member
|
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. |
Moderator
|
if you evaluate the returned expression then you will get and Array of bool, e.g.:
Array<bool,Dynamic,Dynamic> |
Registered Member
|
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. |
Registered Member
|
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). |
Moderator
|
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(....); |
Moderator
|
done in default branch.
|
Registered Member
|
Fantastic. Thanks very much. Is it advisable to use the dev branch, or should I wait until the next release (presumably 3.2?)?
|
Moderator
|
currently it is safe.
|
Registered users: Bing [Bot], Google [Bot], q.ignora, watchstar