#ifndef BOOST_MP_CPP_BIN_FLOAT_IO_HPP
#define BOOST_MP_CPP_BIN_FLOAT_IO_HPP
+#include <boost/multiprecision/detail/no_exceptions_support.hpp>
+#include <boost/multiprecision/detail/assert.hpp>
+
namespace boost { namespace multiprecision {
namespace cpp_bf_io_detail {
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable : 4127) // conditional expression is constant
-#endif
-
//
// Multiplies a by b and shifts the result so it fits inside max_bits bits,
// returns by how much the result was shifted.
//
template <class I>
-inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b, I max_bits, boost::int64_t& error)
+inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b, I max_bits, std::int64_t& error)
{
result = a * b;
I gb = msb(result);
error = error ? error * 2 : 1;
if (rshift)
{
- BOOST_ASSERT(rshift < INT_MAX);
+ BOOST_MP_ASSERT(rshift < INT_MAX);
if (bit_test(result, static_cast<unsigned>(rshift - 1)))
{
if (lb == rshift - 1)
// to the right we are shifted.
//
template <class I>
-inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, boost::int64_t& error)
+inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, std::int64_t& error)
{
- BOOST_ASSERT(&result != &a);
+ BOOST_MP_ASSERT(&result != &a);
I exp = 0;
if (e == 1)
{
return exp;
}
-inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::int64_t error)
+inline int get_round_mode(const cpp_int& what, std::int64_t location, std::int64_t error)
{
//
// Can we round what at /location/, if the error in what is /error/ in
// 1: tie.
// 2: round up.
//
- BOOST_ASSERT(location >= 0);
- BOOST_ASSERT(location < INT_MAX);
- boost::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2;
- if (error_radius && ((int)msb(error_radius) >= location))
+ BOOST_MP_ASSERT(location >= 0);
+ BOOST_MP_ASSERT(location < INT_MAX);
+ std::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2;
+ if (error_radius && (static_cast<int>(msb(error_radius)) >= location))
return -1;
if (bit_test(what, static_cast<unsigned>(location)))
{
- if ((int)lsb(what) == location)
+ if (static_cast<int>(lsb(what)) == location)
return error ? -1 : 1; // Either a tie or can't round depending on whether we have any error
if (!error)
return 2; // no error, round up.
cpp_int t = what - error_radius;
- if ((int)lsb(t) >= location)
+ if (static_cast<int>(lsb(t)) >= location)
return -1;
return 2;
}
return 0;
}
-inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cpp_int& q)
+inline int get_round_mode(cpp_int& r, cpp_int& d, std::int64_t error, const cpp_int& q)
{
//
// Lets suppose we have an inexact division by d+delta, where the true
cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::operator=(const char* s)
{
cpp_int n;
- boost::intmax_t decimal_exp = 0;
- boost::intmax_t digits_seen = 0;
- static const boost::intmax_t max_digits_seen = 4 + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count * 301L) / 1000;
+ std::intmax_t decimal_exp = 0;
+ std::intmax_t digits_seen = 0;
+ constexpr const std::intmax_t max_digits_seen = 4 + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count * 301L) / 1000;
bool ss = false;
//
// Extract the sign:
if (*s && ((*s == 'e') || (*s == 'E')))
{
++s;
- boost::intmax_t e = 0;
+ std::intmax_t e = 0;
bool es = false;
if (*s && (*s == '-'))
{
//
// Oops unexpected input at the end of the number:
//
- BOOST_THROW_EXCEPTION(std::runtime_error("Unable to parse string as a valid floating point number."));
+ BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unable to parse string as a valid floating point number."));
}
if (n == 0)
{
return *this;
}
- static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
+ constexpr const std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
//
// Set our working precision - this is heuristic based, we want
// a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
// seems to be slightly slower in the *average* case:
//
#ifdef BOOST_MP_STRESS_IO
- boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
+ std::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
#else
- 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;
+ std::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;
#endif
- boost::int64_t error = 0;
- boost::intmax_t calc_exp = 0;
- boost::intmax_t final_exponent = 0;
+ std::int64_t error = 0;
+ std::intmax_t calc_exp = 0;
+ std::intmax_t final_exponent = 0;
if (decimal_exp >= 0)
{
}
else
t = n;
- final_exponent = (boost::int64_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp + calc_exp;
- int rshift = msb(t) - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
+ final_exponent = (std::int64_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp + calc_exp;
+ std::ptrdiff_t rshift = msb(t) - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
if (rshift > 0)
{
final_exponent += rshift;
}
else
{
- BOOST_ASSERT(!error);
+ BOOST_MP_ASSERT(!error);
}
if (final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
{
{
cpp_int d;
calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -decimal_exp, max_bits, error);
- int shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb(n) + msb(d);
+ std::ptrdiff_t shift = static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - msb(n) + msb(d);
final_exponent = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp - calc_exp;
if (shift > 0)
{
}
cpp_int q, r;
divide_qr(n, d, q, r);
- int gb = msb(q);
- BOOST_ASSERT((gb >= static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1));
+ std::ptrdiff_t gb = msb(q);
+ BOOST_MP_ASSERT((gb >= static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1));
//
// Check for rounding conditions we have to
// handle ourselves:
// Exactly the right number of bits, use the remainder to round:
roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, q);
}
- 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)))
+ else if (bit_test(q, gb - static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)) && (static_cast<int>(lsb(q)) == (gb - static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))))
{
// Too many bits in q and the bits in q indicate a tie, but we can break that using r,
// note that the radius of error in r is error/2 * q:
- int lshift = gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
+ std::ptrdiff_t lshift = gb - static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) + 1;
q >>= lshift;
final_exponent += static_cast<Exponent>(lshift);
- BOOST_ASSERT((msb(q) >= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
+ BOOST_MP_ASSERT((msb(q) >= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
if (error && (r < (error / 2) * q))
roundup = -1;
else if (error && (r + (error / 2) * q >= d))
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::str(std::streamsize dig, std::ios_base::fmtflags f) const
{
- if (dig == 0)
- dig = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max_digits10;
-
bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
bool fixed = !scientific && (f & std::ios_base::fixed);
+ if (dig == 0 && !fixed)
+ dig = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max_digits10;
+
std::string s;
if (exponent() <= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
{
// How far to left-shift in order to demormalise the mantissa:
- boost::intmax_t shift = (boost::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - (boost::intmax_t)exponent() - 1;
- boost::intmax_t digits_wanted = static_cast<int>(dig);
- 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()));
+ std::intmax_t shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - (std::intmax_t)exponent() - 1;
+ std::intmax_t digits_wanted = static_cast<int>(dig);
+ std::intmax_t base10_exp = exponent() >= 0 ? static_cast<std::intmax_t>(std::floor(0.30103 * exponent())) : static_cast<std::intmax_t>(std::ceil(0.30103 * exponent()));
//
// For fixed formatting we want /dig/ digits after the decimal point,
// so if the exponent is zero, allowing for the one digit before the
// power10 is the base10 exponent we need to multiply/divide by in order
// to convert our denormalised number to an integer with the right number of digits:
//
- boost::intmax_t power10 = digits_wanted - base10_exp - 1;
+ std::intmax_t power10 = digits_wanted - base10_exp - 1;
//
// If we calculate 5^power10 rather than 10^power10 we need to move
// 2^power10 into /shift/
shift -= power10;
cpp_int i;
int roundup = 0; // 0=no rounding, 1=tie, 2=up
- static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
+ constexpr const std::size_t limb_bits = sizeof(limb_type) * CHAR_BIT;
//
// Set our working precision - this is heuristic based, we want
// a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
// but for larger exponents we add a few extra limbs to max_bits:
//
#ifdef BOOST_MP_STRESS_IO
- boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
+ std::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
#else
- 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;
+ std::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;
if (power10)
max_bits += (msb(boost::multiprecision::detail::abs(power10)) / 8) * limb_bits;
#endif
do
{
- boost::int64_t error = 0;
- boost::intmax_t calc_exp = 0;
+ std::int64_t error = 0;
+ std::intmax_t calc_exp = 0;
//
// Our integer result is: bits() * 2^-shift * 5^power10
//
{
// We go straight to the answer with all integer arithmetic,
// the result is always exact and never needs rounding:
- BOOST_ASSERT(power10 <= (boost::intmax_t)INT_MAX);
+ BOOST_MP_ASSERT(power10 <= (std::intmax_t)INT_MAX);
i <<= -shift;
if (power10)
i *= pow(cpp_int(5), static_cast<unsigned>(power10));
cpp_int d;
calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -power10, max_bits, error);
shift += calc_exp;
- BOOST_ASSERT(shift < 0); // Must still be true!
+ BOOST_MP_ASSERT(shift < 0); // Must still be true!
i <<= -shift;
cpp_int r;
divide_qr(i, d, i, r);
#else
max_bits *= 2;
#endif
- shift = (boost::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
+ shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
continue;
}
}
#else
max_bits *= 2;
#endif
- shift = (boost::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
+ shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
continue;
}
if (shift)
#else
max_bits *= 2;
#endif
- shift = (boost::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
+ shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
continue;
}
i >>= shift;
// so 5^-power10 can never be that large or we'd simply
// get zero as a result, and that case is already handled above:
cpp_int r;
- BOOST_ASSERT(-power10 < INT_MAX);
+ BOOST_MP_ASSERT(-power10 < INT_MAX);
cpp_int d = pow(cpp_int(5), static_cast<unsigned>(-power10));
d <<= shift;
divide_qr(i, d, i, r);
// is really a test of whether we calculated the
// decimal exponent correctly:
//
- boost::intmax_t digits_got = i ? static_cast<boost::intmax_t>(s.size()) : 0;
+ std::intmax_t digits_got = i ? static_cast<std::intmax_t>(s.size()) : 0;
if (digits_got != digits_wanted)
{
base10_exp += digits_got - digits_wanted;
if (fixed)
digits_wanted = digits_got; // strange but true.
power10 = digits_wanted - base10_exp - 1;
- shift = (boost::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
+ shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
if (fixed)
break;
roundup = 0;
return s;
}
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
} // namespace backends
}} // namespace boost::multiprecision