bug #80: merge with d_hood branch on adding more coefficient-wise unary array functors

This commit is contained in:
Gael Guennebaud 2015-06-10 15:52:05 +02:00
commit 25a98be948
23 changed files with 845 additions and 77 deletions

View File

@ -198,16 +198,24 @@ EIGEN_MKL_VML_SPECIALIZE_ASSIGN(SliceVectorizedTraversal,NoUnrolling)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sin, Sin)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(asin, Asin)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sinh, Sinh)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cos, Cos)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(acos, Acos)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cosh, Cosh)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tan, Tan)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(atan, Atan)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tanh, Tanh)
//EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(exp, Exp)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log, Ln)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sqrt, Sqrt)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log10, Log10)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sqrt, Sqrt)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX(arg, Arg)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(round, Round)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(floor, Floor)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil)
// The vm*powx functions are not avaibale in the windows version of MKL.
#ifndef _WIN32

View File

@ -49,6 +49,7 @@ struct default_packet_traits
HasMul = 1,
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
@ -61,6 +62,7 @@ struct default_packet_traits
HasRsqrt = 0,
HasExp = 0,
HasLog = 0,
HasLog10 = 0,
HasPow = 0,
HasSin = 0,
@ -68,7 +70,14 @@ struct default_packet_traits
HasTan = 0,
HasASin = 0,
HasACos = 0,
HasATan = 0
HasATan = 0,
HasSinh = 0,
HasCosh = 0,
HasTanh = 0,
HasRound = 0,
HasFloor = 0,
HasCeil = 0
};
};
@ -163,6 +172,10 @@ pmax(const Packet& a,
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
pabs(const Packet& a) { using std::abs; return abs(a); }
/** \internal \returns the phase angle of \a a */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
parg(const Packet& a) { using numext::arg; return arg(a); }
/** \internal \returns the bitwise and of \a a and \a b */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
pand(const Packet& a, const Packet& b) { return a & b; }
@ -359,10 +372,22 @@ Packet pasin(const Packet& a) { using std::asin; return asin(a); }
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pacos(const Packet& a) { using std::acos; return acos(a); }
/** \internal \returns the atan of \a a (coeff-wise) */
/** \internal \returns the arc tangent of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet patan(const Packet& a) { using std::atan; return atan(a); }
/** \internal \returns the hyperbolic sine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet psinh(const Packet& a) { using std::sinh; return sinh(a); }
/** \internal \returns the hyperbolic cosine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pcosh(const Packet& a) { using std::cosh; return cosh(a); }
/** \internal \returns the hyperbolic tan of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet ptanh(const Packet& a) { using std::tanh; return tanh(a); }
/** \internal \returns the exp of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pexp(const Packet& a) { using std::exp; return exp(a); }
@ -371,6 +396,10 @@ Packet pexp(const Packet& a) { using std::exp; return exp(a); }
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet plog(const Packet& a) { using std::log; return log(a); }
/** \internal \returns the log10 of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet plog10(const Packet& a) { using std::log10; return log10(a); }
/** \internal \returns the square-root of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet psqrt(const Packet& a) { using std::sqrt; return sqrt(a); }
@ -381,6 +410,18 @@ Packet prsqrt(const Packet& a) {
return pdiv(pset1<Packet>(1), psqrt(a));
}
/** \internal \returns the rounded value of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pround(const Packet& a) { using numext::round; return round(a); }
/** \internal \returns the floor of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pfloor(const Packet& a) { using numext::floor; return floor(a); }
/** \internal \returns the ceil of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pceil(const Packet& a) { using numext::ceil; return ceil(a); }
/***************************************************************************
* The following functions might not have to be overwritten for vectorized types
***************************************************************************/

View File

@ -40,16 +40,31 @@ namespace Eigen
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real,scalar_real_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag,scalar_imag_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(conj,scalar_conjugate_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(inverse,scalar_inverse_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin,scalar_sin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos,scalar_cos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acos,scalar_acos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tan,scalar_tan_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(atan,scalar_atan_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acos,scalar_acos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sinh,scalar_sinh_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cosh,scalar_cosh_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tanh,scalar_tanh_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10,scalar_log10_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs,scalar_abs_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs2,scalar_abs2_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(arg,scalar_arg_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sqrt,scalar_sqrt_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(square,scalar_square_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cube,scalar_cube_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(round,scalar_round_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(floor,scalar_floor_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(ceil,scalar_ceil_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isNaN,scalar_isNaN_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isInf,scalar_isInf_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isFinite,scalar_isFinite_op)
template<typename Derived>
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar>, const Derived>

View File

@ -361,7 +361,94 @@ inline NewType cast(const OldType& x)
}
/****************************************************************************
* Implementation of logp1 *
* Implementation of round *
****************************************************************************/
// In C++11 we can specialize round_impl for real Scalars
// Let's be conservative and enable the default C++11 implementation only if we are sure it exists
#if (__cplusplus >= 201103L) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC || EIGEN_COMP_ICC) \
&& (EIGEN_ARCH_i386_OR_x86_64) && (EIGEN_OS_GNULINUX || EIGEN_OS_WIN_STRICT || EIGEN_OS_MAC)
template<typename Scalar>
struct round_impl {
static inline Scalar run(const Scalar& x)
{
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
using std::round;
return round(x);
}
};
// No C++11, use our own implementation
#else
template<typename Scalar>
struct round_impl
{
static inline Scalar run(const Scalar& x)
{
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
using std::floor;
using std::ceil;
return (x > 0.0) ? floor(x + 0.5) : ceil(x - 0.5);
}
};
#endif
template<typename Scalar>
struct round_retval
{
typedef Scalar type;
};
/****************************************************************************
* Implementation of arg *
****************************************************************************/
// In C++11 we can specialize arg_impl for all Scalars
// Let's be conservative and enable the default C++11 implementation only if we are sure it exists
#if (__cplusplus >= 201103L) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC || EIGEN_COMP_ICC) \
&& (EIGEN_ARCH_i386_OR_x86_64) && (EIGEN_OS_GNULINUX || EIGEN_OS_WIN_STRICT || EIGEN_OS_MAC)
template<typename Scalar>
struct arg_impl {
static inline Scalar run(const Scalar& x)
{
using std::arg;
return arg(x);
}
};
// No C++11, use our own implementation for real Scalars
#else
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
struct arg_default_impl
{
typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar& x)
{
const double pi = std::acos(-1.0);
return (x < 0.0) ? pi : 0.0; }
};
template<typename Scalar>
struct arg_default_impl<Scalar,true>
{
typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar& x)
{
using std::arg;
return arg(x);
}
};
template<typename Scalar> struct arg_impl : arg_default_impl<Scalar> {};
#endif
template<typename Scalar>
struct arg_retval
{
typedef typename NumTraits<Scalar>::Real type;
};
/****************************************************************************
* Implementation of log1p *
****************************************************************************/
template<typename Scalar, bool isComplex = NumTraits<Scalar>::IsComplex >
struct log1p_impl
@ -588,7 +675,7 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
} // end namespace internal
/****************************************************************************
* Generic math function *
* Generic math functions *
****************************************************************************/
namespace numext {
@ -637,6 +724,13 @@ inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
@ -693,13 +787,16 @@ inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
}
// std::isfinite is non standard, so let's define our own version,
// even though it is not very efficient.
template<typename T>
EIGEN_DEVICE_FUNC
bool (isfinite)(const T& x)
{
#ifdef EIGEN_HAS_C99_MATH
using std::isfinite;
return isfinite(x);
#else
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
#endif
}
template<typename T>
@ -711,6 +808,73 @@ bool (isfinite)(const std::complex<T>& x)
return isfinite(real(x)) && isfinite(imag(x));
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isNaN)(const T& x)
{
#ifdef EIGEN_HAS_C99_MATH
using std::isnan;
return isnan(x);
#else
return x != x;
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isNaN)(const std::complex<T>& x)
{
using std::real;
using std::imag;
using std::isnan;
return isnan(real(x)) || isnan(imag(x));
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isInf)(const T& x)
{
#ifdef EIGEN_HAS_C99_MATH
using std::isinf;
return isinf(x);
#else
return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest();
#endif
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isInf)(const std::complex<T>& x)
{
using std::real;
using std::imag;
using std::isinf;
return isinf(real(x)) || isinf(imag(x));
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(round, Scalar)::run(x);
}
template<typename T>
EIGEN_DEVICE_FUNC
T (floor)(const T& x)
{
using std::floor;
return floor(x);
}
template<typename T>
EIGEN_DEVICE_FUNC
T (ceil)(const T& x)
{
using std::ceil;
return ceil(x);
}
// Log base 2 for 32 bits positive integers.
// Conveniently returns 0 for x==0.
inline int log2(int x)

View File

@ -122,6 +122,27 @@ struct functor_traits<scalar_conjugate_op<Scalar> >
};
};
/** \internal
* \brief Template functor to compute the phase angle of a complex
*
* \sa class CwiseUnaryOp, Cwise::arg
*/
template<typename Scalar> struct scalar_arg_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op)
typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { using numext::arg; return arg(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::parg(a); }
};
template<typename Scalar>
struct functor_traits<scalar_arg_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasArg
};
};
/** \internal
* \brief Template functor to cast a scalar to another type
*
@ -233,6 +254,21 @@ template<typename Scalar>
struct functor_traits<scalar_log_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
/** \internal
*
* \brief Template functor to compute the base-10 logarithm of a scalar
*
* \sa class CwiseUnaryOp, Cwise::log10()
*/
template<typename Scalar> struct scalar_log10_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op)
EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { using std::log10; return log10(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::plog10(a); }
};
template<typename Scalar>
struct functor_traits<scalar_log10_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 }; };
/** \internal
* \brief Template functor to compute the square root of a scalar
@ -367,7 +403,6 @@ struct functor_traits<scalar_asin_op<Scalar> >
};
};
/** \internal
* \brief Template functor to compute the atan of a scalar
* \sa class CwiseUnaryOp, ArrayBase::atan()
@ -387,6 +422,63 @@ struct functor_traits<scalar_atan_op<Scalar> >
};
};
/** \internal
* \brief Template functor to compute the tanh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::tanh()
*/
template<typename Scalar> struct scalar_tanh_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op)
inline const Scalar operator() (const Scalar& a) const { using std::tanh; return tanh(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::ptanh(a); }
};
template<typename Scalar>
struct functor_traits<scalar_tanh_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasTanh
};
};
/** \internal
* \brief Template functor to compute the sinh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::sinh()
*/
template<typename Scalar> struct scalar_sinh_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sinh_op)
inline const Scalar operator() (const Scalar& a) const { using std::sinh; return sinh(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::psinh(a); }
};
template<typename Scalar>
struct functor_traits<scalar_sinh_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasSinh
};
};
/** \internal
* \brief Template functor to compute the cosh of a scalar
* \sa class CwiseUnaryOp, ArrayBase::cosh()
*/
template<typename Scalar> struct scalar_cosh_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cosh_op)
inline const Scalar operator() (const Scalar& a) const { using std::cosh; return cosh(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pcosh(a); }
};
template<typename Scalar>
struct functor_traits<scalar_cosh_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasCosh
};
};
/** \internal
* \brief Template functor to compute the inverse of a scalar
* \sa class CwiseUnaryOp, Cwise::inverse()
@ -435,6 +527,134 @@ template<typename Scalar>
struct functor_traits<scalar_cube_op<Scalar> >
{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
/** \internal
* \brief Template functor to compute the rounded value of a scalar
* \sa class CwiseUnaryOp, ArrayBase::round()
*/
template<typename Scalar> struct scalar_round_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_round_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using numext::round; return round(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pround(a); }
};
template<typename Scalar>
struct functor_traits<scalar_round_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasRound
};
};
/** \internal
* \brief Template functor to compute the floor of a scalar
* \sa class CwiseUnaryOp, ArrayBase::floor()
*/
template<typename Scalar> struct scalar_floor_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_floor_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::floor(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pfloor(a); }
};
template<typename Scalar>
struct functor_traits<scalar_floor_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasFloor
};
};
/** \internal
* \brief Template functor to compute the ceil of a scalar
* \sa class CwiseUnaryOp, ArrayBase::ceil()
*/
template<typename Scalar> struct scalar_ceil_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_ceil_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::ceil(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pceil(a); }
};
template<typename Scalar>
struct functor_traits<scalar_ceil_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasCeil
};
};
/** \internal
* \brief Template functor to compute whether a scalar is NaN
* \sa class CwiseUnaryOp, ArrayBase::isNaN()
*/
template<typename Scalar> struct scalar_isNaN_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_isNaN_op)
typedef bool result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::isNaN(a); }
};
template<typename Scalar>
struct functor_traits<scalar_isNaN_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = false
};
};
/** \internal
* \brief Template functor to compute the isInf of a scalar
* \sa class CwiseUnaryOp, ArrayBase::isInf()
*/
template<typename Scalar> struct scalar_isInf_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_isInf_op)
typedef bool result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::isInf(a); }
};
template<typename Scalar>
struct functor_traits<scalar_isInf_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = false
};
};
/** \internal
* \brief Template functor to compute the isFinite of a scalar
* \sa class CwiseUnaryOp, ArrayBase::isFinite()
*/
template<typename Scalar> struct scalar_isFinite_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_isFinite_op)
typedef bool result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::isfinite(a); }
};
template<typename Scalar>
struct functor_traits<scalar_isFinite_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = false
};
};
/** \internal
* \brief Template functor to compute the logical not of a boolean
*
* \sa class CwiseUnaryOp, ArrayBase::operator!
*/
template<typename Scalar> struct scalar_boolean_not_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_not_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; }
};
template<typename Scalar>
struct functor_traits<scalar_boolean_not_op<Scalar> > {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
};
} // end namespace internal

