1 // fpclassify.hpp 2 3 #ifndef BOOST_SPIRIT_MATH_FPCLASSIFY_HPP 4 #define BOOST_SPIRIT_MATH_FPCLASSIFY_HPP 5 6 // Copyright (c) 2006 Johan Rade 7 8 // Distributed under the Boost Software License, Version 1.0. 9 // (See accompanying file LICENSE_1_0.txt 10 // or copy at http://www.boost.org/LICENSE_1_0.txt) 11 12 /* 13 The following algorithm is used: 14 15 If all exponent bits, the flag bit (if there is one), 16 and all mantissa bits are 0, then the number is zero. 17 18 If all exponent bits and the flag bit (if there is one) are 0, 19 and at least one mantissa bit is 1, then the number is subnormal. 20 21 If all exponent bits are 1 and all mantissa bits are 0, 22 then the number is infinity. 23 24 If all exponent bits are 1 and at least one mantissa bit is 1, 25 then the number is a not-a-number. 26 27 Otherwise the number is normal. 28 29 (Note that the binary representation of infinity 30 has flag bit 0 for Motorola 68K extended double precision, 31 and flag bit 1 for Intel extended double precision.) 32 33 To get the bits, the four or eight most significant bytes are copied 34 into an uint32_t or uint64_t and bit masks are applied. 35 This covers all the exponent bits and the flag bit (if there is one), 36 but not always all the mantissa bits. 37 Some of the functions below have two implementations, 38 depending on whether all the mantissa bits are copied or not. 39 */ 40 41 #if defined(_MSC_VER) 42 #pragma once 43 #endif 44 45 #include <cmath> 46 47 #ifndef FP_INFINITE 48 # define FP_INFINITE 0 49 # define FP_NAN 1 50 # define FP_NORMAL 2 51 # define FP_SUBNORMAL 3 52 # define FP_ZERO 4 53 #endif 54 55 #include <boost/spirit/home/support/detail/math/detail/fp_traits.hpp> 56 57 namespace boost { 58 namespace spirit { 59 namespace math { 60 61 //------------------------------------------------------------------------------ 62 63 template<class T> bool (isfinite)(T x) 64 { 65 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; 66 traits::init(); 67 68 BOOST_DEDUCED_TYPENAME traits::bits a; 69 traits::get_bits(x,a); 70 a &= traits::exponent; 71 return a != traits::exponent; 72 } 73 74 //------------------------------------------------------------------------------ 75 76 template<class T> bool (isnormal)(T x) 77 { 78 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; 79 traits::init(); 80 81 BOOST_DEDUCED_TYPENAME traits::bits a; 82 traits::get_bits(x,a); 83 a &= traits::exponent | traits::flag; 84 return (a != 0) && (a < traits::exponent); 85 } 86 87 //------------------------------------------------------------------------------ 88 89 namespace detail { 90 isinf_impl(T x,all_bits)91 template<class T> bool isinf_impl(T x, all_bits) 92 { 93 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 94 95 BOOST_DEDUCED_TYPENAME traits::bits a; 96 traits::get_bits(x,a); 97 a &= traits::exponent | traits::mantissa; 98 return a == traits::exponent; 99 } 100 isinf_impl(T x,not_all_bits)101 template<class T> bool isinf_impl(T x, not_all_bits) 102 { 103 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 104 105 BOOST_DEDUCED_TYPENAME traits::bits a; 106 traits::get_bits(x,a); 107 a &= traits::exponent | traits::mantissa; 108 if(a != traits::exponent) 109 return false; 110 111 traits::set_bits(x,0); 112 return x == 0; 113 } 114 115 } // namespace detail 116 117 template<class T> bool (isinf)(T x) 118 { 119 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; 120 traits::init(); 121 return detail::isinf_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 122 } 123 124 //------------------------------------------------------------------------------ 125 126 namespace detail { 127 isnan_impl(T x,all_bits)128 template<class T> bool isnan_impl(T x, all_bits) 129 { 130 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 131 traits::init(); 132 133 BOOST_DEDUCED_TYPENAME traits::bits a; 134 traits::get_bits(x,a); 135 a &= traits::exponent | traits::mantissa; 136 return a > traits::exponent; 137 } 138 isnan_impl(T x,not_all_bits)139 template<class T> bool isnan_impl(T x, not_all_bits) 140 { 141 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 142 traits::init(); 143 144 BOOST_DEDUCED_TYPENAME traits::bits a; 145 traits::get_bits(x,a); 146 147 a &= traits::exponent | traits::mantissa; 148 if(a < traits::exponent) 149 return false; 150 151 a &= traits::mantissa; 152 traits::set_bits(x,a); 153 return x != 0; 154 } 155 156 } // namespace detail 157 158 template<class T> bool (isnan)(T x) 159 { 160 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; 161 traits::init(); 162 return detail::isnan_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 163 } 164 165 //------------------------------------------------------------------------------ 166 167 namespace detail { 168 fpclassify_impl(T x,all_bits)169 template<class T> int fpclassify_impl(T x, all_bits) 170 { 171 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 172 173 BOOST_DEDUCED_TYPENAME traits::bits a; 174 traits::get_bits(x,a); 175 a &= traits::exponent | traits::flag | traits::mantissa; 176 177 if(a <= traits::mantissa) { 178 if(a == 0) 179 return FP_ZERO; 180 else 181 return FP_SUBNORMAL; 182 } 183 184 if(a < traits::exponent) 185 return FP_NORMAL; 186 187 a &= traits::mantissa; 188 if(a == 0) 189 return FP_INFINITE; 190 191 return FP_NAN; 192 } 193 fpclassify_impl(T x,not_all_bits)194 template<class T> int fpclassify_impl(T x, not_all_bits) 195 { 196 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 197 198 BOOST_DEDUCED_TYPENAME traits::bits a; 199 traits::get_bits(x,a); 200 a &= traits::exponent | traits::flag | traits::mantissa; 201 202 if(a <= traits::mantissa) { 203 if(x == 0) 204 return FP_ZERO; 205 else 206 return FP_SUBNORMAL; 207 } 208 209 if(a < traits::exponent) 210 return FP_NORMAL; 211 212 a &= traits::mantissa; 213 traits::set_bits(x,a); 214 if(x == 0) 215 return FP_INFINITE; 216 217 return FP_NAN; 218 } 219 220 } // namespace detail 221 222 template<class T> int (fpclassify)(T x) 223 { 224 typedef BOOST_DEDUCED_TYPENAME detail::fp_traits<T>::type traits; 225 traits::init(); 226 return detail::fpclassify_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 227 } 228 229 //------------------------------------------------------------------------------ 230 231 } // namespace math 232 } // namespace spirit 233 } // namespace boost 234 235 #endif 236