// 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 |