View File

@ -415,6 +415,16 @@
#define EIGEN_HAS_CONSTEXPR 1
#endif
// Does the compiler support C99 math?
#if (__cplusplus >= 201103L) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC || EIGEN_COMP_ICC) \
&& (EIGEN_ARCH_i386_OR_x86_64) && (EIGEN_OS_GNULINUX || EIGEN_OS_WIN_STRICT || EIGEN_OS_MAC) || \
(EIGEN_COMP_GNUC_STRICT || \
(EIGEN_COMP_ICC && EIGEN_COMP_GNUC) || \
(EIGEN_COMP_CLANG) || \
(EIGEN_COMP_MSVC >= 1800))
#define EIGEN_HAS_C99_MATH 1
#endif
/** Allows to disable some optimizations which might affect the accuracy of the result.
* Such optimization are enabled by default, and set EIGEN_FAST_MATH to 0 to disable them.
* They currently include:

View File

@ -1,21 +1,33 @@
typedef CwiseUnaryOp<internal::scalar_abs_op<Scalar>, const Derived> AbsReturnType;
typedef CwiseUnaryOp<internal::scalar_arg_op<Scalar>, const Derived> ArgReturnType;
typedef CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const Derived> Abs2ReturnType;
typedef CwiseUnaryOp<internal::scalar_sqrt_op<Scalar>, const Derived> SqrtReturnType;
typedef CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const Derived> InverseReturnType;
typedef CwiseUnaryOp<internal::scalar_boolean_not_op<Scalar>, const Derived> BooleanNotReturnType;
typedef CwiseUnaryOp<internal::scalar_exp_op<Scalar>, const Derived> ExpReturnType;
typedef CwiseUnaryOp<internal::scalar_log_op<Scalar>, const Derived> LogReturnType;
typedef CwiseUnaryOp<internal::scalar_log10_op<Scalar>, const Derived> Log10ReturnType;
typedef CwiseUnaryOp<internal::scalar_cos_op<Scalar>, const Derived> CosReturnType;
typedef CwiseUnaryOp<internal::scalar_sin_op<Scalar>, const Derived> SinReturnType;
typedef CwiseUnaryOp<internal::scalar_tan_op<Scalar>, const Derived> TanReturnType;
typedef CwiseUnaryOp<internal::scalar_acos_op<Scalar>, const Derived> AcosReturnType;
typedef CwiseUnaryOp<internal::scalar_asin_op<Scalar>, const Derived> AsinReturnType;
typedef CwiseUnaryOp<internal::scalar_tan_op<Scalar>, const Derived> TanReturnType;
typedef CwiseUnaryOp<internal::scalar_atan_op<Scalar>, const Derived> AtanReturnType;
typedef CwiseUnaryOp<internal::scalar_tanh_op<Scalar>, const Derived> TanhReturnType;
typedef CwiseUnaryOp<internal::scalar_sinh_op<Scalar>, const Derived> SinhReturnType;
typedef CwiseUnaryOp<internal::scalar_cosh_op<Scalar>, const Derived> CoshReturnType;
typedef CwiseUnaryOp<internal::scalar_pow_op<Scalar>, const Derived> PowReturnType;
typedef CwiseUnaryOp<internal::scalar_square_op<Scalar>, const Derived> SquareReturnType;
typedef CwiseUnaryOp<internal::scalar_cube_op<Scalar>, const Derived> CubeReturnType;
typedef CwiseUnaryOp<internal::scalar_round_op<Scalar>, const Derived> RoundReturnType;
typedef CwiseUnaryOp<internal::scalar_floor_op<Scalar>, const Derived> FloorReturnType;
typedef CwiseUnaryOp<internal::scalar_ceil_op<Scalar>, const Derived> CeilReturnType;
typedef CwiseUnaryOp<internal::scalar_isNaN_op<Scalar>, const Derived> IsNaNReturnType;
typedef CwiseUnaryOp<internal::scalar_isInf_op<Scalar>, const Derived> IsInfReturnType;
typedef CwiseUnaryOp<internal::scalar_isFinite_op<Scalar>, const Derived> IsFiniteReturnType;
/** \returns an expression of the coefficient-wise absolute value of \c *this
*
@ -31,6 +43,20 @@ abs() const
return AbsReturnType(derived());
}
/** \returns an expression of the coefficient-wise phase angle of \c *this
*
* Example: \include Cwise_arg.cpp
* Output: \verbinclude Cwise_arg.out
*
* \sa abs()
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const ArgReturnType
arg() const
{
return ArgReturnType(derived());
}
/** \returns an expression of the coefficient-wise squared absolute value of \c *this
*
* Example: \include Cwise_abs2.cpp
@ -79,6 +105,22 @@ log() const
return LogReturnType(derived());
}
/** \returns an expression of the coefficient-wise base-10 logarithm of *this.
*
* This function computes the coefficient-wise base-10 logarithm.
*
* Example: \include Cwise_log10.cpp
* Output: \verbinclude Cwise_log10.out
*
* \sa log()
*/
EIGEN_DEVICE_FUNC
inline const Log10ReturnType
log10() const
{
return Log10ReturnType(derived());
}
/** \returns an expression of the coefficient-wise square root of *this.
*
* This function computes the coefficient-wise square root. The function MatrixBase::sqrt() in the
@ -131,6 +173,33 @@ sin() const
return SinReturnType(derived());
}
/** \returns an expression of the coefficient-wise tan of *this.
*
* Example: \include Cwise_tan.cpp
* Output: \verbinclude Cwise_tan.out
*
* \sa cos(), sin()
*/
EIGEN_DEVICE_FUNC
inline const TanReturnType
tan() const
{
return TanReturnType(derived());
}
/** \returns an expression of the coefficient-wise arc tan of *this.
*
* Example: \include Cwise_atan.cpp
* Output: \verbinclude Cwise_atan.out
*
* \sa tan(), asin(), acos()
*/
inline const AtanReturnType
atan() const
{
return AtanReturnType(derived());
}
/** \returns an expression of the coefficient-wise arc cosine of *this.
*
* Example: \include Cwise_acos.cpp
@ -159,31 +228,43 @@ asin() const
return AsinReturnType(derived());
}
/** \returns an expression of the coefficient-wise tan of *this.
/** \returns an expression of the coefficient-wise hyperbolic tan of *this.
*
* Example: \include Cwise_tan.cpp
* Output: \verbinclude Cwise_tan.out
* Example: \include Cwise_tanh.cpp
* Output: \verbinclude Cwise_tanh.out
*
* \sa cos(), sin()
* \sa tan(), sinh(), cosh()
*/
EIGEN_DEVICE_FUNC
inline const TanReturnType
tan() const
inline const TanhReturnType
tanh() const
{
return TanReturnType(derived());
return TanhReturnType(derived());
}
/** \returns an expression of the coefficient-wise arc tan of *this.
/** \returns an expression of the coefficient-wise hyperbolic sin of *this.
*
* Example: \include Cwise_atan.cpp
* Output: \verbinclude Cwise_atan.out
* Example: \include Cwise_sinh.cpp
* Output: \verbinclude Cwise_sinh.out
*
* \sa cos(), sin(), tan()
* \sa sin(), tanh(), cosh()
*/
inline const AtanReturnType
atan() const
inline const SinhReturnType
sinh() const
{
return AtanReturnType(derived());
return SinhReturnType(derived());
}
/** \returns an expression of the coefficient-wise hyperbolic cos of *this.
*
* Example: \include Cwise_cosh.cpp
* Output: \verbinclude Cwise_cosh.out
*
* \sa tan(), sinh(), cosh()
*/
inline const CoshReturnType
cosh() const
{
return CoshReturnType(derived());
}
/** \returns an expression of the coefficient-wise power of *this to the given exponent.
@ -246,5 +327,98 @@ cube() const
return CubeReturnType(derived());
}
/** \returns an expression of the coefficient-wise round of *this.
*
* Example: \include Cwise_round.cpp
* Output: \verbinclude Cwise_round.out
*
* \sa ceil(), floor()
*/
inline const RoundReturnType
round() const
{
return RoundReturnType(derived());
}
/** \returns an expression of the coefficient-wise floor of *this.
*
* Example: \include Cwise_floor.cpp
* Output: \verbinclude Cwise_floor.out
*
* \sa ceil(), round()
*/
inline const FloorReturnType
floor() const
{
return FloorReturnType(derived());
}
/** \returns an expression of the coefficient-wise ceil of *this.
*
* Example: \include Cwise_ceil.cpp
* Output: \verbinclude Cwise_ceil.out
*
* \sa floor(), round()
*/
inline const CeilReturnType
ceil() const
{
return CeilReturnType(derived());
}
/** \returns an expression of the coefficient-wise isNaN of *this.
*
* Example: \include Cwise_isNaN.cpp
* Output: \verbinclude Cwise_isNaN.out
*
* \sa isFinite(), isInf()
*/
inline const IsNaNReturnType
isNaN() const
{
return IsNaNReturnType(derived());
}
/** \returns an expression of the coefficient-wise isInf of *this.
*
* Example: \include Cwise_isInf.cpp
* Output: \verbinclude Cwise_isInf.out
*
* \sa isNaN(), isFinite()
*/
inline const IsInfReturnType
isInf() const
{
return IsInfReturnType(derived());
}
/** \returns an expression of the coefficient-wise isFinite of *this.
*
* Example: \include Cwise_isFinite.cpp
* Output: \verbinclude Cwise_isFinite.out
*
* \sa isNaN(), isInf()
*/
inline const IsFiniteReturnType
isFinite() const
{
return IsFiniteReturnType(derived());
}
/** \returns an expression of the coefficient-wise ! operator of *this
*
* \warning this operator is for expression of bool only.
*
* Example: \include Cwise_boolean_not.cpp
* Output: \verbinclude Cwise_boolean_not.out
*
* \sa operator!=()
*/
EIGEN_DEVICE_FUNC
inline const BooleanNotReturnType
operator!() const
{
EIGEN_STATIC_ASSERT((internal::is_same<bool,Scalar>::value),
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return BooleanNotReturnType(derived());
}

View File

@ -0,0 +1,3 @@
ArrayXcf v = ArrayXcf::Random(3);
cout << v << endl << endl;
cout << arg(v) << endl;

View File

@ -0,0 +1,5 @@
Array3d v(1,2,3);
v(1) *= 0.0/0.0;
v(2) /= 0.0;
cout << v << endl << endl;
cout << !isFinite(v) << endl;

View File

@ -0,0 +1,3 @@
ArrayXd v = ArrayXd::LinSpaced(7,-2,2);
cout << v << endl << endl;
cout << ceil(v) << endl;

View File

@ -0,0 +1,2 @@
ArrayXd v = ArrayXd::LinSpaced(5,0,1);
cout << cosh(v) << endl;

View File

@ -0,0 +1,3 @@
ArrayXd v = ArrayXd::LinSpaced(7,-2,2);
cout << v << endl << endl;
cout << floor(v) << endl;

View File

@ -0,0 +1,5 @@
Array3d v(1,2,3);
v(1) *= 0.0/0.0;
v(2) /= 0.0;
cout << v << endl << endl;
cout << isFinite(v) << endl;

View File

@ -0,0 +1,5 @@
Array3d v(1,2,3);
v(1) *= 0.0/0.0;
v(2) /= 0.0;
cout << v << endl << endl;
cout << isInf(v) << endl;

View File

@ -0,0 +1,5 @@
Array3d v(1,2,3);
v(1) *= 0.0/0.0;
v(2) /= 0.0;
cout << v << endl << endl;
cout << isNaN(v) << endl;

View File

@ -0,0 +1,2 @@
Array4d v(-1,0,1,2);
cout << log10(v) << endl;

View File

@ -0,0 +1,3 @@
ArrayXd v = ArrayXd::LinSpaced(7,-2,2);
cout << v << endl << endl;
cout << round(v) << endl;

View File

@ -0,0 +1,2 @@
ArrayXd v = ArrayXd::LinSpaced(5,0,1);
cout << sinh(v) << endl;

View File

@ -0,0 +1,2 @@
ArrayXd v = ArrayXd::LinSpaced(5,0,1);
cout << tanh(v) << endl;

View File

@ -201,18 +201,54 @@ template<typename ArrayType> void array_real(const ArrayType& m)
Scalar s1 = internal::random<Scalar>();
// these tests are mostly to check possible compilation issues.
// these tests are mostly to check possible compilation issues with free-functions.
VERIFY_IS_APPROX(m1.sin(), sin(m1));
VERIFY_IS_APPROX(m1.cos(), cos(m1));
VERIFY_IS_APPROX(m1.tan(), tan(m1));
VERIFY_IS_APPROX(m1.asin(), asin(m1));
VERIFY_IS_APPROX(m1.acos(), acos(m1));
VERIFY_IS_APPROX(m1.tan(), tan(m1));
VERIFY_IS_APPROX(m1.atan(), atan(m1));
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
VERIFY_IS_APPROX(m1.arg(), arg(m1));
VERIFY_IS_APPROX(m1.round(), round(m1));
VERIFY_IS_APPROX(m1.floor(), floor(m1));
VERIFY_IS_APPROX(m1.ceil(), ceil(m1));
VERIFY((m1.isNaN() == isNaN(m1)).all());
VERIFY((m1.isInf() == isInf(m1)).all());
VERIFY((m1.isFinite() == isFinite(m1)).all());
VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
VERIFY_IS_APPROX(m1.abs(), abs(m1));
VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
VERIFY_IS_APPROX(m1.square(), square(m1));
VERIFY_IS_APPROX(m1.cube(), cube(m1));
VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
VERIFY_IS_APPROX(m1.abs().sqrt(), sqrt(abs(m1)));
VERIFY_IS_APPROX(m1.abs(), sqrt(numext::abs2(m1)));
// avoid NaNs with abs() so verification doesn't fail
m3 = m1.abs();
VERIFY_IS_APPROX(m3.sqrt(), sqrt(abs(m1)));
VERIFY_IS_APPROX(m3.log(), log(m3));
VERIFY_IS_APPROX(m3.log10(), log10(m3));
VERIFY((!(m1>m2) == (m1<=m2)).all());
VERIFY_IS_APPROX(sin(m1.asin()), m1);
VERIFY_IS_APPROX(cos(m1.acos()), m1);
VERIFY_IS_APPROX(tan(m1.atan()), m1);
VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
VERIFY_IS_APPROX(arg(m1), ((ArrayType)(m1<0))*std::acos(-1.0));
VERIFY((round(m1) <= ceil(m1) && round(m1) >= floor(m1)).all());
VERIFY(isNaN(m1*0.0/0.0).all());
VERIFY(isInf(m1/0.0).all());
VERIFY((isFinite(m1) && !isFinite(m1*0.0/0.0) && !isFinite(m1/0.0)).all());
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(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
@ -221,7 +257,7 @@ template<typename ArrayType> void array_real(const ArrayType& m)
// shift argument of logarithm so that it is not zero
Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
VERIFY_IS_APPROX((m1.abs() + smallNumber).log() , log(abs(m1) + smallNumber));
VERIFY_IS_APPROX((m3 + smallNumber).log() , log(abs(m1) + smallNumber));
VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
VERIFY_IS_APPROX(m1.exp(), exp(m1));
@ -229,13 +265,15 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(m1.pow(2), m1.square());
VERIFY_IS_APPROX(pow(m1,2), m1.square());
VERIFY_IS_APPROX(m1.pow(3), m1.cube());
VERIFY_IS_APPROX(pow(m1,3), m1.cube());
ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
m3 = m1.abs();
VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
VERIFY_IS_APPROX(log10(m3), log(m3)/log(10));
// scalar by array division
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
@ -254,6 +292,8 @@ template<typename ArrayType> void array_real(const ArrayType& m)
template<typename ArrayType> void array_complex(const ArrayType& m)
{
typedef typename ArrayType::Index Index;
typedef typename ArrayType::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
Index rows = m.rows();
Index cols = m.cols();
@ -261,12 +301,73 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
ArrayType m1 = ArrayType::Random(rows, cols),
m2(rows, cols);
Array<RealScalar, -1, -1> m3(rows, cols);
Scalar s1 = internal::random<Scalar>();
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
m2(i,j) = sqrt(m1(i,j));
VERIFY_IS_APPROX(m1.sqrt(), m2);
VERIFY_IS_APPROX(m1.sqrt(), Eigen::sqrt(m1));
// these tests are mostly to check possible compilation issues with free-functions.
VERIFY_IS_APPROX(m1.sin(), sin(m1));
VERIFY_IS_APPROX(m1.cos(), cos(m1));
VERIFY_IS_APPROX(m1.tan(), tan(m1));
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
VERIFY_IS_APPROX(m1.arg(), arg(m1));
VERIFY((m1.isNaN() == isNaN(m1)).all());
VERIFY((m1.isInf() == isInf(m1)).all());
VERIFY((m1.isFinite() == isFinite(m1)).all());
VERIFY_IS_APPROX(m1.inverse(), inverse(m1));
VERIFY_IS_APPROX(m1.log(), log(m1));
VERIFY_IS_APPROX(m1.log10(), log10(m1));
VERIFY_IS_APPROX(m1.abs(), abs(m1));
VERIFY_IS_APPROX(m1.abs2(), abs2(m1));
VERIFY_IS_APPROX(m1.sqrt(), sqrt(m1));
VERIFY_IS_APPROX(m1.square(), square(m1));
VERIFY_IS_APPROX(m1.cube(), cube(m1));
VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
VERIFY_IS_APPROX(m1.exp(), exp(m1));
VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
VERIFY_IS_APPROX(sinh(m1), 0.5*(exp(m1)-exp(-m1)));
VERIFY_IS_APPROX(cosh(m1), 0.5*(exp(m1)+exp(-m1)));
VERIFY_IS_APPROX(tanh(m1), (0.5*(exp(m1)-exp(-m1)))/(0.5*(exp(m1)+exp(-m1))));
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
m3(i,j) = std::atan2(imag(m1(i,j)), real(m1(i,j)));
VERIFY_IS_APPROX(arg(m1), m3);
std::complex<RealScalar> zero(0.0,0.0);
VERIFY(isNaN(m1*zero/zero).all());
VERIFY(isInf(m1/zero).all());
VERIFY((isFinite(m1) && !isFinite(m1*zero/zero) && !isFinite(m1/zero)).all());
VERIFY_IS_APPROX(inverse(inverse(m1)),m1);
VERIFY_IS_APPROX(conj(m1.conjugate()), m1);
VERIFY_IS_APPROX(abs(m1), sqrt(square(real(m1))+square(imag(m1))));
VERIFY_IS_APPROX(abs(m1), sqrt(abs2(m1)));
VERIFY_IS_APPROX(log10(m1), log(m1)/log(10));
// scalar by array division
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
// check inplace transpose
m2 = m1;
m2.transposeInPlace();
VERIFY_IS_APPROX(m2, m1.transpose());
m2.transposeInPlace();
VERIFY_IS_APPROX(m2, m1);
}
template<typename ArrayType> void min_max(const ArrayType& m)

View File

@ -448,12 +448,7 @@ template<typename T> bool isNotNaN(const T& x)
return x==x;
}
template<typename T> bool isNaN(const T& x)
{
return x!=x;
}
template<typename T> bool isInf(const T& x)
template<typename T> bool isPlusInf(const T& x)
{
return x > NumTraits<T>::highest();
}

View File

@ -317,7 +317,7 @@ template<typename Scalar> void packetmath_real()
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
packet_helper<internal::packet_traits<Scalar>::HasExp,Packet> h;
h.store(data2, internal::pexp(h.load(data1)));
VERIFY(isNaN(data2[0]));
VERIFY(numext::isNaN(data2[0]));
}
for (int i=0; i<size; ++i)
@ -333,14 +333,14 @@ template<typename Scalar> void packetmath_real()
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
packet_helper<internal::packet_traits<Scalar>::HasLog,Packet> h;
h.store(data2, internal::plog(h.load(data1)));
VERIFY(isNaN(data2[0]));
VERIFY(numext::isNaN(data2[0]));
data1[0] = -1.0f;
h.store(data2, internal::plog(h.load(data1)));
VERIFY(isNaN(data2[0]));
VERIFY(numext::isNaN(data2[0]));
#if !EIGEN_FAST_MATH
h.store(data2, internal::psqrt(h.load(data1)));
VERIFY(isNaN(data2[0]));
VERIFY(isNaN(data2[1]));
VERIFY(numext::isNaN(data2[0]));
VERIFY(numext::isNaN(data2[1]));
#endif
}
}

