123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- #ifndef BOOST_MATH_FPCLASSIFY_HPP
- #define BOOST_MATH_FPCLASSIFY_HPP
- #ifdef _MSC_VER
- #pragma once
- #endif
- #include <limits>
- #include <type_traits>
- #include <cmath>
- #include <boost/math/tools/real_cast.hpp>
- #include <boost/math/special_functions/math_fwd.hpp>
- #include <boost/math/special_functions/detail/fp_traits.hpp>
- #if defined(_MSC_VER) || defined(BOOST_BORLANDC)
- #include <cfloat>
- #endif
- #ifdef BOOST_MATH_USE_FLOAT128
- #ifdef __has_include
- #if __has_include("quadmath.h")
- #include "quadmath.h"
- #define BOOST_MATH_HAS_QUADMATH_H
- #endif
- #endif
- #endif
- #ifdef BOOST_NO_STDC_NAMESPACE
- namespace std{ using ::abs; using ::fabs; }
- #endif
- namespace boost{
- namespace math_detail{
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable:4800)
- #endif
- template <class T>
- inline bool is_nan_helper(T t, const std::true_type&)
- {
- #ifdef isnan
- return isnan(t);
- #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY)
- (void)t;
- return false;
- #else
- return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN);
- #endif
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- template <class T>
- inline bool is_nan_helper(T, const std::false_type&)
- {
- return false;
- }
- #if defined(BOOST_MATH_USE_FLOAT128)
- #if defined(BOOST_MATH_HAS_QUADMATH_H)
- inline bool is_nan_helper(__float128 f, const std::true_type&) { return ::isnanq(f); }
- inline bool is_nan_helper(__float128 f, const std::false_type&) { return ::isnanq(f); }
- #elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
- _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
- inline bool is_nan_helper(__float128 f, const std::true_type&) { return std::isnan(static_cast<double>(f)); }
- inline bool is_nan_helper(__float128 f, const std::false_type&) { return std::isnan(static_cast<double>(f)); }
- #else
- inline bool is_nan_helper(__float128 f, const std::true_type&) { return boost::math::isnan(static_cast<double>(f)); }
- inline bool is_nan_helper(__float128 f, const std::false_type&) { return boost::math::isnan(static_cast<double>(f)); }
- #endif
- #endif
- }
- namespace math{
- namespace detail{
- #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template <class T>
- inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&)
- {
- return (std::fpclassify)(t);
- }
- #endif
- template <class T>
- inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<true>&)
- {
- BOOST_MATH_INSTRUMENT_VARIABLE(t);
-
- #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY)
- if(::boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
- return FP_NAN;
- #elif defined(isnan)
- if(boost::math_detail::is_nan_helper(t, typename std::is_floating_point<T>::type()))
- return FP_NAN;
- #elif defined(_MSC_VER) || defined(BOOST_BORLANDC)
- if(::_isnan(boost::math::tools::real_cast<double>(t)))
- return FP_NAN;
- #endif
-
- T at = (t < T(0)) ? -t : t;
-
-
-
-
-
-
- if(at <= (std::numeric_limits<T>::max)())
- {
- if(at >= (std::numeric_limits<T>::min)())
- return FP_NORMAL;
- return (at != 0) ? FP_SUBNORMAL : FP_ZERO;
- }
- else if(at > (std::numeric_limits<T>::max)())
- return FP_INFINITE;
- return FP_NAN;
- }
- template <class T>
- inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag<false>&)
- {
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized)
- return fpclassify_imp(t, generic_tag<true>());
- #endif
-
-
-
-
- BOOST_MATH_INSTRUMENT_VARIABLE(t);
- return t == 0 ? FP_ZERO : FP_NORMAL;
- }
- template<class T>
- int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag)
- {
- typedef typename fp_traits<T>::type traits;
- BOOST_MATH_INSTRUMENT_VARIABLE(x);
- typename traits::bits a;
- traits::get_bits(x,a);
- BOOST_MATH_INSTRUMENT_VARIABLE(a);
- a &= traits::exponent | traits::flag | traits::significand;
- BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand));
- BOOST_MATH_INSTRUMENT_VARIABLE(a);
- if(a <= traits::significand) {
- if(a == 0)
- return FP_ZERO;
- else
- return FP_SUBNORMAL;
- }
- if(a < traits::exponent) return FP_NORMAL;
- a &= traits::significand;
- if(a == 0) return FP_INFINITE;
- return FP_NAN;
- }
- template<class T>
- int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag)
- {
- typedef typename fp_traits<T>::type traits;
- BOOST_MATH_INSTRUMENT_VARIABLE(x);
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::flag | traits::significand;
- if(a <= traits::significand) {
- if(x == 0)
- return FP_ZERO;
- else
- return FP_SUBNORMAL;
- }
- if(a < traits::exponent) return FP_NORMAL;
- a &= traits::significand;
- traits::set_bits(x,a);
- if(x == 0) return FP_INFINITE;
- return FP_NAN;
- }
- #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS))
- inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
- {
- return boost::math::detail::fpclassify_imp(t, generic_tag<true>());
- }
- #endif
- }
- template <class T>
- inline int fpclassify BOOST_NO_MACRO_EXPAND(T t)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
- typedef typename tools::promote_args_permissive<T>::type value_type;
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
- return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
- return detail::fpclassify_imp(static_cast<value_type>(t), method());
- #else
- return detail::fpclassify_imp(static_cast<value_type>(t), method());
- #endif
- }
- #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- template <>
- inline int fpclassify<long double> BOOST_NO_MACRO_EXPAND(long double t)
- {
- typedef detail::fp_traits<long double>::type traits;
- typedef traits::method method;
- typedef long double value_type;
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<long double>::is_specialized && detail::is_generic_tag_false(static_cast<method*>(nullptr)))
- return detail::fpclassify_imp(static_cast<value_type>(t), detail::generic_tag<true>());
- return detail::fpclassify_imp(static_cast<value_type>(t), method());
- #else
- return detail::fpclassify_imp(static_cast<value_type>(t), method());
- #endif
- }
- #endif
- namespace detail {
- #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
- inline bool isfinite_impl(T x, native_tag const&)
- {
- return (std::isfinite)(x);
- }
- #endif
- template<class T>
- inline bool isfinite_impl(T x, generic_tag<true> const&)
- {
- return x >= -(std::numeric_limits<T>::max)()
- && x <= (std::numeric_limits<T>::max)();
- }
- template<class T>
- inline bool isfinite_impl(T x, generic_tag<false> const&)
- {
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized)
- return isfinite_impl(x, generic_tag<true>());
- #endif
- (void)x;
- return true;
- }
- template<class T>
- inline bool isfinite_impl(T x, ieee_tag const&)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent;
- return a != traits::exponent;
- }
- #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
- inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
- {
- return boost::math::detail::isfinite_impl(t, generic_tag<true>());
- }
- #endif
- }
- template<class T>
- inline bool (isfinite)(T x)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
-
- typedef typename tools::promote_args_permissive<T>::type value_type;
- return detail::isfinite_impl(static_cast<value_type>(x), method());
- }
- #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- template<>
- inline bool (isfinite)(long double x)
- {
- typedef detail::fp_traits<long double>::type traits;
- typedef traits::method method;
-
- typedef long double value_type;
- return detail::isfinite_impl(static_cast<value_type>(x), method());
- }
- #endif
- namespace detail {
- #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
- inline bool isnormal_impl(T x, native_tag const&)
- {
- return (std::isnormal)(x);
- }
- #endif
- template<class T>
- inline bool isnormal_impl(T x, generic_tag<true> const&)
- {
- if(x < 0) x = -x;
- return x >= (std::numeric_limits<T>::min)()
- && x <= (std::numeric_limits<T>::max)();
- }
- template<class T>
- inline bool isnormal_impl(T x, generic_tag<false> const&)
- {
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized)
- return isnormal_impl(x, generic_tag<true>());
- #endif
- return !(x == 0);
- }
- template<class T>
- inline bool isnormal_impl(T x, ieee_tag const&)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::flag;
- return (a != 0) && (a < traits::exponent);
- }
- #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
- inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
- {
- return boost::math::detail::isnormal_impl(t, generic_tag<true>());
- }
- #endif
- }
- template<class T>
- inline bool (isnormal)(T x)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
-
- typedef typename tools::promote_args_permissive<T>::type value_type;
- return detail::isnormal_impl(static_cast<value_type>(x), method());
- }
- #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- template<>
- inline bool (isnormal)(long double x)
- {
- typedef detail::fp_traits<long double>::type traits;
- typedef traits::method method;
-
- typedef long double value_type;
- return detail::isnormal_impl(static_cast<value_type>(x), method());
- }
- #endif
- namespace detail {
- #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
- inline bool isinf_impl(T x, native_tag const&)
- {
- return (std::isinf)(x);
- }
- #endif
- template<class T>
- inline bool isinf_impl(T x, generic_tag<true> const&)
- {
- (void)x;
- return std::numeric_limits<T>::has_infinity
- && ( x == std::numeric_limits<T>::infinity()
- || x == -std::numeric_limits<T>::infinity());
- }
- template<class T>
- inline bool isinf_impl(T x, generic_tag<false> const&)
- {
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized)
- return isinf_impl(x, generic_tag<true>());
- #endif
- (void)x;
- return false;
- }
- template<class T>
- inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&)
- {
- typedef typename fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::significand;
- return a == traits::exponent;
- }
- template<class T>
- inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&)
- {
- typedef typename fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::significand;
- if(a != traits::exponent)
- return false;
- traits::set_bits(x,0);
- return x == 0;
- }
- #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY)
- inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&)
- {
- return boost::math::detail::isinf_impl(t, generic_tag<true>());
- }
- #endif
- }
- template<class T>
- inline bool (isinf)(T x)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
-
- typedef typename tools::promote_args_permissive<T>::type value_type;
- return detail::isinf_impl(static_cast<value_type>(x), method());
- }
- #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- template<>
- inline bool (isinf)(long double x)
- {
- typedef detail::fp_traits<long double>::type traits;
- typedef traits::method method;
-
- typedef long double value_type;
- return detail::isinf_impl(static_cast<value_type>(x), method());
- }
- #endif
- #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
- template<>
- inline bool (isinf)(__float128 x)
- {
- return ::isinfq(x);
- }
- #endif
- namespace detail {
- #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
- template<class T>
- inline bool isnan_impl(T x, native_tag const&)
- {
- return (std::isnan)(x);
- }
- #endif
- template<class T>
- inline bool isnan_impl(T x, generic_tag<true> const&)
- {
- return std::numeric_limits<T>::has_infinity
- ? !(x <= std::numeric_limits<T>::infinity())
- : x != x;
- }
- template<class T>
- inline bool isnan_impl(T x, generic_tag<false> const&)
- {
- #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- if(std::numeric_limits<T>::is_specialized)
- return isnan_impl(x, generic_tag<true>());
- #endif
- (void)x;
- return false;
- }
- template<class T>
- inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&)
- {
- typedef typename fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::significand;
- return a > traits::exponent;
- }
- template<class T>
- inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&)
- {
- typedef typename fp_traits<T>::type traits;
- typename traits::bits a;
- traits::get_bits(x,a);
- a &= traits::exponent | traits::significand;
- if(a < traits::exponent)
- return false;
- a &= traits::significand;
- traits::set_bits(x,a);
- return x != 0;
- }
- }
- template<class T>
- inline bool (isnan)(T x)
- {
- typedef typename detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
-
- return detail::isnan_impl(x, method());
- }
- #ifdef isnan
- template <> inline bool isnan BOOST_NO_MACRO_EXPAND<float>(float t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
- template <> inline bool isnan BOOST_NO_MACRO_EXPAND<double>(double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
- template <> inline bool isnan BOOST_NO_MACRO_EXPAND<long double>(long double t){ return ::boost::math_detail::is_nan_helper(t, std::true_type()); }
- #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
- template<>
- inline bool (isnan)(long double x)
- {
- typedef detail::fp_traits<long double>::type traits;
- typedef traits::method method;
-
- return detail::isnan_impl(x, method());
- }
- #endif
- #if defined(BOOST_MATH_USE_FLOAT128) && defined(BOOST_MATH_HAS_QUADMATH_H)
- template<>
- inline bool (isnan)(__float128 x)
- {
- return ::isnanq(x);
- }
- #endif
- }
- }
- #endif
|