From a09cfe650fe56b181747af04d61548800da1f72b Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Fri, 21 Aug 2015 16:01:40 -0700 Subject: [PATCH] std::numeric_limits doesn't work reliably on CUDA devices. Use our own definition of numeric_limit::max() and numeric_limit::min() instead of the stl ones. --- Eigen/src/Core/NumTraits.h | 20 ++++++++++++++++++-- Eigen/src/Core/util/Meta.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/Eigen/src/Core/NumTraits.h b/Eigen/src/Core/NumTraits.h index a04227f57..4d60cf88b 100644 --- a/Eigen/src/Core/NumTraits.h +++ b/Eigen/src/Core/NumTraits.h @@ -83,8 +83,24 @@ template struct GenericNumTraits // make sure to override this for floating-point types return Real(0); } - static inline T highest() { return (std::numeric_limits::max)(); } - static inline T lowest() { return IsInteger ? (std::numeric_limits::min)() : (-(std::numeric_limits::max)()); } + + + EIGEN_DEVICE_FUNC + static inline T highest() { +#if defined(__CUDA_ARCH__) + return internal::device::numeric_limits::max(); +#else + return (std::numeric_limits::max)(); +#endif + } + + EIGEN_DEVICE_FUNC + static inline T lowest() { +#if defined(__CUDA_ARCH__) + return IsInteger ? (internal::device::numeric_limits::min)() : (-(internal::device::numeric_limits::max)()); +#else + return IsInteger ? (std::numeric_limits::min)() : (-(std::numeric_limits::max)()); +#endif }; template struct NumTraits : GenericNumTraits diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index 7c8932511..152a0fd78 100644 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -128,16 +128,53 @@ template struct numeric_limits { EIGEN_DEVICE_FUNC static T epsilon() { return 0; } + static T max() { assert(false && "Highest not suppoted for this type"); } + static T min() { assert(false && "Lowest not suppoted for this type"); } }; template<> struct numeric_limits { EIGEN_DEVICE_FUNC static float epsilon() { return __FLT_EPSILON__; } + EIGEN_DEVICE_FUNC + static float max() { return CUDART_MAX_NORMAL_F; } + EIGEN_DEVICE_FUNC + static float min() { return __FLT_EPSILON__; } }; template<> struct numeric_limits { EIGEN_DEVICE_FUNC static double epsilon() { return __DBL_EPSILON__; } + EIGEN_DEVICE_FUNC + static double max() { return CUDART_INF; } + EIGEN_DEVICE_FUNC + static double min() { return __DBL_EPSILON__; } +}; +template<> struct numeric_limits +{ + EIGEN_DEVICE_FUNC + static int epsilon() { return 0; } + EIGEN_DEVICE_FUNC + static int max() { return INT_MAX; } + EIGEN_DEVICE_FUNC + static int min() { return INT_MIN; } +}; +template<> struct numeric_limits +{ + EIGEN_DEVICE_FUNC + static long epsilon() { return 0; } + EIGEN_DEVICE_FUNC + static long max() { return LONG_MAX; } + EIGEN_DEVICE_FUNC + static long min() { return LONG_MIN; } +}; +template<> struct numeric_limits +{ + EIGEN_DEVICE_FUNC + static long long epsilon() { return 0; } + EIGEN_DEVICE_FUNC + static long long max() { return LLONG_MAX; } + EIGEN_DEVICE_FUNC + static long long min() { return LLONG_MIN; } }; }