File indexing completed on 2025-01-18 09:40:13
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_FPCLASSIFY_HPP
0008 #define BOOST_MATH_FPCLASSIFY_HPP
0009
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #endif
0013
0014 #include <limits>
0015 #include <type_traits>
0016 #include <cmath>
0017 #include <boost/math/tools/real_cast.hpp>
0018 #include <boost/math/special_functions/math_fwd.hpp>
0019 #include <boost/math/special_functions/detail/fp_traits.hpp>
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 #if defined(_MSC_VER) || defined(BOOST_BORLANDC)
0080 #include <cfloat>
0081 #endif
0082 #ifdef BOOST_MATH_USE_FLOAT128
0083 #ifdef __has_include
0084 #if __has_include("quadmath.h")
0085 #include "quadmath.h"
0086 #define BOOST_MATH_HAS_QUADMATH_H
0087 #endif
0088 #endif
0089 #endif
0090
0091 #ifdef BOOST_NO_STDC_NAMESPACE
0092 namespace std{ using ::abs; using ::fabs; }
0093 #endif
0094
0095 namespace boost{
0096
0097
0098
0099
0100
0101
0102 namespace math_detail{
0103
0104 #ifdef _MSC_VER
0105 #pragma warning(push)
0106 #pragma warning(disable:4800)
0107 #endif
0108
0109 template <class T>
0110 inline bool is_nan_helper(T t, const std::true_type&)
0111 {
0112 #ifdef isnan
0113 return isnan(t);
0114 #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
0115 (void)t;
0116 return false;
0117 #else
0118 return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
0119 #endif
0120 }
0121
0122 #ifdef _MSC_VER
0123 #pragma warning(pop)
0124 #endif
0125
0126 template <class T>
0127 inline bool is_nan_helper(T, const std::false_type&)
0128 {
0129 return false;
0130 }
0131 #if defined(BOOST_MATH_USE_FLOAT128)
0132 #if defined(BOOST_MATH_HAS_QUADMATH_H)
0133 inline bool is_nan_helper(__float128 f, const std::true_type&) { return ::isnanq(f); }
0134 inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnanq(f); }
0135 #elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
0136 _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
0137 inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast<double>(f)); }
0138 inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast<double>(f)); }
0139 #else
0140 inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast<double>(f)); }
0141 inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast<double>(f)); }
0142 #endif
0143 #endif
0144 }
0145
0146 namespace math{
0147
0148 namespace detail{
0149
0150 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0151 template <class T>
0152 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
0153 {
0154 return (std::fpclassify)(t);
0155 }
0156 #endif
0157
0158 template <class T>
0159 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
0160 {
0161 BOOST_MATH_INSTRUMENT_VARIABLE(t);
0162
0163
0164 #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
0165 if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
0166 return FP_NAN;
0167 #elif defined(isnan)
0168 if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
0169 return FP_NAN;
0170 #elif defined(_MSC_VER) || defined(BOOST_BORLANDC)
0171 if(::_isnan(boost::math::tools::real_cast<double>(t)))
0172 return FP_NAN;
0173 #endif
0174
0175 T at = (t < T(0)) ? -t : t;
0176
0177
0178
0179
0180
0181
0182
0183 if(at <= (std::numeric_limits<T>::max)())
0184 {
0185 if(at >= (std::numeric_limits<T>::min)())
0186 return FP_NORMAL;
0187 return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
0188 }
0189 else if(at > (std::numeric_limits<T>::max)())
0190 return FP_INFINITE;
0191 return FP_NAN;
0192 }
0193
0194 template <class T>
0195 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
0196 {
0197 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0198 if(std::numeric_limits<T>::is_specialized)
0199 return fpclassify_imp(t, generic_tag<true>());
0200 #endif
0201
0202
0203
0204
0205 BOOST_MATH_INSTRUMENT_VARIABLE(t);
0206
0207 return t == 0 ? FP_ZERO : FP_NORMAL;
0208 }
0209
0210 template<class T>
0211 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
0212 {
0213 typedef typename fp_traits<T>::type traits;
0214
0215 BOOST_MATH_INSTRUMENT_VARIABLE(x);
0216
0217 typename traits::bits a;
0218 traits::get_bits(x,a);
0219 BOOST_MATH_INSTRUMENT_VARIABLE(a);
0220 a &= traits::exponent | traits::flag | traits::significand;
0221 BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
0222 BOOST_MATH_INSTRUMENT_VARIABLE(a);
0223
0224 if(a <= traits::significand) {
0225 if(a == 0)
0226 return FP_ZERO;
0227 else
0228 return FP_SUBNORMAL;
0229 }
0230
0231 if(a < traits::exponent) return FP_NORMAL;
0232
0233 a &= traits::significand;
0234 if(a == 0) return FP_INFINITE;
0235
0236 return FP_NAN;
0237 }
0238
0239 template<class T>
0240 int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
0241 {
0242 typedef typename fp_traits<T>::type traits;
0243
0244 BOOST_MATH_INSTRUMENT_VARIABLE(x);
0245
0246 typename traits::bits a;
0247 traits::get_bits(x,a);
0248 a &= traits::exponent | traits::flag | traits::significand;
0249
0250 if(a <= traits::significand) {
0251 if(x == 0)
0252 return FP_ZERO;
0253 else
0254 return FP_SUBNORMAL;
0255 }
0256
0257 if(a < traits::exponent) return FP_NORMAL;
0258
0259 a &= traits::significand;
0260 traits::set_bits(x,a);
0261 if(x == 0) return FP_INFINITE;
0262
0263 return FP_NAN;
0264 }
0265
0266 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
0267 inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0268 {
0269 return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
0270 }
0271 #endif
0272
0273 }
0274
0275 template <class T>
0276 inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
0277 {
0278 typedef typename detail::fp_traits<T>::type traits;
0279 typedef typename traits::method method;
0280 typedef typename tools::promote_args_permissive<T>::type value_type;
0281 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0282 if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
0283 return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
0284 return detail::fpclassify_imp(static_cast<value_type>(t), method());
0285 #else
0286 return detail::fpclassify_imp(static_cast<value_type>(t), method());
0287 #endif
0288 }
0289
0290 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0291 template <>
0292 inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
0293 {
0294 typedef detail::fp_traits<long double>::type traits;
0295 typedef traits::method method;
0296 typedef long double value_type;
0297 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0298 if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
0299 return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
0300 return detail::fpclassify_imp(static_cast<value_type>(t), method());
0301 #else
0302 return detail::fpclassify_imp(static_cast<value_type>(t), method());
0303 #endif
0304 }
0305 #endif
0306
0307 namespace detail {
0308
0309 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0310 template<class T>
0311 inline bool isfinite_impl(T x, native_tag const&)
0312 {
0313 return (std::isfinite)(x);
0314 }
0315 #endif
0316
0317 template<class T>
0318 inline bool isfinite_impl(T x, generic_tag<true> const&)
0319 {
0320 return x >= -(std::numeric_limits<T>::max)()
0321 && x <= (std::numeric_limits<T>::max)();
0322 }
0323
0324 template<class T>
0325 inline bool isfinite_impl(T x, generic_tag<false> const&)
0326 {
0327 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0328 if(std::numeric_limits<T>::is_specialized)
0329 return isfinite_impl(x, generic_tag<true>());
0330 #endif
0331 (void)x;
0332 return true;
0333 }
0334
0335 template<class T>
0336 inline bool isfinite_impl(T x, ieee_tag const&)
0337 {
0338 typedef typename detail::fp_traits<T>::type traits;
0339 typename traits::bits a;
0340 traits::get_bits(x,a);
0341 a &= traits::exponent;
0342 return a != traits::exponent;
0343 }
0344
0345 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0346 inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0347 {
0348 return boost::math::detail::isfinite_impl(t, generic_tag<true>());
0349 }
0350 #endif
0351
0352 }
0353
0354 template<class T>
0355 inline bool (isfinite)(T x)
0356 {
0357 typedef typename detail::fp_traits<T>::type traits;
0358 typedef typename traits::method method;
0359
0360 typedef typename tools::promote_args_permissive<T>::type value_type;
0361 return detail::isfinite_impl(static_cast<value_type>(x), method());
0362 }
0363
0364 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0365 template<>
0366 inline bool (isfinite)(long double x)
0367 {
0368 typedef detail::fp_traits<long double>::type traits;
0369 typedef traits::method method;
0370
0371 typedef long double value_type;
0372 return detail::isfinite_impl(static_cast<value_type>(x), method());
0373 }
0374 #endif
0375
0376
0377
0378 namespace detail {
0379
0380 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0381 template<class T>
0382 inline bool isnormal_impl(T x, native_tag const&)
0383 {
0384 return (std::isnormal)(x);
0385 }
0386 #endif
0387
0388 template<class T>
0389 inline bool isnormal_impl(T x, generic_tag<true> const&)
0390 {
0391 if(x < 0) x = -x;
0392 return x >= (std::numeric_limits<T>::min)()
0393 && x <= (std::numeric_limits<T>::max)();
0394 }
0395
0396 template<class T>
0397 inline bool isnormal_impl(T x, generic_tag<false> const&)
0398 {
0399 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0400 if(std::numeric_limits<T>::is_specialized)
0401 return isnormal_impl(x, generic_tag<true>());
0402 #endif
0403 return !(x == 0);
0404 }
0405
0406 template<class T>
0407 inline bool isnormal_impl(T x, ieee_tag const&)
0408 {
0409 typedef typename detail::fp_traits<T>::type traits;
0410 typename traits::bits a;
0411 traits::get_bits(x,a);
0412 a &= traits::exponent | traits::flag;
0413 return (a != 0) && (a < traits::exponent);
0414 }
0415
0416 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0417 inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0418 {
0419 return boost::math::detail::isnormal_impl(t, generic_tag<true>());
0420 }
0421 #endif
0422
0423 }
0424
0425 template<class T>
0426 inline bool (isnormal)(T x)
0427 {
0428 typedef typename detail::fp_traits<T>::type traits;
0429 typedef typename traits::method method;
0430
0431 typedef typename tools::promote_args_permissive<T>::type value_type;
0432 return detail::isnormal_impl(static_cast<value_type>(x), method());
0433 }
0434
0435 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0436 template<>
0437 inline bool (isnormal)(long double x)
0438 {
0439 typedef detail::fp_traits<long double>::type traits;
0440 typedef traits::method method;
0441
0442 typedef long double value_type;
0443 return detail::isnormal_impl(static_cast<value_type>(x), method());
0444 }
0445 #endif
0446
0447
0448
0449 namespace detail {
0450
0451 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0452 template<class T>
0453 inline bool isinf_impl(T x, native_tag const&)
0454 {
0455 return (std::isinf)(x);
0456 }
0457 #endif
0458
0459 template<class T>
0460 inline bool isinf_impl(T x, generic_tag<true> const&)
0461 {
0462 (void)x;
0463 return std::numeric_limits<T>::has_infinity
0464 && ( x == std::numeric_limits<T>::infinity()
0465 || x == -std::numeric_limits<T>::infinity());
0466 }
0467
0468 template<class T>
0469 inline bool isinf_impl(T x, generic_tag<false> const&)
0470 {
0471 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0472 if(std::numeric_limits<T>::is_specialized)
0473 return isinf_impl(x, generic_tag<true>());
0474 #endif
0475 (void)x;
0476 return false;
0477 }
0478
0479 template<class T>
0480 inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
0481 {
0482 typedef typename fp_traits<T>::type traits;
0483
0484 typename traits::bits a;
0485 traits::get_bits(x,a);
0486 a &= traits::exponent | traits::significand;
0487 return a == traits::exponent;
0488 }
0489
0490 template<class T>
0491 inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
0492 {
0493 typedef typename fp_traits<T>::type traits;
0494
0495 typename traits::bits a;
0496 traits::get_bits(x,a);
0497 a &= traits::exponent | traits::significand;
0498 if(a != traits::exponent)
0499 return false;
0500
0501 traits::set_bits(x,0);
0502 return x == 0;
0503 }
0504
0505 #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
0506 inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
0507 {
0508 return boost::math::detail::isinf_impl(t, generic_tag<true>());
0509 }
0510 #endif
0511
0512 }
0513
0514 template<class T>
0515 inline bool (isinf)(T x)
0516 {
0517 typedef typename detail::fp_traits<T>::type traits;
0518 typedef typename traits::method method;
0519
0520 typedef typename tools::promote_args_permissive<T>::type value_type;
0521 return detail::isinf_impl(static_cast<value_type>(x), method());
0522 }
0523
0524 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0525 template<>
0526 inline bool (isinf)(long double x)
0527 {
0528 typedef detail::fp_traits<long double>::type traits;
0529 typedef traits::method method;
0530
0531 typedef long double value_type;
0532 return detail::isinf_impl(static_cast<value_type>(x), method());
0533 }
0534 #endif
0535 #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
0536 template<>
0537 inline bool (isinf)(__float128 x)
0538 {
0539 return ::isinfq(x);
0540 }
0541 #endif
0542
0543
0544
0545 namespace detail {
0546
0547 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0548 template<class T>
0549 inline bool isnan_impl(T x, native_tag const&)
0550 {
0551 return (std::isnan)(x);
0552 }
0553 #endif
0554
0555 template<class T>
0556 inline bool isnan_impl(T x, generic_tag<true> const&)
0557 {
0558 return std::numeric_limits<T>::has_infinity
0559 ? !(x <= std::numeric_limits<T>::infinity())
0560 : x != x;
0561 }
0562
0563 template<class T>
0564 inline bool isnan_impl(T x, generic_tag<false> const&)
0565 {
0566 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0567 if(std::numeric_limits<T>::is_specialized)
0568 return isnan_impl(x, generic_tag<true>());
0569 #endif
0570 (void)x;
0571 return false;
0572 }
0573
0574 template<class T>
0575 inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
0576 {
0577 typedef typename fp_traits<T>::type traits;
0578
0579 typename traits::bits a;
0580 traits::get_bits(x,a);
0581 a &= traits::exponent | traits::significand;
0582 return a > traits::exponent;
0583 }
0584
0585 template<class T>
0586 inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
0587 {
0588 typedef typename fp_traits<T>::type traits;
0589
0590 typename traits::bits a;
0591 traits::get_bits(x,a);
0592
0593 a &= traits::exponent | traits::significand;
0594 if(a < traits::exponent)
0595 return false;
0596
0597 a &= traits::significand;
0598 traits::set_bits(x,a);
0599 return x != 0;
0600 }
0601
0602 }
0603
0604 template<class T>
0605 inline bool (isnan)(T x)
0606 {
0607 typedef typename detail::fp_traits<T>::type traits;
0608 typedef typename traits::method method;
0609
0610 return detail::isnan_impl(x, method());
0611 }
0612
0613 #ifdef isnan
0614 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0615 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0616 template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
0617 #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
0618 template<>
0619 inline bool (isnan)(long double x)
0620 {
0621 typedef detail::fp_traits<long double>::type traits;
0622 typedef traits::method method;
0623
0624 return detail::isnan_impl(x, method());
0625 }
0626 #endif
0627 #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
0628 template<>
0629 inline bool (isnan)(__float128 x)
0630 {
0631 return ::isnanq(x);
0632 }
0633 #endif
0634
0635 }
0636 }
0637 #endif
0638