diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index ecc6f3883..6b1bfacdd 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -229,63 +229,6 @@ struct imag_ref_retval typedef typename NumTraits::Real & type; }; - -/**************************************************************************** -* Implementation of sign * -****************************************************************************/ -template::IsComplex!=0), - bool IsInteger = (NumTraits::IsInteger!=0)> -struct sign_impl -{ - EIGEN_DEVICE_FUNC - static inline Scalar run(const Scalar& a) - { - return Scalar( (a>Scalar(0)) - (a -struct sign_impl -{ - EIGEN_DEVICE_FUNC - static inline Scalar run(const Scalar& a) - { - return (std::isnan)(a) ? a : Scalar( (a>Scalar(0)) - (a -struct sign_impl -{ - EIGEN_DEVICE_FUNC - static inline Scalar run(const Scalar& a) - { - using real_type = typename NumTraits::Real; - real_type aa = std::abs(a); - if (aa==real_type(0)) - return Scalar(0); - aa = real_type(1)/aa; - return Scalar(a.real()*aa, a.imag()*aa ); - } -}; - -// The sign function for bool is the identity. -template<> -struct sign_impl -{ - EIGEN_DEVICE_FUNC - static inline bool run(const bool& a) - { - return a; - } -}; - -template -struct sign_retval -{ - typedef Scalar type; -}; - /**************************************************************************** * Implementation of conj * ****************************************************************************/ @@ -664,7 +607,7 @@ struct expm1_impl { EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) - using std::expm1; + EIGEN_USING_STD(expm1); return expm1(x); } }; @@ -725,7 +668,7 @@ struct log1p_impl { EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { - using std::log1p; + EIGEN_USING_STD(log1p); return log1p(x); } }; @@ -938,128 +881,114 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() // Implementation of is* functions -// std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang. -#if (!(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC) || (EIGEN_COMP_CLANG) -#define EIGEN_USE_STD_FPCLASSIFY 1 -#else -#define EIGEN_USE_STD_FPCLASSIFY 0 -#endif - -template -EIGEN_DEVICE_FUNC -std::enable_if_t::value,bool> -isnan_impl(const T&) { return false; } - -template -EIGEN_DEVICE_FUNC -std::enable_if_t::value,bool> -isinf_impl(const T&) { return false; } - -template -EIGEN_DEVICE_FUNC -std::enable_if_t::value,bool> -isfinite_impl(const T&) { return true; } - -template -EIGEN_DEVICE_FUNC -std::enable_if_t<(!internal::is_integral::value)&&(!NumTraits::IsComplex),bool> -isfinite_impl(const T& x) -{ - #if defined(EIGEN_GPU_COMPILE_PHASE) - return (::isfinite)(x); - #elif EIGEN_USE_STD_FPCLASSIFY - using std::isfinite; - return isfinite EIGEN_NOT_A_MACRO (x); - #else - return x<=NumTraits::highest() && x>=NumTraits::lowest(); - #endif +template +EIGEN_DEVICE_FUNC std::enable_if_t::has_infinity || + std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN), + bool> +isfinite_impl(const T&) { + return true; } -template +template +EIGEN_DEVICE_FUNC std::enable_if_t<(std::numeric_limits::has_infinity || std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + (!NumTraits::IsComplex), + bool> +isfinite_impl(const T& x) { + EIGEN_USING_STD(isfinite); + return (isfinite)(x); +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t::has_infinity, bool> +isinf_impl(const T&) { + return false; +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t< + (std::numeric_limits::has_infinity && !NumTraits::IsComplex), bool> +isinf_impl(const T& x) { + EIGEN_USING_STD(isinf); + return (isinf)(x); +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN), + bool> +isnan_impl(const T&) { + return false; +} + +template EIGEN_DEVICE_FUNC -std::enable_if_t<(!internal::is_integral::value)&&(!NumTraits::IsComplex),bool> -isinf_impl(const T& x) -{ - #if defined(EIGEN_GPU_COMPILE_PHASE) - return (::isinf)(x); - #elif EIGEN_USE_STD_FPCLASSIFY - using std::isinf; - return isinf EIGEN_NOT_A_MACRO (x); - #else - return x>NumTraits::highest() || x::lowest(); - #endif + std::enable_if_t<(std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + (!NumTraits::IsComplex), + bool> + isnan_impl(const T& x) { + EIGEN_USING_STD(isnan); + return (isnan)(x); } -template -EIGEN_DEVICE_FUNC -std::enable_if_t<(!internal::is_integral::value)&&(!NumTraits::IsComplex),bool> -isnan_impl(const T& x) -{ - #if defined(EIGEN_GPU_COMPILE_PHASE) - return (::isnan)(x); - #elif EIGEN_USE_STD_FPCLASSIFY - using std::isnan; - return isnan EIGEN_NOT_A_MACRO (x); - #else - return x != x; - #endif -} - -#if (!EIGEN_USE_STD_FPCLASSIFY) - -#if EIGEN_COMP_MSVC - -template EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x) -{ - return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF; -} - -//MSVC defines a _isnan builtin function, but for double only -#ifndef EIGEN_GPU_COMPILE_PHASE -EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x)!=0; } -#endif -EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x)!=0; } -EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x)!=0; } - -#ifndef EIGEN_GPU_COMPILE_PHASE -EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); } -#endif -EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); } -EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); } - -#elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC) - -#if EIGEN_COMP_GNUC - #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only"))) -#else - // NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol), - // while the second prevent too aggressive optimizations in fast-math mode: - #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only"))) -#endif - -#ifndef EIGEN_GPU_COMPILE_PHASE -template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); } -#endif -template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); } -template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); } -template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); } -template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); } -#ifndef EIGEN_GPU_COMPILE_PHASE -template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); } -#endif - -#undef EIGEN_TMP_NOOPT_ATTRIB - -#endif - -#endif - // The following overload are defined at the end of this file -template EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex& x); -template EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex& x); -template EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex& x); +template +EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex& x); +template +EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex& x); +template +EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex& x); +template +T generic_fast_tanh_float(const T& a_x); + +/**************************************************************************** + * Implementation of sign * + ****************************************************************************/ +template ::IsComplex != 0), + bool IsInteger = (NumTraits::IsInteger != 0)> +struct sign_impl { + EIGEN_DEVICE_FUNC + static inline Scalar run(const Scalar& a) { + return Scalar((a > Scalar(0)) - (a < Scalar(0))); + } +}; + +template +struct sign_impl { + EIGEN_DEVICE_FUNC + static inline Scalar run(const Scalar& a) { + return (isnan_impl)(a) ? a + : Scalar((a > Scalar(0)) - (a < Scalar(0))); + } +}; + +template +struct sign_impl { + EIGEN_DEVICE_FUNC + static inline Scalar run(const Scalar& a) { + using real_type = typename NumTraits::Real; + EIGEN_USING_STD(abs); + real_type aa = abs(a); + if (aa == real_type(0)) return Scalar(0); + aa = real_type(1) / aa; + return Scalar(a.real() * aa, a.imag() * aa); + } +}; + +// The sign function for bool is the identity. +template <> +struct sign_impl { + EIGEN_DEVICE_FUNC + static inline bool run(const bool& a) { return a; } +}; + +template +struct sign_retval { + typedef Scalar type; +}; -template T generic_fast_tanh_float(const T& a_x); } // end namespace internal /**************************************************************************** diff --git a/test/AnnoyingScalar.h b/test/AnnoyingScalar.h index dc20d43a7..94b513c41 100644 --- a/test/AnnoyingScalar.h +++ b/test/AnnoyingScalar.h @@ -65,7 +65,7 @@ class AnnoyingScalar AnnoyingScalar operator-() const { return AnnoyingScalar(-*v); } - + AnnoyingScalar operator-(const AnnoyingScalar& other) const { return AnnoyingScalar(*v-*other.v); } @@ -140,11 +140,6 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool (isfinite)(const AnnoyingScalar& x) { return (numext::isfinite)(*x.v); } -template<> -EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE -bool (isnan)(const AnnoyingScalar& x) { - return (numext::isnan)(*x.v); -} } namespace internal {