Chris@16: // Copyright John Maddock 2005-2008. Chris@16: // Copyright (c) 2006-2008 Johan Rade Chris@16: // Use, modification and distribution are subject to the Chris@16: // Boost Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MATH_FPCLASSIFY_HPP Chris@16: #define BOOST_MATH_FPCLASSIFY_HPP Chris@16: Chris@16: #ifdef _MSC_VER Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: /*! Chris@16: \file fpclassify.hpp Chris@16: \brief Classify floating-point value as normal, subnormal, zero, infinite, or NaN. Chris@16: \version 1.0 Chris@16: \author John Maddock Chris@16: */ Chris@16: Chris@16: /* Chris@16: Chris@16: 1. If the platform is C99 compliant, then the native floating point Chris@16: classification functions are used. However, note that we must only Chris@16: define the functions which call std::fpclassify etc if that function Chris@16: really does exist: otherwise a compiler may reject the code even though Chris@16: the template is never instantiated. Chris@16: Chris@16: 2. If the platform is not C99 compliant, and the binary format for Chris@16: a floating point type (float, double or long double) can be determined Chris@16: at compile time, then the following algorithm is used: Chris@16: Chris@16: If all exponent bits, the flag bit (if there is one), Chris@16: and all significand bits are 0, then the number is zero. Chris@16: Chris@16: If all exponent bits and the flag bit (if there is one) are 0, Chris@16: and at least one significand bit is 1, then the number is subnormal. Chris@16: Chris@16: If all exponent bits are 1 and all significand bits are 0, Chris@16: then the number is infinity. Chris@16: Chris@16: If all exponent bits are 1 and at least one significand bit is 1, Chris@16: then the number is a not-a-number. Chris@16: Chris@16: Otherwise the number is normal. Chris@16: Chris@16: This algorithm works for the IEEE 754 representation, Chris@16: and also for several non IEEE 754 formats. Chris@16: Chris@16: Most formats have the structure Chris@16: sign bit + exponent bits + significand bits. Chris@16: Chris@16: A few have the structure Chris@16: sign bit + exponent bits + flag bit + significand bits. Chris@16: The flag bit is 0 for zero and subnormal numbers, Chris@16: and 1 for normal numbers and NaN. Chris@16: It is 0 (Motorola 68K) or 1 (Intel) for infinity. Chris@16: Chris@16: To get the bits, the four or eight most significant bytes are copied Chris@16: into an uint32_t or uint64_t and bit masks are applied. Chris@16: This covers all the exponent bits and the flag bit (if there is one), Chris@16: but not always all the significand bits. Chris@16: Some of the functions below have two implementations, Chris@16: depending on whether all the significand bits are copied or not. Chris@16: Chris@16: 3. If the platform is not C99 compliant, and the binary format for Chris@16: a floating point type (float, double or long double) can not be determined Chris@16: at compile time, then comparison with std::numeric_limits values Chris@16: is used. Chris@16: Chris@16: */ Chris@16: Chris@16: #if defined(_MSC_VER) || defined(__BORLANDC__) Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_NO_STDC_NAMESPACE Chris@16: namespace std{ using ::abs; using ::fabs; } Chris@16: #endif Chris@16: Chris@16: namespace boost{ Chris@16: Chris@16: // Chris@16: // This must not be located in any namespace under boost::math Chris@16: // otherwise we can get into an infinite loop if isnan is Chris@16: // a #define for "isnan" ! Chris@16: // Chris@16: namespace math_detail{ Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4800) Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool is_nan_helper(T t, const boost::true_type&) Chris@16: { Chris@16: #ifdef isnan Chris@16: return isnan(t); Chris@16: #elif defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) || !defined(BOOST_HAS_FPCLASSIFY) Chris@16: (void)t; Chris@16: return false; Chris@16: #else // BOOST_HAS_FPCLASSIFY Chris@16: return (BOOST_FPCLASSIFY_PREFIX fpclassify(t) == (int)FP_NAN); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool is_nan_helper(T, const boost::false_type&) Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: namespace math{ Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const native_tag&) Chris@16: { Chris@16: return (std::fpclassify)(t); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag&) Chris@16: { Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(t); Chris@16: Chris@16: // whenever possible check for Nan's first: Chris@16: #if defined(BOOST_HAS_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) Chris@16: if(::boost::math_detail::is_nan_helper(t, ::boost::is_floating_point())) Chris@16: return FP_NAN; Chris@16: #elif defined(isnan) Chris@16: if(boost::math_detail::is_nan_helper(t, ::boost::is_floating_point())) Chris@16: return FP_NAN; Chris@16: #elif defined(_MSC_VER) || defined(__BORLANDC__) Chris@16: if(::_isnan(boost::math::tools::real_cast(t))) Chris@16: return FP_NAN; Chris@16: #endif Chris@16: // std::fabs broken on a few systems especially for long long!!!! Chris@16: T at = (t < T(0)) ? -t : t; Chris@16: Chris@16: // Use a process of exclusion to figure out Chris@16: // what kind of type we have, this relies on Chris@16: // IEEE conforming reals that will treat Chris@16: // Nan's as unordered. Some compilers Chris@16: // don't do this once optimisations are Chris@16: // turned on, hence the check for nan's above. Chris@16: if(at <= (std::numeric_limits::max)()) Chris@16: { Chris@16: if(at >= (std::numeric_limits::min)()) Chris@16: return FP_NORMAL; Chris@16: return (at != 0) ? FP_SUBNORMAL : FP_ZERO; Chris@16: } Chris@16: else if(at > (std::numeric_limits::max)()) Chris@16: return FP_INFINITE; Chris@16: return FP_NAN; Chris@16: } Chris@16: Chris@16: template Chris@16: inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(T t, const generic_tag&) Chris@16: { Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized) Chris@16: return fpclassify_imp(t, generic_tag()); Chris@16: #endif Chris@16: // Chris@16: // An unknown type with no numeric_limits support, Chris@16: // so what are we supposed to do we do here? Chris@16: // Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(t); Chris@16: Chris@16: return t == 0 ? FP_ZERO : FP_NORMAL; Chris@16: } Chris@16: Chris@16: template Chris@16: int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_all_bits_tag) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(x); Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(a); Chris@16: a &= traits::exponent | traits::flag | traits::significand; Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE((traits::exponent | traits::flag | traits::significand)); Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(a); Chris@16: Chris@16: if(a <= traits::significand) { Chris@16: if(a == 0) Chris@16: return FP_ZERO; Chris@16: else Chris@16: return FP_SUBNORMAL; Chris@16: } Chris@16: Chris@16: if(a < traits::exponent) return FP_NORMAL; Chris@16: Chris@16: a &= traits::significand; Chris@16: if(a == 0) return FP_INFINITE; Chris@16: Chris@16: return FP_NAN; Chris@16: } Chris@16: Chris@16: template Chris@16: int fpclassify_imp BOOST_NO_MACRO_EXPAND(T x, ieee_copy_leading_bits_tag) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_MATH_INSTRUMENT_VARIABLE(x); Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent | traits::flag | traits::significand; Chris@16: Chris@16: if(a <= traits::significand) { Chris@16: if(x == 0) Chris@16: return FP_ZERO; Chris@16: else Chris@16: return FP_SUBNORMAL; Chris@16: } Chris@16: Chris@16: if(a < traits::exponent) return FP_NORMAL; Chris@16: Chris@16: a &= traits::significand; Chris@16: traits::set_bits(x,a); Chris@16: if(x == 0) return FP_INFINITE; Chris@16: Chris@16: return FP_NAN; Chris@16: } Chris@16: Chris@16: #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && (defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)) Chris@16: inline int fpclassify_imp BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) Chris@16: { Chris@16: return boost::math::detail::fpclassify_imp(t, generic_tag()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: inline int fpclassify BOOST_NO_MACRO_EXPAND(T t) Chris@16: { Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: typedef typename tools::promote_args_permissive::type value_type; Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized && detail::is_generic_tag_false(static_cast(0))) Chris@16: return detail::fpclassify_imp(static_cast(t), detail::generic_tag()); Chris@16: return detail::fpclassify_imp(static_cast(t), method()); Chris@16: #else Chris@16: return detail::fpclassify_imp(static_cast(t), method()); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS Chris@16: template <> Chris@16: inline int fpclassify BOOST_NO_MACRO_EXPAND(long double t) Chris@16: { Chris@16: typedef detail::fp_traits::type traits; Chris@16: typedef traits::method method; Chris@16: typedef long double value_type; Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized && detail::is_generic_tag_false(static_cast(0))) Chris@16: return detail::fpclassify_imp(static_cast(t), detail::generic_tag()); Chris@16: return detail::fpclassify_imp(static_cast(t), method()); Chris@16: #else Chris@16: return detail::fpclassify_imp(static_cast(t), method()); Chris@16: #endif Chris@16: } Chris@16: #endif Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline bool isfinite_impl(T x, native_tag const&) Chris@16: { Chris@16: return (std::isfinite)(x); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool isfinite_impl(T x, generic_tag const&) Chris@16: { Chris@16: return x >= -(std::numeric_limits::max)() Chris@16: && x <= (std::numeric_limits::max)(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isfinite_impl(T x, generic_tag const&) Chris@16: { Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized) Chris@16: return isfinite_impl(x, generic_tag()); Chris@16: #endif Chris@101: (void)x; // warning suppression. Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isfinite_impl(T x, ieee_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent; Chris@16: return a != traits::exponent; Chris@16: } Chris@16: Chris@16: #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) Chris@16: inline bool isfinite_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) Chris@16: { Chris@16: return boost::math::detail::isfinite_impl(t, generic_tag()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool (isfinite)(T x) Chris@16: { //!< \brief return true if floating-point type t is finite. Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: // typedef typename boost::is_floating_point::type fp_tag; Chris@16: typedef typename tools::promote_args_permissive::type value_type; Chris@16: return detail::isfinite_impl(static_cast(x), method()); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS Chris@16: template<> Chris@16: inline bool (isfinite)(long double x) Chris@16: { //!< \brief return true if floating-point type t is finite. Chris@16: typedef detail::fp_traits::type traits; Chris@16: typedef traits::method method; Chris@101: //typedef boost::is_floating_point::type fp_tag; Chris@16: typedef long double value_type; Chris@16: return detail::isfinite_impl(static_cast(x), method()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline bool isnormal_impl(T x, native_tag const&) Chris@16: { Chris@16: return (std::isnormal)(x); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool isnormal_impl(T x, generic_tag const&) Chris@16: { Chris@16: if(x < 0) x = -x; Chris@16: return x >= (std::numeric_limits::min)() Chris@16: && x <= (std::numeric_limits::max)(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isnormal_impl(T x, generic_tag const&) Chris@16: { Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized) Chris@16: return isnormal_impl(x, generic_tag()); Chris@16: #endif Chris@16: return !(x == 0); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isnormal_impl(T x, ieee_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent | traits::flag; Chris@16: return (a != 0) && (a < traits::exponent); Chris@16: } Chris@16: Chris@16: #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) Chris@16: inline bool isnormal_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) Chris@16: { Chris@16: return boost::math::detail::isnormal_impl(t, generic_tag()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool (isnormal)(T x) Chris@16: { Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: //typedef typename boost::is_floating_point::type fp_tag; Chris@16: typedef typename tools::promote_args_permissive::type value_type; Chris@16: return detail::isnormal_impl(static_cast(x), method()); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS Chris@16: template<> Chris@16: inline bool (isnormal)(long double x) Chris@16: { Chris@16: typedef detail::fp_traits::type traits; Chris@16: typedef traits::method method; Chris@101: //typedef boost::is_floating_point::type fp_tag; Chris@16: typedef long double value_type; Chris@16: return detail::isnormal_impl(static_cast(x), method()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline bool isinf_impl(T x, native_tag const&) Chris@16: { Chris@16: return (std::isinf)(x); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool isinf_impl(T x, generic_tag const&) Chris@16: { Chris@16: (void)x; // in case the compiler thinks that x is unused because std::numeric_limits::has_infinity is false Chris@16: return std::numeric_limits::has_infinity Chris@16: && ( x == std::numeric_limits::infinity() Chris@16: || x == -std::numeric_limits::infinity()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isinf_impl(T x, generic_tag const&) Chris@16: { Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized) Chris@16: return isinf_impl(x, generic_tag()); Chris@16: #endif Chris@101: (void)x; // warning suppression. Chris@16: return false; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isinf_impl(T x, ieee_copy_all_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent | traits::significand; Chris@16: return a == traits::exponent; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isinf_impl(T x, ieee_copy_leading_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent | traits::significand; Chris@16: if(a != traits::exponent) Chris@16: return false; Chris@16: Chris@16: traits::set_bits(x,0); Chris@16: return x == 0; Chris@16: } Chris@16: Chris@16: #if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && defined(BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) Chris@16: inline bool isinf_impl BOOST_NO_MACRO_EXPAND(long double t, const native_tag&) Chris@16: { Chris@16: return boost::math::detail::isinf_impl(t, generic_tag()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: inline bool (isinf)(T x) Chris@16: { Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: // typedef typename boost::is_floating_point::type fp_tag; Chris@16: typedef typename tools::promote_args_permissive::type value_type; Chris@16: return detail::isinf_impl(static_cast(x), method()); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS Chris@16: template<> Chris@16: inline bool (isinf)(long double x) Chris@16: { Chris@16: typedef detail::fp_traits::type traits; Chris@16: typedef traits::method method; Chris@101: //typedef boost::is_floating_point::type fp_tag; Chris@16: typedef long double value_type; Chris@16: return detail::isinf_impl(static_cast(x), method()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //------------------------------------------------------------------------------ Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline bool isnan_impl(T x, native_tag const&) Chris@16: { Chris@16: return (std::isnan)(x); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: inline bool isnan_impl(T x, generic_tag const&) Chris@16: { Chris@16: return std::numeric_limits::has_infinity Chris@16: ? !(x <= std::numeric_limits::infinity()) Chris@16: : x != x; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isnan_impl(T x, generic_tag const&) Chris@16: { Chris@16: #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@16: if(std::numeric_limits::is_specialized) Chris@16: return isnan_impl(x, generic_tag()); Chris@16: #endif Chris@101: (void)x; // warning suppression Chris@16: return false; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isnan_impl(T x, ieee_copy_all_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a &= traits::exponent | traits::significand; Chris@16: return a > traits::exponent; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool isnan_impl(T x, ieee_copy_leading_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: Chris@16: a &= traits::exponent | traits::significand; Chris@16: if(a < traits::exponent) Chris@16: return false; Chris@16: Chris@16: a &= traits::significand; Chris@16: traits::set_bits(x,a); Chris@16: return x != 0; Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: inline bool (isnan)(T x) Chris@16: { //!< \brief return true if floating-point type t is NaN (Not A Number). Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: // typedef typename boost::is_floating_point::type fp_tag; Chris@16: return detail::isnan_impl(x, method()); Chris@16: } Chris@16: Chris@16: #ifdef isnan Chris@16: template <> inline bool isnan BOOST_NO_MACRO_EXPAND(float t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } Chris@16: template <> inline bool isnan BOOST_NO_MACRO_EXPAND(double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } Chris@16: template <> inline bool isnan BOOST_NO_MACRO_EXPAND(long double t){ return ::boost::math_detail::is_nan_helper(t, boost::true_type()); } Chris@16: #elif defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) Chris@16: template<> Chris@16: inline bool (isnan)(long double x) Chris@16: { //!< \brief return true if floating-point type t is NaN (Not A Number). Chris@16: typedef detail::fp_traits::type traits; Chris@16: typedef traits::method method; Chris@101: //typedef boost::is_floating_point::type fp_tag; Chris@16: return detail::isnan_impl(x, method()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } // namespace math Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_MATH_FPCLASSIFY_HPP Chris@16: