aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core/MathFunctions.h
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2015-06-10 15:52:05 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2015-06-10 15:52:05 +0200
commit25a98be948095c1487936c45aec0b7717509dac5 (patch)
tree2d195462c9c55803c1a6b99dec884545e90577b1 /Eigen/src/Core/MathFunctions.h
parent192bce2795bbfaa0d4e6fdcd270a95d59da82f66 (diff)
parente5048b5501a4c2cd86fa3f92ad214938eb3f9b3f (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.h174
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)