| // fpclassify.hpp |
| |
| #ifndef BOOST_SPIRIT_MATH_FPCLASSIFY_HPP |
| #define BOOST_SPIRIT_MATH_FPCLASSIFY_HPP |
| |
| // Copyright (c) 2006 Johan Rade |
| |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt |
| // or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| /* |
| The following algorithm is used: |
| |
| If all exponent bits, the flag bit (if there is one), |
| and all mantissa bits are 0, then the number is zero. |
| |
| If all exponent bits and the flag bit (if there is one) are 0, |
| and at least one mantissa bit is 1, then the number is subnormal. |
| |
| If all exponent bits are 1 and all mantissa bits are 0, |
| then the number is infinity. |
| |
| If all exponent bits are 1 and at least one mantissa bit is 1, |
| then the number is a not-a-number. |
| |
| Otherwise the number is normal. |
| |
| (Note that the binary representation of infinity |
| has flag bit 0 for Motorola 68K extended double precision, |
| and flag bit 1 for Intel extended double precision.) |
| |
| To get the bits, the four or eight most significant bytes are copied |
| into an uint32_t or uint64_t and bit masks are applied. |
| This covers all the exponent bits and the flag bit (if there is one), |
| but not always all the mantissa bits. |
| Some of the functions below have two implementations, |
| depending on whether all the mantissa bits are copied or not. |
| */ |
| |
| #if defined(_MSC_VER) |
| #pragma once |
| #endif |
| |
| #include <cmath> |
| |
| #ifndef FP_INFINITE |
| # define FP_INFINITE 0 |
| # define FP_NAN 1 |
| # define FP_NORMAL 2 |
| # define FP_SUBNORMAL 3 |
| # define FP_ZERO 4 |
| #endif |
| |
| #include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp> |
| |
| namespace boost { |
| namespace spirit { |
| namespace math { |
| |
| //------------------------------------------------------------------------------ |
| |
| template<class T> bool (isfinite)(T x) |
| { |
| typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; |
| traits::init(); |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent; |
| return a != traits::exponent; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| template<class T> bool (isnormal)(T x) |
| { |
| typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; |
| traits::init(); |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::flag; |
| return (a != 0) && (a < traits::exponent); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| namespace detail { |
| |
| template<class T> bool isinf_impl(T x, all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::mantissa; |
| return a == traits::exponent; |
| } |
| |
| template<class T> bool isinf_impl(T x, not_all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::mantissa; |
| if(a != traits::exponent) |
| return false; |
| |
| traits::set_bits(x,0); |
| return x == 0; |
| } |
| |
| } // namespace detail |
| |
| template<class T> bool (isinf)(T x) |
| { |
| typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; |
| traits::init(); |
| return detail::isinf_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| namespace detail { |
| |
| template<class T> bool isnan_impl(T x, all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| traits::init(); |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::mantissa; |
| return a > traits::exponent; |
| } |
| |
| template<class T> bool isnan_impl(T x, not_all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| traits::init(); |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| |
| a &= traits::exponent | traits::mantissa; |
| if(a < traits::exponent) |
| return false; |
| |
| a &= traits::mantissa; |
| traits::set_bits(x,a); |
| return x != 0; |
| } |
| |
| } // namespace detail |
| |
| template<class T> bool (isnan)(T x) |
| { |
| typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; |
| traits::init(); |
| return detail::isnan_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| namespace detail { |
| |
| template<class T> int fpclassify_impl(T x, all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::flag | traits::mantissa; |
| |
| if(a <= traits::mantissa) { |
| if(a == 0) |
| return FP_ZERO; |
| else |
| return FP_SUBNORMAL; |
| } |
| |
| if(a < traits::exponent) |
| return FP_NORMAL; |
| |
| a &= traits::mantissa; |
| if(a == 0) |
| return FP_INFINITE; |
| |
| return FP_NAN; |
| } |
| |
| template<class T> int fpclassify_impl(T x, not_all_bits) |
| { |
| typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; |
| |
| BOOST_DEDUCED_TYPENAME traits::bits a; |
| traits::get_bits(x,a); |
| a &= traits::exponent | traits::flag | traits::mantissa; |
| |
| if(a <= traits::mantissa) { |
| if(x == 0) |
| return FP_ZERO; |
| else |
| return FP_SUBNORMAL; |
| } |
| |
| if(a < traits::exponent) |
| return FP_NORMAL; |
| |
| a &= traits::mantissa; |
| traits::set_bits(x,a); |
| if(x == 0) |
| return FP_INFINITE; |
| |
| return FP_NAN; |
| } |
| |
| } // namespace detail |
| |
| template<class T> int (fpclassify)(T x) |
| { |
| typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; |
| traits::init(); |
| return detail::fpclassify_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| } // namespace math |
| } // namespace spirit |
| } // namespace boost |
| |
| #endif |