diff options
author | 2015-06-10 15:52:05 +0200 | |
---|---|---|
committer | 2015-06-10 15:52:05 +0200 | |
commit | 25a98be948095c1487936c45aec0b7717509dac5 (patch) | |
tree | 2d195462c9c55803c1a6b99dec884545e90577b1 /Eigen/src/Core/MathFunctions.h | |
parent | 192bce2795bbfaa0d4e6fdcd270a95d59da82f66 (diff) | |
parent | e5048b5501a4c2cd86fa3f92ad214938eb3f9b3f (diff) |
bug #80: merge with d_hood branch on adding more coefficient-wise unary array functors
Diffstat (limited to 'Eigen/src/Core/MathFunctions.h')
-rw-r--r-- | Eigen/src/Core/MathFunctions.h | 174 |
1 files changed, 169 insertions, 5 deletions
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 3c240c272..1ce935909 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -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 { @@ -639,6 +726,13 @@ inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& 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) { return internal::imag_ref_impl<Scalar>::run(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) { - return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest(); + #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) |