annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_bin_float/io.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_MP_CPP_BIN_FLOAT_IO_HPP
Chris@102 7 #define BOOST_MP_CPP_BIN_FLOAT_IO_HPP
Chris@102 8
Chris@102 9 namespace boost{ namespace multiprecision{ namespace cpp_bf_io_detail{
Chris@102 10
Chris@102 11 //
Chris@102 12 // Multiplies a by b and shifts the result so it fits inside max_bits bits,
Chris@102 13 // returns by how much the result was shifted.
Chris@102 14 //
Chris@102 15 template <class I>
Chris@102 16 inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b, I max_bits, boost::int64_t& error)
Chris@102 17 {
Chris@102 18 result = a * b;
Chris@102 19 I gb = msb(result);
Chris@102 20 I rshift = 0;
Chris@102 21 if(gb > max_bits)
Chris@102 22 {
Chris@102 23 rshift = gb - max_bits;
Chris@102 24 I lb = lsb(result);
Chris@102 25 int roundup = 0;
Chris@102 26 // The error rate increases by the error of both a and b,
Chris@102 27 // this may be overly pessimistic in many case as we're assuming
Chris@102 28 // that a and b have the same level of uncertainty...
Chris@102 29 if(lb < rshift)
Chris@102 30 error = error ? error * 2 : 1;
Chris@102 31 if(rshift)
Chris@102 32 {
Chris@102 33 BOOST_ASSERT(rshift < INT_MAX);
Chris@102 34 if(bit_test(result, static_cast<unsigned>(rshift - 1)))
Chris@102 35 {
Chris@102 36 if(lb == rshift - 1)
Chris@102 37 roundup = 1;
Chris@102 38 else
Chris@102 39 roundup = 2;
Chris@102 40 }
Chris@102 41 result >>= rshift;
Chris@102 42 }
Chris@102 43 if((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1)))
Chris@102 44 ++result;
Chris@102 45 }
Chris@102 46 return rshift;
Chris@102 47 }
Chris@102 48 //
Chris@102 49 // Computes a^e shifted to the right so it fits in max_bits, returns how far
Chris@102 50 // to the right we are shifted.
Chris@102 51 //
Chris@102 52 template <class I>
Chris@102 53 inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, boost::int64_t& error)
Chris@102 54 {
Chris@102 55 BOOST_ASSERT(&result != &a);
Chris@102 56 I exp = 0;
Chris@102 57 if(e == 1)
Chris@102 58 {
Chris@102 59 result = a;
Chris@102 60 return exp;
Chris@102 61 }
Chris@102 62 else if(e == 2)
Chris@102 63 {
Chris@102 64 return restricted_multiply(result, a, a, max_bits, error);
Chris@102 65 }
Chris@102 66 else if(e == 3)
Chris@102 67 {
Chris@102 68 exp = restricted_multiply(result, a, a, max_bits, error);
Chris@102 69 exp += restricted_multiply(result, result, a, max_bits, error);
Chris@102 70 return exp;
Chris@102 71 }
Chris@102 72 I p = e / 2;
Chris@102 73 exp = restricted_pow(result, a, p, max_bits, error);
Chris@102 74 exp *= 2;
Chris@102 75 exp += restricted_multiply(result, result, result, max_bits, error);
Chris@102 76 if(e & 1)
Chris@102 77 exp += restricted_multiply(result, result, a, max_bits, error);
Chris@102 78 return exp;
Chris@102 79 }
Chris@102 80
Chris@102 81 inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::int64_t error)
Chris@102 82 {
Chris@102 83 //
Chris@102 84 // Can we round what at /location/, if the error in what is /error/ in
Chris@102 85 // units of 0.5ulp. Return:
Chris@102 86 //
Chris@102 87 // -1: Can't round.
Chris@102 88 // 0: leave as is.
Chris@102 89 // 1: tie.
Chris@102 90 // 2: round up.
Chris@102 91 //
Chris@102 92 BOOST_ASSERT(location >= 0);
Chris@102 93 BOOST_ASSERT(location < INT_MAX);
Chris@102 94 boost::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2;
Chris@102 95 if(error_radius && ((int)msb(error_radius) >= location))
Chris@102 96 return -1;
Chris@102 97 if(bit_test(what, static_cast<unsigned>(location)))
Chris@102 98 {
Chris@102 99 if((int)lsb(what) == location)
Chris@102 100 return error ? -1 : 1; // Either a tie or can't round depending on whether we have any error
Chris@102 101 if(!error)
Chris@102 102 return 2; // no error, round up.
Chris@102 103 cpp_int t = what - error_radius;
Chris@102 104 if((int)lsb(t) >= location)
Chris@102 105 return -1;
Chris@102 106 return 2;
Chris@102 107 }
Chris@102 108 else if(error)
Chris@102 109 {
Chris@102 110 cpp_int t = what + error_radius;
Chris@102 111 return bit_test(t, static_cast<unsigned>(location)) ? -1 : 0;
Chris@102 112 }
Chris@102 113 return 0;
Chris@102 114 }
Chris@102 115
Chris@102 116 inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cpp_int& q)
Chris@102 117 {
Chris@102 118 //
Chris@102 119 // Lets suppose we have an inexact division by d+delta, where the true
Chris@102 120 // value for the divisor is d, and with |delta| <= error/2, then
Chris@102 121 // we have calculated q and r such that:
Chris@102 122 //
Chris@102 123 // n r
Chris@102 124 // --- = q + -----------
Chris@102 125 // d + error d + error
Chris@102 126 //
Chris@102 127 // Rearranging for n / d we get:
Chris@102 128 //
Chris@102 129 // n delta*q + r
Chris@102 130 // --- = q + -------------
Chris@102 131 // d d
Chris@102 132 //
Chris@102 133 // So rounding depends on whether 2r + error * q > d.
Chris@102 134 //
Chris@102 135 // We return:
Chris@102 136 // 0 = down down.
Chris@102 137 // 1 = tie.
Chris@102 138 // 2 = round up.
Chris@102 139 // -1 = couldn't decide.
Chris@102 140 //
Chris@102 141 r <<= 1;
Chris@102 142 int c = r.compare(d);
Chris@102 143 if(c == 0)
Chris@102 144 return error ? -1 : 1;
Chris@102 145 if(c > 0)
Chris@102 146 {
Chris@102 147 if(error)
Chris@102 148 {
Chris@102 149 r -= error * q;
Chris@102 150 return r.compare(d) > 0 ? 2 : -1;
Chris@102 151 }
Chris@102 152 return 2;
Chris@102 153 }
Chris@102 154 if(error)
Chris@102 155 {
Chris@102 156 r += error * q;
Chris@102 157 return r.compare(d) < 0 ? 0 : -1;
Chris@102 158 }
Chris@102 159 return 0;
Chris@102 160 }
Chris@102 161
Chris@102 162 } // namespace
Chris@102 163
Chris@102 164 namespace backends{
Chris@102 165
Chris@102 166 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 167 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::operator=(const char *s)
Chris@102 168 {
Chris@102 169 cpp_int n;
Chris@102 170 boost::intmax_t decimal_exp = 0;
Chris@102 171 boost::intmax_t digits_seen = 0;
Chris@102 172 static const boost::intmax_t max_digits_seen = 4 + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count * 301L) / 1000;
Chris@102 173 bool ss = false;
Chris@102 174 //
Chris@102 175 // Extract the sign:
Chris@102 176 //
Chris@102 177 if(*s == '-')
Chris@102 178 {
Chris@102 179 ss = true;
Chris@102 180 ++s;
Chris@102 181 }
Chris@102 182 else if(*s == '+')
Chris@102 183 ++s;
Chris@102 184 //
Chris@102 185 // Special cases first:
Chris@102 186 //
Chris@102 187 if((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || (std::strcmp(s, "NAN") == 0))
Chris@102 188 {
Chris@102 189 return *this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
Chris@102 190 }
Chris@102 191 if((std::strcmp(s, "inf") == 0) || (std::strcmp(s, "Inf") == 0) || (std::strcmp(s, "INF") == 0) || (std::strcmp(s, "infinity") == 0) || (std::strcmp(s, "Infinity") == 0) || (std::strcmp(s, "INFINITY") == 0))
Chris@102 192 {
Chris@102 193 *this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
Chris@102 194 if(ss)
Chris@102 195 negate();
Chris@102 196 return *this;
Chris@102 197 }
Chris@102 198 //
Chris@102 199 // Digits before the point:
Chris@102 200 //
Chris@102 201 while(*s && (*s >= '0') && (*s <= '9'))
Chris@102 202 {
Chris@102 203 n *= 10u;
Chris@102 204 n += *s - '0';
Chris@102 205 if(digits_seen || (*s != '0'))
Chris@102 206 ++digits_seen;
Chris@102 207 ++s;
Chris@102 208 }
Chris@102 209 // The decimal point (we really should localise this!!)
Chris@102 210 if(*s && (*s == '.'))
Chris@102 211 ++s;
Chris@102 212 //
Chris@102 213 // Digits after the point:
Chris@102 214 //
Chris@102 215 while(*s && (*s >= '0') && (*s <= '9'))
Chris@102 216 {
Chris@102 217 n *= 10u;
Chris@102 218 n += *s - '0';
Chris@102 219 --decimal_exp;
Chris@102 220 if(digits_seen || (*s != '0'))
Chris@102 221 ++digits_seen;
Chris@102 222 ++s;
Chris@102 223 if(digits_seen > max_digits_seen)
Chris@102 224 break;
Chris@102 225 }
Chris@102 226 //
Chris@102 227 // Digits we're skipping:
Chris@102 228 //
Chris@102 229 while(*s && (*s >= '0') && (*s <= '9'))
Chris@102 230 ++s;
Chris@102 231 //
Chris@102 232 // See if there's an exponent:
Chris@102 233 //
Chris@102 234 if(*s && ((*s == 'e') || (*s == 'E')))
Chris@102 235 {
Chris@102 236 ++s;
Chris@102 237 boost::intmax_t e = 0;
Chris@102 238 bool es = false;
Chris@102 239 if(*s && (*s == '-'))
Chris@102 240 {
Chris@102 241 es = true;
Chris@102 242 ++s;
Chris@102 243 }
Chris@102 244 else if(*s && (*s == '+'))
Chris@102 245 ++s;
Chris@102 246 while(*s && (*s >= '0') && (*s <= '9'))
Chris@102 247 {
Chris@102 248 e *= 10u;
Chris@102 249 e += *s - '0';
Chris@102 250 ++s;
Chris@102 251 }
Chris@102 252 if(es)
Chris@102 253 e = -e;
Chris@102 254 decimal_exp += e;
Chris@102 255 }
Chris@102 256 if(*s)
Chris@102 257 {
Chris@102 258 //
Chris@102 259 // Oops unexpected input at the end of the number:
Chris@102 260 //
Chris@102 261 BOOST_THROW_EXCEPTION(std::runtime_error("Unable to parse string as a valid floating point number."));
Chris@102 262 }
Chris@102 263 if(n == 0)
Chris@102 264 {
Chris@102 265 // Result is necessarily zero:
Chris@102 266 *this = static_cast<limb_type>(0u);
Chris@102 267 return *this;
Chris@102 268 }
Chris@102 269
Chris@102 270 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
Chris@102 271 //
Chris@102 272 // Set our working precision - this is heuristic based, we want
Chris@102 273 // a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
Chris@102 274 // and excessive memory usage, but we also want to avoid having to
Chris@102 275 // up the computation and start again at a higher precision.
Chris@102 276 // So we round cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count up to the nearest whole number of limbs, and add
Chris@102 277 // one limb for good measure. This works very well for small exponents,
Chris@102 278 // but for larger exponents we may may need to restart, we could add some
Chris@102 279 // extra precision right from the start for larger exponents, but this
Chris@102 280 // seems to be slightly slower in the *average* case:
Chris@102 281 //
Chris@102 282 #ifdef BOOST_MP_STRESS_IO
Chris@102 283 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
Chris@102 284 #else
Chris@102 285 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits ? limb_bits - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits : 0) + limb_bits;
Chris@102 286 #endif
Chris@102 287 boost::int64_t error = 0;
Chris@102 288 boost::intmax_t calc_exp = 0;
Chris@102 289 boost::intmax_t final_exponent = 0;
Chris@102 290
Chris@102 291 if(decimal_exp >= 0)
Chris@102 292 {
Chris@102 293 // Nice and simple, the result is an integer...
Chris@102 294 do
Chris@102 295 {
Chris@102 296 cpp_int t;
Chris@102 297 if(decimal_exp)
Chris@102 298 {
Chris@102 299 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), decimal_exp, max_bits, error);
Chris@102 300 calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(t, t, n, max_bits, error);
Chris@102 301 }
Chris@102 302 else
Chris@102 303 t = n;
Chris@102 304 final_exponent = (boost::int64_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp + calc_exp;
Chris@102 305 int rshift = msb(t) - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
Chris@102 306 if(rshift > 0)
Chris@102 307 {
Chris@102 308 final_exponent += rshift;
Chris@102 309 int roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(t, rshift - 1, error);
Chris@102 310 t >>= rshift;
Chris@102 311 if((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1))
Chris@102 312 ++t;
Chris@102 313 else if(roundup < 0)
Chris@102 314 {
Chris@102 315 #ifdef BOOST_MP_STRESS_IO
Chris@102 316 max_bits += 32;
Chris@102 317 #else
Chris@102 318 max_bits *= 2;
Chris@102 319 #endif
Chris@102 320 error = 0;
Chris@102 321 continue;
Chris@102 322 }
Chris@102 323 }
Chris@102 324 else
Chris@102 325 {
Chris@102 326 BOOST_ASSERT(!error);
Chris@102 327 }
Chris@102 328 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 329 {
Chris@102 330 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 331 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 332 }
Chris@102 333 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
Chris@102 334 {
Chris@102 335 // Underflow:
Chris@102 336 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 337 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 338 }
Chris@102 339 else
Chris@102 340 {
Chris@102 341 exponent() = static_cast<Exponent>(final_exponent);
Chris@102 342 final_exponent = 0;
Chris@102 343 }
Chris@102 344 copy_and_round(*this, t.backend());
Chris@102 345 break;
Chris@102 346 }
Chris@102 347 while(true);
Chris@102 348
Chris@102 349 if(ss != sign())
Chris@102 350 negate();
Chris@102 351 }
Chris@102 352 else
Chris@102 353 {
Chris@102 354 // Result is the ratio of two integers: we need to organise the
Chris@102 355 // division so as to produce at least an N-bit result which we can
Chris@102 356 // round according to the remainder.
Chris@102 357 //cpp_int d = pow(cpp_int(5), -decimal_exp);
Chris@102 358 do
Chris@102 359 {
Chris@102 360 cpp_int d;
Chris@102 361 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -decimal_exp, max_bits, error);
Chris@102 362 int shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb(n) + msb(d);
Chris@102 363 final_exponent = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp - calc_exp;
Chris@102 364 if(shift > 0)
Chris@102 365 {
Chris@102 366 n <<= shift;
Chris@102 367 final_exponent -= static_cast<Exponent>(shift);
Chris@102 368 }
Chris@102 369 cpp_int q, r;
Chris@102 370 divide_qr(n, d, q, r);
Chris@102 371 int gb = msb(q);
Chris@102 372 BOOST_ASSERT((gb >= static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1));
Chris@102 373 //
Chris@102 374 // Check for rounding conditions we have to
Chris@102 375 // handle ourselves:
Chris@102 376 //
Chris@102 377 int roundup = 0;
Chris@102 378 if(gb == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
Chris@102 379 {
Chris@102 380 // Exactly the right number of bits, use the remainder to round:
Chris@102 381 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, q);
Chris@102 382 }
Chris@102 383 else if(bit_test(q, gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) && ((int)lsb(q) == (gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)))
Chris@102 384 {
Chris@102 385 // Too many bits in q and the bits in q indicate a tie, but we can break that using r,
Chris@102 386 // note that the radius of error in r is error/2 * q:
Chris@102 387 int shift = gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
Chris@102 388 q >>= shift;
Chris@102 389 final_exponent += static_cast<Exponent>(shift);
Chris@102 390 BOOST_ASSERT((msb(q) >= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
Chris@102 391 if(error && (r < (error / 2) * q))
Chris@102 392 roundup = -1;
Chris@102 393 else if(error && (r + (error / 2) * q >= d))
Chris@102 394 roundup = -1;
Chris@102 395 else
Chris@102 396 roundup = r ? 2 : 1;
Chris@102 397 }
Chris@102 398 else if(error && (((error / 2) * q + r >= d) || (r < (error / 2) * q)))
Chris@102 399 {
Chris@102 400 // We might have been rounding up, or got the wrong quotient: can't tell!
Chris@102 401 roundup = -1;
Chris@102 402 }
Chris@102 403 if(roundup < 0)
Chris@102 404 {
Chris@102 405 #ifdef BOOST_MP_STRESS_IO
Chris@102 406 max_bits += 32;
Chris@102 407 #else
Chris@102 408 max_bits *= 2;
Chris@102 409 #endif
Chris@102 410 error = 0;
Chris@102 411 if(shift > 0)
Chris@102 412 {
Chris@102 413 n >>= shift;
Chris@102 414 final_exponent += static_cast<Exponent>(shift);
Chris@102 415 }
Chris@102 416 continue;
Chris@102 417 }
Chris@102 418 else if((roundup == 2) || ((roundup == 1) && q.backend().limbs()[0] & 1))
Chris@102 419 ++q;
Chris@102 420 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 421 {
Chris@102 422 // Overflow:
Chris@102 423 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 424 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
Chris@102 425 }
Chris@102 426 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
Chris@102 427 {
Chris@102 428 // Underflow:
Chris@102 429 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 430 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
Chris@102 431 }
Chris@102 432 else
Chris@102 433 {
Chris@102 434 exponent() = static_cast<Exponent>(final_exponent);
Chris@102 435 final_exponent = 0;
Chris@102 436 }
Chris@102 437 copy_and_round(*this, q.backend());
Chris@102 438 if(ss != sign())
Chris@102 439 negate();
Chris@102 440 break;
Chris@102 441 }
Chris@102 442 while(true);
Chris@102 443 }
Chris@102 444 //
Chris@102 445 // Check for scaling and/or over/under-flow:
Chris@102 446 //
Chris@102 447 final_exponent += exponent();
Chris@102 448 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 449 {
Chris@102 450 // Overflow:
Chris@102 451 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
Chris@102 452 bits() = limb_type(0);
Chris@102 453 }
Chris@102 454 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
Chris@102 455 {
Chris@102 456 // Underflow:
Chris@102 457 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
Chris@102 458 bits() = limb_type(0);
Chris@102 459 sign() = 0;
Chris@102 460 }
Chris@102 461 else
Chris@102 462 {
Chris@102 463 exponent() = static_cast<Exponent>(final_exponent);
Chris@102 464 }
Chris@102 465 return *this;
Chris@102 466 }
Chris@102 467
Chris@102 468 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
Chris@102 469 std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::str(std::streamsize dig, std::ios_base::fmtflags f) const
Chris@102 470 {
Chris@102 471 if(dig == 0)
Chris@102 472 dig = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max_digits10;
Chris@102 473
Chris@102 474 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
Chris@102 475 bool fixed = !scientific && (f & std::ios_base::fixed);
Chris@102 476
Chris@102 477 std::string s;
Chris@102 478
Chris@102 479 if(exponent() <= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
Chris@102 480 {
Chris@102 481 // How far to left-shift in order to demormalise the mantissa:
Chris@102 482 boost::intmax_t shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1;
Chris@102 483 boost::intmax_t digits_wanted = static_cast<int>(dig);
Chris@102 484 boost::intmax_t base10_exp = exponent() >= 0 ? static_cast<boost::intmax_t>(std::floor(0.30103 * exponent())) : static_cast<boost::intmax_t>(std::ceil(0.30103 * exponent()));
Chris@102 485 //
Chris@102 486 // For fixed formatting we want /dig/ digits after the decimal point,
Chris@102 487 // so if the exponent is zero, allowing for the one digit before the
Chris@102 488 // decimal point, we want 1 + dig digits etc.
Chris@102 489 //
Chris@102 490 if(fixed)
Chris@102 491 digits_wanted += 1 + base10_exp;
Chris@102 492 if(scientific)
Chris@102 493 digits_wanted += 1;
Chris@102 494 if(digits_wanted < -1)
Chris@102 495 {
Chris@102 496 // Fixed precision, no significant digits, and nothing to round!
Chris@102 497 s = "0";
Chris@102 498 if(sign())
Chris@102 499 s.insert(static_cast<std::string::size_type>(0), 1, '-');
Chris@102 500 boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, true);
Chris@102 501 return s;
Chris@102 502 }
Chris@102 503 //
Chris@102 504 // power10 is the base10 exponent we need to multiply/divide by in order
Chris@102 505 // to convert our denormalised number to an integer with the right number of digits:
Chris@102 506 //
Chris@102 507 boost::intmax_t power10 = digits_wanted - base10_exp - 1;
Chris@102 508 //
Chris@102 509 // If we calculate 5^power10 rather than 10^power10 we need to move
Chris@102 510 // 2^power10 into /shift/
Chris@102 511 //
Chris@102 512 shift -= power10;
Chris@102 513 cpp_int i;
Chris@102 514 int roundup = 0; // 0=no rounding, 1=tie, 2=up
Chris@102 515 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
Chris@102 516 //
Chris@102 517 // Set our working precision - this is heuristic based, we want
Chris@102 518 // a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
Chris@102 519 // and excessive memory usage, but we also want to avoid having to
Chris@102 520 // up the computation and start again at a higher precision.
Chris@102 521 // So we round cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count up to the nearest whole number of limbs, and add
Chris@102 522 // one limb for good measure. This works very well for small exponents,
Chris@102 523 // but for larger exponents we add a few extra limbs to max_bits:
Chris@102 524 //
Chris@102 525 #ifdef BOOST_MP_STRESS_IO
Chris@102 526 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
Chris@102 527 #else
Chris@102 528 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits ? limb_bits - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits : 0) + limb_bits;
Chris@102 529 if(power10)
Chris@102 530 max_bits += (msb(boost::multiprecision::detail::abs(power10)) / 8) * limb_bits;
Chris@102 531 #endif
Chris@102 532 do
Chris@102 533 {
Chris@102 534 boost::int64_t error = 0;
Chris@102 535 boost::intmax_t calc_exp = 0;
Chris@102 536 //
Chris@102 537 // Our integer result is: bits() * 2^-shift * 5^power10
Chris@102 538 //
Chris@102 539 i = bits();
Chris@102 540 if(shift < 0)
Chris@102 541 {
Chris@102 542 if(power10 >= 0)
Chris@102 543 {
Chris@102 544 // We go straight to the answer with all integer arithmetic,
Chris@102 545 // the result is always exact and never needs rounding:
Chris@102 546 BOOST_ASSERT(power10 <= (boost::intmax_t)INT_MAX);
Chris@102 547 i <<= -shift;
Chris@102 548 if(power10)
Chris@102 549 i *= pow(cpp_int(5), static_cast<unsigned>(power10));
Chris@102 550 }
Chris@102 551 else if(power10 < 0)
Chris@102 552 {
Chris@102 553 cpp_int d;
Chris@102 554 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -power10, max_bits, error);
Chris@102 555 shift += calc_exp;
Chris@102 556 BOOST_ASSERT(shift < 0); // Must still be true!
Chris@102 557 i <<= -shift;
Chris@102 558 cpp_int r;
Chris@102 559 divide_qr(i, d, i, r);
Chris@102 560 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, i);
Chris@102 561 if(roundup < 0)
Chris@102 562 {
Chris@102 563 #ifdef BOOST_MP_STRESS_IO
Chris@102 564 max_bits += 32;
Chris@102 565 #else
Chris@102 566 max_bits *= 2;
Chris@102 567 #endif
Chris@102 568 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
Chris@102 569 continue;
Chris@102 570 }
Chris@102 571 }
Chris@102 572 }
Chris@102 573 else
Chris@102 574 {
Chris@102 575 //
Chris@102 576 // Our integer is bits() * 2^-shift * 10^power10
Chris@102 577 //
Chris@102 578 if(power10 > 0)
Chris@102 579 {
Chris@102 580 if(power10)
Chris@102 581 {
Chris@102 582 cpp_int t;
Chris@102 583 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), power10, max_bits, error);
Chris@102 584 calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(i, i, t, max_bits, error);
Chris@102 585 shift -= calc_exp;
Chris@102 586 }
Chris@102 587 if((shift < 0) || ((shift == 0) && error))
Chris@102 588 {
Chris@102 589 // We only get here if we were asked for a crazy number of decimal digits -
Chris@102 590 // more than are present in a 2^max_bits number.
Chris@102 591 #ifdef BOOST_MP_STRESS_IO
Chris@102 592 max_bits += 32;
Chris@102 593 #else
Chris@102 594 max_bits *= 2;
Chris@102 595 #endif
Chris@102 596 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
Chris@102 597 continue;
Chris@102 598 }
Chris@102 599 if(shift)
Chris@102 600 {
Chris@102 601 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(i, shift - 1, error);
Chris@102 602 if(roundup < 0)
Chris@102 603 {
Chris@102 604 #ifdef BOOST_MP_STRESS_IO
Chris@102 605 max_bits += 32;
Chris@102 606 #else
Chris@102 607 max_bits *= 2;
Chris@102 608 #endif
Chris@102 609 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
Chris@102 610 continue;
Chris@102 611 }
Chris@102 612 i >>= shift;
Chris@102 613 }
Chris@102 614 }
Chris@102 615 else
Chris@102 616 {
Chris@102 617 // We're right shifting, *and* dividing by 5^-power10,
Chris@102 618 // so 5^-power10 can never be that large or we'd simply
Chris@102 619 // get zero as a result, and that case is already handled above:
Chris@102 620 cpp_int r;
Chris@102 621 BOOST_ASSERT(-power10 < INT_MAX);
Chris@102 622 cpp_int d = pow(cpp_int(5), static_cast<unsigned>(-power10));
Chris@102 623 d <<= shift;
Chris@102 624 divide_qr(i, d, i, r);
Chris@102 625 r <<= 1;
Chris@102 626 int c = r.compare(d);
Chris@102 627 roundup = c < 0 ? 0 : c == 0 ? 1 : 2;
Chris@102 628 }
Chris@102 629 }
Chris@102 630 s = i.str(0, std::ios_base::fmtflags(0));
Chris@102 631 //
Chris@102 632 // Check if we got the right number of digits, this
Chris@102 633 // is really a test of whether we calculated the
Chris@102 634 // decimal exponent correctly:
Chris@102 635 //
Chris@102 636 boost::intmax_t digits_got = i ? static_cast<boost::intmax_t>(s.size()) : 0;
Chris@102 637 if(digits_got != digits_wanted)
Chris@102 638 {
Chris@102 639 base10_exp += digits_got - digits_wanted;
Chris@102 640 if(fixed)
Chris@102 641 digits_wanted = digits_got; // strange but true.
Chris@102 642 power10 = digits_wanted - base10_exp - 1;
Chris@102 643 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
Chris@102 644 if(fixed)
Chris@102 645 break;
Chris@102 646 roundup = 0;
Chris@102 647 }
Chris@102 648 else
Chris@102 649 break;
Chris@102 650 }
Chris@102 651 while(true);
Chris@102 652 //
Chris@102 653 // Check whether we need to round up: note that we could equally round up
Chris@102 654 // the integer /i/ above, but since we need to perform the rounding *after*
Chris@102 655 // the conversion to a string and the digit count check, we might as well
Chris@102 656 // do it here:
Chris@102 657 //
Chris@102 658 if((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1)))
Chris@102 659 {
Chris@102 660 boost::multiprecision::detail::round_string_up_at(s, static_cast<int>(s.size() - 1), base10_exp);
Chris@102 661 }
Chris@102 662
Chris@102 663 if(sign())
Chris@102 664 s.insert(static_cast<std::string::size_type>(0), 1, '-');
Chris@102 665
Chris@102 666 boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, false);
Chris@102 667 }
Chris@102 668 else
Chris@102 669 {
Chris@102 670 switch(exponent())
Chris@102 671 {
Chris@102 672 case exponent_zero:
Chris@102 673 s = "0";
Chris@102 674 boost::multiprecision::detail::format_float_string(s, 0, dig, f, true);
Chris@102 675 break;
Chris@102 676 case exponent_nan:
Chris@102 677 s = "nan";
Chris@102 678 break;
Chris@102 679 case exponent_infinity:
Chris@102 680 s = sign() ? "-inf" : f & std::ios_base::showpos ? "+inf" : "inf";
Chris@102 681 break;
Chris@102 682 }
Chris@102 683 }
Chris@102 684 return s;
Chris@102 685 }
Chris@102 686
Chris@102 687 }}} // namespaces
Chris@102 688
Chris@102 689 #endif
Chris@102 690