mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-09-23 06:43:13 +08:00
Use C++11 standard features for detecting presence of Inf and NaN
This commit is contained in:
parent
d71ac6a755
commit
690ae9502f
@ -229,63 +229,6 @@ struct imag_ref_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real & type;
|
typedef typename NumTraits<Scalar>::Real & type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Implementation of sign *
|
|
||||||
****************************************************************************/
|
|
||||||
template<typename Scalar, bool IsComplex = (NumTraits<Scalar>::IsComplex!=0),
|
|
||||||
bool IsInteger = (NumTraits<Scalar>::IsInteger!=0)>
|
|
||||||
struct sign_impl
|
|
||||||
{
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
static inline Scalar run(const Scalar& a)
|
|
||||||
{
|
|
||||||
return Scalar( (a>Scalar(0)) - (a<Scalar(0)) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
struct sign_impl<Scalar, false, false>
|
|
||||||
{
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
static inline Scalar run(const Scalar& a)
|
|
||||||
{
|
|
||||||
return (std::isnan)(a) ? a : Scalar( (a>Scalar(0)) - (a<Scalar(0)) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Scalar, bool IsInteger>
|
|
||||||
struct sign_impl<Scalar, true, IsInteger>
|
|
||||||
{
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
static inline Scalar run(const Scalar& a)
|
|
||||||
{
|
|
||||||
using real_type = typename NumTraits<Scalar>::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<bool, false, true>
|
|
||||||
{
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
static inline bool run(const bool& a)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
struct sign_retval
|
|
||||||
{
|
|
||||||
typedef Scalar type;
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of conj *
|
* Implementation of conj *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -664,7 +607,7 @@ struct expm1_impl {
|
|||||||
EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
|
EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||||
using std::expm1;
|
EIGEN_USING_STD(expm1);
|
||||||
return expm1(x);
|
return expm1(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -725,7 +668,7 @@ struct log1p_impl {
|
|||||||
|
|
||||||
EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
|
EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
using std::log1p;
|
EIGEN_USING_STD(log1p);
|
||||||
return log1p(x);
|
return log1p(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -938,128 +881,114 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
|
|||||||
|
|
||||||
// Implementation of is* functions
|
// 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.
|
template <typename T>
|
||||||
#if (!(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC) || (EIGEN_COMP_CLANG)
|
EIGEN_DEVICE_FUNC std::enable_if_t<!(std::numeric_limits<T>::has_infinity ||
|
||||||
#define EIGEN_USE_STD_FPCLASSIFY 1
|
std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
#else
|
std::numeric_limits<T>::has_signaling_NaN),
|
||||||
#define EIGEN_USE_STD_FPCLASSIFY 0
|
bool>
|
||||||
#endif
|
isfinite_impl(const T&) {
|
||||||
|
return true;
|
||||||
template<typename T>
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
std::enable_if_t<internal::is_integral<T>::value,bool>
|
|
||||||
isnan_impl(const T&) { return false; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
std::enable_if_t<internal::is_integral<T>::value,bool>
|
|
||||||
isinf_impl(const T&) { return false; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
std::enable_if_t<internal::is_integral<T>::value,bool>
|
|
||||||
isfinite_impl(const T&) { return true; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
std::enable_if_t<(!internal::is_integral<T>::value)&&(!NumTraits<T>::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<T>::highest() && x>=NumTraits<T>::lowest();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC std::enable_if_t<(std::numeric_limits<T>::has_infinity || std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
|
std::numeric_limits<T>::has_signaling_NaN) &&
|
||||||
|
(!NumTraits<T>::IsComplex),
|
||||||
|
bool>
|
||||||
|
isfinite_impl(const T& x) {
|
||||||
|
EIGEN_USING_STD(isfinite);
|
||||||
|
return (isfinite)(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC std::enable_if_t<!std::numeric_limits<T>::has_infinity, bool>
|
||||||
|
isinf_impl(const T&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC std::enable_if_t<
|
||||||
|
(std::numeric_limits<T>::has_infinity && !NumTraits<T>::IsComplex), bool>
|
||||||
|
isinf_impl(const T& x) {
|
||||||
|
EIGEN_USING_STD(isinf);
|
||||||
|
return (isinf)(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC std::enable_if_t<!(std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
|
std::numeric_limits<T>::has_signaling_NaN),
|
||||||
|
bool>
|
||||||
|
isnan_impl(const T&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
std::enable_if_t<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>
|
std::enable_if_t<(std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
isinf_impl(const T& x)
|
std::numeric_limits<T>::has_signaling_NaN) &&
|
||||||
{
|
(!NumTraits<T>::IsComplex),
|
||||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
bool>
|
||||||
return (::isinf)(x);
|
isnan_impl(const T& x) {
|
||||||
#elif EIGEN_USE_STD_FPCLASSIFY
|
EIGEN_USING_STD(isnan);
|
||||||
using std::isinf;
|
return (isnan)(x);
|
||||||
return isinf EIGEN_NOT_A_MACRO (x);
|
|
||||||
#else
|
|
||||||
return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
std::enable_if_t<(!internal::is_integral<T>::value)&&(!NumTraits<T>::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<typename T> 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
|
// The following overload are defined at the end of this file
|
||||||
template<typename T> EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x);
|
template <typename T>
|
||||||
template<typename T> EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x);
|
EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x);
|
||||||
template<typename T> EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x);
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x);
|
||||||
|
template <typename T>
|
||||||
|
EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x);
|
||||||
|
template <typename T>
|
||||||
|
T generic_fast_tanh_float(const T& a_x);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Implementation of sign *
|
||||||
|
****************************************************************************/
|
||||||
|
template <typename Scalar, bool IsComplex = (NumTraits<Scalar>::IsComplex != 0),
|
||||||
|
bool IsInteger = (NumTraits<Scalar>::IsInteger != 0)>
|
||||||
|
struct sign_impl {
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
static inline Scalar run(const Scalar& a) {
|
||||||
|
return Scalar((a > Scalar(0)) - (a < Scalar(0)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Scalar>
|
||||||
|
struct sign_impl<Scalar, false, false> {
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
static inline Scalar run(const Scalar& a) {
|
||||||
|
return (isnan_impl<Scalar>)(a) ? a
|
||||||
|
: Scalar((a > Scalar(0)) - (a < Scalar(0)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Scalar, bool IsInteger>
|
||||||
|
struct sign_impl<Scalar, true, IsInteger> {
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
static inline Scalar run(const Scalar& a) {
|
||||||
|
using real_type = typename NumTraits<Scalar>::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<bool, false, true> {
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
|
static inline bool run(const bool& a) { return a; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Scalar>
|
||||||
|
struct sign_retval {
|
||||||
|
typedef Scalar type;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> T generic_fast_tanh_float(const T& a_x);
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -140,11 +140,6 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
|||||||
bool (isfinite)(const AnnoyingScalar& x) {
|
bool (isfinite)(const AnnoyingScalar& x) {
|
||||||
return (numext::isfinite)(*x.v);
|
return (numext::isfinite)(*x.v);
|
||||||
}
|
}
|
||||||
template<>
|
|
||||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
|
||||||
bool (isnan)(const AnnoyingScalar& x) {
|
|
||||||
return (numext::isnan)(*x.v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user