annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_bin_float.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 ///////////////////////////////////////////////////////////////
Chris@102 2 // Copyright 2013 John Maddock. Distributed under the Boost
Chris@102 3 // Software License, Version 1.0. (See accompanying file
Chris@102 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
Chris@102 5
Chris@102 6 #ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP
Chris@102 7 #define BOOST_MATH_CPP_BIN_FLOAT_HPP
Chris@102 8
Chris@102 9 #include <boost/multiprecision/cpp_int.hpp>
Chris@102 10 #include <boost/multiprecision/integer.hpp>
Chris@102 11 #include <boost/math/special_functions/trunc.hpp>
Chris@102 12 #include <boost/multiprecision/detail/float_string_cvt.hpp>
Chris@102 13
Chris@102 14 namespace boost{ namespace multiprecision{ namespace backends{
Chris@102 15
Chris@102 16 enum digit_base_type
Chris@102 17 {
Chris@102 18 digit_base_2 = 2,
Chris@102 19 digit_base_10 = 10
Chris@102 20 };
Chris@102 21
Chris@102 22 #ifdef BOOST_MSVC
Chris@102 23 #pragma warning(push)
Chris@102 24 #pragma warning(disable:4522) // multiple assignment operators specified
Chris@102 25 #endif
Chris@102 26
Chris@102 27 namespace detail{
Chris@102 28
Chris@102 29 template <class U>
Chris@102 30 inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
Chris@102 31 template <class S>
Chris@102 32 inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
Chris@102 33
Chris@102 34 }
Chris@102 35
Chris@102 36 template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
Chris@102 37 class cpp_bin_float
Chris@102 38 {
Chris@102 39 public:
Chris@102 40 static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + ((Digits * 1000uL) % 301 ? 2u : 1u);
Chris@102 41 typedef cpp_int_backend<is_void<Allocator>::value ? bit_count : 0, bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> rep_type;
Chris@102 42 typedef cpp_int_backend<is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> double_rep_type;
Chris@102 43
Chris@102 44 typedef typename rep_type::signed_types signed_types;
Chris@102 45 typedef typename rep_type::unsigned_types unsigned_types;
Chris@102 46 typedef boost::mpl::list<double, long double> float_types;
Chris@102 47 typedef Exponent exponent_type;
Chris@102 48
Chris@102 49 static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count);
Chris@102 50 static const exponent_type min_exponent_limit = boost::integer_traits<exponent_type>::const_min + 2 * static_cast<exponent_type>(bit_count);
Chris@102 51
Chris@102 52 BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
Chris@102 53 BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
Chris@102 54 BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
Chris@102 55 BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
Chris@102 56
Chris@102 57 static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
Chris@102 58 static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
Chris@102 59
Chris@102 60 static const exponent_type exponent_zero = max_exponent + 1;
Chris@102 61 static const exponent_type exponent_infinity = max_exponent + 2;
Chris@102 62 static const exponent_type exponent_nan = max_exponent + 3;
Chris@102 63
Chris@102 64 private:
Chris@102 65
Chris@102 66 rep_type m_data;
Chris@102 67 exponent_type m_exponent;
Chris@102 68 bool m_sign;
Chris@102 69 public:
Chris@102 70 cpp_bin_float() BOOST_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_nan), m_sign(false) {}
Chris@102 71
Chris@102 72 cpp_bin_float(const cpp_bin_float &o) BOOST_NOEXCEPT_IF(noexcept(rep_type(std::declval<const rep_type&>())))
Chris@102 73 : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
Chris@102 74
Chris@102 75 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
Chris@102 76 cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::enable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
Chris@102 77 : m_exponent(o.exponent()), m_sign(o.sign())
Chris@102 78 {
Chris@102 79 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
Chris@102 80 this->sign() = o.sign();
Chris@102 81 this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
Chris@102 82 copy_and_round(*this, b);
Chris@102 83 }
Chris@102 84
Chris@102 85 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
Chris@102 86 explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::disable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
Chris@102 87 : m_exponent(o.exponent()), m_sign(o.sign())
Chris@102 88 {
Chris@102 89 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
Chris@102 90 this->sign() = o.sign();
Chris@102 91 this->exponent() = o.exponent() - (int)(cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count - bit_count);
Chris@102 92 copy_and_round(*this, b);
Chris@102 93 }
Chris@102 94
Chris@102 95 template <class Float>
Chris@102 96 cpp_bin_float(const Float& f,
Chris@102 97 typename boost::enable_if_c<
Chris@102 98 (number_category<Float>::value == number_kind_floating_point)
Chris@102 99 && (std::numeric_limits<Float>::digits <= (int)bit_count)
Chris@102 100 && (std::numeric_limits<Float>::radix == 2)
Chris@102 101 >::type const* = 0)
Chris@102 102 : m_data(), m_exponent(0), m_sign(false)
Chris@102 103 {
Chris@102 104 this->assign_float(f);
Chris@102 105 }
Chris@102 106
Chris@102 107 cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
Chris@102 108 {
Chris@102 109 m_data = o.m_data;
Chris@102 110 m_exponent = o.m_exponent;
Chris@102 111 m_sign = o.m_sign;
Chris@102 112 return *this;
Chris@102 113 }
Chris@102 114
Chris@102 115 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
Chris@102 116 cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o)
Chris@102 117 {
Chris@102 118 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
Chris@102 119 this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
Chris@102 120 this->sign() = o.sign();
Chris@102 121 copy_and_round(*this, b);
Chris@102 122 return *this;
Chris@102 123 }
Chris@102 124
Chris@102 125 template <class Float>
Chris@102 126 typename boost::enable_if_c<
Chris@102 127 (number_category<Float>::value == number_kind_floating_point)
Chris@102 128 && (std::numeric_limits<Float>::digits <= (int)bit_count)
Chris@102 129 && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f)
Chris@102 130 {
Chris@102 131 return assign_float(f);
Chris@102 132 }
Chris@102 133
Chris@102 134 template <class Float>
Chris@102 135 typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
Chris@102 136 {
Chris@102 137 BOOST_MATH_STD_USING
Chris@102 138 using default_ops::eval_add;
Chris@102 139 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
Chris@102 140
Chris@102 141 switch((boost::math::fpclassify)(f))
Chris@102 142 {
Chris@102 143 case FP_ZERO:
Chris@102 144 m_data = limb_type(0);
Chris@102 145 m_sign = false;
Chris@102 146 m_exponent = exponent_zero;
Chris@102 147 return *this;
Chris@102 148 case FP_NAN:
Chris@102 149 m_data = limb_type(0);
Chris@102 150 m_sign = false;
Chris@102 151 m_exponent = exponent_nan;
Chris@102 152 return *this;
Chris@102 153 case FP_INFINITE:
Chris@102 154 m_data = limb_type(0);
Chris@102 155 m_sign = false;
Chris@102 156 m_exponent = exponent_infinity;
Chris@102 157 return *this;
Chris@102 158 }
Chris@102 159 if(f < 0)
Chris@102 160 {
Chris@102 161 *this = -f;
Chris@102 162 this->negate();
Chris@102 163 return *this;
Chris@102 164 }
Chris@102 165
Chris@102 166 typedef typename mpl::front<unsigned_types>::type ui_type;
Chris@102 167 m_data = static_cast<ui_type>(0u);
Chris@102 168 m_sign = false;
Chris@102 169 m_exponent = 0;
Chris@102 170
Chris@102 171 static const int bits = sizeof(int) * CHAR_BIT - 1;
Chris@102 172 int e;
Chris@102 173 f = frexp(f, &e);
Chris@102 174 while(f)
Chris@102 175 {
Chris@102 176 f = ldexp(f, bits);
Chris@102 177 e -= bits;
Chris@102 178 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Chris@102 179 int ipart = itrunc(f);
Chris@102 180 #else
Chris@102 181 int ipart = static_cast<int>(f);
Chris@102 182 #endif
Chris@102 183 f -= ipart;
Chris@102 184 m_exponent += bits;
Chris@102 185 cpp_bin_float t;
Chris@102 186 t = static_cast<bf_int_type>(ipart);
Chris@102 187 eval_add(*this, t);
Chris@102 188 }
Chris@102 189 m_exponent += static_cast<Exponent>(e);
Chris@102 190 return *this;
Chris@102 191 }
Chris@102 192
Chris@102 193 template <class Float>
Chris@102 194 typename boost::enable_if_c<
Chris@102 195 (number_category<Float>::value == number_kind_floating_point)
Chris@102 196 && !is_floating_point<Float>::value
Chris@102 197 /*&& (std::numeric_limits<number<Float> >::radix == 2)*/,
Chris@102 198 cpp_bin_float&>::type assign_float(Float f)
Chris@102 199 {
Chris@102 200 BOOST_MATH_STD_USING
Chris@102 201 using default_ops::eval_add;
Chris@102 202 using default_ops::eval_get_sign;
Chris@102 203 using default_ops::eval_convert_to;
Chris@102 204 using default_ops::eval_subtract;
Chris@102 205
Chris@102 206 typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type;
Chris@102 207 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
Chris@102 208
Chris@102 209 switch(eval_fpclassify(f))
Chris@102 210 {
Chris@102 211 case FP_ZERO:
Chris@102 212 m_data = limb_type(0);
Chris@102 213 m_sign = false;
Chris@102 214 m_exponent = exponent_zero;
Chris@102 215 return *this;
Chris@102 216 case FP_NAN:
Chris@102 217 m_data = limb_type(0);
Chris@102 218 m_sign = false;
Chris@102 219 m_exponent = exponent_nan;
Chris@102 220 return *this;
Chris@102 221 case FP_INFINITE:
Chris@102 222 m_data = limb_type(0);
Chris@102 223 m_sign = false;
Chris@102 224 m_exponent = exponent_infinity;
Chris@102 225 return *this;
Chris@102 226 }
Chris@102 227 if(eval_get_sign(f) < 0)
Chris@102 228 {
Chris@102 229 f.negate();
Chris@102 230 *this = f;
Chris@102 231 this->negate();
Chris@102 232 return *this;
Chris@102 233 }
Chris@102 234
Chris@102 235 typedef typename mpl::front<unsigned_types>::type ui_type;
Chris@102 236 m_data = static_cast<ui_type>(0u);
Chris@102 237 m_sign = false;
Chris@102 238 m_exponent = 0;
Chris@102 239
Chris@102 240 static const int bits = sizeof(int) * CHAR_BIT - 1;
Chris@102 241 int e;
Chris@102 242 eval_frexp(f, f, &e);
Chris@102 243 while(eval_get_sign(f) != 0)
Chris@102 244 {
Chris@102 245 eval_ldexp(f, f, bits);
Chris@102 246 e -= bits;
Chris@102 247 int ipart;
Chris@102 248 eval_convert_to(&ipart, f);
Chris@102 249 eval_subtract(f, static_cast<f_int_type>(ipart));
Chris@102 250 m_exponent += bits;
Chris@102 251 eval_add(*this, static_cast<bf_int_type>(ipart));
Chris@102 252 }
Chris@102 253 m_exponent += e;
Chris@102 254 if(m_exponent > max_exponent)
Chris@102 255 m_exponent = exponent_infinity;
Chris@102 256 if(m_exponent < min_exponent)
Chris@102 257 {
Chris@102 258 m_data = limb_type(0u);
Chris@102 259 m_exponent = exponent_zero;
Chris@102 260 m_sign = false;
Chris@102 261 }
Chris@102 262 else if(eval_get_sign(m_data) == 0)
Chris@102 263 {
Chris@102 264 m_exponent = exponent_zero;
Chris@102 265 m_sign = false;
Chris@102 266 }
Chris@102 267 return *this;
Chris@102 268 }
Chris@102 269
Chris@102 270 template <class I>
Chris@102 271 typename boost::enable_if<is_integral<I>, cpp_bin_float&>::type operator=(const I& i)
Chris@102 272 {
Chris@102 273 using default_ops::eval_bit_test;
Chris@102 274 if(!i)
Chris@102 275 {
Chris@102 276 m_data = static_cast<limb_type>(0);
Chris@102 277 m_exponent = exponent_zero;
Chris@102 278 m_sign = false;
Chris@102 279 }
Chris@102 280 else
Chris@102 281 {
Chris@102 282 typedef typename make_unsigned<I>::type ui_type;
Chris@102 283 ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
Chris@102 284 typedef typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type ar_type;
Chris@102 285 m_data = static_cast<ar_type>(fi);
Chris@102 286 unsigned shift = msb(fi);
Chris@102 287 if(shift >= bit_count)
Chris@102 288 {
Chris@102 289 m_exponent = static_cast<Exponent>(shift);
Chris@102 290 m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count));
Chris@102 291 }
Chris@102 292 else
Chris@102 293 {
Chris@102 294 m_exponent = static_cast<Exponent>(shift);
Chris@102 295 eval_left_shift(m_data, bit_count - shift - 1);
Chris@102 296 }
Chris@102 297 BOOST_ASSERT(eval_bit_test(m_data, bit_count-1));
Chris@102 298 m_sign = detail::is_negative(i);
Chris@102 299 }
Chris@102 300 return *this;
Chris@102 301 }
Chris@102 302
Chris@102 303 cpp_bin_float& operator=(const char *s);
Chris@102 304
Chris@102 305 void swap(cpp_bin_float &o) BOOST_NOEXCEPT
Chris@102 306 {
Chris@102 307 m_data.swap(o.m_data);
Chris@102 308 std::swap(m_exponent, o.m_exponent);
Chris@102 309 std::swap(m_sign, o.m_sign);
Chris@102 310 }
Chris@102 311
Chris@102 312 std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
Chris@102 313
Chris@102 314 void negate()
Chris@102 315 {
Chris@102 316 if((m_exponent != exponent_zero) && (m_exponent != exponent_nan))
Chris@102 317 m_sign = !m_sign;
Chris@102 318 }
Chris@102 319
Chris@102 320 int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT
Chris@102 321 {
Chris@102 322 if(m_sign != o.m_sign)
Chris@102 323 return m_sign ? -1 : 1;
Chris@102 324 int result;
Chris@102 325 if(m_exponent == exponent_nan)
Chris@102 326 return -1;
Chris@102 327 else if(m_exponent != o.m_exponent)
Chris@102 328 {
Chris@102 329 if(m_exponent == exponent_zero)
Chris@102 330 result = -1;
Chris@102 331 else if(o.m_exponent == exponent_zero)
Chris@102 332 result = 1;
Chris@102 333 else
Chris@102 334 result = m_exponent > o.m_exponent ? 1 : -1;
Chris@102 335 }
Chris@102 336 else
Chris@102 337 result = m_data.compare(o.m_data);
Chris@102 338 if(m_sign)
Chris@102 339 result = -result;
Chris@102 340 return result;
Chris@102 341 }
Chris@102 342 template <class A>
Chris@102 343 int compare(const A& o) const BOOST_NOEXCEPT
Chris@102 344 {
Chris@102 345 cpp_bin_float b;
Chris@102 346 b = o;
Chris@102 347 return compare(b);
Chris@102 348 }
Chris@102 349
Chris@102 350 rep_type& bits() { return m_data; }
Chris@102 351 const rep_type& bits()const { return m_data; }
Chris@102 352 exponent_type& exponent() { return m_exponent; }
Chris@102 353 const exponent_type& exponent()const { return m_exponent; }
Chris@102 354 bool& sign() { return m_sign; }
Chris@102 355 const bool& sign()const { return m_sign; }
Chris@102 356 void check_invariants()
Chris@102 357 {
Chris@102 358 using default_ops::eval_bit_test;
Chris@102 359 using default_ops::eval_is_zero;
Chris@102 360 if((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
Chris@102 361 {
Chris@102 362 BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1));
Chris@102 363 }
Chris@102 364 else
Chris@102 365 {
Chris@102 366 BOOST_ASSERT(m_exponent > max_exponent);
Chris@102 367 BOOST_ASSERT(m_exponent <= exponent_nan);
Chris@102 368 BOOST_ASSERT(eval_is_zero(m_data));
Chris@102 369 }
Chris@102 370 }
Chris@102 371 template<class Archive>
Chris@102 372 void serialize(Archive & ar, const unsigned int /*version*/)
Chris@102 373 {
Chris@102 374 ar & m_data;
Chris@102 375 ar & m_exponent;
Chris@102 376 ar & m_sign;
Chris@102 377 }
Chris@102 378 };
Chris@102 379
Chris@102 380 #ifdef BOOST_MSVC
Chris@102 381 #pragma warning(pop)
Chris@102 382 #endif
Chris@102 383
Chris@102 384 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
Chris@102 385 inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, Int &arg)
Chris@102 386 {
Chris@102 387 // Precondition: exponent of res must have been set before this function is called
Chris@102 388 // as we may need to adjust it based on how many cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in arg are set.
Chris@102 389 using default_ops::eval_msb;
Chris@102 390 using default_ops::eval_lsb;
Chris@102 391 using default_ops::eval_left_shift;
Chris@102 392 using default_ops::eval_bit_test;
Chris@102 393 using default_ops::eval_right_shift;
Chris@102 394 using default_ops::eval_increment;
Chris@102 395 using default_ops::eval_get_sign;
Chris@102 396
Chris@102 397 // cancellation may have resulted in arg being all zeros:
Chris@102 398 if(eval_get_sign(arg) == 0)
Chris@102 399 {
Chris@102 400 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 401 res.sign() = false;
Chris@102 402 res.bits() = static_cast<limb_type>(0u);
Chris@102 403 return;
Chris@102 404 }
Chris@102 405 int msb = eval_msb(arg);
Chris@102 406 if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) > msb + 1)
Chris@102 407 {
Chris@102 408 // Must have had cancellation in subtraction, shift left and copy:
Chris@102 409 res.bits() = arg;
Chris@102 410 eval_left_shift(res.bits(), cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
Chris@102 411 res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
Chris@102 412 }
Chris@102 413 else if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) < msb + 1)
Chris@102 414 {
Chris@102 415 // We have more cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than we need, so round as required,
Chris@102 416 // first get the rounding bit:
Chris@102 417 bool roundup = eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
Chris@102 418 // Then check for a tie:
Chris@102 419 if(roundup && (msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count == eval_lsb(arg)))
Chris@102 420 {
Chris@102 421 // Ties round towards even:
Chris@102 422 if(!eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1))
Chris@102 423 roundup = false;
Chris@102 424 }
Chris@102 425 // Shift off the cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count we don't need:
Chris@102 426 eval_right_shift(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
Chris@102 427 res.exponent() += static_cast<Exponent>(msb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
Chris@102 428 if(roundup)
Chris@102 429 {
Chris@102 430 eval_increment(arg);
Chris@102 431 if(eval_bit_test(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
Chris@102 432 {
Chris@102 433 // This happens very very rairly:
Chris@102 434 eval_right_shift(arg, 1u);
Chris@102 435 ++res.exponent();
Chris@102 436 }
Chris@102 437 }
Chris@102 438 res.bits() = arg;
Chris@102 439 }
Chris@102 440 else
Chris@102 441 {
Chris@102 442 res.bits() = arg;
Chris@102 443 }
Chris@102 444 BOOST_ASSERT((eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
Chris@102 445
Chris@102 446 if(res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 447 {
Chris@102 448 // Overflow:
Chris@102 449 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
Chris@102 450 res.bits() = static_cast<limb_type>(0u);
Chris@102 451 }
Chris@102 452 else if(res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
Chris@102 453 {
Chris@102 454 // Underflow:
Chris@102 455 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 456 res.bits() = static_cast<limb_type>(0u);
Chris@102 457 res.sign() = false;
Chris@102 458 }
Chris@102 459 }
Chris@102 460
Chris@102 461 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 462 inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 463 {
Chris@102 464 using default_ops::eval_add;
Chris@102 465 using default_ops::eval_bit_test;
Chris@102 466
Chris@102 467 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
Chris@102 468
Chris@102 469 // Special cases first:
Chris@102 470 switch(a.exponent())
Chris@102 471 {
Chris@102 472 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 473 res = b;
Chris@102 474 if(res.sign())
Chris@102 475 res.negate();
Chris@102 476 return;
Chris@102 477 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 478 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
Chris@102 479 res = b;
Chris@102 480 else
Chris@102 481 res = a;
Chris@102 482 return; // result is still infinite.
Chris@102 483 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 484 res = a;
Chris@102 485 return; // result is still a NaN.
Chris@102 486 }
Chris@102 487 switch(b.exponent())
Chris@102 488 {
Chris@102 489 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 490 res = a;
Chris@102 491 return;
Chris@102 492 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 493 res = b;
Chris@102 494 if(res.sign())
Chris@102 495 res.negate();
Chris@102 496 return; // result is infinite.
Chris@102 497 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 498 res = b;
Chris@102 499 return; // result is a NaN.
Chris@102 500 }
Chris@102 501
Chris@102 502 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
Chris@102 503 bool s = a.sign();
Chris@102 504 if(e_diff >= 0)
Chris@102 505 {
Chris@102 506 dt = a.bits();
Chris@102 507 if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 508 {
Chris@102 509 eval_left_shift(dt, e_diff);
Chris@102 510 res.exponent() = a.exponent() - e_diff;
Chris@102 511 eval_add(dt, b.bits());
Chris@102 512 }
Chris@102 513 else
Chris@102 514 res.exponent() = a.exponent();
Chris@102 515 }
Chris@102 516 else
Chris@102 517 {
Chris@102 518 dt= b.bits();
Chris@102 519 if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 520 {
Chris@102 521 eval_left_shift(dt, -e_diff);
Chris@102 522 res.exponent() = b.exponent() + e_diff;
Chris@102 523 eval_add(dt, a.bits());
Chris@102 524 }
Chris@102 525 else
Chris@102 526 res.exponent() = b.exponent();
Chris@102 527 }
Chris@102 528
Chris@102 529 copy_and_round(res, dt);
Chris@102 530 res.check_invariants();
Chris@102 531 if(res.sign() != s)
Chris@102 532 res.negate();
Chris@102 533 }
Chris@102 534
Chris@102 535 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 536 inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 537 {
Chris@102 538 using default_ops::eval_subtract;
Chris@102 539 using default_ops::eval_bit_test;
Chris@102 540
Chris@102 541 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
Chris@102 542
Chris@102 543 // Special cases first:
Chris@102 544 switch(a.exponent())
Chris@102 545 {
Chris@102 546 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 547 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
Chris@102 548 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 549 else
Chris@102 550 {
Chris@102 551 res = b;
Chris@102 552 if(!res.sign())
Chris@102 553 res.negate();
Chris@102 554 }
Chris@102 555 return;
Chris@102 556 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 557 if((b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) || (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity))
Chris@102 558 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 559 else
Chris@102 560 res = a;
Chris@102 561 return;
Chris@102 562 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 563 res = a;
Chris@102 564 return; // result is still a NaN.
Chris@102 565 }
Chris@102 566 switch(b.exponent())
Chris@102 567 {
Chris@102 568 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 569 res = a;
Chris@102 570 return;
Chris@102 571 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 572 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
Chris@102 573 res.sign() = false;
Chris@102 574 res.bits() = static_cast<limb_type>(0u);
Chris@102 575 return; // result is a NaN.
Chris@102 576 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 577 res = b;
Chris@102 578 return; // result is still a NaN.
Chris@102 579 }
Chris@102 580
Chris@102 581 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
Chris@102 582 bool s = a.sign();
Chris@102 583 if((e_diff > 0) || ((e_diff == 0) && a.bits().compare(b.bits()) >= 0))
Chris@102 584 {
Chris@102 585 dt = a.bits();
Chris@102 586 if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 587 {
Chris@102 588 eval_left_shift(dt, e_diff);
Chris@102 589 res.exponent() = a.exponent() - e_diff;
Chris@102 590 eval_subtract(dt, b.bits());
Chris@102 591 }
Chris@102 592 else
Chris@102 593 res.exponent() = a.exponent();
Chris@102 594 }
Chris@102 595 else
Chris@102 596 {
Chris@102 597 dt = b.bits();
Chris@102 598 if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 599 {
Chris@102 600 eval_left_shift(dt, -e_diff);
Chris@102 601 res.exponent() = b.exponent() + e_diff;
Chris@102 602 eval_subtract(dt, a.bits());
Chris@102 603 }
Chris@102 604 else
Chris@102 605 res.exponent() = b.exponent();
Chris@102 606 s = !s;
Chris@102 607 }
Chris@102 608
Chris@102 609 copy_and_round(res, dt);
Chris@102 610 if(res.sign() != s)
Chris@102 611 res.negate();
Chris@102 612 res.check_invariants();
Chris@102 613 }
Chris@102 614
Chris@102 615 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 616 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 617 {
Chris@102 618 if(a.sign() == b.sign())
Chris@102 619 do_eval_add(res, a, b);
Chris@102 620 else
Chris@102 621 do_eval_subtract(res, a, b);
Chris@102 622 }
Chris@102 623
Chris@102 624 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 625 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
Chris@102 626 {
Chris@102 627 return eval_add(res, res, a);
Chris@102 628 }
Chris@102 629
Chris@102 630 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 631 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 632 {
Chris@102 633 if(a.sign() != b.sign())
Chris@102 634 do_eval_add(res, a, b);
Chris@102 635 else
Chris@102 636 do_eval_subtract(res, a, b);
Chris@102 637 }
Chris@102 638
Chris@102 639 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 640 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
Chris@102 641 {
Chris@102 642 return eval_subtract(res, res, a);
Chris@102 643 }
Chris@102 644
Chris@102 645 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 646 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 647 {
Chris@102 648 using default_ops::eval_bit_test;
Chris@102 649 using default_ops::eval_multiply;
Chris@102 650
Chris@102 651 // Special cases first:
Chris@102 652 switch(a.exponent())
Chris@102 653 {
Chris@102 654 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 655 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
Chris@102 656 res = b;
Chris@102 657 else
Chris@102 658 res = a;
Chris@102 659 return;
Chris@102 660 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 661 switch(b.exponent())
Chris@102 662 {
Chris@102 663 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 664 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 665 break;
Chris@102 666 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 667 res = b;
Chris@102 668 break;
Chris@102 669 default:
Chris@102 670 res = a;
Chris@102 671 break;
Chris@102 672 }
Chris@102 673 return;
Chris@102 674 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 675 res = a;
Chris@102 676 return;
Chris@102 677 }
Chris@102 678 if(b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 679 {
Chris@102 680 res = b;
Chris@102 681 return;
Chris@102 682 }
Chris@102 683 if((a.exponent() > 0) && (b.exponent() > 0))
Chris@102 684 {
Chris@102 685 if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
Chris@102 686 {
Chris@102 687 // We will certainly overflow:
Chris@102 688 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
Chris@102 689 res.sign() = a.sign() != b.sign();
Chris@102 690 res.bits() = static_cast<limb_type>(0u);
Chris@102 691 return;
Chris@102 692 }
Chris@102 693 }
Chris@102 694 if((a.exponent() < 0) && (b.exponent() < 0))
Chris@102 695 {
Chris@102 696 if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent())
Chris@102 697 {
Chris@102 698 // We will certainly underflow:
Chris@102 699 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 700 res.sign() = false;
Chris@102 701 res.bits() = static_cast<limb_type>(0u);
Chris@102 702 return;
Chris@102 703 }
Chris@102 704 }
Chris@102 705
Chris@102 706 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
Chris@102 707 eval_multiply(dt, a.bits(), b.bits());
Chris@102 708 res.exponent() = a.exponent() + b.exponent() - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
Chris@102 709 copy_and_round(res, dt);
Chris@102 710 res.check_invariants();
Chris@102 711 res.sign() = a.sign() != b.sign();
Chris@102 712 }
Chris@102 713
Chris@102 714 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 715 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
Chris@102 716 {
Chris@102 717 eval_multiply(res, res, a);
Chris@102 718 }
Chris@102 719
Chris@102 720 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
Chris@102 721 inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const U &b)
Chris@102 722 {
Chris@102 723 using default_ops::eval_bit_test;
Chris@102 724 using default_ops::eval_multiply;
Chris@102 725
Chris@102 726 // Special cases first:
Chris@102 727 switch(a.exponent())
Chris@102 728 {
Chris@102 729 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 730 res = a;
Chris@102 731 return;
Chris@102 732 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 733 if(b == 0)
Chris@102 734 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 735 else
Chris@102 736 res = a;
Chris@102 737 return;
Chris@102 738 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 739 res = a;
Chris@102 740 return;
Chris@102 741 }
Chris@102 742
Chris@102 743 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
Chris@102 744 typedef typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type canon_ui_type;
Chris@102 745 eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b));
Chris@102 746 res.exponent() = a.exponent();
Chris@102 747 copy_and_round(res, dt);
Chris@102 748 res.check_invariants();
Chris@102 749 res.sign() = a.sign();
Chris@102 750 }
Chris@102 751
Chris@102 752 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
Chris@102 753 inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &b)
Chris@102 754 {
Chris@102 755 eval_multiply(res, res, b);
Chris@102 756 }
Chris@102 757
Chris@102 758 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
Chris@102 759 inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const S &b)
Chris@102 760 {
Chris@102 761 typedef typename make_unsigned<S>::type ui_type;
Chris@102 762 eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b)));
Chris@102 763 if(b < 0)
Chris@102 764 res.negate();
Chris@102 765 }
Chris@102 766
Chris@102 767 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
Chris@102 768 inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &b)
Chris@102 769 {
Chris@102 770 eval_multiply(res, res, b);
Chris@102 771 }
Chris@102 772
Chris@102 773 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 774 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &v)
Chris@102 775 {
Chris@102 776 using default_ops::eval_subtract;
Chris@102 777 using default_ops::eval_qr;
Chris@102 778 using default_ops::eval_bit_test;
Chris@102 779 using default_ops::eval_get_sign;
Chris@102 780 using default_ops::eval_increment;
Chris@102 781
Chris@102 782 //
Chris@102 783 // Special cases first:
Chris@102 784 //
Chris@102 785 switch(u.exponent())
Chris@102 786 {
Chris@102 787 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 788 switch(v.exponent())
Chris@102 789 {
Chris@102 790 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 791 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 792 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 793 return;
Chris@102 794 }
Chris@102 795 res = u;
Chris@102 796 return;
Chris@102 797 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 798 switch(v.exponent())
Chris@102 799 {
Chris@102 800 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 801 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 802 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 803 return;
Chris@102 804 }
Chris@102 805 res = u;
Chris@102 806 return;
Chris@102 807 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 808 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 809 return;
Chris@102 810 }
Chris@102 811 switch(v.exponent())
Chris@102 812 {
Chris@102 813 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 814 {
Chris@102 815 bool s = u.sign() != v.sign();
Chris@102 816 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 817 res.sign() = s;
Chris@102 818 return;
Chris@102 819 }
Chris@102 820 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 821 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 822 res.bits() = limb_type(0);
Chris@102 823 res.sign() = false;
Chris@102 824 return;
Chris@102 825 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 826 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 827 return;
Chris@102 828 }
Chris@102 829
Chris@102 830 // We can scale u and v so that both are integers, then perform integer
Chris@102 831 // division to obtain quotient q and remainder r, such that:
Chris@102 832 //
Chris@102 833 // q * v + r = u
Chris@102 834 //
Chris@102 835 // and hense:
Chris@102 836 //
Chris@102 837 // q + r/v = u/v
Chris@102 838 //
Chris@102 839 // From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count
Chris@102 840 // bits we only need to determine whether
Chris@102 841 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
Chris@102 842 // this we can do with a shift and comparison.
Chris@102 843 //
Chris@102 844 // We can set the exponent and sign of the result up front:
Chris@102 845 //
Chris@102 846 res.exponent() = u.exponent() - v.exponent() - 1;
Chris@102 847 res.sign() = u.sign() != v.sign();
Chris@102 848 //
Chris@102 849 // Now get the quotient and remainder:
Chris@102 850 //
Chris@102 851 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
Chris@102 852 eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
Chris@102 853 eval_qr(t, t2, q, r);
Chris@102 854 //
Chris@102 855 // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count"
Chris@102 856 // or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant
Chris@102 857 // bits in q.
Chris@102 858 //
Chris@102 859 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
Chris@102 860 if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
Chris@102 861 {
Chris@102 862 //
Chris@102 863 // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits,
Chris@102 864 // so we already have rounding info,
Chris@102 865 // we just need to changes things if the last bit is 1 and either the
Chris@102 866 // remainder is non-zero (ie we do not have a tie) or the quotient would
Chris@102 867 // be odd if it were shifted to the correct number of bits (ie a tiebreak).
Chris@102 868 //
Chris@102 869 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
Chris@102 870 if((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u)))
Chris@102 871 {
Chris@102 872 eval_increment(q);
Chris@102 873 }
Chris@102 874 }
Chris@102 875 else
Chris@102 876 {
Chris@102 877 //
Chris@102 878 // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q.
Chris@102 879 // Get rounding info, which we can get by comparing 2r with v.
Chris@102 880 // We want to call copy_and_round to handle rounding and general cleanup,
Chris@102 881 // so we'll left shift q and add some fake digits on the end to represent
Chris@102 882 // how we'll be rounding.
Chris@102 883 //
Chris@102 884 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
Chris@102 885 static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
Chris@102 886 eval_left_shift(q, lshift);
Chris@102 887 res.exponent() -= lshift;
Chris@102 888 eval_left_shift(r, 1u);
Chris@102 889 int c = r.compare(v.bits());
Chris@102 890 if(c == 0)
Chris@102 891 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
Chris@102 892 else if(c > 0)
Chris@102 893 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
Chris@102 894 }
Chris@102 895 copy_and_round(res, q);
Chris@102 896 }
Chris@102 897
Chris@102 898 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 899 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 900 {
Chris@102 901 eval_divide(res, res, arg);
Chris@102 902 }
Chris@102 903
Chris@102 904 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
Chris@102 905 inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const U &v)
Chris@102 906 {
Chris@102 907 using default_ops::eval_subtract;
Chris@102 908 using default_ops::eval_qr;
Chris@102 909 using default_ops::eval_bit_test;
Chris@102 910 using default_ops::eval_get_sign;
Chris@102 911 using default_ops::eval_increment;
Chris@102 912
Chris@102 913 //
Chris@102 914 // Special cases first:
Chris@102 915 //
Chris@102 916 switch(u.exponent())
Chris@102 917 {
Chris@102 918 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 919 if(v == 0)
Chris@102 920 {
Chris@102 921 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 922 return;
Chris@102 923 }
Chris@102 924 res = u;
Chris@102 925 return;
Chris@102 926 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 927 res = u;
Chris@102 928 return;
Chris@102 929 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 930 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 931 return;
Chris@102 932 }
Chris@102 933 if(v == 0)
Chris@102 934 {
Chris@102 935 bool s = u.sign();
Chris@102 936 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 937 res.sign() = s;
Chris@102 938 return;
Chris@102 939 }
Chris@102 940
Chris@102 941 // We can scale u and v so that both are integers, then perform integer
Chris@102 942 // division to obtain quotient q and remainder r, such that:
Chris@102 943 //
Chris@102 944 // q * v + r = u
Chris@102 945 //
Chris@102 946 // and hense:
Chris@102 947 //
Chris@102 948 // q + r/v = u/v
Chris@102 949 //
Chris@102 950 // From this, assuming q has "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, we only need to determine whether
Chris@102 951 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
Chris@102 952 // this we can do with a shift and comparison.
Chris@102 953 //
Chris@102 954 // We can set the exponent and sign of the result up front:
Chris@102 955 //
Chris@102 956 int gb = msb(v);
Chris@102 957 res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1);
Chris@102 958 res.sign() = u.sign();
Chris@102 959 //
Chris@102 960 // Now get the quotient and remainder:
Chris@102 961 //
Chris@102 962 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r;
Chris@102 963 eval_left_shift(t, gb + 1);
Chris@102 964 eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r);
Chris@102 965 //
Chris@102 966 // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
Chris@102 967 //
Chris@102 968 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
Chris@102 969 if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
Chris@102 970 {
Chris@102 971 //
Chris@102 972 // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, so we already have rounding info,
Chris@102 973 // we just need to changes things if the last bit is 1 and the
Chris@102 974 // remainder is non-zero (ie we do not have a tie).
Chris@102 975 //
Chris@102 976 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
Chris@102 977 if((q.limbs()[0] & 1u) && eval_get_sign(r))
Chris@102 978 {
Chris@102 979 eval_increment(q);
Chris@102 980 }
Chris@102 981 }
Chris@102 982 else
Chris@102 983 {
Chris@102 984 //
Chris@102 985 // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
Chris@102 986 // Get rounding info, which we can get by comparing 2r with v.
Chris@102 987 // We want to call copy_and_round to handle rounding and general cleanup,
Chris@102 988 // so we'll left shift q and add some fake cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count on the end to represent
Chris@102 989 // how we'll be rounding.
Chris@102 990 //
Chris@102 991 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
Chris@102 992 static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
Chris@102 993 eval_left_shift(q, lshift);
Chris@102 994 res.exponent() -= lshift;
Chris@102 995 eval_left_shift(r, 1u);
Chris@102 996 int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v));
Chris@102 997 if(c == 0)
Chris@102 998 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
Chris@102 999 else if(c > 0)
Chris@102 1000 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
Chris@102 1001 }
Chris@102 1002 copy_and_round(res, q);
Chris@102 1003 }
Chris@102 1004
Chris@102 1005 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
Chris@102 1006 inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &v)
Chris@102 1007 {
Chris@102 1008 eval_divide(res, res, v);
Chris@102 1009 }
Chris@102 1010
Chris@102 1011 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
Chris@102 1012 inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const S &v)
Chris@102 1013 {
Chris@102 1014 typedef typename make_unsigned<S>::type ui_type;
Chris@102 1015 eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v)));
Chris@102 1016 if(v < 0)
Chris@102 1017 res.negate();
Chris@102 1018 }
Chris@102 1019
Chris@102 1020 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
Chris@102 1021 inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &v)
Chris@102 1022 {
Chris@102 1023 eval_divide(res, res, v);
Chris@102 1024 }
Chris@102 1025
Chris@102 1026 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1027 inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1028 {
Chris@102 1029 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1;
Chris@102 1030 }
Chris@102 1031
Chris@102 1032 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1033 inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1034 {
Chris@102 1035 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 1036 }
Chris@102 1037
Chris@102 1038 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1039 inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
Chris@102 1040 {
Chris@102 1041 return (a.exponent() == b.exponent())
Chris@102 1042 && (a.sign() == b.sign())
Chris@102 1043 && (a.bits().compare(b.bits()) == 0)
Chris@102 1044 && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
Chris@102 1045 }
Chris@102 1046
Chris@102 1047 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1048 inline void eval_convert_to(long long *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1049 {
Chris@102 1050 switch(arg.exponent())
Chris@102 1051 {
Chris@102 1052 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1053 *res = 0;
Chris@102 1054 return;
Chris@102 1055 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1056 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
Chris@102 1057 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1058 *res = (std::numeric_limits<long long>::max)();
Chris@102 1059 if(arg.sign())
Chris@102 1060 *res = -*res;
Chris@102 1061 return;
Chris@102 1062 }
Chris@102 1063 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
Chris@102 1064 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift
Chris@102 1065 = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
Chris@102 1066 if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
Chris@102 1067 {
Chris@102 1068 *res = 0;
Chris@102 1069 return;
Chris@102 1070 }
Chris@102 1071 if(arg.sign() && (arg.compare((std::numeric_limits<long long>::min)()) <= 0))
Chris@102 1072 {
Chris@102 1073 *res = (std::numeric_limits<long long>::min)();
Chris@102 1074 return;
Chris@102 1075 }
Chris@102 1076 else if(!arg.sign() && (arg.compare((std::numeric_limits<long long>::max)()) >= 0))
Chris@102 1077 {
Chris@102 1078 *res = (std::numeric_limits<long long>::max)();
Chris@102 1079 return;
Chris@102 1080 }
Chris@102 1081 eval_right_shift(man, shift);
Chris@102 1082 eval_convert_to(res, man);
Chris@102 1083 if(arg.sign())
Chris@102 1084 {
Chris@102 1085 *res = -*res;
Chris@102 1086 }
Chris@102 1087 }
Chris@102 1088
Chris@102 1089 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1090 inline void eval_convert_to(unsigned long long *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1091 {
Chris@102 1092 switch(arg.exponent())
Chris@102 1093 {
Chris@102 1094 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1095 *res = 0;
Chris@102 1096 return;
Chris@102 1097 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1098 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
Chris@102 1099 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1100 *res = (std::numeric_limits<unsigned long long>::max)();
Chris@102 1101 return;
Chris@102 1102 }
Chris@102 1103 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
Chris@102 1104 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift
Chris@102 1105 = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
Chris@102 1106 if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
Chris@102 1107 {
Chris@102 1108 *res = 0;
Chris@102 1109 return;
Chris@102 1110 }
Chris@102 1111 else if(shift < 0)
Chris@102 1112 {
Chris@102 1113 // TODO: what if we have fewer cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than a long long?
Chris@102 1114 *res = (std::numeric_limits<long long>::max)();
Chris@102 1115 return;
Chris@102 1116 }
Chris@102 1117 eval_right_shift(man, shift);
Chris@102 1118 eval_convert_to(res, man);
Chris@102 1119 }
Chris@102 1120
Chris@102 1121 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1122 inline void eval_convert_to(long double *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1123 {
Chris@102 1124 switch(arg.exponent())
Chris@102 1125 {
Chris@102 1126 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1127 *res = 0;
Chris@102 1128 return;
Chris@102 1129 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1130 *res = std::numeric_limits<long double>::quiet_NaN();
Chris@102 1131 return;
Chris@102 1132 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1133 *res = (std::numeric_limits<long double>::infinity)();
Chris@102 1134 if(arg.sign())
Chris@102 1135 *res = -*res;
Chris@102 1136 return;
Chris@102 1137 }
Chris@102 1138 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e = arg.exponent();
Chris@102 1139 e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
Chris@102 1140 *res = std::ldexp(static_cast<long double>(*arg.bits().limbs()), e);
Chris@102 1141 for(unsigned i = 1; i < arg.bits().size(); ++i)
Chris@102 1142 {
Chris@102 1143 e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
Chris@102 1144 *res += std::ldexp(static_cast<long double>(arg.bits().limbs()[i]), e);
Chris@102 1145 }
Chris@102 1146 if(arg.sign())
Chris@102 1147 *res = -*res;
Chris@102 1148 }
Chris@102 1149
Chris@102 1150 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1151 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent *e)
Chris@102 1152 {
Chris@102 1153 switch(arg.exponent())
Chris@102 1154 {
Chris@102 1155 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1156 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1157 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1158 *e = 0;
Chris@102 1159 res = arg;
Chris@102 1160 return;
Chris@102 1161 }
Chris@102 1162 res = arg;
Chris@102 1163 *e = arg.exponent() + 1;
Chris@102 1164 res.exponent() = -1;
Chris@102 1165 }
Chris@102 1166
Chris@102 1167 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
Chris@102 1168 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I *pe)
Chris@102 1169 {
Chris@102 1170 Exponent e;
Chris@102 1171 eval_frexp(res, arg, &e);
Chris@102 1172 if((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)()))
Chris@102 1173 {
Chris@102 1174 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp."));
Chris@102 1175 }
Chris@102 1176 *pe = static_cast<I>(e);
Chris@102 1177 }
Chris@102 1178
Chris@102 1179 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1180 inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent e)
Chris@102 1181 {
Chris@102 1182 switch(arg.exponent())
Chris@102 1183 {
Chris@102 1184 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1185 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1186 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1187 res = arg;
Chris@102 1188 return;
Chris@102 1189 }
Chris@102 1190 if((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent()))
Chris@102 1191 {
Chris@102 1192 // Overflow:
Chris@102 1193 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 1194 res.sign() = arg.sign();
Chris@102 1195 }
Chris@102 1196 else if((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent()))
Chris@102 1197 {
Chris@102 1198 // Underflow:
Chris@102 1199 res = limb_type(0);
Chris@102 1200 }
Chris@102 1201 else
Chris@102 1202 {
Chris@102 1203 res = arg;
Chris@102 1204 res.exponent() += e;
Chris@102 1205 }
Chris@102 1206 }
Chris@102 1207
Chris@102 1208 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
Chris@102 1209 inline typename enable_if_c<is_unsigned<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e)
Chris@102 1210 {
Chris@102 1211 typedef typename make_signed<I>::type si_type;
Chris@102 1212 if(e > static_cast<I>((std::numeric_limits<si_type>::max)()))
Chris@102 1213 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 1214 else
Chris@102 1215 eval_ldexp(res, arg, static_cast<si_type>(e));
Chris@102 1216 }
Chris@102 1217
Chris@102 1218 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
Chris@102 1219 inline typename enable_if_c<is_signed<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e)
Chris@102 1220 {
Chris@102 1221 if((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)()))
Chris@102 1222 {
Chris@102 1223 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 1224 if(e < 0)
Chris@102 1225 res.negate();
Chris@102 1226 }
Chris@102 1227 else
Chris@102 1228 eval_ldexp(res, arg, static_cast<Exponent>(e));
Chris@102 1229 }
Chris@102 1230
Chris@102 1231 /*
Chris@102 1232 * Sign manipulation
Chris@102 1233 */
Chris@102 1234
Chris@102 1235 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1236 inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1237 {
Chris@102 1238 res = arg;
Chris@102 1239 res.sign() = false;
Chris@102 1240 }
Chris@102 1241
Chris@102 1242 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1243 inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1244 {
Chris@102 1245 res = arg;
Chris@102 1246 res.sign() = false;
Chris@102 1247 }
Chris@102 1248
Chris@102 1249 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1250 inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1251 {
Chris@102 1252 switch(arg.exponent())
Chris@102 1253 {
Chris@102 1254 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1255 return FP_ZERO;
Chris@102 1256 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1257 return FP_INFINITE;
Chris@102 1258 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1259 return FP_NAN;
Chris@102 1260 }
Chris@102 1261 return FP_NORMAL;
Chris@102 1262 }
Chris@102 1263
Chris@102 1264 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1265 inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1266 {
Chris@102 1267 using default_ops::eval_integer_sqrt;
Chris@102 1268 using default_ops::eval_bit_test;
Chris@102 1269 using default_ops::eval_increment;
Chris@102 1270 switch(arg.exponent())
Chris@102 1271 {
Chris@102 1272 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1273 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1274 res = arg;
Chris@102 1275 return;
Chris@102 1276 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1277 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 1278 return;
Chris@102 1279 }
Chris@102 1280 if(arg.sign())
Chris@102 1281 {
Chris@102 1282 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 1283 return;
Chris@102 1284 }
Chris@102 1285
Chris@102 1286 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s;
Chris@102 1287 eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count : cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
Chris@102 1288 eval_integer_sqrt(s, r, t);
Chris@102 1289
Chris@102 1290 if(!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
Chris@102 1291 {
Chris@102 1292 // We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required:
Chris@102 1293 if(s.compare(r) < 0)
Chris@102 1294 {
Chris@102 1295 eval_increment(s);
Chris@102 1296 }
Chris@102 1297 }
Chris@102 1298 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent();
Chris@102 1299 res.exponent() = ae / 2;
Chris@102 1300 if((ae & 1) && (ae < 0))
Chris@102 1301 --res.exponent();
Chris@102 1302 copy_and_round(res, s);
Chris@102 1303 }
Chris@102 1304
Chris@102 1305 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1306 inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1307 {
Chris@102 1308 using default_ops::eval_increment;
Chris@102 1309 switch(arg.exponent())
Chris@102 1310 {
Chris@102 1311 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1312 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1313 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1314 res = arg;
Chris@102 1315 return;
Chris@102 1316 }
Chris@102 1317 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift =
Chris@102 1318 (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
Chris@102 1319 if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
Chris@102 1320 {
Chris@102 1321 // Either arg is already an integer, or a special value:
Chris@102 1322 res = arg;
Chris@102 1323 return;
Chris@102 1324 }
Chris@102 1325 if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 1326 {
Chris@102 1327 res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0);
Chris@102 1328 return;
Chris@102 1329 }
Chris@102 1330 bool fractional = (int)eval_lsb(arg.bits()) < shift;
Chris@102 1331 res = arg;
Chris@102 1332 eval_right_shift(res.bits(), shift);
Chris@102 1333 if(fractional && res.sign())
Chris@102 1334 {
Chris@102 1335 eval_increment(res.bits());
Chris@102 1336 if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
Chris@102 1337 {
Chris@102 1338 // Must have extended result by one bit in the increment:
Chris@102 1339 --shift;
Chris@102 1340 ++res.exponent();
Chris@102 1341 }
Chris@102 1342 }
Chris@102 1343 eval_left_shift(res.bits(), shift);
Chris@102 1344 }
Chris@102 1345
Chris@102 1346 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1347 inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
Chris@102 1348 {
Chris@102 1349 using default_ops::eval_increment;
Chris@102 1350 switch(arg.exponent())
Chris@102 1351 {
Chris@102 1352 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
Chris@102 1353 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
Chris@102 1354 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
Chris@102 1355 res = arg;
Chris@102 1356 return;
Chris@102 1357 }
Chris@102 1358 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
Chris@102 1359 if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
Chris@102 1360 {
Chris@102 1361 // Either arg is already an integer, or a special value:
Chris@102 1362 res = arg;
Chris@102 1363 return;
Chris@102 1364 }
Chris@102 1365 if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
Chris@102 1366 {
Chris@102 1367 res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
Chris@102 1368 return;
Chris@102 1369 }
Chris@102 1370 bool fractional = (int)eval_lsb(arg.bits()) < shift;
Chris@102 1371 res = arg;
Chris@102 1372 eval_right_shift(res.bits(), shift);
Chris@102 1373 if(fractional && !res.sign())
Chris@102 1374 {
Chris@102 1375 eval_increment(res.bits());
Chris@102 1376 if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
Chris@102 1377 {
Chris@102 1378 // Must have extended result by one bit in the increment:
Chris@102 1379 --shift;
Chris@102 1380 ++res.exponent();
Chris@102 1381 }
Chris@102 1382 }
Chris@102 1383 eval_left_shift(res.bits(), shift);
Chris@102 1384 }
Chris@102 1385
Chris@102 1386 } // namespace backends
Chris@102 1387
Chris@102 1388 #ifdef BOOST_NO_SFINAE_EXPR
Chris@102 1389
Chris@102 1390 namespace detail{
Chris@102 1391
Chris@102 1392 template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
Chris@102 1393 struct is_explicitly_convertible<backends::cpp_bin_float<D1, B1, A1, E1, M1, M2>, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public mpl::true_ {};
Chris@102 1394
Chris@102 1395 }
Chris@102 1396 #endif
Chris@102 1397
Chris@102 1398
Chris@102 1399 using backends::cpp_bin_float;
Chris@102 1400 using backends::digit_base_2;
Chris@102 1401 using backends::digit_base_10;
Chris@102 1402
Chris@102 1403 template<unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator>
Chris@102 1404 struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public boost::mpl::int_<boost::multiprecision::number_kind_floating_point>{};
Chris@102 1405
Chris@102 1406 template<unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 1407 struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >
Chris@102 1408 {
Chris@102 1409 static const expression_template_option value = is_void<Allocator>::value ? et_off : et_on;
Chris@102 1410 };
Chris@102 1411
Chris@102 1412 typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50;
Chris@102 1413 typedef number<backends::cpp_bin_float<100> > cpp_bin_float_100;
Chris@102 1414
Chris@102 1415 typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
Chris@102 1416 typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
Chris@102 1417 typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
Chris@102 1418 typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
Chris@102 1419
Chris@102 1420 }} // namespaces
Chris@102 1421
Chris@102 1422 #include <boost/multiprecision/cpp_bin_float/io.hpp>
Chris@102 1423 #include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
Chris@102 1424
Chris@102 1425 namespace std{
Chris@102 1426
Chris@102 1427 //
Chris@102 1428 // numeric_limits [partial] specializations for the types declared in this header:
Chris@102 1429 //
Chris@102 1430 template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1431 class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >
Chris@102 1432 {
Chris@102 1433 typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> number_type;
Chris@102 1434 public:
Chris@102 1435 BOOST_STATIC_CONSTEXPR bool is_specialized = true;
Chris@102 1436 static number_type (min)()
Chris@102 1437 {
Chris@102 1438 initializer.do_nothing();
Chris@102 1439 static std::pair<bool, number_type> value;
Chris@102 1440 if(!value.first)
Chris@102 1441 {
Chris@102 1442 value.first = true;
Chris@102 1443 value.second = 1u;
Chris@102 1444 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 1445 }
Chris@102 1446 return value.second;
Chris@102 1447 }
Chris@102 1448 static number_type (max)()
Chris@102 1449 {
Chris@102 1450 initializer.do_nothing();
Chris@102 1451 static std::pair<bool, number_type> value;
Chris@102 1452 if(!value.first)
Chris@102 1453 {
Chris@102 1454 value.first = true;
Chris@102 1455 eval_complement(value.second.backend().bits(), value.second.backend().bits());
Chris@102 1456 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 1457 }
Chris@102 1458 return value.second;
Chris@102 1459 }
Chris@102 1460 BOOST_STATIC_CONSTEXPR number_type lowest()
Chris@102 1461 {
Chris@102 1462 return -(max)();
Chris@102 1463 }
Chris@102 1464 BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
Chris@102 1465 BOOST_STATIC_CONSTEXPR int digits10 = digits * 301 / 1000;
Chris@102 1466 // Is this really correct???
Chris@102 1467 BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
Chris@102 1468 BOOST_STATIC_CONSTEXPR bool is_signed = true;
Chris@102 1469 BOOST_STATIC_CONSTEXPR bool is_integer = false;
Chris@102 1470 BOOST_STATIC_CONSTEXPR bool is_exact = false;
Chris@102 1471 BOOST_STATIC_CONSTEXPR int radix = 2;
Chris@102 1472 static number_type epsilon()
Chris@102 1473 {
Chris@102 1474 initializer.do_nothing();
Chris@102 1475 static std::pair<bool, number_type> value;
Chris@102 1476 if(!value.first)
Chris@102 1477 {
Chris@102 1478 value.first = true;
Chris@102 1479 value.second = 1;
Chris@102 1480 value.second = ldexp(value.second, 1 - (int)digits);
Chris@102 1481 }
Chris@102 1482 return value.second;
Chris@102 1483 }
Chris@102 1484 // What value should this be????
Chris@102 1485 static number_type round_error()
Chris@102 1486 {
Chris@102 1487 // returns 0.5
Chris@102 1488 initializer.do_nothing();
Chris@102 1489 static std::pair<bool, number_type> value;
Chris@102 1490 if(!value.first)
Chris@102 1491 {
Chris@102 1492 value.first = true;
Chris@102 1493 value.second = 1;
Chris@102 1494 value.second = ldexp(value.second, -1);
Chris@102 1495 }
Chris@102 1496 return value.second;
Chris@102 1497 }
Chris@102 1498 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 1499 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
Chris@102 1500 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 1501 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
Chris@102 1502 BOOST_STATIC_CONSTEXPR bool has_infinity = true;
Chris@102 1503 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
Chris@102 1504 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
Chris@102 1505 BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
Chris@102 1506 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
Chris@102 1507 static number_type infinity()
Chris@102 1508 {
Chris@102 1509 // returns epsilon/2
Chris@102 1510 initializer.do_nothing();
Chris@102 1511 static std::pair<bool, number_type> value;
Chris@102 1512 if(!value.first)
Chris@102 1513 {
Chris@102 1514 value.first = true;
Chris@102 1515 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
Chris@102 1516 }
Chris@102 1517 return value.second;
Chris@102 1518 }
Chris@102 1519 static number_type quiet_NaN()
Chris@102 1520 {
Chris@102 1521 return number_type();
Chris@102 1522 }
Chris@102 1523 BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
Chris@102 1524 {
Chris@102 1525 return number_type(0);
Chris@102 1526 }
Chris@102 1527 BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
Chris@102 1528 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
Chris@102 1529 BOOST_STATIC_CONSTEXPR bool is_bounded = true;
Chris@102 1530 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
Chris@102 1531 BOOST_STATIC_CONSTEXPR bool traps = true;
Chris@102 1532 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
Chris@102 1533 BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
Chris@102 1534 private:
Chris@102 1535 struct data_initializer
Chris@102 1536 {
Chris@102 1537 data_initializer()
Chris@102 1538 {
Chris@102 1539 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::epsilon();
Chris@102 1540 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::round_error();
Chris@102 1541 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::min)();
Chris@102 1542 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max)();
Chris@102 1543 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity();
Chris@102 1544 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN();
Chris@102 1545 }
Chris@102 1546 void do_nothing()const{}
Chris@102 1547 };
Chris@102 1548 static const data_initializer initializer;
Chris@102 1549 };
Chris@102 1550
Chris@102 1551 template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1552 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::initializer;
Chris@102 1553
Chris@102 1554 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@102 1555
Chris@102 1556 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1557 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits;
Chris@102 1558 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1559 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10;
Chris@102 1560 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1561 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10;
Chris@102 1562 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1563 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed;
Chris@102 1564 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1565 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer;
Chris@102 1566 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1567 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact;
Chris@102 1568 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1569 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix;
Chris@102 1570 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1571 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent;
Chris@102 1572 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1573 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent10;
Chris@102 1574 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1575 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent;
Chris@102 1576 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1577 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent10;
Chris@102 1578 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1579 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity;
Chris@102 1580 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1581 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN;
Chris@102 1582 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1583 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN;
Chris@102 1584 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1585 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm;
Chris@102 1586 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1587 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss;
Chris@102 1588 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1589 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559;
Chris@102 1590 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1591 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded;
Chris@102 1592 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1593 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo;
Chris@102 1594 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1595 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps;
Chris@102 1596 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1597 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before;
Chris@102 1598 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
Chris@102 1599 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style;
Chris@102 1600
Chris@102 1601 #endif
Chris@102 1602
Chris@102 1603 } // namespace std
Chris@102 1604
Chris@102 1605 #endif