brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.5 KiB · c17b4a3 Raw
798 lines · plain
1//  Copyright John Maddock 2005-2008.2//  Copyright (c) 2006-2008 Johan Rade3//  Copyright (c) 2024 Matt Borland4//  Use, modification and distribution are subject to the5//  Boost Software License, Version 1.0. (See accompanying file6//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)7 8#ifndef BOOST_MATH_FPCLASSIFY_HPP9#define BOOST_MATH_FPCLASSIFY_HPP10 11#ifdef _MSC_VER12#pragma once13#endif14 15#include <boost/math/tools/config.hpp>16 17#ifndef BOOST_MATH_HAS_NVRTC18 19#include <boost/math/tools/real_cast.hpp>20#include <boost/math/special_functions/math_fwd.hpp>21#include <boost/math/special_functions/detail/fp_traits.hpp>22#include <limits>23#include <type_traits>24#include <cmath>25 26/*!27  \file fpclassify.hpp28  \brief Classify floating-point value as normal, subnormal, zero, infinite, or NaN.29  \version 1.030  \author John Maddock31 */32 33/*34 351. If the platform is C99 compliant, then the native floating point36classification functions are used.  However, note that we must only37define the functions which call std::fpclassify etc if that function38really does exist: otherwise a compiler may reject the code even though39the template is never instantiated.40 412. If the platform is not C99 compliant, and the binary format for42a floating point type (float, double or long double) can be determined43at compile time, then the following algorithm is used:44 45        If all exponent bits, the flag bit (if there is one),46        and all significand bits are 0, then the number is zero.47 48        If all exponent bits and the flag bit (if there is one) are 0,49        and at least one significand bit is 1, then the number is subnormal.50 51        If all exponent bits are 1 and all significand bits are 0,52        then the number is infinity.53 54        If all exponent bits are 1 and at least one significand bit is 1,55        then the number is a not-a-number.56 57        Otherwise the number is normal.58 59        This algorithm works for the IEEE 754 representation,60        and also for several non IEEE 754 formats.61 62    Most formats have the structure63        sign bit + exponent bits + significand bits.64 65    A few have the structure66        sign bit + exponent bits + flag bit + significand bits.67    The flag bit is 0 for zero and subnormal numbers,68        and 1 for normal numbers and NaN.69        It is 0 (Motorola 68K) or 1 (Intel) for infinity.70 71    To get the bits, the four or eight most significant bytes are copied72    into an uint32_t or uint64_t and bit masks are applied.73    This covers all the exponent bits and the flag bit (if there is one),74    but not always all the significand bits.75    Some of the functions below have two implementations,76    depending on whether all the significand bits are copied or not.77 783. If the platform is not C99 compliant, and the binary format for79a floating point type (float, double or long double) can not be determined80at compile time, then comparison with std::numeric_limits values81is used.82 83*/84 85#ifdef BOOST_MATH_HAS_GPU_SUPPORT86 87namespace boost { namespace math {88 89template<> BOOST_MATH_GPU_ENABLED inline bool (isnan)(float x) { return x != x; }90template<> BOOST_MATH_GPU_ENABLED inline bool (isnan)(double x) { return x != x; }91 92template<> BOOST_MATH_GPU_ENABLED inline bool (isinf)(float x) { return x > FLT_MAX || x < -FLT_MAX; }93template<> BOOST_MATH_GPU_ENABLED inline bool (isinf)(double x) { return x > DBL_MAX || x < -DBL_MAX; }94 95template<> BOOST_MATH_GPU_ENABLED inline bool (isfinite)(float x) {  return !isnan(x) && !isinf(x);  }96template<> BOOST_MATH_GPU_ENABLED inline bool (isfinite)(double x) {  return !isnan(x) && !isinf(x); }97 98template<> BOOST_MATH_GPU_ENABLED inline bool (isnormal)(float x)99{100   if(x < 0) x = -x;101   return (x >= FLT_MIN) && (x <= FLT_MAX);102}103template<> BOOST_MATH_GPU_ENABLED inline bool (isnormal)(double x)104{105   if(x < 0) x = -x;106   return (x >= DBL_MIN) && (x <= DBL_MAX);107}108 109template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(float t)110{111   if((boost::math::isnan)(t))112      return FP_NAN;113   // std::fabs broken on a few systems especially for long long!!!!114   float at = (t < 0.0f) ? -t : t;115 116   // Use a process of exclusion to figure out117   // what kind of type we have, this relies on118   // IEEE conforming reals that will treat119   // Nan's as unordered.  Some compilers120   // don't do this once optimisations are121   // turned on, hence the check for nan's above.122   if(at <= FLT_MAX)123   {124      if(at >= FLT_MIN)125         return FP_NORMAL;126      return (at != 0) ? FP_SUBNORMAL : FP_ZERO;127   }128   else if(at > FLT_MAX)129      return FP_INFINITE;130   return FP_NAN;    // LCOV_EXCL_LINE  should not normally be reachable.131}132 133template<> BOOST_MATH_GPU_ENABLED inline int (fpclassify)(double t)134{135   if((boost::math::isnan)(t))136      return FP_NAN;137   // std::fabs broken on a few systems especially for long long!!!!138   double at = (t < 0.0) ? -t : t;139 140   // Use a process of exclusion to figure out141   // what kind of type we have, this relies on142   // IEEE conforming reals that will treat143   // Nan's as unordered.  Some compilers144   // don't do this once optimisations are145   // turned on, hence the check for nan's above.146   if(at <= DBL_MAX)147   {148      if(at >= DBL_MIN)149         return FP_NORMAL;150      return (at != 0) ? FP_SUBNORMAL : FP_ZERO;151   }152   else if(at > DBL_MAX)153      return FP_INFINITE;154   return FP_NAN;155}156 157#else158 159#if defined(_MSC_VER) || defined(BOOST_BORLANDC)160#include <cfloat>161#endif162#ifdef BOOST_MATH_USE_FLOAT128163#ifdef __has_include164#if  __has_include("quadmath.h")165#include "quadmath.h"166#define BOOST_MATH_HAS_QUADMATH_H167#endif168#endif169#endif170 171#ifdef BOOST_NO_STDC_NAMESPACE172  namespace std{ using ::abs; using ::fabs; }173#endif174 175namespace boost{176 177//178// This must not be located in any namespace under boost::math179// otherwise we can get into an infinite loop if isnan is180// a #define for "isnan" !181//182namespace math_detail{183 184#ifdef _MSC_VER185#pragma warning(push)186#pragma warning(disable:4800)187#endif188 189template <class T>190inline bool is_nan_helper(T t, const std::true_type&)191{192#ifdef isnan193   return isnan(t);194#elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)195   (void)t;196   return false;197#else // BOOST_HAS_FPCLASSIFY198   return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);199#endif200}201 202#ifdef _MSC_VER203#pragma warning(pop)204#endif205 206template <class T>207inline bool is_nan_helper(T, const std::false_type&)208{209   return false;210}211#if defined(BOOST_MATH_USE_FLOAT128)212#if defined(BOOST_MATH_HAS_QUADMATH_H)213inline bool is_nan_helper(__float128 f, const std::true_type&) { return ::isnanq(f); }214inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnanq(f); }215#elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \216      _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC217inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast<double>(f)); }218inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast<double>(f)); }219#else220inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast<double>(f)); }221inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast<double>(f)); }222#endif223#endif224}225 226namespace math{227 228namespace detail{229 230#ifdef BOOST_MATH_USE_STD_FPCLASSIFY231template <class T>232inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)233{234   return (std::fpclassify)(t);235}236#endif237 238template <class T>239inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)240{241   BOOST_MATH_INSTRUMENT_VARIABLE(t);242 243   // whenever possible check for Nan's first:244#if defined(BOOST_HAS_FPCLASSIFY)  && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)245   if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))246      return FP_NAN;  // LCOV_EXCL_LINE only called in UDT contexts (excluded from coverage checks).247#elif defined(isnan)248   if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))249      return FP_NAN;250#elif defined(_MSC_VER) || defined(BOOST_BORLANDC)251   if(::_isnan(boost::math::tools::real_cast<double>(t)))252      return FP_NAN;253#endif254   // std::fabs broken on a few systems especially for long long!!!!255   T at = (t < T(0)) ? -t : t;256 257   // Use a process of exclusion to figure out258   // what kind of type we have, this relies on259   // IEEE conforming reals that will treat260   // Nan's as unordered.  Some compilers261   // don't do this once optimisations are262   // turned on, hence the check for nan's above.263   if(at <= (std::numeric_limits<T>::max)())264   {265      if(at >= (std::numeric_limits<T>::min)())266         return FP_NORMAL;267      return (at != 0) ? FP_SUBNORMAL : FP_ZERO;268   }269   else if(at > (std::numeric_limits<T>::max)())270      return FP_INFINITE;271   return FP_NAN;272}273 274template <class T>275inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)276{277#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS278   if(std::numeric_limits<T>::is_specialized)279      return fpclassify_imp(t, generic_tag<true>());280#endif281   //282   // An unknown type with no numeric_limits support,283   // so what are we supposed to do we do here?284   //285   BOOST_MATH_INSTRUMENT_VARIABLE(t);286 287   return t == 0 ? FP_ZERO : FP_NORMAL;288}289 290template<class T>291int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)292{293   typedef typename fp_traits<T>::type traits;294 295   BOOST_MATH_INSTRUMENT_VARIABLE(x);296 297   typename traits::bits a;298   traits::get_bits(x,a);299   BOOST_MATH_INSTRUMENT_VARIABLE(a);300   a &= traits::exponent | traits::flag | traits::significand;301   BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));302   BOOST_MATH_INSTRUMENT_VARIABLE(a);303 304   if(a <= traits::significand) {305      if(a == 0)306         return FP_ZERO;307      else308         return FP_SUBNORMAL;309   }310 311   if(a < traits::exponent) return FP_NORMAL;312 313   a &= traits::significand;314   if(a == 0) return FP_INFINITE;315 316   return FP_NAN;317}318 319template<class T>320int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)321{322   typedef typename fp_traits<T>::type traits;323 324   BOOST_MATH_INSTRUMENT_VARIABLE(x);325 326   typename traits::bits a;327   traits::get_bits(x,a);328   a &= traits::exponent | traits::flag | traits::significand;329 330   if(a <= traits::significand) {331      if(x == 0)332         return FP_ZERO;333      else334         return FP_SUBNORMAL;335   }336 337   if(a < traits::exponent) return FP_NORMAL;338 339   a &= traits::significand;340   traits::set_bits(x,a);341   if(x == 0) return FP_INFINITE;342 343   return FP_NAN;344}345 346#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))347inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)348{349   return boost::math::detail::fpclassify_imp(t, generic_tag<true>());350}351#endif352 353}  // namespace detail354 355template <class T>356inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)357{358   typedef typename detail::fp_traits<T>::type traits;359   typedef typename traits::method method;360   typedef typename tools::promote_args_permissive<T>::type value_type;361#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS362   if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))363      return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());364   return detail::fpclassify_imp(static_cast<value_type>(t), method());365#else366   return detail::fpclassify_imp(static_cast<value_type>(t), method());367#endif368}369 370#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS371template <>372inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)373{374   typedef detail::fp_traits<long double>::type traits;375   typedef traits::method method;376   typedef long double value_type;377#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS378   if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))379      return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());380   return detail::fpclassify_imp(static_cast<value_type>(t), method());381#else382   return detail::fpclassify_imp(static_cast<value_type>(t), method());383#endif384}385#endif386 387namespace detail {388 389#ifdef BOOST_MATH_USE_STD_FPCLASSIFY390    template<class T>391    inline bool isfinite_impl(T x, native_tag const&)392    {393        return (std::isfinite)(x);394    }395#endif396 397    template<class T>398    inline bool isfinite_impl(T x, generic_tag<true> const&)399    {400        return x >= -(std::numeric_limits<T>::max)()401            && x <= (std::numeric_limits<T>::max)();402    }403 404    template<class T>405    inline bool isfinite_impl(T x, generic_tag<false> const&)406    {407#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS408      if(std::numeric_limits<T>::is_specialized)409         return isfinite_impl(x, generic_tag<true>());410#endif411       (void)x; // warning suppression.412       return true;413    }414 415    template<class T>416    inline bool isfinite_impl(T x, ieee_tag const&)417    {418        typedef typename detail::fp_traits<T>::type traits;419        typename traits::bits a;420        traits::get_bits(x,a);421        a &= traits::exponent;422        return a != traits::exponent;423    }424 425#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)426inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)427{428   return boost::math::detail::isfinite_impl(t, generic_tag<true>());429}430#endif431 432}433 434template<class T>435inline bool (isfinite)(T x)436{ //!< \brief return true if floating-point type t is finite.437   typedef typename detail::fp_traits<T>::type traits;438   typedef typename traits::method method;439   // typedef typename boost::is_floating_point<T>::type fp_tag;440   typedef typename tools::promote_args_permissive<T>::type value_type;441   return detail::isfinite_impl(static_cast<value_type>(x), method());442}443 444#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS445template<>446inline bool (isfinite)(long double x)447{ //!< \brief return true if floating-point type t is finite.448   typedef detail::fp_traits<long double>::type traits;449   typedef traits::method method;450   //typedef boost::is_floating_point<long double>::type fp_tag;451   typedef long double value_type;452   return detail::isfinite_impl(static_cast<value_type>(x), method());453}454#endif455 456//------------------------------------------------------------------------------457 458namespace detail {459 460#ifdef BOOST_MATH_USE_STD_FPCLASSIFY461    template<class T>462    inline bool isnormal_impl(T x, native_tag const&)463    {464        return (std::isnormal)(x);465    }466#endif467 468    template<class T>469    inline bool isnormal_impl(T x, generic_tag<true> const&)470    {471        if(x < 0) x = -x;472        return x >= (std::numeric_limits<T>::min)()473            && x <= (std::numeric_limits<T>::max)();474    }475 476    template<class T>477    inline bool isnormal_impl(T x, generic_tag<false> const&)478    {479#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS480      if(std::numeric_limits<T>::is_specialized)481         return isnormal_impl(x, generic_tag<true>());482#endif483       return !(x == 0);484    }485 486    template<class T>487    inline bool isnormal_impl(T x, ieee_tag const&)488    {489        typedef typename detail::fp_traits<T>::type traits;490        typename traits::bits a;491        traits::get_bits(x,a);492        a &= traits::exponent | traits::flag;493        return (a != 0) && (a < traits::exponent);494    }495 496#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)497inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)498{499   return boost::math::detail::isnormal_impl(t, generic_tag<true>());500}501#endif502 503}504 505template<class T>506inline bool (isnormal)(T x)507{508   typedef typename detail::fp_traits<T>::type traits;509   typedef typename traits::method method;510   //typedef typename boost::is_floating_point<T>::type fp_tag;511   typedef typename tools::promote_args_permissive<T>::type value_type;512   return detail::isnormal_impl(static_cast<value_type>(x), method());513}514 515#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS516template<>517inline bool (isnormal)(long double x)518{519   typedef detail::fp_traits<long double>::type traits;520   typedef traits::method method;521   //typedef boost::is_floating_point<long double>::type fp_tag;522   typedef long double value_type;523   return detail::isnormal_impl(static_cast<value_type>(x), method());524}525#endif526 527//------------------------------------------------------------------------------528 529namespace detail {530 531#ifdef BOOST_MATH_USE_STD_FPCLASSIFY532    template<class T>533    inline bool isinf_impl(T x, native_tag const&)534    {535        return (std::isinf)(x);536    }537#endif538 539    template<class T>540    inline bool isinf_impl(T x, generic_tag<true> const&)541    {542        (void)x; // in case the compiler thinks that x is unused because std::numeric_limits<T>::has_infinity is false543        return std::numeric_limits<T>::has_infinity544            && ( x == std::numeric_limits<T>::infinity()545                 || x == -std::numeric_limits<T>::infinity());546    }547 548    template<class T>549    inline bool isinf_impl(T x, generic_tag<false> const&)550    {551#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS552      if(std::numeric_limits<T>::is_specialized)553         return isinf_impl(x, generic_tag<true>());554#endif555        (void)x; // warning suppression.556        return false;557    }558 559    template<class T>560    inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)561    {562        typedef typename fp_traits<T>::type traits;563 564        typename traits::bits a;565        traits::get_bits(x,a);566        a &= traits::exponent | traits::significand;567        return a == traits::exponent;568    }569 570    template<class T>571    inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)572    {573        typedef typename fp_traits<T>::type traits;574 575        typename traits::bits a;576        traits::get_bits(x,a);577        a &= traits::exponent | traits::significand;578        if(a != traits::exponent)579            return false;580 581        traits::set_bits(x,0);582        return x == 0;583    }584 585#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)586inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)587{588   return boost::math::detail::isinf_impl(t, generic_tag<true>());589}590#endif591 592}   // namespace detail593 594template<class T>595inline bool (isinf)(T x)596{597   typedef typename detail::fp_traits<T>::type traits;598   typedef typename traits::method method;599   // typedef typename boost::is_floating_point<T>::type fp_tag;600   typedef typename tools::promote_args_permissive<T>::type value_type;601   return detail::isinf_impl(static_cast<value_type>(x), method());602}603 604#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS605template<>606inline bool (isinf)(long double x)607{608   typedef detail::fp_traits<long double>::type traits;609   typedef traits::method method;610   //typedef boost::is_floating_point<long double>::type fp_tag;611   typedef long double value_type;612   return detail::isinf_impl(static_cast<value_type>(x), method());613}614#endif615#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)616template<>617inline bool (isinf)(__float128 x)618{619   return ::isinfq(x);620}621#endif622 623//------------------------------------------------------------------------------624 625namespace detail {626 627#ifdef BOOST_MATH_USE_STD_FPCLASSIFY628    template<class T>629    inline bool isnan_impl(T x, native_tag const&)630    {631        return (std::isnan)(x);632    }633#endif634 635    template<class T>636    inline bool isnan_impl(T x, generic_tag<true> const&)637    {638        return std::numeric_limits<T>::has_infinity639            ? !(x <= std::numeric_limits<T>::infinity())640            : x != x;641    }642 643    template<class T>644    inline bool isnan_impl(T x, generic_tag<false> const&)645    {646#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS647      if(std::numeric_limits<T>::is_specialized)648         return isnan_impl(x, generic_tag<true>());649#endif650        (void)x; // warning suppression651        return false;652    }653 654    template<class T>655    inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)656    {657        typedef typename fp_traits<T>::type traits;658 659        typename traits::bits a;660        traits::get_bits(x,a);661        a &= traits::exponent | traits::significand;662        return a > traits::exponent;663    }664 665    template<class T>666    inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)667    {668        typedef typename fp_traits<T>::type traits;669 670        typename traits::bits a;671        traits::get_bits(x,a);672 673        a &= traits::exponent | traits::significand;674        if(a < traits::exponent)675            return false;676 677        a &= traits::significand;678        traits::set_bits(x,a);679        return x != 0;680    }681 682}   // namespace detail683 684template<class T>685inline bool (isnan)(T x)686{ //!< \brief return true if floating-point type t is NaN (Not A Number).687   typedef typename detail::fp_traits<T>::type traits;688   typedef typename traits::method method;689   // typedef typename boost::is_floating_point<T>::type fp_tag;690   return detail::isnan_impl(x, method());691}692 693#ifdef isnan694template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }695template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }696template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }697#elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)698template<>699inline bool (isnan)(long double x)700{ //!< \brief return true if floating-point type t is NaN (Not A Number).701   typedef detail::fp_traits<long double>::type traits;702   typedef traits::method method;703   //typedef boost::is_floating_point<long double>::type fp_tag;704   return detail::isnan_impl(x, method());705}706#endif707#if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)708template<>709inline bool (isnan)(__float128 x)710{711   return ::isnanq(x);712}713#endif714 715#endif716 717} // namespace math718} // namespace boost719 720#else // Special handling generally using the CUDA library721 722#include <boost/math/tools/type_traits.hpp>723 724namespace boost {725namespace math {726 727template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>728BOOST_MATH_GPU_ENABLED inline bool isnan(T x)729{730   return false;731}732 733template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>734BOOST_MATH_GPU_ENABLED inline bool isnan(T x)735{736   return ::isnan(x);737}738 739template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>740BOOST_MATH_GPU_ENABLED inline bool isinf(T x)741{742   return false;743}744 745template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>746BOOST_MATH_GPU_ENABLED inline bool isinf(T x)747{748   return ::isinf(x);749}750 751template <typename T, boost::math::enable_if_t<boost::math::is_integral_v<T>, bool> = true>752BOOST_MATH_GPU_ENABLED inline bool isfinite(T x)753{754   return true;755}756 757template <typename T, boost::math::enable_if_t<!boost::math::is_integral_v<T>, bool> = true>758BOOST_MATH_GPU_ENABLED inline bool isfinite(T x)759{760   return ::isfinite(x);761}762 763template <typename T>764BOOST_MATH_GPU_ENABLED inline bool isnormal(T x)765{766   return x != static_cast<T>(0) && x != static_cast<T>(-0) && 767            !boost::math::isnan(x) && 768            !boost::math::isinf(x);769}770 771// We skip the check for FP_SUBNORMAL since they are not supported on these platforms772template <typename T>773BOOST_MATH_GPU_ENABLED inline int fpclassify(T x)774{775   if (boost::math::isnan(x))776   {777      return BOOST_MATH_FP_NAN;778   }779   else if (boost::math::isinf(x))780   {781      return BOOST_MATH_FP_INFINITE;782   }783   else if (x == static_cast<T>(0) || x == static_cast<T>(-0))784   {785      return BOOST_MATH_FP_ZERO;786   }787 788   return BOOST_MATH_FP_NORMAL;789}790 791} // Namespace math792} // Namespace boost793 794#endif // BOOST_MATH_HAS_NVRTC795 796#endif // BOOST_MATH_FPCLASSIFY_HPP797 798