diff options
author | Joel Holdsworth <joel@airwebreathe.org.uk> | 2020-03-19 17:45:20 +0000 |
---|---|---|
committer | Rasmus Munk Larsen <rmlarsen@google.com> | 2020-03-19 17:45:20 +0000 |
commit | d5c665742beb8dc00ce0f6eab633f719a9218e03 (patch) | |
tree | 2cea4f868303064d37e9321c810cd07c0fcfceac | |
parent | 6ff5a14091151ce0d722878de93b57025976facb (diff) |
Add absolute_difference coefficient-wise binary Array function
-rw-r--r-- | Eigen/src/Core/GenericPacketMath.h | 5 | ||||
-rw-r--r-- | Eigen/src/Core/MathFunctions.h | 30 | ||||
-rw-r--r-- | Eigen/src/Core/arch/NEON/PacketMath.h | 48 | ||||
-rw-r--r-- | Eigen/src/Core/functors/BinaryFunctors.h | 30 | ||||
-rw-r--r-- | Eigen/src/Core/util/ForwardDeclarations.h | 1 | ||||
-rw-r--r-- | Eigen/src/plugins/ArrayCwiseBinaryOps.h | 26 | ||||
-rw-r--r-- | test/array_cwise.cpp | 1 | ||||
-rw-r--r-- | test/packetmath.cpp | 2 |
8 files changed, 143 insertions, 0 deletions
diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h index 13c639f7e..ddfdc39e6 100644 --- a/Eigen/src/Core/GenericPacketMath.h +++ b/Eigen/src/Core/GenericPacketMath.h @@ -52,6 +52,7 @@ struct default_packet_traits HasAbs = 1, HasArg = 0, HasAbs2 = 1, + HasAbsDiff = 0, HasMin = 1, HasMax = 1, HasConj = 1, @@ -322,6 +323,10 @@ pcmp_eq(const Packet& a, const Packet& b) { return a==b ? ptrue(a) : pzero(a); } template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pcmp_lt_or_nan(const Packet& a, const Packet& b) { return pnot(pcmp_le(b,a)); } +/** \internal \returns the min of \a a and \a b (coeff-wise) */ +template<typename Packet> EIGEN_DEVICE_FUNC inline Packet +pabsdiff(const Packet& a, const Packet& b) { return pselect(pcmp_lt(a, b), psub(b, a), psub(a, b)); } + /** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */ template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pload(const typename unpacket_traits<Packet>::type* from) { return *from; } diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 090ad43bd..96cb24fcb 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -1181,6 +1181,36 @@ inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) EIGEN_DEVICE_FUNC inline bool abs2(bool x) { return x; } +template<typename T> +EIGEN_DEVICE_FUNC +EIGEN_ALWAYS_INLINE T absdiff(const T& x, const T& y) +{ + return x > y ? x - y : y - x; +} +template<> +EIGEN_DEVICE_FUNC +EIGEN_ALWAYS_INLINE float absdiff(const float& x, const float& y) +{ + return fabsf(x - y); +} +template<> +EIGEN_DEVICE_FUNC +EIGEN_ALWAYS_INLINE double absdiff(const double& x, const double& y) +{ + return fabs(x - y); +} +template<> +EIGEN_DEVICE_FUNC +EIGEN_ALWAYS_INLINE long double absdiff(const long double& x, const long double& y) +{ +#if defined(EIGEN_HIPCC) + // no "fabsl" on HIP yet + return (x > y) ? x : y; +#else + return fabsl(x - y); +#endif +} + template<typename Scalar> EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) diff --git a/Eigen/src/Core/arch/NEON/PacketMath.h b/Eigen/src/Core/arch/NEON/PacketMath.h index 4b162d493..76c61b42f 100644 --- a/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/Eigen/src/Core/arch/NEON/PacketMath.h @@ -145,6 +145,7 @@ struct packet_traits<float> : default_packet_traits HasAbs = 1, HasArg = 0, HasAbs2 = 1, + HasAbsDiff = 1, HasMin = 1, HasMax = 1, HasConj = 1, @@ -183,6 +184,7 @@ struct packet_traits<int8_t> : default_packet_traits HasMul = 1, HasNegate = 1, HasAbs = 1, + HasAbsDiff = 1, HasArg = 0, HasAbs2 = 1, HasMin = 1, @@ -212,6 +214,7 @@ struct packet_traits<uint8_t> : default_packet_traits HasMul = 1, HasNegate = 0, HasAbs = 1, + HasAbsDiff = 1, HasArg = 0, HasAbs2 = 1, HasMin = 1, @@ -243,6 +246,7 @@ struct packet_traits<int16_t> : default_packet_traits HasMul = 1, HasNegate = 1, HasAbs = 1, + HasAbsDiff = 1, HasArg = 0, HasAbs2 = 1, HasMin = 1, @@ -272,6 +276,7 @@ struct packet_traits<uint16_t> : default_packet_traits HasMul = 1, HasNegate = 0, HasAbs = 0, + HasAbsDiff = 1, HasArg = 0, HasAbs2 = 1, HasMin = 1, @@ -305,6 +310,7 @@ struct packet_traits<int32_t> : default_packet_traits HasAbs = 1, HasArg = 0, HasAbs2 = 1, + HasAbsDiff = 1, HasMin = 1, HasMax = 1, HasConj = 1, @@ -334,6 +340,7 @@ struct packet_traits<uint32_t> : default_packet_traits HasAbs = 0, HasArg = 0, HasAbs2 = 1, + HasAbsDiff = 1, HasMin = 1, HasMax = 1, HasConj = 1, @@ -1101,6 +1108,47 @@ template<> EIGEN_STRONG_INLINE Packet2ui pmadd(const Packet2ui& a, const Packet2 template<> EIGEN_STRONG_INLINE Packet4ui pmadd(const Packet4ui& a, const Packet4ui& b, const Packet4ui& c) { return vmlaq_u32(c,a,b); } +template<> EIGEN_STRONG_INLINE Packet2f pabsdiff<Packet2f>(const Packet2f& a, const Packet2f& b) +{ return vabd_f32(a,b); } +template<> EIGEN_STRONG_INLINE Packet4f pabsdiff<Packet4f>(const Packet4f& a, const Packet4f& b) +{ return vabdq_f32(a,b); } +template<> EIGEN_STRONG_INLINE Packet4c pabsdiff<Packet4c>(const Packet4c& a, const Packet4c& b) +{ + return vget_lane_s32(vreinterpret_s32_s8(vabd_s8( + vreinterpret_s8_s32(vdup_n_s32(a)), + vreinterpret_s8_s32(vdup_n_s32(b)))), 0); +} +template<> EIGEN_STRONG_INLINE Packet8c pabsdiff<Packet8c>(const Packet8c& a, const Packet8c& b) +{ return vabd_s8(a,b); } +template<> EIGEN_STRONG_INLINE Packet16c pabsdiff<Packet16c>(const Packet16c& a, const Packet16c& b) +{ return vabdq_s8(a,b); } +template<> EIGEN_STRONG_INLINE Packet4uc pabsdiff<Packet4uc>(const Packet4uc& a, const Packet4uc& b) +{ + return vget_lane_u32(vreinterpret_u32_u8(vabd_u8( + vreinterpret_u8_u32(vdup_n_u32(a)), + vreinterpret_u8_u32(vdup_n_u32(b)))), 0); +} +template<> EIGEN_STRONG_INLINE Packet8uc pabsdiff<Packet8uc>(const Packet8uc& a, const Packet8uc& b) +{ return vabd_u8(a,b); } +template<> EIGEN_STRONG_INLINE Packet16uc pabsdiff<Packet16uc>(const Packet16uc& a, const Packet16uc& b) +{ return vabdq_u8(a,b); } +template<> EIGEN_STRONG_INLINE Packet4s pabsdiff<Packet4s>(const Packet4s& a, const Packet4s& b) +{ return vabd_s16(a,b); } +template<> EIGEN_STRONG_INLINE Packet8s pabsdiff<Packet8s>(const Packet8s& a, const Packet8s& b) +{ return vabdq_s16(a,b); } +template<> EIGEN_STRONG_INLINE Packet4us pabsdiff<Packet4us>(const Packet4us& a, const Packet4us& b) +{ return vabd_u16(a,b); } +template<> EIGEN_STRONG_INLINE Packet8us pabsdiff<Packet8us>(const Packet8us& a, const Packet8us& b) +{ return vabdq_u16(a,b); } +template<> EIGEN_STRONG_INLINE Packet2i pabsdiff<Packet2i>(const Packet2i& a, const Packet2i& b) +{ return vabd_s32(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pabsdiff<Packet4i>(const Packet4i& a, const Packet4i& b) +{ return vabdq_s32(a,b); } +template<> EIGEN_STRONG_INLINE Packet2ui pabsdiff<Packet2ui>(const Packet2ui& a, const Packet2ui& b) +{ return vabd_u32(a,b); } +template<> EIGEN_STRONG_INLINE Packet4ui pabsdiff<Packet4ui>(const Packet4ui& a, const Packet4ui& b) +{ return vabdq_u32(a,b); } + template<> EIGEN_STRONG_INLINE Packet2f pmin<Packet2f>(const Packet2f& a, const Packet2f& b) { return vmin_f32(a,b); } template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return vminq_f32(a,b); } template<> EIGEN_STRONG_INLINE Packet4c pmin<Packet4c>(const Packet4c& a, const Packet4c& b) diff --git a/Eigen/src/Core/functors/BinaryFunctors.h b/Eigen/src/Core/functors/BinaryFunctors.h index 401d597d8..ca89e9718 100644 --- a/Eigen/src/Core/functors/BinaryFunctors.h +++ b/Eigen/src/Core/functors/BinaryFunctors.h @@ -422,6 +422,36 @@ template<> struct functor_traits<scalar_boolean_xor_op> { }; }; +/** \internal + * \brief Template functor to compute the absolute difference of two scalars + * + * \sa class CwiseBinaryOp, MatrixBase::absolute_difference + */ +template<typename LhsScalar,typename RhsScalar> +struct scalar_absolute_difference_op : binary_op_base<LhsScalar,RhsScalar> +{ + typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_absolute_difference_op>::ReturnType result_type; +#ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN + EIGEN_EMPTY_STRUCT_CTOR(scalar_absolute_difference_op) +#else + scalar_absolute_difference_op() { + EIGEN_SCALAR_BINARY_OP_PLUGIN + } +#endif + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const + { return numext::absdiff(); } + template<typename Packet> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pabsdiff(a,b); } +}; +template<typename LhsScalar,typename RhsScalar> +struct functor_traits<scalar_absolute_difference_op<LhsScalar,RhsScalar> > { + enum { + Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2, + PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAbsDiff + }; +}; + //---------- binary functors bound to a constant, thus appearing as a unary functor ---------- diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 953f52af0..676dee15d 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -187,6 +187,7 @@ template<typename Scalar> struct scalar_real_op; template<typename Scalar> struct scalar_imag_op; template<typename Scalar> struct scalar_abs_op; template<typename Scalar> struct scalar_abs2_op; +template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_absolute_difference_op; template<typename Scalar> struct scalar_sqrt_op; template<typename Scalar> struct scalar_rsqrt_op; template<typename Scalar> struct scalar_exp_op; diff --git a/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/Eigen/src/plugins/ArrayCwiseBinaryOps.h index 8dce1ba9d..73d5f51c8 100644 --- a/Eigen/src/plugins/ArrayCwiseBinaryOps.h +++ b/Eigen/src/plugins/ArrayCwiseBinaryOps.h @@ -75,6 +75,32 @@ max return (max)(Derived::PlainObject::Constant(rows(), cols(), other)); } +/** \returns an expression of the coefficient-wise absdiff of \c *this and \a other + * + * Example: \include Cwise_absolute_difference.cpp + * Output: \verbinclude Cwise_absolute_difference.out + * + * \sa absolute_difference() + */ +EIGEN_MAKE_CWISE_BINARY_OP(absolute_difference,absolute_difference) + +/** \returns an expression of the coefficient-wise absolute_difference of \c *this and scalar \a other + * + * \sa absolute_difference() + */ +EIGEN_DEVICE_FUNC +EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_absolute_difference_op<Scalar,Scalar>, const Derived, + const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject> > +#ifdef EIGEN_PARSED_BY_DOXYGEN +absolute_difference +#else +(absolute_difference) +#endif +(const Scalar &other) const +{ + return (absolute_difference)(Derived::PlainObject::Constant(rows(), cols(), other)); +} + /** \returns an expression of the coefficient-wise power of \c *this to the given array of \a exponents. * * This function computes the coefficient-wise power. diff --git a/test/array_cwise.cpp b/test/array_cwise.cpp index 76fc83c33..e7af1a92f 100644 --- a/test/array_cwise.cpp +++ b/test/array_cwise.cpp @@ -343,6 +343,7 @@ template<typename ArrayType> void array_real(const ArrayType& m) VERIFY_IS_APPROX(inverse(inverse(m1)),m1); VERIFY((abs(m1) == m1 || abs(m1) == -m1).all()); VERIFY_IS_APPROX(m3, sqrt(abs2(m1))); + VERIFY_IS_APPROX(m1.absolute_difference(m2), (m1 > m2).select(m1 - m2, m2 - m1)); VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() ); VERIFY_IS_APPROX( m1*m1.sign(),m1.abs()); VERIFY_IS_APPROX(m1.sign() * m1.abs(), m1); diff --git a/test/packetmath.cpp b/test/packetmath.cpp index 3548eb481..1ba15496b 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -14,6 +14,7 @@ #define REF_SUB(a,b) ((a)-(b)) #define REF_MUL(a,b) ((a)*(b)) #define REF_DIV(a,b) ((a)/(b)) +#define REF_ABS_DIFF(a,b) ((a)>(b)?(a)-(b):(b)-(a)) template<typename Scalar,typename Packet> void packetmath() { @@ -557,6 +558,7 @@ template<typename Scalar,typename Packet> void packetmath_notcomplex() CHECK_CWISE2_IF(PacketTraits::HasMin, (std::min), internal::pmin); CHECK_CWISE2_IF(PacketTraits::HasMax, (std::max), internal::pmax); CHECK_CWISE1(numext::abs, internal::pabs); + CHECK_CWISE2_IF(PacketTraits::HasAbsDiff, REF_ABS_DIFF, internal::pabsdiff); ref[0] = data1[0]; for (int i=0; i<PacketSize; ++i) |