Add absolute_difference coefficient-wise binary Array function

This commit is contained in:
Joel Holdsworth 2020-03-19 17:45:20 +00:00 committed by Rasmus Munk Larsen
parent 6ff5a14091
commit d5c665742b
8 changed files with 143 additions and 0 deletions

View File

@ -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; }

View File

@ -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)

View File

@ -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)

View File

@ -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 ----------

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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)