fpclassify.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2022 Matt Borland. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MP_DETAIL_FPCLASSIFY_HPP
  6. #define BOOST_MP_DETAIL_FPCLASSIFY_HPP
  7. #include <cmath>
  8. #include <limits>
  9. #include <type_traits>
  10. #include <boost/multiprecision/detail/standalone_config.hpp>
  11. #include <boost/multiprecision/detail/float128_functions.hpp>
  12. #ifdef BOOST_MP_MATH_AVAILABLE
  13. #include <boost/math/special_functions/fpclassify.hpp>
  14. #define BOOST_MP_ISNAN(x) (boost::math::isnan)(x)
  15. #define BOOST_MP_ISINF(x) (boost::math::isinf)(x)
  16. #define BOOST_MP_FPCLASSIFY(x) (boost::math::fpclassify)(x)
  17. #define BOOST_MP_ISFINITE(x) (!(boost::math::isnan)(x) && !(boost::math::isinf)(x))
  18. #else
  19. namespace boost { namespace multiprecision { namespace detail {
  20. template <typename T, typename std::enable_if<std::is_floating_point<T>::value
  21. #ifdef BOOST_HAS_FLOAT128
  22. || std::is_same<T, float128_type>::value
  23. #endif
  24. , bool>::type = true>
  25. inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  26. {
  27. BOOST_MP_FLOAT128_USING;
  28. using std::isnan;
  29. return static_cast<bool>((isnan)(x));
  30. }
  31. template <typename T, typename std::enable_if<!std::is_floating_point<T>::value
  32. #ifdef BOOST_HAS_FLOAT128
  33. && !std::is_same<T, float128_type>::value
  34. #endif
  35. , bool>::type = true>
  36. inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  37. {
  38. return x != x;
  39. }
  40. template <typename T, typename std::enable_if<std::is_floating_point<T>::value
  41. #ifdef BOOST_HAS_FLOAT128
  42. || std::is_same<T, float128_type>::value
  43. #endif
  44. , bool>::type = true>
  45. inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  46. {
  47. BOOST_MP_FLOAT128_USING;
  48. using std::isinf;
  49. return static_cast<bool>((isinf)(x));
  50. }
  51. template <typename T, typename std::enable_if<!std::is_floating_point<T>::value
  52. #ifdef BOOST_HAS_FLOAT128
  53. && !std::is_same<T, float128_type>::value
  54. #endif
  55. , bool>::type = true>
  56. inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  57. {
  58. return x == std::numeric_limits<T>::infinity() || x == -std::numeric_limits<T>::infinity();
  59. }
  60. template <typename T, typename std::enable_if<std::is_floating_point<T>::value, bool>::type = true>
  61. inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  62. {
  63. using std::fpclassify;
  64. return fpclassify(x);
  65. }
  66. template <typename T, typename std::enable_if<!std::is_floating_point<T>::value, bool>::type = true>
  67. inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const T x)
  68. {
  69. BOOST_MP_FLOAT128_USING;
  70. using std::isnan;
  71. using std::isinf;
  72. using std::abs;
  73. return (isnan)(x) ? FP_NAN :
  74. (isinf)(x) ? FP_INFINITE :
  75. abs(x) == T(0) ? FP_ZERO :
  76. abs(x) > 0 && abs(x) < (std::numeric_limits<T>::min)() ? FP_SUBNORMAL : FP_NORMAL;
  77. }
  78. }}} // Namespace boost::multiprecision::detail
  79. #define BOOST_MP_ISNAN(x) (boost::multiprecision::detail::isnan)(x)
  80. #define BOOST_MP_ISINF(x) (boost::multiprecision::detail::isinf)(x)
  81. #define BOOST_MP_FPCLASSIFY(x) (boost::multiprecision::detail::fpclassify)(x)
  82. #define BOOST_MP_ISFINITE(x) (!(boost::multiprecision::detail::isnan)(x) && !(boost::multiprecision::detail::isinf)(x))
  83. #endif
  84. #endif // BOOST_MP_DETAIL_FPCLASSIFY_HPP