From aea630a98a39a523bfb008e884262d69ee473b8d Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 17 Feb 2011 17:37:11 +0100 Subject: [PATCH] factorize implementation of standard real unary math functions, and add acos, asin --- Eigen/src/Core/Functors.h | 44 +++++- Eigen/src/Core/GenericPacketMath.h | 12 +- Eigen/src/Core/GlobalFunctions.h | 4 + Eigen/src/Core/MathFunctions.h | 210 +++---------------------- Eigen/src/plugins/ArrayCwiseUnaryOps.h | 29 +++- doc/snippets/Cwise_acos.cpp | 2 + test/array.cpp | 5 + test/packetmath.cpp | 9 ++ 8 files changed, 124 insertions(+), 191 deletions(-) create mode 100644 doc/snippets/Cwise_acos.cpp diff --git a/Eigen/src/Core/Functors.h b/Eigen/src/Core/Functors.h index 9671f0f45..ddfc67d82 100644 --- a/Eigen/src/Core/Functors.h +++ b/Eigen/src/Core/Functors.h @@ -669,7 +669,7 @@ struct functor_traits > /** \internal * \brief Template functor to compute the cosine of a scalar - * \sa class CwiseUnaryOp, Cwise::cos() + * \sa class CwiseUnaryOp, ArrayBase::cos() */ template struct scalar_cos_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) @@ -688,7 +688,7 @@ struct functor_traits > /** \internal * \brief Template functor to compute the sine of a scalar - * \sa class CwiseUnaryOp, Cwise::sin() + * \sa class CwiseUnaryOp, ArrayBase::sin() */ template struct scalar_sin_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) @@ -708,7 +708,7 @@ struct functor_traits > /** \internal * \brief Template functor to compute the tan of a scalar - * \sa class CwiseUnaryOp, Cwise::tan() + * \sa class CwiseUnaryOp, ArrayBase::tan() */ template struct scalar_tan_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) @@ -725,6 +725,44 @@ struct functor_traits > }; }; +/** \internal + * \brief Template functor to compute the arc cosine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::acos() + */ +template struct scalar_acos_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) + inline const Scalar operator() (const Scalar& a) const { return acos(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasACos + }; +}; + +/** \internal + * \brief Template functor to compute the arc sine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::asin() + */ +template struct scalar_asin_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) + inline const Scalar operator() (const Scalar& a) const { return acos(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasASin + }; +}; + /** \internal * \brief Template functor to raise a scalar to a power * \sa class CwiseUnaryOp, Cwise::pow diff --git a/Eigen/src/Core/GenericPacketMath.h b/Eigen/src/Core/GenericPacketMath.h index e3d492b8d..052aa8330 100644 --- a/Eigen/src/Core/GenericPacketMath.h +++ b/Eigen/src/Core/GenericPacketMath.h @@ -229,11 +229,11 @@ template inline Packet preverse(const Packet& a) * Special math functions ***************************/ -/** \internal \returns the sin of \a a (coeff-wise) */ +/** \internal \returns the sine of \a a (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psin(const Packet& a) { return sin(a); } -/** \internal \returns the cos of \a a (coeff-wise) */ +/** \internal \returns the cosine of \a a (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcos(const Packet& a) { return cos(a); } @@ -241,6 +241,14 @@ Packet pcos(const Packet& a) { return cos(a); } template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptan(const Packet& a) { return tan(a); } +/** \internal \returns the arc sine of \a a (coeff-wise) */ +template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS +Packet pasin(const Packet& a) { return asin(a); } + +/** \internal \returns the arc cosine of \a a (coeff-wise) */ +template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS +Packet pacos(const Packet& a) { return acos(a); } + /** \internal \returns the exp of \a a (coeff-wise) */ template EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp(const Packet& a) { return exp(a); } diff --git a/Eigen/src/Core/GlobalFunctions.h b/Eigen/src/Core/GlobalFunctions.h index f049bff42..144145a95 100644 --- a/Eigen/src/Core/GlobalFunctions.h +++ b/Eigen/src/Core/GlobalFunctions.h @@ -56,6 +56,8 @@ namespace std EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(imag,scalar_imag_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sin,scalar_sin_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(cos,scalar_cos_op) + EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(asin,scalar_asin_op) + EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(acos,scalar_acos_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(tan,scalar_tan_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(exp,scalar_exp_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(log,scalar_log_op) @@ -77,6 +79,8 @@ namespace Eigen EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag,scalar_imag_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sin,scalar_sin_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(cos,scalar_cos_op) + EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(asin,scalar_asin_op) + EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(acos,scalar_acos_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(tan,scalar_tan_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(exp,scalar_exp_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(log,scalar_log_op) diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 3f1405c62..2760e67b1 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -454,194 +454,36 @@ inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x) } /**************************************************************************** -* Implementation of exp * +* Implementation of standard unary real functions (exp, log, sin, cos, ... * ****************************************************************************/ -template -struct exp_default_impl -{ - static inline Scalar run(const Scalar& x) - { - return std::exp(x); +// This macro instanciate all the necessary template mechanism which is common to all unary real functions. +#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \ + template struct NAME##_default_impl { \ + static inline Scalar run(const Scalar& x) { return std::NAME(x); } \ + }; \ + template struct NAME##_default_impl { \ + static inline Scalar run(const Scalar&) { \ + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \ + return Scalar(0); \ + } \ + }; \ + template struct NAME##_impl \ + : NAME##_default_impl::IsInteger> \ + {}; \ + template struct NAME##_retval { typedef Scalar type; }; \ + template \ + inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \ + return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \ } -}; -template -struct exp_default_impl -{ - static inline Scalar run(const Scalar&) - { - EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - return Scalar(0); - } -}; - -template -struct exp_impl : exp_default_impl::IsInteger> {}; - -template -struct exp_retval -{ - typedef Scalar type; -}; - -template -inline EIGEN_MATHFUNC_RETVAL(exp, Scalar) exp(const Scalar& x) -{ - return EIGEN_MATHFUNC_IMPL(exp, Scalar)::run(x); -} - -/**************************************************************************** -* Implementation of cos * -****************************************************************************/ - -template -struct cos_default_impl -{ - static inline Scalar run(const Scalar& x) - { - return std::cos(x); - } -}; - -template -struct cos_default_impl -{ - static inline Scalar run(const Scalar&) - { - EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - return Scalar(0); - } -}; - -template -struct cos_impl : cos_default_impl::IsInteger> {}; - -template -struct cos_retval -{ - typedef Scalar type; -}; - -template -inline EIGEN_MATHFUNC_RETVAL(cos, Scalar) cos(const Scalar& x) -{ - return EIGEN_MATHFUNC_IMPL(cos, Scalar)::run(x); -} - -/**************************************************************************** -* Implementation of sin * -****************************************************************************/ - -template -struct sin_default_impl -{ - static inline Scalar run(const Scalar& x) - { - return std::sin(x); - } -}; - -template -struct sin_default_impl -{ - static inline Scalar run(const Scalar&) - { - EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - return Scalar(0); - } -}; - -template -struct sin_impl : sin_default_impl::IsInteger> {}; - -template -struct sin_retval -{ - typedef Scalar type; -}; - -template -inline EIGEN_MATHFUNC_RETVAL(sin, Scalar) sin(const Scalar& x) -{ - return EIGEN_MATHFUNC_IMPL(sin, Scalar)::run(x); -} - -/**************************************************************************** -* Implementation of tan * -****************************************************************************/ - -template -struct tan_default_impl -{ - static inline Scalar run(const Scalar& x) - { - return std::tan(x); - } -}; - -template -struct tan_default_impl -{ - static inline Scalar run(const Scalar&) - { - EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - return Scalar(0); - } -}; - -template -struct tan_impl : tan_default_impl::IsInteger> {}; - -template -struct tan_retval -{ - typedef Scalar type; -}; - -template -inline EIGEN_MATHFUNC_RETVAL(tan, Scalar) tan(const Scalar& x) -{ - return EIGEN_MATHFUNC_IMPL(tan, Scalar)::run(x); -} - -/**************************************************************************** -* Implementation of log * -****************************************************************************/ - -template -struct log_default_impl -{ - static inline Scalar run(const Scalar& x) - { - return std::log(x); - } -}; - -template -struct log_default_impl -{ - static inline Scalar run(const Scalar&) - { - EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - return Scalar(0); - } -}; - -template -struct log_impl : log_default_impl::IsInteger> {}; - -template -struct log_retval -{ - typedef Scalar type; -}; - -template -inline EIGEN_MATHFUNC_RETVAL(log, Scalar) log(const Scalar& x) -{ - return EIGEN_MATHFUNC_IMPL(log, Scalar)::run(x); -} +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin) +EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos) /**************************************************************************** * Implementation of atan2 * diff --git a/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/Eigen/src/plugins/ArrayCwiseUnaryOps.h index 7e0c827db..0dffaf413 100644 --- a/Eigen/src/plugins/ArrayCwiseUnaryOps.h +++ b/Eigen/src/plugins/ArrayCwiseUnaryOps.h @@ -70,7 +70,7 @@ sqrt() const * Example: \include Cwise_cos.cpp * Output: \verbinclude Cwise_cos.out * - * \sa sin(), exp() + * \sa sin(), acos() */ inline const CwiseUnaryOp, const Derived> cos() const @@ -84,7 +84,7 @@ cos() const * Example: \include Cwise_sin.cpp * Output: \verbinclude Cwise_sin.out * - * \sa cos(), exp() + * \sa cos(), asin() */ inline const CwiseUnaryOp, const Derived> sin() const @@ -92,6 +92,31 @@ sin() const return derived(); } +/** \returns an expression of the coefficient-wise arc cosine of *this. + * + * Example: \include Cwise_acos.cpp + * Output: \verbinclude Cwise_acos.out + * + * \sa cos(), asin() + */ +inline const CwiseUnaryOp, const Derived> +acos() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise arc sine of *this. + * + * Example: \include Cwise_asin.cpp + * Output: \verbinclude Cwise_asin.out + * + * \sa sin(), acos() + */ +inline const CwiseUnaryOp, const Derived> +asin() const +{ + return derived(); +} /** \returns an expression of the coefficient-wise tan of *this. * diff --git a/doc/snippets/Cwise_acos.cpp b/doc/snippets/Cwise_acos.cpp new file mode 100644 index 000000000..34432cbac --- /dev/null +++ b/doc/snippets/Cwise_acos.cpp @@ -0,0 +1,2 @@ +Array3d v(0, sqrt(2.)/2, 1); +cout << v.acos() << endl; diff --git a/test/array.cpp b/test/array.cpp index 26c6c33b7..8ec80d55f 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -169,10 +169,15 @@ template void array_real(const ArrayType& m) m2 = ArrayType::Random(rows, cols), m3(rows, cols); + // these these are mostly to check possible compilation issues. VERIFY_IS_APPROX(m1.sin(), std::sin(m1)); VERIFY_IS_APPROX(m1.sin(), internal::sin(m1)); VERIFY_IS_APPROX(m1.cos(), std::cos(m1)); VERIFY_IS_APPROX(m1.cos(), internal::cos(m1)); + VERIFY_IS_APPROX(m1.asin(), std::sin(m1)); + VERIFY_IS_APPROX(m1.asin(), internal::sin(m1)); + VERIFY_IS_APPROX(m1.acos(), std::acos(m1)); + VERIFY_IS_APPROX(m1.acos(), internal::acos(m1)); VERIFY_IS_APPROX(m1.tan(), std::tan(m1)); VERIFY_IS_APPROX(m1.tan(), internal::tan(m1)); diff --git a/test/packetmath.cpp b/test/packetmath.cpp index 001dbc4d2..c6c5bd3b0 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -223,6 +223,15 @@ template void packetmath_real() } CHECK_CWISE1_IF(internal::packet_traits::HasSin, internal::sin, internal::psin); CHECK_CWISE1_IF(internal::packet_traits::HasCos, internal::cos, internal::pcos); + CHECK_CWISE1_IF(internal::packet_traits::HasTan, internal::tan, internal::ptan); + + for (int i=0; i(-1,1); + data2[i] = internal::random(-1,1); + } + CHECK_CWISE1_IF(internal::packet_traits::HasASin, internal::asin, internal::pasin); + CHECK_CWISE1_IF(internal::packet_traits::HasACos, internal::acos, internal::pacos); for (int i=0; i