update boost
This commit is contained in:
@@ -1,52 +1,52 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
||||
// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_MP_CPP_BIN_FLOAT_IO_HPP
|
||||
#define BOOST_MP_CPP_BIN_FLOAT_IO_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
|
||||
#include <boost/multiprecision/detail/no_exceptions_support.hpp>
|
||||
#include <boost/multiprecision/detail/assert.hpp>
|
||||
|
||||
namespace boost { namespace multiprecision {
|
||||
namespace cpp_bf_io_detail {
|
||||
|
||||
//
|
||||
// Multiplies a by b and shifts the result so it fits inside max_bits bits,
|
||||
// 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);
|
||||
I rshift = 0;
|
||||
if(gb > max_bits)
|
||||
using local_integral_type = I;
|
||||
|
||||
result = a * b;
|
||||
local_integral_type gb = static_cast<local_integral_type>(msb(result));
|
||||
local_integral_type rshift = 0;
|
||||
if (gb > max_bits)
|
||||
{
|
||||
rshift = gb - max_bits;
|
||||
I lb = lsb(result);
|
||||
local_integral_type lb = static_cast<local_integral_type>(lsb(result));
|
||||
int roundup = 0;
|
||||
// The error rate increases by the error of both a and b,
|
||||
// The error rate increases by the error of both a and b,
|
||||
// this may be overly pessimistic in many case as we're assuming
|
||||
// that a and b have the same level of uncertainty...
|
||||
if(lb < rshift)
|
||||
if (lb < rshift)
|
||||
error = error ? error * 2 : 1;
|
||||
if(rshift)
|
||||
if (rshift)
|
||||
{
|
||||
BOOST_ASSERT(rshift < INT_MAX);
|
||||
if(bit_test(result, static_cast<unsigned>(rshift - 1)))
|
||||
BOOST_MP_ASSERT(rshift < INT_MAX);
|
||||
if (bit_test(result, static_cast<unsigned>(rshift - 1)))
|
||||
{
|
||||
if(lb == rshift - 1)
|
||||
if (lb == rshift - 1)
|
||||
roundup = 1;
|
||||
else
|
||||
roundup = 2;
|
||||
}
|
||||
result >>= rshift;
|
||||
}
|
||||
if((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1)))
|
||||
if ((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1)))
|
||||
++result;
|
||||
}
|
||||
return rshift;
|
||||
@@ -56,20 +56,20 @@ inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b
|
||||
// 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)
|
||||
if (e == 1)
|
||||
{
|
||||
result = a;
|
||||
return exp;
|
||||
}
|
||||
else if(e == 2)
|
||||
else if (e == 2)
|
||||
{
|
||||
return restricted_multiply(result, a, a, max_bits, error);
|
||||
}
|
||||
else if(e == 3)
|
||||
else if (e == 3)
|
||||
{
|
||||
exp = restricted_multiply(result, a, a, max_bits, error);
|
||||
exp += restricted_multiply(result, result, a, max_bits, error);
|
||||
@@ -79,12 +79,12 @@ inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, boos
|
||||
exp = restricted_pow(result, a, p, max_bits, error);
|
||||
exp *= 2;
|
||||
exp += restricted_multiply(result, result, result, max_bits, error);
|
||||
if(e & 1)
|
||||
if (e & 1)
|
||||
exp += restricted_multiply(result, result, a, max_bits, error);
|
||||
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
|
||||
@@ -95,23 +95,23 @@ inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::i
|
||||
// 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 (bit_test(what, static_cast<unsigned>(location)))
|
||||
{
|
||||
if((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.
|
||||
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;
|
||||
}
|
||||
else if(error)
|
||||
else if (error)
|
||||
{
|
||||
cpp_int t = what + error_radius;
|
||||
return bit_test(t, static_cast<unsigned>(location)) ? -1 : 0;
|
||||
@@ -119,7 +119,7 @@ inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::i
|
||||
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
|
||||
@@ -146,18 +146,18 @@ inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cp
|
||||
//
|
||||
r <<= 1;
|
||||
int c = r.compare(d);
|
||||
if(c == 0)
|
||||
if (c == 0)
|
||||
return error ? -1 : 1;
|
||||
if(c > 0)
|
||||
if (c > 0)
|
||||
{
|
||||
if(error)
|
||||
if (error)
|
||||
{
|
||||
r -= error * q;
|
||||
return r.compare(d) > 0 ? 2 : -1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if(error)
|
||||
if (error)
|
||||
{
|
||||
r += error * q;
|
||||
return r.compare(d) < 0 ? 0 : -1;
|
||||
@@ -165,115 +165,115 @@ inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cp
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpp_bf_io_detail
|
||||
|
||||
namespace backends{
|
||||
namespace backends {
|
||||
|
||||
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
||||
cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::operator=(const char *s)
|
||||
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;
|
||||
bool ss = false;
|
||||
cpp_int n;
|
||||
std::intmax_t decimal_exp = 0;
|
||||
std::intmax_t digits_seen = 0;
|
||||
constexpr 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 == '-')
|
||||
if (*s == '-')
|
||||
{
|
||||
ss = true;
|
||||
++s;
|
||||
}
|
||||
else if(*s == '+')
|
||||
else if (*s == '+')
|
||||
++s;
|
||||
//
|
||||
// Special cases first:
|
||||
//
|
||||
if((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || (std::strcmp(s, "NAN") == 0))
|
||||
if ((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || (std::strcmp(s, "NAN") == 0))
|
||||
{
|
||||
return *this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
||||
}
|
||||
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))
|
||||
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))
|
||||
{
|
||||
*this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
||||
if(ss)
|
||||
if (ss)
|
||||
negate();
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// Digits before the point:
|
||||
//
|
||||
while(*s && (*s >= '0') && (*s <= '9'))
|
||||
while (*s && (*s >= '0') && (*s <= '9'))
|
||||
{
|
||||
n *= 10u;
|
||||
n += *s - '0';
|
||||
if(digits_seen || (*s != '0'))
|
||||
if (digits_seen || (*s != '0'))
|
||||
++digits_seen;
|
||||
++s;
|
||||
}
|
||||
// The decimal point (we really should localise this!!)
|
||||
if(*s && (*s == '.'))
|
||||
if (*s && (*s == '.'))
|
||||
++s;
|
||||
//
|
||||
// Digits after the point:
|
||||
//
|
||||
while(*s && (*s >= '0') && (*s <= '9'))
|
||||
while (*s && (*s >= '0') && (*s <= '9'))
|
||||
{
|
||||
n *= 10u;
|
||||
n += *s - '0';
|
||||
--decimal_exp;
|
||||
if(digits_seen || (*s != '0'))
|
||||
if (digits_seen || (*s != '0'))
|
||||
++digits_seen;
|
||||
++s;
|
||||
if(digits_seen > max_digits_seen)
|
||||
if (digits_seen > max_digits_seen)
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Digits we're skipping:
|
||||
//
|
||||
while(*s && (*s >= '0') && (*s <= '9'))
|
||||
while (*s && (*s >= '0') && (*s <= '9'))
|
||||
++s;
|
||||
//
|
||||
// See if there's an exponent:
|
||||
//
|
||||
if(*s && ((*s == 'e') || (*s == 'E')))
|
||||
if (*s && ((*s == 'e') || (*s == 'E')))
|
||||
{
|
||||
++s;
|
||||
boost::intmax_t e = 0;
|
||||
bool es = false;
|
||||
if(*s && (*s == '-'))
|
||||
std::intmax_t e = 0;
|
||||
bool es = false;
|
||||
if (*s && (*s == '-'))
|
||||
{
|
||||
es = true;
|
||||
++s;
|
||||
}
|
||||
else if(*s && (*s == '+'))
|
||||
else if (*s && (*s == '+'))
|
||||
++s;
|
||||
while(*s && (*s >= '0') && (*s <= '9'))
|
||||
while (*s && (*s >= '0') && (*s <= '9'))
|
||||
{
|
||||
e *= 10u;
|
||||
e += *s - '0';
|
||||
++s;
|
||||
}
|
||||
if(es)
|
||||
if (es)
|
||||
e = -e;
|
||||
decimal_exp += e;
|
||||
}
|
||||
if(*s)
|
||||
if (*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)
|
||||
if (n == 0)
|
||||
{
|
||||
// Result is necessarily zero:
|
||||
*this = static_cast<limb_type>(0u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
||||
constexpr 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
|
||||
@@ -286,37 +286,37 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
// 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)
|
||||
if (decimal_exp >= 0)
|
||||
{
|
||||
// Nice and simple, the result is an integer...
|
||||
do
|
||||
{
|
||||
cpp_int t;
|
||||
if(decimal_exp)
|
||||
if (decimal_exp)
|
||||
{
|
||||
calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), decimal_exp, max_bits, error);
|
||||
calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(t, t, n, max_bits, error);
|
||||
}
|
||||
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;
|
||||
if(rshift > 0)
|
||||
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 = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(msb(t)) - static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) + 1);
|
||||
if (rshift > 0)
|
||||
{
|
||||
final_exponent += rshift;
|
||||
int roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(t, rshift - 1, error);
|
||||
t >>= rshift;
|
||||
if((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1))
|
||||
if ((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1))
|
||||
++t;
|
||||
else if(roundup < 0)
|
||||
else if (roundup < 0)
|
||||
{
|
||||
#ifdef BOOST_MP_STRESS_IO
|
||||
max_bits += 32;
|
||||
@@ -329,14 +329,14 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(!error);
|
||||
BOOST_MP_ASSERT(!error);
|
||||
}
|
||||
if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
if (final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
{
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
||||
final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
||||
}
|
||||
else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
else if (final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
{
|
||||
// Underflow:
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
||||
@@ -344,15 +344,14 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
}
|
||||
else
|
||||
{
|
||||
exponent() = static_cast<Exponent>(final_exponent);
|
||||
exponent() = static_cast<Exponent>(final_exponent);
|
||||
final_exponent = 0;
|
||||
}
|
||||
copy_and_round(*this, t.backend());
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
} while (true);
|
||||
|
||||
if(ss != sign())
|
||||
if (ss != sign())
|
||||
negate();
|
||||
}
|
||||
else
|
||||
@@ -364,49 +363,49 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
do
|
||||
{
|
||||
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);
|
||||
final_exponent = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp - calc_exp;
|
||||
if(shift > 0)
|
||||
calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -decimal_exp, max_bits, error);
|
||||
const std::ptrdiff_t shift = static_cast<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - static_cast<std::ptrdiff_t>(msb(n)) + static_cast<std::ptrdiff_t>(msb(d)));
|
||||
final_exponent = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp - calc_exp;
|
||||
if (shift > 0)
|
||||
{
|
||||
n <<= shift;
|
||||
final_exponent -= static_cast<Exponent>(shift);
|
||||
}
|
||||
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 = static_cast<std::ptrdiff_t>(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:
|
||||
//
|
||||
int roundup = 0;
|
||||
if(gb == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
||||
if (gb == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
||||
{
|
||||
// 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, static_cast<std::size_t>(gb - static_cast<std::ptrdiff_t>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))) && (static_cast<std::ptrdiff_t>(lsb(q)) == static_cast<std::ptrdiff_t>(gb - static_cast<std::ptrdiff_t>(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));
|
||||
if(error && (r < (error / 2) * q))
|
||||
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))
|
||||
else if (error && (r + (error / 2) * q >= d))
|
||||
roundup = -1;
|
||||
else
|
||||
roundup = r ? 2 : 1;
|
||||
}
|
||||
else if(error && (((error / 2) * q + r >= d) || (r < (error / 2) * q)))
|
||||
else if (error && (((error / 2) * q + r >= d) || (r < (error / 2) * q)))
|
||||
{
|
||||
// We might have been rounding up, or got the wrong quotient: can't tell!
|
||||
roundup = -1;
|
||||
}
|
||||
if(roundup < 0)
|
||||
if (roundup < 0)
|
||||
{
|
||||
#ifdef BOOST_MP_STRESS_IO
|
||||
max_bits += 32;
|
||||
@@ -414,22 +413,22 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
max_bits *= 2;
|
||||
#endif
|
||||
error = 0;
|
||||
if(shift > 0)
|
||||
if (shift > 0)
|
||||
{
|
||||
n >>= shift;
|
||||
final_exponent += static_cast<Exponent>(shift);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if((roundup == 2) || ((roundup == 1) && q.backend().limbs()[0] & 1))
|
||||
else if ((roundup == 2) || ((roundup == 1) && q.backend().limbs()[0] & 1))
|
||||
++q;
|
||||
if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
if (final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
{
|
||||
// Overflow:
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
||||
final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
||||
}
|
||||
else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
else if (final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
{
|
||||
// Underflow:
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
||||
@@ -437,32 +436,31 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
}
|
||||
else
|
||||
{
|
||||
exponent() = static_cast<Exponent>(final_exponent);
|
||||
exponent() = static_cast<Exponent>(final_exponent);
|
||||
final_exponent = 0;
|
||||
}
|
||||
copy_and_round(*this, q.backend());
|
||||
if(ss != sign())
|
||||
if (ss != sign())
|
||||
negate();
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
} while (true);
|
||||
}
|
||||
//
|
||||
// Check for scaling and/or over/under-flow:
|
||||
//
|
||||
final_exponent += exponent();
|
||||
if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
if (final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
||||
{
|
||||
// Overflow:
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
||||
bits() = limb_type(0);
|
||||
bits() = limb_type(0);
|
||||
}
|
||||
else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
else if (final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
||||
{
|
||||
// Underflow:
|
||||
exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
||||
bits() = limb_type(0);
|
||||
sign() = 0;
|
||||
bits() = limb_type(0);
|
||||
sign() = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -474,34 +472,34 @@ cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float
|
||||
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);
|
||||
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)
|
||||
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
|
||||
// decimal point, we want 1 + dig digits etc.
|
||||
//
|
||||
if(fixed)
|
||||
if (fixed)
|
||||
digits_wanted += 1 + base10_exp;
|
||||
if(scientific)
|
||||
if (scientific)
|
||||
digits_wanted += 1;
|
||||
if(digits_wanted < -1)
|
||||
if (digits_wanted < -1)
|
||||
{
|
||||
// Fixed precision, no significant digits, and nothing to round!
|
||||
s = "0";
|
||||
if(sign())
|
||||
if (sign())
|
||||
s.insert(static_cast<std::string::size_type>(0), 1, '-');
|
||||
boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, true);
|
||||
return s;
|
||||
@@ -510,15 +508,15 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
// 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;
|
||||
cpp_int i;
|
||||
int roundup = 0; // 0=no rounding, 1=tie, 2=up
|
||||
constexpr 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
|
||||
@@ -529,49 +527,54 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
// 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;
|
||||
if(power10)
|
||||
max_bits += (msb(boost::multiprecision::detail::abs(power10)) / 8) * 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)
|
||||
{
|
||||
const std::uintmax_t abs_power10 = static_cast<std::uintmax_t>(boost::multiprecision::detail::abs(power10));
|
||||
const std::intmax_t msb_div8 = static_cast<std::intmax_t>(msb(abs_power10) / 8u);
|
||||
|
||||
max_bits += (msb_div8 * static_cast<std::intmax_t>(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
|
||||
//
|
||||
i = bits();
|
||||
if(shift < 0)
|
||||
if (shift < 0)
|
||||
{
|
||||
if(power10 >= 0)
|
||||
if (power10 >= 0)
|
||||
{
|
||||
// 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)
|
||||
if (power10)
|
||||
i *= pow(cpp_int(5), static_cast<unsigned>(power10));
|
||||
}
|
||||
else if(power10 < 0)
|
||||
else if (power10 < 0)
|
||||
{
|
||||
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);
|
||||
roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, i);
|
||||
if(roundup < 0)
|
||||
if (roundup < 0)
|
||||
{
|
||||
#ifdef BOOST_MP_STRESS_IO
|
||||
max_bits += 32;
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -581,16 +584,16 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
//
|
||||
// Our integer is bits() * 2^-shift * 10^power10
|
||||
//
|
||||
if(power10 > 0)
|
||||
if (power10 > 0)
|
||||
{
|
||||
if(power10)
|
||||
if (power10)
|
||||
{
|
||||
cpp_int t;
|
||||
calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), power10, max_bits, error);
|
||||
calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(i, i, t, max_bits, error);
|
||||
shift -= calc_exp;
|
||||
}
|
||||
if((shift < 0) || ((shift == 0) && error))
|
||||
if ((shift < 0) || ((shift == 0) && error))
|
||||
{
|
||||
// We only get here if we were asked for a crazy number of decimal digits -
|
||||
// more than are present in a 2^max_bits number.
|
||||
@@ -599,20 +602,20 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
#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)
|
||||
if (shift)
|
||||
{
|
||||
roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(i, shift - 1, error);
|
||||
if(roundup < 0)
|
||||
if (roundup < 0)
|
||||
{
|
||||
#ifdef BOOST_MP_STRESS_IO
|
||||
max_bits += 32;
|
||||
#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;
|
||||
@@ -624,12 +627,12 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
// 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);
|
||||
r <<= 1;
|
||||
int c = r.compare(d);
|
||||
int c = r.compare(d);
|
||||
roundup = c < 0 ? 0 : c == 0 ? 1 : 2;
|
||||
}
|
||||
}
|
||||
@@ -639,41 +642,40 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
// 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;
|
||||
if(digits_got != digits_wanted)
|
||||
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.
|
||||
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;
|
||||
if(fixed)
|
||||
shift = (std::intmax_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
|
||||
if (fixed)
|
||||
break;
|
||||
roundup = 0;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while(true);
|
||||
} while (true);
|
||||
//
|
||||
// Check whether we need to round up: note that we could equally round up
|
||||
// the integer /i/ above, but since we need to perform the rounding *after*
|
||||
// the conversion to a string and the digit count check, we might as well
|
||||
// do it here:
|
||||
//
|
||||
if((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1)))
|
||||
if ((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1)))
|
||||
{
|
||||
boost::multiprecision::detail::round_string_up_at(s, static_cast<int>(s.size() - 1), base10_exp);
|
||||
}
|
||||
|
||||
if(sign())
|
||||
if (sign())
|
||||
s.insert(static_cast<std::string::size_type>(0), 1, '-');
|
||||
|
||||
boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(exponent())
|
||||
switch (exponent())
|
||||
{
|
||||
case exponent_zero:
|
||||
s = sign() ? "-0" : f & std::ios_base::showpos ? "+0" : "0";
|
||||
@@ -690,11 +692,7 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}}} // namespaces
|
||||
} // namespace backends
|
||||
}} // namespace boost::multiprecision
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
||||
// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_MULTIPRECISION_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
|
||||
#define BOOST_MULTIPRECISION_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
|
||||
#ifndef BOOST_MP_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
|
||||
#define BOOST_MP_CPP_BIN_FLOAT_TRANSCENDENTAL_HPP
|
||||
|
||||
namespace boost{ namespace multiprecision{ namespace backends{
|
||||
#include <boost/multiprecision/detail/assert.hpp>
|
||||
|
||||
namespace boost { namespace multiprecision { namespace backends {
|
||||
|
||||
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
||||
void eval_exp_taylor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
||||
void eval_exp_taylor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
||||
{
|
||||
static const int bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
|
||||
constexpr std::ptrdiff_t bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
|
||||
//
|
||||
// Taylor series for small argument, note returns exp(x) - 1:
|
||||
//
|
||||
@@ -20,19 +22,19 @@ void eval_exp_taylor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE,
|
||||
denom = limb_type(1);
|
||||
eval_add(res, num);
|
||||
|
||||
for(unsigned k = 2; ; ++k)
|
||||
for (std::size_t k = 2;; ++k)
|
||||
{
|
||||
eval_multiply(denom, k);
|
||||
eval_multiply(num, arg);
|
||||
eval_divide(t, num, denom);
|
||||
eval_add(res, t);
|
||||
if(eval_is_zero(t) || (res.exponent() - bits > t.exponent()))
|
||||
if (eval_is_zero(t) || (res.exponent() - bits > t.exponent()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
||||
void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
||||
void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
|
||||
{
|
||||
//
|
||||
// This is based on MPFR's method, let:
|
||||
@@ -60,36 +62,36 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
|
||||
// Then add the final 1 at the end, given that e0 is small, this effectively wipes
|
||||
// out the error in the last step.
|
||||
//
|
||||
using default_ops::eval_multiply;
|
||||
using default_ops::eval_subtract;
|
||||
using default_ops::eval_add;
|
||||
using default_ops::eval_convert_to;
|
||||
using default_ops::eval_increment;
|
||||
using default_ops::eval_multiply;
|
||||
using default_ops::eval_subtract;
|
||||
|
||||
int type = eval_fpclassify(arg);
|
||||
int type = eval_fpclassify(arg);
|
||||
bool isneg = eval_get_sign(arg) < 0;
|
||||
if(type == (int)FP_NAN)
|
||||
if (type == static_cast<int>(FP_NAN))
|
||||
{
|
||||
res = arg;
|
||||
res = arg;
|
||||
errno = EDOM;
|
||||
return;
|
||||
}
|
||||
else if(type == (int)FP_INFINITE)
|
||||
else if (type == static_cast<int>(FP_INFINITE))
|
||||
{
|
||||
res = arg;
|
||||
if(isneg)
|
||||
if (isneg)
|
||||
res = limb_type(0u);
|
||||
else
|
||||
else
|
||||
res = arg;
|
||||
return;
|
||||
}
|
||||
else if(type == (int)FP_ZERO)
|
||||
else if (type == static_cast<int>(FP_ZERO))
|
||||
{
|
||||
res = limb_type(1);
|
||||
return;
|
||||
}
|
||||
cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> t, n;
|
||||
if(isneg)
|
||||
if (isneg)
|
||||
{
|
||||
t = arg;
|
||||
t.negate();
|
||||
@@ -112,7 +114,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
|
||||
eval_increment(n);
|
||||
t = limb_type(0);
|
||||
}
|
||||
if(eval_get_sign(t) < 0)
|
||||
if (eval_get_sign(t) < 0)
|
||||
{
|
||||
// There are some very rare cases where arg/ln2 is an integer, and the subsequent multiply
|
||||
// rounds up, in that situation t ends up negative at this point which breaks our invariants below:
|
||||
@@ -129,7 +131,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0);
|
||||
BOOST_MP_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0);
|
||||
|
||||
k = nn ? Exponent(1) << (msb(nn) / 2) : 0;
|
||||
k = (std::min)(k, (Exponent)(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count / 4));
|
||||
@@ -139,7 +141,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
|
||||
//
|
||||
// Square 1 + res k times:
|
||||
//
|
||||
for(Exponent s = 0; s < k; ++s)
|
||||
for (Exponent s = 0; s < k; ++s)
|
||||
{
|
||||
t.swap(res);
|
||||
eval_multiply(res, t, t);
|
||||
@@ -150,7 +152,6 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
|
||||
eval_ldexp(res, res, nn);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
}}} // namespace boost::multiprecision::backends
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user