factorize implementation of standard real unary math functions, and add acos, asin

This commit is contained in:
Gael Guennebaud 2011-02-17 17:37:11 +01:00
parent 2ba55e90db
commit aea630a98a
8 changed files with 124 additions and 191 deletions

View File

@ -669,7 +669,7 @@ struct functor_traits<scalar_sqrt_op<Scalar> >
/** \internal
* \brief Template functor to compute the cosine of a scalar
* \sa class CwiseUnaryOp, Cwise::cos()
* \sa class CwiseUnaryOp, ArrayBase::cos()
*/
template<typename Scalar> struct scalar_cos_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
@ -688,7 +688,7 @@ struct functor_traits<scalar_cos_op<Scalar> >
/** \internal
* \brief Template functor to compute the sine of a scalar
* \sa class CwiseUnaryOp, Cwise::sin()
* \sa class CwiseUnaryOp, ArrayBase::sin()
*/
template<typename Scalar> struct scalar_sin_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
@ -708,7 +708,7 @@ struct functor_traits<scalar_sin_op<Scalar> >
/** \internal
* \brief Template functor to compute the tan of a scalar
* \sa class CwiseUnaryOp, Cwise::tan()
* \sa class CwiseUnaryOp, ArrayBase::tan()
*/
template<typename Scalar> struct scalar_tan_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
@ -725,6 +725,44 @@ struct functor_traits<scalar_tan_op<Scalar> >
};
};
/** \internal
* \brief Template functor to compute the arc cosine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::acos()
*/
template<typename Scalar> 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<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
};
template<typename Scalar>
struct functor_traits<scalar_acos_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasACos
};
};
/** \internal
* \brief Template functor to compute the arc sine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::asin()
*/
template<typename Scalar> 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<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
};
template<typename Scalar>
struct functor_traits<scalar_asin_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasASin
};
};
/** \internal
* \brief Template functor to raise a scalar to a power
* \sa class CwiseUnaryOp, Cwise::pow

View File

@ -229,11 +229,11 @@ template<typename Packet> 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<typename Packet> 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<typename Packet> 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<typename Packet> 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<typename Packet> 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<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pacos(const Packet& a) { return acos(a); }
/** \internal \returns the exp of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pexp(const Packet& a) { return exp(a); }

View File

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

View File

@ -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<typename Scalar, bool IsInteger>
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<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
static inline Scalar run(const Scalar& x) { return std::NAME(x); } \
}; \
template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
static inline Scalar run(const Scalar&) { \
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \
return Scalar(0); \
} \
}; \
template<typename Scalar> struct NAME##_impl \
: NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \
{}; \
template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \
template<typename Scalar> \
inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \
return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \
}
};
template<typename Scalar>
struct exp_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct exp_impl : exp_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct exp_retval
{
typedef Scalar type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(exp, Scalar) exp(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(exp, Scalar)::run(x);
}
/****************************************************************************
* Implementation of cos *
****************************************************************************/
template<typename Scalar, bool IsInteger>
struct cos_default_impl
{
static inline Scalar run(const Scalar& x)
{
return std::cos(x);
}
};
template<typename Scalar>
struct cos_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct cos_impl : cos_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct cos_retval
{
typedef Scalar type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(cos, Scalar) cos(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(cos, Scalar)::run(x);
}
/****************************************************************************
* Implementation of sin *
****************************************************************************/
template<typename Scalar, bool IsInteger>
struct sin_default_impl
{
static inline Scalar run(const Scalar& x)
{
return std::sin(x);
}
};
template<typename Scalar>
struct sin_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct sin_impl : sin_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct sin_retval
{
typedef Scalar type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(sin, Scalar) sin(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(sin, Scalar)::run(x);
}
/****************************************************************************
* Implementation of tan *
****************************************************************************/
template<typename Scalar, bool IsInteger>
struct tan_default_impl
{
static inline Scalar run(const Scalar& x)
{
return std::tan(x);
}
};
template<typename Scalar>
struct tan_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct tan_impl : tan_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct tan_retval
{
typedef Scalar type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(tan, Scalar) tan(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(tan, Scalar)::run(x);
}
/****************************************************************************
* Implementation of log *
****************************************************************************/
template<typename Scalar, bool IsInteger>
struct log_default_impl
{
static inline Scalar run(const Scalar& x)
{
return std::log(x);
}
};
template<typename Scalar>
struct log_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct log_impl : log_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct log_retval
{
typedef Scalar type;
};
template<typename Scalar>
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 *

View File

@ -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<internal::scalar_cos_op<Scalar>, 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<internal::scalar_sin_op<Scalar>, 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<internal::scalar_acos_op<Scalar>, 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<internal::scalar_asin_op<Scalar>, const Derived>
asin() const
{
return derived();
}
/** \returns an expression of the coefficient-wise tan of *this.
*

View File

@ -0,0 +1,2 @@
Array3d v(0, sqrt(2.)/2, 1);
cout << v.acos() << endl;

View File

@ -169,10 +169,15 @@ template<typename ArrayType> 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));

View File

@ -223,6 +223,15 @@ template<typename Scalar> void packetmath_real()
}
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSin, internal::sin, internal::psin);
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasCos, internal::cos, internal::pcos);
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasTan, internal::tan, internal::ptan);
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-1,1);
data2[i] = internal::random<Scalar>(-1,1);
}
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasASin, internal::asin, internal::pasin);
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasACos, internal::acos, internal::pacos);
for (int i=0; i<size; ++i)
{