View File

@ -111,33 +111,33 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
{
v = vrand;
v(i,j) = std::numeric_limits<RealScalar>::quiet_NaN();
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isNaN(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isNaN(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isNaN(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isNaN(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isNaN(v.hypotNorm()));
VERIFY(!isFinite(v.squaredNorm())); VERIFY(numext::isNaN(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(numext::isNaN(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(numext::isNaN(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(numext::isNaN(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(numext::isNaN(v.hypotNorm()));
}
// +inf
{
v = vrand;
v(i,j) = std::numeric_limits<RealScalar>::infinity();
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isInf(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isInf(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isInf(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isInf(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isInf(v.hypotNorm()));
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isPlusInf(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isPlusInf(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isPlusInf(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isPlusInf(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isPlusInf(v.hypotNorm()));
}
// -inf
{
v = vrand;
v(i,j) = -std::numeric_limits<RealScalar>::infinity();
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isInf(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isInf(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isInf(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isInf(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isInf(v.hypotNorm()));
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isPlusInf(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isPlusInf(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isPlusInf(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isPlusInf(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isPlusInf(v.hypotNorm()));
}
// mix
@ -147,11 +147,11 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
v = vrand;
v(i,j) = -std::numeric_limits<RealScalar>::infinity();
v(i2,j2) = std::numeric_limits<RealScalar>::quiet_NaN();
VERIFY(!isFinite(v.squaredNorm())); VERIFY(isNaN(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(isNaN(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(isNaN(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(isNaN(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(isNaN(v.hypotNorm()));
VERIFY(!isFinite(v.squaredNorm())); VERIFY(numext::isNaN(v.squaredNorm()));
VERIFY(!isFinite(v.norm())); VERIFY(numext::isNaN(v.norm()));
VERIFY(!isFinite(v.stableNorm())); VERIFY(numext::isNaN(v.stableNorm()));
VERIFY(!isFinite(v.blueNorm())); VERIFY(numext::isNaN(v.blueNorm()));
VERIFY(!isFinite(v.hypotNorm())); VERIFY(numext::isNaN(v.hypotNorm()));
}
}