Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:40:12

0001 //  Copyright John Maddock 2005-2008.
0002 //  Copyright (c) 2006-2008 Johan Rade
0003 //  Copyright (c) 2024 Matt Borland
0004 //  Use, modification and distribution are subject to the
0005 //  Boost Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_MATH_FPCLASSIFY_HPP
0009 #define BOOST_MATH_FPCLASSIFY_HPP
0010 
0011 #ifdef _MSC_VER
0012 #pragma once
0013 #endif
0014 
0015 #include <boost/math/tools/config.hpp>
0016 
0017 #ifndef BOOST_MATH_HAS_NVRTC
0018 
0019 #include <boost/math/tools/real_cast.hpp>
0020 #include <boost/math/special_functions/math_fwd.hpp>
0021 #include <boost/math/special_functions/detail/fp_traits.hpp>
0022 #include <limits>
0023 #include <type_traits>
0024 #include <cmath>
0025 
0026 /*!
0027   \file fpclassify.hpp
0028   \brief Classify floating-point value as normal, subnormal, zero, infinite, or NaN.
0029   \version 1.0
0030   \author John Maddock
0031  */
0032 
0033 /*
0034 
0035 1. If the platform is C99 compliant, then the native floating point
0036 classification functions are used.  However, note that we must only
0037 define the functions which call std::fpclassify etc if that function
0038 really does exist: otherwise a compiler may reject the code even though
0039 the template is never instantiated.
0040 
0041 2. If the platform is not C99 compliant, and the binary format for
0042 a floating point type (float, double or long double) can be determined
0043 at compile time, then the following algorithm is used:
0044 
0045         If all exponent bits, the flag bit (if there is one),
0046         and all significand bits are 0, then the number is zero.
0047 
0048         If all exponent bits and the flag bit (if there is one) are 0,
0049         and at least one significand bit is 1, then the number is subnormal.
0050 
0051         If all exponent bits are 1 and all significand bits are 0,
0052         then the number is infinity.
0053 
0054         If all exponent bits are 1 and at least one significand bit is 1,
0055         then the number is a not-a-number.
0056 
0057         Otherwise the number is normal.
0058 
0059         This algorithm works for the IEEE 754 representation,
0060         and also for several non IEEE 754 formats.
0061 
0062     Most formats have the structure
0063         sign bit + exponent bits + significand bits.
0064 
0065     A few have the structure
0066         sign bit + exponent bits + flag bit + significand bits.
0067     The flag bit is 0 for zero and subnormal numbers,
0068         and 1 for normal numbers and NaN.
0069         It is 0 (Motorola 68K) or 1 (Intel) for infinity.
0070 
0071     To get the bits, the four or eight most significant bytes are copied
0072     into an uint32_t or uint64_t and bit masks are applied.
0073     This covers all the exponent bits and the flag bit (if there is one),
0074     but not always all the significand bits.
0075     Some of the functions below have two implementations,
0076     depending on whether all the significand bits are copied or not.
0077 
0078 3. If the platform is not C99 compliant, and the binary format for
0079 a floating point type (float, double or long double) can not be determined
0080 at compile time, then comparison with std::numeric_limits values
0081 is used.
0082 
0083 */
0084 
0085 #ifdef BOOST_MATH_HAS_GPU_SUPPORT
0086 
0087 namespace boost { namespace math {
0088 
0089 template<> inline BOOST_MATH_GPU_ENABLED bool (isnan)(float x) { return x != x; }
0090 template<> inline BOOST_MATH_GPU_ENABLED bool (isnan)(double x) { return x != x; }
0091 
0092 template<> inline BOOST_MATH_GPU_ENABLED bool (isinf)(float x) { return x > FLT_MAX || x < -FLT_MAX; }
0093 template<> inline BOOST_MATH_GPU_ENABLED bool (isinf)(double x) { return x > DBL_MAX || x < -DBL_MAX; }
0094 
0095 template<> inline BOOST_MATH_GPU_ENABLED bool (isfinite)(float x) {  return !isnan(x) && !isinf(x);  }
0096 template<> inline BOOST_MATH_GPU_ENABLED bool (isfinite)(double x) {  return !isnan(x) && !isinf(x); }
0097 
0098 template<> inline BOOST_MATH_GPU_ENABLED bool (isnormal)(float x)
0099 {
0100    if(x < 0) x = -x;
0101    return (x >= FLT_MIN) && (x <= FLT_MAX);
0102 }
0103 template<> inline BOOST_MATH_GPU_ENABLED bool (isnormal)(double x)
0104 {
0105    if(x < 0) x = -x;
0106    return (x >= DBL_MIN) && (x <= DBL_MAX);
0107 }
0108 
0109 template<> inline BOOST_MATH_GPU_ENABLED int (fpclassify)(float t)
0110 {
0111    if((boost::math::isnan)(t))
0112       return FP_NAN;
0113    // std::fabs broken on a few systems especially for long long!!!!
0114    float at = (t < 0.0f) ? -t : t;
0115 
0116    // Use a process of exclusion to figure out
0117    // what kind of type we have, this relies on
0118    // IEEE conforming reals that will treat
0119    // Nan's as unordered.  Some compilers
0120    // don't do this once optimisations are
0121    // turned on, hence the check for nan's above.
0122    if(at <= FLT_MAX)
0123    {
0124       if(at >= FLT_MIN)
0125          return FP_NORMAL;
0126       return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
0127    }
0128    else if(at > FLT_MAX)
0129       return FP_INFINITE;
0130    return FP_NAN;
0131 }
0132 
0133 template<> inline BOOST_MATH_GPU_ENABLED int (fpclassify)(double t)
0134 {
0135    if((boost::math::isnan)(t))
0136       return FP_NAN;
0137    // std::fabs broken on a few systems especially for long long!!!!
0138    double at = (t < 0.0) ? -t : t;
0139 
0140    // Use a process of exclusion to figure out
0141    // what kind of type we have, this relies on
0142    // IEEE conforming reals that will treat
0143    // Nan's as unordered.  Some compilers
0144    // don't do this once optimisations are
0145    // turned on, hence the check for nan's above.
0146    if(at <= DBL_MAX)
0147    {
0148       if(at >= DBL_MIN)
0149          return FP_NORMAL;
0150       return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
0151    }
0152    else if(at > DBL_MAX)
0153       return FP_INFINITE;
0154    return FP_NAN;
0155 }
0156 
0157 #else
0158 
0159 #if defined(_MSC_VER) || defined(BOOST_BORLANDC)
0160 #include <cfloat>
0161 #endif
0162 #ifdef BOOST_MATH_USE_FLOAT128
0163 #ifdef __has_include
0164 #if  __has_include("quadmath.h")
0165 #include "quadmath.h"
0166 #define BOOST_MATH_HAS_QUADMATH_H
0167 #endif
0168 #endif
0169 #endif
0170 
0171 #ifdef BOOST_NO_STDC_NAMESPACE
0172   namespace std{ using ::abs; using ::fabs; }
0173 #endif
0174 
0175 namespace boost{
0176 
0177 //
0178 // This must not be located in any namespace under boost::math
0179 // otherwise we can get into an infinite loop if isnan is
0180 // a #define for "isnan" !
0181 //
0182 namespace math_detail{
0183 
0184 #ifdef _MSC_VER
0185 #pragma warning(push)
0186 #pragma warning(disable:4800)
0187 #endif
0188 
0189 template <class T>
0190 inline bool is_nan_helper(T t, const std::true_type&)
0191 {
0192 #ifdef isnan
0193    return isnan(t);
0194 #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
0195    (void)t;
0196    return false;
0197 #else // BOOST_HAS_FPCLASSIFY
0198    return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
0199 #endif
0200 }
0201 
0202 #ifdef _MSC_VER
0203 #pragma warning(pop)
0204 #endif
0205 
0206 template <class T>
0207 inline bool is_nan_helper(T, const std::false_type&)
0208 {
0209    return false;
0210 }
0211 #if defined(BOOST_MATH_USE_FLOAT128)
0212 #if defined(BOOST_MATH_HAS_QUADMATH_H)
0213 inline bool is_nan_helper(__float128 f, const std::true_type&) { return ::isnanq(f); }
0214 inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnanq(f); }
0215 #elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
0216       _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
0217 inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast<double>(f)); }
0218 inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast<double>(f)); }
0219 #else
0220 inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast<double>(f)); }
0221 inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast<double>(f)); }
0222 #endif
0223 #endif
0224 }
0225 
0226 namespace math{
0227 
0228 namespace detail{
0229 
0230 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0231 template <class T>
0232 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
0233 {
0234    return (std::fpclassify)(t);
0235 }
0236 #endif
0237 
0238 template <class T>
0239 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
0240 {
0241    BOOST_MATH_INSTRUMENT_VARIABLE(t);
0242 
0243    // whenever possible check for Nan's first:
0244 #if defined(BOOST_HAS_FPCLASSIFY)  && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
0245    if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
0246       return FP_NAN;
0247 #elif defined(isnan)
0248    if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
0249       return FP_NAN;
0250 #elif defined(_MSC_VER) || defined(BOOST_BORLANDC)
0251    if(::_isnan(boost::math::tools::real_cast<double>(t)))
0252       return FP_NAN;
0253 #endif
0254    // std::fabs broken on a few systems especially for long long!!!!
0255    T at = (t < T(0)) ? -t : t;
0256 
0257    // Use a process of exclusion to figure out
0258    // what kind of type we have, this relies on
0259    // IEEE conforming reals that will treat
0260    // Nan's as unordered.  Some compilers
0261    // don't do this once optimisations are
0262    // turned on, hence the check for nan's above.
0263    if(at <= (std::numeric_limits<T>::max)())
0264    {
0265       if(at >= (std::numeric_limits<T>::min)())
0266          return FP_NORMAL;
0267       return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
0268    }
0269    else if(at > (std::numeric_limits<T>::max)())
0270       return FP_INFINITE;
0271    return FP_NAN;
0272 }
0273 
0274 template <class T>
0275 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
0276 {
0277 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0278    if(std::numeric_limits<T>::is_specialized)
0279       return fpclassify_imp(t, generic_tag<true>());
0280 #endif
0281    //
0282    // An unknown type with no numeric_limits support,
0283    // so what are we supposed to do we do here?
0284    //
0285    BOOST_MATH_INSTRUMENT_VARIABLE(t);
0286 
0287    return t == 0 ? FP_ZERO : FP_NORMAL;
0288 }
0289 
0290 template<class T>
0291 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
0292 {
0293    typedef typename fp_traits<T>::type traits;
0294 
0295    BOOST_MATH_INSTRUMENT_VARIABLE(x);
0296 
0297    typename traits::bits a;
0298    traits::get_bits(x,a);
0299    BOOST_MATH_INSTRUMENT_VARIABLE(a);
0300    a &= traits::exponent | traits::flag | traits::significand;
0301    BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
0302    BOOST_MATH_INSTRUMENT_VARIABLE(a);
0303 
0304    if(a <= traits::significand) {
0305       if(a == 0)
0306          return FP_ZERO;
0307       else
0308          return FP_SUBNORMAL;
0309    }
0310 
0311    if(a < traits::exponent) return FP_NORMAL;
0312 
0313    a &= traits::significand;
0314    if(a == 0) return FP_INFINITE;
0315 
0316    return FP_NAN;
0317 }
0318 
0319 template<class T>
0320 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
0321 {
0322    typedef typename fp_traits<T>::type traits;
0323 
0324    BOOST_MATH_INSTRUMENT_VARIABLE(x);
0325 
0326    typename traits::bits a;
0327    traits::get_bits(x,a);
0328    a &= traits::exponent | traits::flag | traits::significand;
0329 
0330    if(a <= traits::significand) {
0331       if(x == 0)
0332          return FP_ZERO;
0333       else
0334          return FP_SUBNORMAL;
0335    }
0336 
0337    if(a < traits::exponent) return FP_NORMAL;
0338 
0339    a &= traits::significand;
0340    traits::set_bits(x,a);
0341    if(x == 0) return FP_INFINITE;
0342 
0343    return FP_NAN;
0344 }
0345 
0346 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
0347 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0348 {
0349    return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
0350 }
0351 #endif
0352 
0353 }  // namespace detail
0354 
0355 template <class T>
0356 inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
0357 {
0358    typedef typename detail::fp_traits<T>::type traits;
0359    typedef typename traits::method method;
0360    typedef typename tools::promote_args_permissive<T>::type value_type;
0361 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0362    if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
0363       return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
0364    return detail::fpclassify_imp(static_cast<value_type>(t), method());
0365 #else
0366    return detail::fpclassify_imp(static_cast<value_type>(t), method());
0367 #endif
0368 }
0369 
0370 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0371 template <>
0372 inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
0373 {
0374    typedef detail::fp_traits<long double>::type traits;
0375    typedef traits::method method;
0376    typedef long double value_type;
0377 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0378    if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
0379       return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
0380    return detail::fpclassify_imp(static_cast<value_type>(t), method());
0381 #else
0382    return detail::fpclassify_imp(static_cast<value_type>(t), method());
0383 #endif
0384 }
0385 #endif
0386 
0387 namespace detail {
0388 
0389 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0390     template<class T>
0391     inline bool isfinite_impl(T x, native_tag const&)
0392     {
0393         return (std::isfinite)(x);
0394     }
0395 #endif
0396 
0397     template<class T>
0398     inline bool isfinite_impl(T x, generic_tag<true> const&)
0399     {
0400         return x >= -(std::numeric_limits<T>::max)()
0401             && x <= (std::numeric_limits<T>::max)();
0402     }
0403 
0404     template<class T>
0405     inline bool isfinite_impl(T x, generic_tag<false> const&)
0406     {
0407 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0408       if(std::numeric_limits<T>::is_specialized)
0409          return isfinite_impl(x, generic_tag<true>());
0410 #endif
0411        (void)x; // warning suppression.
0412        return true;
0413     }
0414 
0415     template<class T>
0416     inline bool isfinite_impl(T x, ieee_tag const&)
0417     {
0418         typedef typename detail::fp_traits<T>::type traits;
0419         typename traits::bits a;
0420         traits::get_bits(x,a);
0421         a &= traits::exponent;
0422         return a != traits::exponent;
0423     }
0424 
0425 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0426 inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0427 {
0428    return boost::math::detail::isfinite_impl(t, generic_tag<true>());
0429 }
0430 #endif
0431 
0432 }
0433 
0434 template<class T>
0435 inline bool (isfinite)(T x)
0436 { //!< \brief return true if floating-point type t is finite.
0437    typedef typename detail::fp_traits<T>::type traits;
0438    typedef typename traits::method method;
0439    // typedef typename boost::is_floating_point<T>::type fp_tag;
0440    typedef typename tools::promote_args_permissive<T>::type value_type;
0441    return detail::isfinite_impl(static_cast<value_type>(x), method());
0442 }
0443 
0444 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0445 template<>
0446 inline bool (isfinite)(long double x)
0447 { //!< \brief return true if floating-point type t is finite.
0448    typedef detail::fp_traits<long double>::type traits;
0449    typedef traits::method method;
0450    //typedef boost::is_floating_point<long double>::type fp_tag;
0451    typedef long double value_type;
0452    return detail::isfinite_impl(static_cast<value_type>(x), method());
0453 }
0454 #endif
0455 
0456 //------------------------------------------------------------------------------
0457 
0458 namespace detail {
0459 
0460 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0461     template<class T>
0462     inline bool isnormal_impl(T x, native_tag const&)
0463     {
0464         return (std::isnormal)(x);
0465     }
0466 #endif
0467 
0468     template<class T>
0469     inline bool isnormal_impl(T x, generic_tag<true> const&)
0470     {
0471         if(x < 0) x = -x;
0472         return x >= (std::numeric_limits<T>::min)()
0473             && x <= (std::numeric_limits<T>::max)();
0474     }
0475 
0476     template<class T>
0477     inline bool isnormal_impl(T x, generic_tag<false> const&)
0478     {
0479 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0480       if(std::numeric_limits<T>::is_specialized)
0481          return isnormal_impl(x, generic_tag<true>());
0482 #endif
0483        return !(x == 0);
0484     }
0485 
0486     template<class T>
0487     inline bool isnormal_impl(T x, ieee_tag const&)
0488     {
0489         typedef typename detail::fp_traits<T>::type traits;
0490         typename traits::bits a;
0491         traits::get_bits(x,a);
0492         a &= traits::exponent | traits::flag;
0493         return (a != 0) && (a < traits::exponent);
0494     }
0495 
0496 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0497 inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0498 {
0499    return boost::math::detail::isnormal_impl(t, generic_tag<true>());
0500 }
0501 #endif
0502 
0503 }
0504 
0505 template<class T>
0506 inline bool (isnormal)(T x)
0507 {
0508    typedef typename detail::fp_traits<T>::type traits;
0509    typedef typename traits::method method;
0510    //typedef typename boost::is_floating_point<T>::type fp_tag;
0511    typedef typename tools::promote_args_permissive<T>::type value_type;
0512    return detail::isnormal_impl(static_cast<value_type>(x), method());
0513 }
0514 
0515 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0516 template<>
0517 inline bool (isnormal)(long double x)
0518 {
0519    typedef detail::fp_traits<long double>::type traits;
0520    typedef traits::method method;
0521    //typedef boost::is_floating_point<long double>::type fp_tag;
0522    typedef long double value_type;
0523    return detail::isnormal_impl(static_cast<value_type>(x), method());
0524 }
0525 #endif
0526 
0527 //------------------------------------------------------------------------------
0528 
0529 namespace detail {
0530 
0531 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0532     template<class T>
0533     inline bool isinf_impl(T x, native_tag const&)
0534     {
0535         return (std::isinf)(x);
0536     }
0537 #endif
0538 
0539     template<class T>
0540     inline bool isinf_impl(T x, generic_tag<true> const&)
0541     {
0542         (void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false
0543         return std::numeric_limits<T>::has_infinity
0544             && ( x == std::numeric_limits<T>::infinity()
0545                  || x == -std::numeric_limits<T>::infinity());
0546     }
0547 
0548     template<class T>
0549     inline bool isinf_impl(T x, generic_tag<false> const&)
0550     {
0551 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0552       if(std::numeric_limits<T>::is_specialized)
0553          return isinf_impl(x, generic_tag<true>());
0554 #endif
0555         (void)x; // warning suppression.
0556         return false;
0557     }
0558 
0559     template<class T>
0560     inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
0561     {
0562         typedef typename fp_traits<T>::type traits;
0563 
0564         typename traits::bits a;
0565         traits::get_bits(x,a);
0566         a &= traits::exponent | traits::significand;
0567         return a == traits::exponent;
0568     }
0569 
0570     template<class T>
0571     inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
0572     {
0573         typedef typename fp_traits<T>::type traits;
0574 
0575         typename traits::bits a;
0576         traits::get_bits(x,a);
0577         a &= traits::exponent | traits::significand;
0578         if(a != traits::exponent)
0579             return false;
0580 
0581         traits::set_bits(x,0);
0582         return x == 0;
0583     }
0584 
0585 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0586 inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0587 {
0588    return boost::math::detail::isinf_impl(t, generic_tag<true>());
0589 }
0590 #endif
0591 
0592 }   // namespace detail
0593 
0594 template<class T>
0595 inline bool (isinf)(T x)
0596 {
0597    typedef typename detail::fp_traits<T>::type traits;
0598    typedef typename traits::method method;
0599    // typedef typename boost::is_floating_point<T>::type fp_tag;
0600    typedef typename tools::promote_args_permissive<T>::type value_type;
0601    return detail::isinf_impl(static_cast<value_type>(x), method());
0602 }
0603 
0604 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0605 template<>
0606 inline bool (isinf)(long double x)
0607 {
0608    typedef detail::fp_traits<long double>::type traits;
0609    typedef traits::method method;
0610    //typedef boost::is_floating_point<long double>::type fp_tag;
0611    typedef long double value_type;
0612    return detail::isinf_impl(static_cast<value_type>(x), method());
0613 }
0614 #endif
0615 #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
0616 template<>
0617 inline bool (isinf)(__float128 x)
0618 {
0619    return ::isinfq(x);
0620 }
0621 #endif
0622 
0623 //------------------------------------------------------------------------------
0624 
0625 namespace detail {
0626 
0627 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0628     template<class T>
0629     inline bool isnan_impl(T x, native_tag const&)
0630     {
0631         return (std::isnan)(x);
0632     }
0633 #endif
0634 
0635     template<class T>
0636     inline bool isnan_impl(T x, generic_tag<true> const&)
0637     {
0638         return std::numeric_limits<T>::has_infinity
0639             ? !(x <= std::numeric_limits<T>::infinity())
0640             : x != x;
0641     }
0642 
0643     template<class T>
0644     inline bool isnan_impl(T x, generic_tag<false> const&)
0645     {
0646 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0647       if(std::numeric_limits<T>::is_specialized)
0648          return isnan_impl(x, generic_tag<true>());
0649 #endif
0650         (void)x; // warning suppression
0651         return false;
0652     }
0653 
0654     template<class T>
0655     inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
0656     {
0657         typedef typename fp_traits<T>::type traits;
0658 
0659         typename traits::bits a;
0660         traits::get_bits(x,a);
0661         a &= traits::exponent | traits::significand;
0662         return a > traits::exponent;
0663     }
0664 
0665     template<class T>
0666     inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
0667     {
0668         typedef typename fp_traits<T>::type traits;
0669 
0670         typename traits::bits a;
0671         traits::get_bits(x,a);
0672 
0673         a &= traits::exponent | traits::significand;
0674         if(a < traits::exponent)
0675             return false;
0676 
0677         a &= traits::significand;
0678         traits::set_bits(x,a);
0679         return x != 0;
0680     }
0681 
0682 }   // namespace detail
0683 
0684 template<class T>
0685 inline bool (isnan)(T x)
0686 { //!< \brief return true if floating-point type t is NaN (Not A Number).
0687    typedef typename detail::fp_traits<T>::type traits;
0688    typedef typename traits::method method;
0689    // typedef typename boost::is_floating_point<T>::type fp_tag;
0690    return detail::isnan_impl(x, method());
0691 }
0692 
0693 #ifdef isnan
0694 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0695 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0696 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0697 #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
0698 template<>
0699 inline bool (isnan)(long double x)
0700 { //!< \brief return true if floating-point type t is NaN (Not A Number).
0701    typedef detail::fp_traits<long double>::type traits;
0702    typedef traits::method method;
0703    //typedef boost::is_floating_point<long double>::type fp_tag;
0704    return detail::isnan_impl(x, method());
0705 }
0706 #endif
0707 #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
0708 template<>
0709 inline bool (isnan)(__float128 x)
0710 {
0711    return ::isnanq(x);
0712 }
0713 #endif
0714 
0715 #endif
0716 
0717 } // namespace math
0718 } // namespace boost
0719 
0720 #else // Special handling generally using the CUDA library
0721 
0722 #include <boost/math/tools/type_traits.hpp>
0723 
0724 namespace boost {
0725 namespace math {
0726 
0727 template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>
0728 inline BOOST_MATH_GPU_ENABLED bool isnan(T x)
0729 {
0730    return false;
0731 }
0732 
0733 template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>
0734 inline BOOST_MATH_GPU_ENABLED bool isnan(T x)
0735 {
0736    return ::isnan(x);
0737 }
0738 
0739 template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>
0740 inline BOOST_MATH_GPU_ENABLED bool isinf(T x)
0741 {
0742    return false;
0743 }
0744 
0745 template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>
0746 inline BOOST_MATH_GPU_ENABLED bool isinf(T x)
0747 {
0748    return ::isinf(x);
0749 }
0750 
0751 template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>
0752 inline BOOST_MATH_GPU_ENABLED bool isfinite(T x)
0753 {
0754    return true;
0755 }
0756 
0757 template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>
0758 inline BOOST_MATH_GPU_ENABLED bool isfinite(T x)
0759 {
0760    return ::isfinite(x);
0761 }
0762 
0763 template <typename T>
0764 inline BOOST_MATH_GPU_ENABLED bool isnormal(T x)
0765 {
0766    return x != static_cast<T>(0) && x != static_cast<T>(-0) && 
0767             !boost::math::isnan(x) && 
0768             !boost::math::isinf(x);
0769 }
0770 
0771 // We skip the check for FP_SUBNORMAL since they are not supported on these platforms
0772 template <typename T>
0773 inline BOOST_MATH_GPU_ENABLED int fpclassify(T x)
0774 {
0775    if (boost::math::isnan(x))
0776    {
0777       return BOOST_MATH_FP_NAN;
0778    }
0779    else if (boost::math::isinf(x))
0780    {
0781       return BOOST_MATH_FP_INFINITE;
0782    }
0783    else if (x == static_cast<T>(0) || x == static_cast<T>(-0))
0784    {
0785       return BOOST_MATH_FP_ZERO;
0786    }
0787 
0788    return BOOST_MATH_FP_NORMAL;
0789 }
0790 
0791 } // Namespace math
0792 } // Namespace boost
0793 
0794 #endif // BOOST_MATH_HAS_NVRTC
0795 
0796 #endif // BOOST_MATH_FPCLASSIFY_HPP
0797