summaryrefslogtreecommitdiff
path: root/boost/multiprecision
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:41:18 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:43:11 +0900
commitf763a99a501650eff2c60288aa6f10ef916d769e (patch)
tree02af7e13f9a38c888ebf340fe764cbe7dae99da9 /boost/multiprecision
parent5cde13f21d36c7224b0e13d11c4b49379ae5210d (diff)
downloadboost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.gz
boost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.bz2
boost-f763a99a501650eff2c60288aa6f10ef916d769e.zip
Imported Upstream version 1.62.0upstream/1.62.0
Change-Id: I9d4c1ddb7b7d8f0069217ecc582700f9fda6dd4c Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/multiprecision')
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp203
-rw-r--r--boost/multiprecision/cpp_bin_float/io.hpp12
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp38
-rw-r--r--boost/multiprecision/cpp_int.hpp46
-rw-r--r--boost/multiprecision/cpp_int/add.hpp21
-rw-r--r--boost/multiprecision/cpp_int/bitwise.hpp1
-rw-r--r--boost/multiprecision/cpp_int/divide.hpp8
-rw-r--r--boost/multiprecision/cpp_int/import_export.hpp8
-rw-r--r--boost/multiprecision/cpp_int/limits.hpp8
-rw-r--r--boost/multiprecision/cpp_int/misc.hpp78
-rw-r--r--boost/multiprecision/cpp_int/multiply.hpp57
-rw-r--r--boost/multiprecision/debug_adaptor.hpp33
-rw-r--r--boost/multiprecision/detail/big_lanczos.hpp4
-rw-r--r--boost/multiprecision/detail/default_ops.hpp151
-rw-r--r--boost/multiprecision/detail/functions/constants.hpp33
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp43
-rw-r--r--boost/multiprecision/detail/functions/trig.hpp58
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp23
-rw-r--r--boost/multiprecision/detail/number_base.hpp66
-rw-r--r--boost/multiprecision/detail/ublas_interop.hpp12
-rw-r--r--boost/multiprecision/float128.hpp27
-rw-r--r--boost/multiprecision/gmp.hpp211
-rw-r--r--boost/multiprecision/logged_adaptor.hpp22
-rw-r--r--boost/multiprecision/miller_rabin.hpp2
-rw-r--r--boost/multiprecision/mpfi.hpp160
-rw-r--r--boost/multiprecision/mpfr.hpp249
-rw-r--r--boost/multiprecision/number.hpp64
-rw-r--r--boost/multiprecision/rational_adaptor.hpp10
-rw-r--r--boost/multiprecision/tommath.hpp11
-rw-r--r--boost/multiprecision/traits/explicit_conversion.hpp92
30 files changed, 1496 insertions, 255 deletions
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index 92b73c5715..453a406f28 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -122,7 +122,7 @@ public:
{
case FP_ZERO:
m_data = limb_type(0);
- m_sign = false;
+ m_sign = f.sign();
m_exponent = exponent_zero;
break;
case FP_NAN:
@@ -164,7 +164,7 @@ public:
{
case FP_ZERO:
m_data = limb_type(0);
- m_sign = false;
+ m_sign = ((boost::math::signbit)(f) > 0);
m_exponent = exponent_zero;
return *this;
case FP_NAN:
@@ -232,7 +232,7 @@ public:
{
case FP_ZERO:
m_data = limb_type(0);
- m_sign = false;
+ m_sign = ((boost::math::signbit)(f) > 0);
m_exponent = exponent_zero;
return *this;
case FP_NAN:
@@ -279,12 +279,12 @@ public:
{
m_data = limb_type(0u);
m_exponent = exponent_zero;
- m_sign = false;
+ m_sign = ((boost::math::signbit)(f) > 0);
}
else if(eval_get_sign(m_data) == 0)
{
m_exponent = exponent_zero;
- m_sign = false;
+ m_sign = ((boost::math::signbit)(f) > 0);
}
return *this;
}
@@ -335,14 +335,14 @@ public:
void negate()
{
- if((m_exponent != exponent_zero) && (m_exponent != exponent_nan))
+ if(m_exponent != exponent_nan)
m_sign = !m_sign;
}
int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT
{
if(m_sign != o.m_sign)
- return m_sign ? -1 : 1;
+ return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1;
int result;
if(m_exponent == exponent_nan)
return -1;
@@ -476,26 +476,38 @@ inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
// Underflow:
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
res.bits() = static_cast<limb_type>(0u);
- res.sign() = false;
}
}
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
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)
{
+ if(a.exponent() < b.exponent())
+ {
+ bool s = a.sign();
+ do_eval_add(res, b, a);
+ if(res.sign() != s)
+ res.negate();
+ return;
+ }
+
using default_ops::eval_add;
using default_ops::eval_bit_test;
+ typedef typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type exponent_type;
+
typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
// Special cases first:
switch(a.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ {
+ bool s = a.sign();
res = b;
- if(res.sign())
- res.negate();
+ res.sign() = s;
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
res = b;
@@ -520,32 +532,22 @@ inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
res = b;
return; // result is a NaN.
}
-
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
+
+ BOOST_STATIC_ASSERT(boost::integer_traits<exponent_type>::const_max - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent);
+
bool s = a.sign();
- if(e_diff >= 0)
+ dt = a.bits();
+ if(a.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
{
- dt = a.bits();
- if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
- {
- eval_left_shift(dt, e_diff);
- res.exponent() = a.exponent() - e_diff;
- eval_add(dt, b.bits());
- }
- else
- res.exponent() = a.exponent();
+ res.exponent() = a.exponent();
}
else
{
- dt= b.bits();
- if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
- {
- eval_left_shift(dt, -e_diff);
- res.exponent() = b.exponent() + e_diff;
- eval_add(dt, a.bits());
- }
- else
- res.exponent() = b.exponent();
+ exponent_type e_diff = a.exponent() - b.exponent();
+ BOOST_ASSERT(e_diff >= 0);
+ eval_left_shift(dt, e_diff);
+ res.exponent() = a.exponent() - e_diff;
+ eval_add(dt, b.bits());
}
copy_and_round(res, dt);
@@ -570,8 +572,9 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
else
{
+ bool s = a.sign();
res = b;
- if(!res.sign())
+ if(res.sign() == s)
res.negate();
}
return;
@@ -592,7 +595,7 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
- res.sign() = true;
+ res.sign() = !a.sign();
res.bits() = static_cast<limb_type>(0u);
return; // result is a NaN.
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
@@ -600,13 +603,13 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
return; // result is still a NaN.
}
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
bool s = a.sign();
- if((e_diff > 0) || ((e_diff == 0) && a.bits().compare(b.bits()) >= 0))
+ if((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0))
{
dt = a.bits();
- if(e_diff <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ if(a.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
{
+ typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
eval_left_shift(dt, e_diff);
res.exponent() = a.exponent() - e_diff;
eval_subtract(dt, b.bits());
@@ -617,8 +620,9 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
else
{
dt = b.bits();
- if(-e_diff <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
+ if(b.exponent() <= a.exponent() + (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
{
+ typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
eval_left_shift(dt, -e_diff);
res.exponent() = b.exponent() + e_diff;
eval_subtract(dt, a.bits());
@@ -674,11 +678,19 @@ inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
switch(a.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ {
if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
res = b;
+ else if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity)
+ res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
else
+ {
+ bool s = a.sign() != b.sign();
res = a;
+ res.sign() = s;
+ }
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
switch(b.exponent())
{
@@ -689,7 +701,9 @@ inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
res = b;
break;
default:
+ bool s = a.sign() != b.sign();
res = a;
+ res.sign() = s;
break;
}
return;
@@ -699,7 +713,9 @@ inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
}
if(b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
{
+ bool s = a.sign() != b.sign();
res = b;
+ res.sign() = s;
return;
}
if((a.exponent() > 0) && (b.exponent() > 0))
@@ -707,8 +723,9 @@ inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
{
// We will certainly overflow:
+ bool s = a.sign() != b.sign();
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
- res.sign() = a.sign() != b.sign();
+ res.sign() = s;
res.bits() = static_cast<limb_type>(0u);
return;
}
@@ -719,7 +736,7 @@ inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent,
{
// We will certainly underflow:
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
- res.sign() = false;
+ res.sign() = a.sign() != b.sign();
res.bits() = static_cast<limb_type>(0u);
return;
}
@@ -749,8 +766,12 @@ inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_f
switch(a.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ {
+ bool s = a.sign();
res = a;
+ res.sign() = s;
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
if(b == 0)
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
@@ -811,6 +832,7 @@ inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
switch(u.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ {
switch(v.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
@@ -818,9 +840,13 @@ inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
return;
}
+ bool s = u.sign() != v.sign();
res = u;
+ res.sign() = s;
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+ {
switch(v.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
@@ -828,8 +854,11 @@ inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
return;
}
+ bool s = u.sign() != v.sign();
res = u;
+ res.sign() = s;
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
return;
@@ -846,7 +875,7 @@ inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
res.bits() = limb_type(0);
- res.sign() = false;
+ res.sign() = u.sign() != v.sign();
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
@@ -869,6 +898,29 @@ inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, Mi
//
// We can set the exponent and sign of the result up front:
//
+ if((v.exponent() < 0) && (u.exponent() > 0))
+ {
+ // Check for overflow:
+ if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + v.exponent() < u.exponent() - 1)
+ {
+ res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
+ res.sign() = u.sign() != v.sign();
+ res.bits() = static_cast<limb_type>(0u);
+ return;
+ }
+ }
+ else if((v.exponent() > 0) && (u.exponent() < 0))
+ {
+ // Check for underflow:
+ if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent + v.exponent() > u.exponent())
+ {
+ // We will certainly underflow:
+ res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
+ res.sign() = u.sign() != v.sign();
+ res.bits() = static_cast<limb_type>(0u);
+ return;
+ }
+ }
res.exponent() = u.exponent() - v.exponent() - 1;
res.sign() = u.sign() != v.sign();
//
@@ -949,13 +1001,17 @@ inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_flo
switch(u.exponent())
{
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ {
if(v == 0)
{
res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
return;
}
+ bool s = u.sign() != (v < 0);
res = u;
+ res.sign() = s;
return;
+ }
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
res = u;
return;
@@ -1074,10 +1130,15 @@ inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Expon
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
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)
{
- return (a.exponent() == b.exponent())
- && (a.sign() == b.sign())
- && (a.bits().compare(b.bits()) == 0)
- && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
+ if(a.exponent() == b.exponent())
+ {
+ if(a.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
+ return true;
+ return (a.sign() == b.sign())
+ && (a.bits().compare(b.bits()) == 0)
+ && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
+ }
+ return false;
}
template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
@@ -1160,22 +1221,25 @@ inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_con
//
// Perform rounding first, then afterwards extract the digits:
//
- cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> arg(original_arg);
+ typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
+ conv_type arg(original_arg);
switch(arg.exponent())
{
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
+ case conv_type::exponent_zero:
*res = 0;
+ if(arg.sign())
+ *res = -*res;
return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
+ case conv_type::exponent_nan:
*res = std::numeric_limits<Float>::quiet_NaN();
return;
- case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
+ case conv_type::exponent_infinity:
*res = (std::numeric_limits<Float>::infinity)();
if(arg.sign())
*res = -*res;
return;
}
- typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e = arg.exponent();
+ typename conv_type::exponent_type e = arg.exponent();
e -= cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - 1;
*res = std::ldexp(static_cast<Float>(*arg.bits().limbs()), e);
for(unsigned i = 1; i < arg.bits().size(); ++i)
@@ -1314,7 +1378,10 @@ inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
res = arg;
return;
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
- res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
+ if(arg.sign())
+ res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
+ else
+ res = arg;
return;
}
if(arg.sign())
@@ -1423,6 +1490,16 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
eval_left_shift(res.bits(), shift);
}
+template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
+inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
+{
+ std::size_t result = hash_value(val.bits());
+ boost::hash_combine(result, val.exponent());
+ boost::hash_combine(result, val.sign());
+ return result;
+}
+
+
} // namespace backends
#ifdef BOOST_NO_SFINAE_EXPR
@@ -1459,7 +1536,31 @@ typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::
typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
-}} // namespaces
+} // namespace multiprecision
+
+namespace math {
+
+ template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& arg)
+ {
+ return arg.backend().sign();
+ }
+
+ template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
+ copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
+ const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
+ const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& b)
+ {
+ boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> res(a);
+ res.backend().sign() = b.backend().sign();
+ return res;
+ }
+
+
+} // namespace math
+
+} // namespace boost
#include <boost/multiprecision/cpp_bin_float/io.hpp>
#include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
diff --git a/boost/multiprecision/cpp_bin_float/io.hpp b/boost/multiprecision/cpp_bin_float/io.hpp
index 88d5ddd053..630d651d9d 100644
--- a/boost/multiprecision/cpp_bin_float/io.hpp
+++ b/boost/multiprecision/cpp_bin_float/io.hpp
@@ -8,6 +8,12 @@
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.
@@ -670,7 +676,7 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
switch(exponent())
{
case exponent_zero:
- s = "0";
+ s = sign() ? "-0" : f & std::ios_base::showpos ? "+0" : "0";
boost::multiprecision::detail::format_float_string(s, 0, dig, f, true);
break;
case exponent_nan:
@@ -684,6 +690,10 @@ std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::s
return s;
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
}}} // namespaces
#endif
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index 057095e2b4..ee14becf5d 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -25,6 +25,7 @@
#include <boost/array.hpp>
#endif
#include <boost/cstdint.hpp>
+#include <boost/functional/hash_fwd.hpp>
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/detail/big_lanczos.hpp>
#include <boost/multiprecision/detail/dynamic_array.hpp>
@@ -257,6 +258,17 @@ public:
cpp_dec_float(const double mantissa, const ExponentType exponent);
+ std::size_t hash()const
+ {
+ std::size_t result = 0;
+ for(int i = 0; i < prec_elem; ++i)
+ boost::hash_combine(result, data[i]);
+ boost::hash_combine(result, exp);
+ boost::hash_combine(result, neg);
+ boost::hash_combine(result, fpclass);
+ return result;
+ }
+
// Specific special values.
static const cpp_dec_float& nan()
{
@@ -948,6 +960,18 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
template <unsigned Digits10, class ExponentType, class Allocator>
cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator/=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v)
{
+ if(iszero())
+ {
+ if((v.isnan)())
+ {
+ return *this = v;
+ }
+ else if(v.iszero())
+ {
+ return *this = nan();
+ }
+ }
+
const bool u_and_v_are_finite_and_identical = ( (isfinite)()
&& (fpclass == v.fpclass)
&& (exp == v.exp)
@@ -966,14 +990,6 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
}
else
{
- if(iszero())
- {
- if((v.isnan)() || v.iszero())
- {
- return *this = v;
- }
- return *this;
- }
cpp_dec_float t(v);
t.calculate_inv();
return operator*=(t);
@@ -2957,6 +2973,12 @@ inline int eval_get_sign(const cpp_dec_float<Digits10, ExponentType, Allocator>&
return val.iszero() ? 0 : val.isneg() ? -1 : 1;
}
+template <unsigned Digits10, class ExponentType, class Allocator>
+inline std::size_t hash_value(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
+{
+ return val.hash();
+}
+
} // namespace backends
using boost::multiprecision::backends::cpp_dec_float;
diff --git a/boost/multiprecision/cpp_int.hpp b/boost/multiprecision/cpp_int.hpp
index b8681677e2..c348020d40 100644
--- a/boost/multiprecision/cpp_int.hpp
+++ b/boost/multiprecision/cpp_int.hpp
@@ -34,9 +34,10 @@ namespace backends{
#ifdef BOOST_MSVC
-// warning C4127: conditional expression is constant
#pragma warning(push)
-#pragma warning(disable:4127 4351 4293 4996 4307 4702 6285)
+#pragma warning(disable:4307) // integral constant overflow (oveflow is in a branch not taken when it would overflow)
+#pragma warning(disable:4127) // conditional expression is constant
+#pragma warning(disable:4702) // Unreachable code (reachability depends on template params)
#endif
template <unsigned MinBits = 0, unsigned MaxBits = 0, boost::multiprecision::cpp_integer_type SignType = signed_magnitude, cpp_int_check_type Checked = unchecked, class Allocator = typename mpl::if_c<MinBits && (MinBits == MaxBits), void, std::allocator<limb_type> >::type >
@@ -226,7 +227,7 @@ public:
: m_data(i), m_limbs(1), m_sign(false), m_internal(true) { }
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT
: m_data(i), m_limbs(1), m_sign(i < 0), m_internal(true) { }
-#if defined(BOOST_LITTLE_ENDIAN)
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
: m_data(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false), m_internal(true) { }
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
@@ -444,7 +445,7 @@ public:
: m_wrapper(i), m_limbs(1), m_sign(false) {}
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_limb_type i)BOOST_NOEXCEPT
: m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(i)) : i)), m_limbs(1), m_sign(i < 0) {}
-#if defined(BOOST_LITTLE_ENDIAN)
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
: m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1), m_sign(false) {}
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(signed_double_limb_type i)BOOST_NOEXCEPT
@@ -595,7 +596,7 @@ public:
: m_wrapper(i), m_limbs(1) {}
BOOST_MP_FORCEINLINE cpp_int_base(signed_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
: m_wrapper(limb_type(i < 0 ? static_cast<limb_type>(-static_cast<signed_double_limb_type>(i)) : i)), m_limbs(1) { if(i < 0) negate(); }
-#ifdef BOOST_LITTLE_ENDIAN
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(double_limb_type i)BOOST_NOEXCEPT
: m_wrapper(i), m_limbs(i > max_limb_value ? 2 : 1) {}
BOOST_MP_FORCEINLINE cpp_int_base(signed_double_limb_type i)BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
@@ -773,10 +774,10 @@ public:
//
template <class SI>
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast<local_limb_type>(i)& limb_mask), m_sign(i < 0) {}
+ : m_data(i < 0 ? static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0) {}
template <class SI>
BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
- : m_data(i < 0 ? (static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast<local_limb_type>(i)& limb_mask), m_sign(i < 0)
+ : m_data(i < 0 ? (static_cast<local_limb_type>(static_cast<typename make_unsigned<SI>::type>(boost::multiprecision::detail::unsigned_abs(i)) & limb_mask)) : static_cast<local_limb_type>(i & limb_mask)), m_sign(i < 0)
{ check_in_range(i); }
template <class UI>
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked)>::type const* = 0) BOOST_NOEXCEPT
@@ -914,6 +915,20 @@ public:
//
// Direct construction:
//
+#ifdef __MSVC_RUNTIME_CHECKS
+ template <class SI>
+ BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
+ : m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i & limb_mask)) & limb_mask : static_cast<local_limb_type>(i & limb_mask)) {}
+ template <class SI>
+ BOOST_MP_FORCEINLINE cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<SI>())))
+ : m_data(i < 0 ? 1 + ~static_cast<local_limb_type>(-i & limb_mask) : static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
+ template <class UI>
+ BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
+ : m_data(static_cast<local_limb_type>(i & limb_mask)) {}
+ template <class UI>
+ BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
+ : m_data(static_cast<local_limb_type>(i & limb_mask)) { check_in_range(i); }
+#else
template <class SI>
BOOST_MP_FORCEINLINE BOOST_CONSTEXPR cpp_int_base(SI i, typename boost::enable_if_c<is_signed<SI>::value && (Checked == unchecked) >::type const* = 0) BOOST_NOEXCEPT
: m_data(i < 0 ? (1 + ~static_cast<local_limb_type>(-i)) & limb_mask : static_cast<local_limb_type>(i) & limb_mask) {}
@@ -926,6 +941,7 @@ public:
template <class UI>
BOOST_MP_FORCEINLINE cpp_int_base(UI i, typename boost::enable_if_c<is_unsigned<UI>::value && (Checked == checked) >::type const* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<cpp_int_base>().check_in_range(std::declval<UI>())))
: m_data(static_cast<local_limb_type>(i)) { check_in_range(i); }
+#endif
template <class F>
BOOST_MP_FORCEINLINE cpp_int_base(F i, typename boost::enable_if<is_floating_point<F> >::type const* = 0) BOOST_MP_NOEXCEPT_IF((Checked == unchecked))
: m_data(static_cast<local_limb_type>(std::fabs(i)) & limb_mask)
@@ -999,7 +1015,7 @@ public:
template <class Arg, class Base>
struct is_allowed_cpp_int_base_conversion : public mpl::if_c<
is_same<Arg, limb_type>::value || is_same<Arg, signed_limb_type>::value
-#ifdef BOOST_LITTLE_ENDIAN
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
|| is_same<Arg, double_limb_type>::value || is_same<Arg, signed_double_limb_type>::value
#endif
#if defined(BOOST_MP_USER_DEFINED_LITERALS)
@@ -1207,7 +1223,11 @@ private:
BOOST_STATIC_ASSERT(sizeof(i) == 2 * sizeof(limb_type));
BOOST_STATIC_ASSERT(base_type::internal_limb_count >= 2);
typename base_type::limb_pointer p = this->limbs();
+#ifdef __MSVC_RUNTIME_CHECKS
+ *p = static_cast<limb_type>(i & ~static_cast<limb_type>(0));
+#else
*p = static_cast<limb_type>(i);
+#endif
p[1] = static_cast<limb_type>(i >> base_type::limb_bits);
this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
this->sign(false);
@@ -1222,7 +1242,11 @@ private:
s = true;
ui = static_cast<double_limb_type>(boost::multiprecision::detail::unsigned_abs(i));
typename base_type::limb_pointer p = this->limbs();
+#ifdef __MSVC_RUNTIME_CHECKS
+ *p = static_cast<limb_type>(ui & ~static_cast<limb_type>(0));
+#else
*p = static_cast<limb_type>(ui);
+#endif
p[1] = static_cast<limb_type>(ui >> base_type::limb_bits);
this->resize(p[1] ? 2 : 1, p[1] ? 2 : 1);
this->sign(s);
@@ -1368,7 +1392,7 @@ private:
}
}
//
- // Exception guarentee: create the result in stack variable "result"
+ // Exception guarantee: create the result in stack variable "result"
// then do a swap at the end. In the event of a throw, *this will
// be left unchanged.
//
@@ -1923,6 +1947,10 @@ struct is_explicitly_convertible<cpp_int_backend<MinBits, MaxBits, SignType, Che
}
#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
}} // namespaces
//
diff --git a/boost/multiprecision/cpp_int/add.hpp b/boost/multiprecision/cpp_int/add.hpp
index 372998d672..22b8c186dc 100644
--- a/boost/multiprecision/cpp_int/add.hpp
+++ b/boost/multiprecision/cpp_int/add.hpp
@@ -10,6 +10,11 @@
namespace boost{ namespace multiprecision{ namespace backends{
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
//
// This is the key addition routine where all the argument types are non-trivial cpp_int's:
//
@@ -44,7 +49,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO
while(pr != pr_end)
{
carry += static_cast<double_limb_type>(*pa) + static_cast<double_limb_type>(*pb);
+#ifdef __MSVC_RUNTIME_CHECKS
+ *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
*pr = static_cast<limb_type>(carry);
+#endif
carry >>= CppInt1::limb_bits;
++pr, ++pa, ++pb;
}
@@ -63,7 +72,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const CppInt3& b) BO
break;
}
carry += static_cast<double_limb_type>(*pa);
+#ifdef __MSVC_RUNTIME_CHECKS
+ *pr = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
*pr = static_cast<limb_type>(carry);
+#endif
carry >>= CppInt1::limb_bits;
++pr, ++pa;
}
@@ -95,7 +108,11 @@ inline void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o)
for(; carry && (i < result.size()); ++i)
{
carry += static_cast<double_limb_type>(pa[i]);
+#ifdef __MSVC_RUNTIME_CHECKS
+ pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
pr[i] = static_cast<limb_type>(carry);
+#endif
carry >>= CppInt1::limb_bits;
}
// Just copy any remaining digits:
@@ -524,6 +541,10 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
result.normalize();
}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
}}} // namespaces
#endif
diff --git a/boost/multiprecision/cpp_int/bitwise.hpp b/boost/multiprecision/cpp_int/bitwise.hpp
index e39be3d12c..748d088056 100644
--- a/boost/multiprecision/cpp_int/bitwise.hpp
+++ b/boost/multiprecision/cpp_int/bitwise.hpp
@@ -351,7 +351,6 @@ inline void left_shift_limb(Int& result, double_limb_type s)
++rs; // Most significant limb will overflow when shifted
rs += offset;
result.resize(rs, rs);
- bool truncated = result.size() != rs;
typename Int::limb_pointer pr = result.limbs();
diff --git a/boost/multiprecision/cpp_int/divide.hpp b/boost/multiprecision/cpp_int/divide.hpp
index 5fe6ce6ad8..2f83d1ba71 100644
--- a/boost/multiprecision/cpp_int/divide.hpp
+++ b/boost/multiprecision/cpp_int/divide.hpp
@@ -227,12 +227,20 @@ void divide_unsigned_helper(
for(unsigned i = 0; i < y.size(); ++i)
{
carry += static_cast<double_limb_type>(py[i]) * static_cast<double_limb_type>(guess);
+#ifdef __MSVC_RUNTIME_CHECKS
+ pt[i + shift] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
pt[i + shift] = static_cast<limb_type>(carry);
+#endif
carry >>= CppInt1::limb_bits;
}
if(carry && !truncated_t)
{
+#ifdef __MSVC_RUNTIME_CHECKS
+ pt[t.size() - 1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
pt[t.size() - 1] = static_cast<limb_type>(carry);
+#endif
}
else if(!truncated_t)
{
diff --git a/boost/multiprecision/cpp_int/import_export.hpp b/boost/multiprecision/cpp_int/import_export.hpp
index 3a2473b0b2..0fe3249ddc 100644
--- a/boost/multiprecision/cpp_int/import_export.hpp
+++ b/boost/multiprecision/cpp_int/import_export.hpp
@@ -20,7 +20,7 @@ namespace boost {
limb_type mask = chunk_bits >= sizeof(limb_type) * CHAR_BIT ? ~static_cast<limb_type>(0u) : (static_cast<limb_type>(1u) << chunk_bits) - 1;
- limb_type value = (static_cast<limb_type>(bits) & mask) << shift;
+ limb_type value = static_cast<limb_type>(bits & mask) << shift;
if(value)
{
if(val.size() == limb)
@@ -132,7 +132,7 @@ namespace boost {
if(byte_len % sizeof(limb_type))
++limb_len;
cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
- result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(limb_len)); // checked types may throw here if they're not large enough to hold the data!
result.limbs()[result.size() - 1] = 0u;
std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type)));
result.normalize(); // In case data has leading zeros.
@@ -149,7 +149,7 @@ namespace boost {
if(byte_len % sizeof(result.limbs()[0]))
++limb_len;
result.limbs()[0] = 0u;
- result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ result.resize(static_cast<unsigned>(limb_len), static_cast<unsigned>(limb_len)); // checked types may throw here if they're not large enough to hold the data!
std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0])));
result.normalize(); // In case data has leading zeros.
return val;
@@ -221,7 +221,7 @@ namespace boost {
++out;
return out;
}
- unsigned bitcount = msb(val) + 1;
+ unsigned bitcount = boost::multiprecision::backends::eval_msb_imp(val.backend()) + 1;
unsigned chunks = bitcount / chunk_size;
if(bitcount % chunk_size)
++chunks;
diff --git a/boost/multiprecision/cpp_int/limits.hpp b/boost/multiprecision/cpp_int/limits.hpp
index 36a38d5a3b..518bb9f4e0 100644
--- a/boost/multiprecision/cpp_int/limits.hpp
+++ b/boost/multiprecision/cpp_int/limits.hpp
@@ -12,6 +12,11 @@ namespace std{
namespace detail{
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4307)
+#endif
+
template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>
get_min(const boost::mpl::true_&, const boost::mpl::true_&)
@@ -210,6 +215,9 @@ template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer
BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates> >::round_style;
#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
} // namespace std
diff --git a/boost/multiprecision/cpp_int/misc.hpp b/boost/multiprecision/cpp_int/misc.hpp
index a124710c28..0412ff144e 100644
--- a/boost/multiprecision/cpp_int/misc.hpp
+++ b/boost/multiprecision/cpp_int/misc.hpp
@@ -10,12 +10,15 @@
#include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
#include <boost/integer/common_factor_rt.hpp> // gcd/lcm
+#include <boost/functional/hash_fwd.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4702)
+#pragma warning(disable:4127) // conditional expression is constant
#endif
+
namespace boost{ namespace multiprecision{ namespace backends{
template <class R, class CppInt>
@@ -146,6 +149,16 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
//
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+{
+ //
+ // Find the index of the most significant bit that is non-zero:
+ //
+ return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
using default_ops::eval_get_sign;
@@ -157,11 +170,7 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
-
- //
- // Find the index of the most significant bit that is non-zero:
- //
- return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
+ return eval_msb_imp(a);
}
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
@@ -262,7 +271,8 @@ inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
{
using default_ops::eval_qr;
- cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(y);
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
+ t = y;
eval_qr(x, t, q, r);
}
@@ -317,7 +327,11 @@ inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type
break;
}
v -= u;
+#ifdef __MSVC_RUNTIME_CHECKS
+ while((v & 1u) == 0)
+#else
while((static_cast<unsigned>(v) & 1u) == 0)
+#endif
v >>= 1;
} while(true);
return u;
@@ -527,21 +541,33 @@ template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignTy
inline typename enable_if_c<
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
>::type
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{
typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
{
- conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
- *result = (std::numeric_limits<R>::max)();
+ if(val.isneg())
+ {
+ if(static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
+ conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
+ *result = (std::numeric_limits<R>::min)();
+ }
+ else
+ {
+ conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
+ *result = (std::numeric_limits<R>::max)();
+ }
}
else
- *result = static_cast<R>(*val.limbs());
- if(val.isneg())
{
- check_is_negative(mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
- *result = negate_integer(*result, mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
+ *result = static_cast<R>(*val.limbs());
+ if(val.isneg())
+ {
+ check_is_negative(mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
+ *result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
+ }
}
}
@@ -549,6 +575,7 @@ template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignTy
inline typename enable_if_c<
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
+ && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
>::type
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{
@@ -583,6 +610,16 @@ inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits
template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
+eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
+{
+ //
+ // Find the index of the least significant bit within that limb:
+ //
+ return boost::multiprecision::detail::find_msb(*a.limbs());
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
{
using default_ops::eval_get_sign;
@@ -594,10 +631,19 @@ inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- //
- // Find the index of the least significant bit within that limb:
- //
- return boost::multiprecision::detail::find_msb(*a.limbs());
+ return eval_msb_imp(a);
+}
+
+template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
+inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
+{
+ std::size_t result = 0;
+ for(unsigned i = 0; i < val.size(); ++i)
+ {
+ boost::hash_combine(result, val.limbs()[i]);
+ }
+ boost::hash_combine(result, val.sign());
+ return result;
}
#ifdef BOOST_MSVC
diff --git a/boost/multiprecision/cpp_int/multiply.hpp b/boost/multiprecision/cpp_int/multiply.hpp
index 226bc9d192..88264c47be 100644
--- a/boost/multiprecision/cpp_int/multiply.hpp
+++ b/boost/multiprecision/cpp_int/multiply.hpp
@@ -10,7 +10,12 @@
namespace boost{ namespace multiprecision{ namespace backends{
-template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
+ template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type
eval_multiply(
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
@@ -31,7 +36,11 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
while(p != pe)
{
carry += static_cast<double_limb_type>(*pa) * static_cast<double_limb_type>(val);
+#ifdef __MSVC_RUNTIME_CHECKS
+ *p = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
*p = static_cast<limb_type>(carry);
+#endif
carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
++p, ++pa;
}
@@ -139,7 +148,11 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
carry += static_cast<double_limb_type>(pa[i]) * static_cast<double_limb_type>(pb[j]);
BOOST_ASSERT(!std::numeric_limits<double_limb_type>::is_specialized || ((std::numeric_limits<double_limb_type>::max)() - carry >= pr[i+j]));
carry += pr[i + j];
+#ifdef __MSVC_RUNTIME_CHECKS
+ pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+#else
pr[i + j] = static_cast<limb_type>(carry);
+#endif
carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value));
}
@@ -184,7 +197,12 @@ BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<Mi
}
else
{
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
+#else
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
+ t = val;
+#endif
eval_multiply(result, a, t);
}
}
@@ -240,7 +258,12 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit
result.negate();
return;
}
+#if defined(BOOST_LITTLE_ENDIAN) && !defined(BOOST_MP_TEST_NO_LE)
cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t(val);
+#else
+ cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
+ t = val;
+#endif
eval_multiply(result, a, t);
}
@@ -348,6 +371,16 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
limb_type* pr = result.limbs();
double_limb_type carry = w * y;
+#ifdef __MSVC_RUNTIME_CHECKS
+ pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry >>= limb_bits;
+ carry += w * z + x * y;
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry >>= limb_bits;
+ carry += x * z;
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
+#else
pr[0] = static_cast<limb_type>(carry);
carry >>= limb_bits;
carry += w * z + x * y;
@@ -356,7 +389,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
carry += x * z;
pr[2] = static_cast<limb_type>(carry);
pr[3] = static_cast<limb_type>(carry >> limb_bits);
-
+#endif
result.sign(s);
result.normalize();
}
@@ -382,6 +415,20 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
limb_type* pr = result.limbs();
double_limb_type carry = w * y;
+#ifdef __MSVC_RUNTIME_CHECKS
+ pr[0] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry >>= limb_bits;
+ carry += w * z;
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry >>= limb_bits;
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry = x * y + pr[1];
+ pr[1] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ carry >>= limb_bits;
+ carry += pr[2] + x * z;
+ pr[2] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0));
+ pr[3] = static_cast<limb_type>(carry >> limb_bits);
+#else
pr[0] = static_cast<limb_type>(carry);
carry >>= limb_bits;
carry += w * z;
@@ -394,7 +441,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<
carry += pr[2] + x * z;
pr[2] = static_cast<limb_type>(carry);
pr[3] = static_cast<limb_type>(carry >> limb_bits);
-
+#endif
result.sign(false);
result.normalize();
}
@@ -434,6 +481,10 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned<UI>::value && (sizeof(UI)
result = static_cast<double_limb_type>(a) * static_cast<double_limb_type>(b);
}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
}}} // namespaces
#endif
diff --git a/boost/multiprecision/debug_adaptor.hpp b/boost/multiprecision/debug_adaptor.hpp
index a6ed903c44..1b69ba4aa6 100644
--- a/boost/multiprecision/debug_adaptor.hpp
+++ b/boost/multiprecision/debug_adaptor.hpp
@@ -13,7 +13,12 @@ namespace boost{
namespace multiprecision{
namespace backends{
-template <class Backend>
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+
+ template <class Backend>
struct debug_adaptor
{
typedef typename Backend::signed_types signed_types;
@@ -120,6 +125,22 @@ public:
if(tag::value)
update_view();
}
+ static unsigned default_precision() BOOST_NOEXCEPT
+ {
+ return Backend::default_precision();
+ }
+ static void default_precision(unsigned v) BOOST_NOEXCEPT
+ {
+ Backend::default_precision(v);
+ }
+ unsigned precision()const BOOST_NOEXCEPT
+ {
+ return value().precision();
+ }
+ void precision(unsigned digits10) BOOST_NOEXCEPT
+ {
+ value().precision(digits10);
+ }
};
template <class Backend>
@@ -434,6 +455,13 @@ NON_MEMBER_OP3(fmod, "fmod");
NON_MEMBER_OP3(pow, "pow");
NON_MEMBER_OP3(atan2, "atan2");
+template <class Backend>
+std::size_t hash_value(const debug_adaptor<Backend>& val)
+{
+ return hash_value(val.value());
+}
+
+
} // namespace backends
using backends::debug_adaptor;
@@ -441,6 +469,9 @@ using backends::debug_adaptor;
template<class Backend>
struct number_category<backends::debug_adaptor<Backend> > : public number_category<Backend> {};
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
}} // namespaces
namespace std{
diff --git a/boost/multiprecision/detail/big_lanczos.hpp b/boost/multiprecision/detail/big_lanczos.hpp
index 03d3203ec8..0a5a154da1 100644
--- a/boost/multiprecision/detail/big_lanczos.hpp
+++ b/boost/multiprecision/detail/big_lanczos.hpp
@@ -21,10 +21,10 @@ struct lanczos<multiprecision::number<Backend, ExpressionTemplates>, Policy>
{
typedef typename boost::math::policies::precision<multiprecision::number<Backend, ExpressionTemplates>, Policy>::type precision_type;
typedef typename mpl::if_c<
- precision_type::value <= 73,
+ precision_type::value && (precision_type::value <= 73),
lanczos13UDT,
typename mpl::if_c<
- precision_type::value <= 122,
+ precision_type::value&& (precision_type::value <= 122),
lanczos22UDT,
undefined_lanczos
>::type
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index 59d098ba0d..d9fa19479b 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -25,7 +25,25 @@
#endif
-namespace boost{ namespace multiprecision{ namespace default_ops{
+namespace boost{ namespace multiprecision{
+
+ namespace detail {
+
+ template <class To, class From>
+ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
+ template <class To, class From>
+ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
+ template <class To, class From>
+ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/);
+ template <class To, class From>
+ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/);
+ template <class To, class From>
+ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
+
+}
+
+
+namespace default_ops{
#ifdef BOOST_MSVC
// warning C4127: conditional expression is constant
@@ -309,7 +327,14 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_si
t.negate();
}
template <class T, class U>
-inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
+inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
+{
+ T temp;
+ temp = u;
+ eval_subtract(t, temp, v);
+}
+template <class T, class U>
+inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
{
T temp(u);
eval_subtract(t, temp, v);
@@ -351,6 +376,7 @@ inline void eval_multiply_default(T& t, const T& u, const T& v)
eval_multiply(t, v);
}
}
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
{
@@ -369,6 +395,7 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type e
{
eval_multiply(t, v, u);
}
+#endif
template <class T, class U, class V>
inline void eval_multiply_default(T& t, const U& u, const V& v)
{
@@ -449,6 +476,7 @@ inline void eval_divide_default(T& t, const T& u, const T& v)
eval_divide(t, v);
}
}
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
{
@@ -475,12 +503,14 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_co
T uu(u);
eval_divide(t, uu, v);
}
+#endif
template <class T, class U, class V>
inline void eval_divide_default(T& t, const U& u, const V& v)
{
if(is_same<T, V>::value && ((void*)&t == (void*)&v))
{
- T temp(u);
+ T temp;
+ temp = u;
eval_divide(temp, v);
t = temp;
}
@@ -882,6 +912,16 @@ inline void eval_convert_to(terminal<R>* result, const B& backend)
result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
}
+template <class B1, class B2, expression_template_option et>
+inline void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
+{
+ //
+ // We ran out of types to try for the conversion, try
+ // a generic conversion and hope for the best:
+ //
+ boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
+}
+
template <class B>
inline void eval_convert_to(std::string* result, const B& backend)
{
@@ -974,6 +1014,38 @@ inline void eval_trunc(T& result, const T& a)
}
template <class T>
+inline void eval_modf(T& result, T const& arg, T* pipart)
+{
+ typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
+ int c = eval_fpclassify(arg);
+ if(c == (int)FP_NAN)
+ {
+ if(pipart)
+ *pipart = arg;
+ result = arg;
+ return;
+ }
+ else if(c == (int)FP_INFINITE)
+ {
+ if(pipart)
+ *pipart = arg;
+ result = ui_type(0u);
+ return;
+ }
+ if(pipart)
+ {
+ eval_trunc(*pipart, arg);
+ eval_subtract(result, arg, *pipart);
+ }
+ else
+ {
+ T ipart;
+ eval_trunc(ipart, arg);
+ eval_subtract(result, arg, ipart);
+ }
+}
+
+template <class T>
inline void eval_round(T& result, const T& a)
{
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
@@ -1212,6 +1284,15 @@ inline typename B::exponent_type eval_ilogb(const B& val)
{
BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
typename B::exponent_type e;
+ switch(eval_fpclassify(val))
+ {
+ case FP_NAN:
+ return (std::numeric_limits<typename B::exponent_type>::min)();
+ case FP_INFINITE:
+ return (std::numeric_limits<typename B::exponent_type>::max)();
+ case FP_ZERO:
+ return (std::numeric_limits<typename B::exponent_type>::min)();
+ }
B result;
eval_frexp(result, val, &e);
return e - 1;
@@ -1301,9 +1382,49 @@ inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::deta
return (isnormal)(value_type(arg));
}
+// Default versions of sign manipulation functions, if individual backends can do better than this
+// (for example with signed zero), then they should overload these functions further:
+
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ return arg.sign();
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
+ return (sign)(value_type(arg));
+}
+
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ return arg.sign() < 0;
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+{
+ typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
+ return (signbit)(value_type(arg));
+}
+
} // namespace math
+
namespace multiprecision{
+ //
+ // Import Math functions here, so they can be found via ADL:
+ //
+ using boost::math::signbit;
+ using boost::math::sign;
+ using boost::math::copysign;
+ using boost::math::changesign;
+ using boost::math::fpclassify;
+ using boost::math::isinf;
+ using boost::math::isnan;
+ using boost::math::isnormal;
+
template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
{
@@ -1626,7 +1747,31 @@ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* p
typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
}
+//
+// modf does not return an expression template since we require the
+// second argument to be evaluated even if the returned value is
+// not assigned to anything...
+//
+template <class T, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
+{
+ using default_ops::eval_modf;
+ number<T, ExpressionTemplates> result;
+ eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0);
+ return BOOST_MP_MOVE(result);
+}
+template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
+{
+ using default_ops::eval_modf;
+ number<T, ExpressionTemplates> result, arg(v);
+ eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0);
+ return BOOST_MP_MOVE(result);
+}
+//
+// Integer square root:
+//
template <class B, expression_template_option ExpressionTemplates>
inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
sqrt(const number<B, ExpressionTemplates>& x)
diff --git a/boost/multiprecision/detail/functions/constants.hpp b/boost/multiprecision/detail/functions/constants.hpp
index 3a283c5f2e..e0a2ff5fcf 100644
--- a/boost/multiprecision/detail/functions/constants.hpp
+++ b/boost/multiprecision/detail/functions/constants.hpp
@@ -241,28 +241,35 @@ typename constant_initializer<T, F>::initializer const constant_initializer<T, F
template <class T>
const T& get_constant_ln2()
{
- static T result;
- static bool b = false;
- if(!b)
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL bool b = false;
+ static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
+ if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
- calc_log2(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ calc_log2(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
b = true;
+ digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
constant_initializer<T, &get_constant_ln2<T> >::do_nothing();
return result;
}
+#ifndef BOOST_MP_THREAD_LOCAL
+#error 1
+#endif
template <class T>
const T& get_constant_e()
{
- static T result;
- static bool b = false;
- if(!b)
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL bool b = false;
+ static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
+ if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
- calc_e(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ calc_e(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
b = true;
+ digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
constant_initializer<T, &get_constant_e<T> >::do_nothing();
@@ -273,12 +280,14 @@ const T& get_constant_e()
template <class T>
const T& get_constant_pi()
{
- static T result;
- static bool b = false;
- if(!b)
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL bool b = false;
+ static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
+ if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
- calc_pi(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ calc_pi(result, boost::multiprecision::detail::digits2<number<T, et_on> >::value());
b = true;
+ digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
constant_initializer<T, &get_constant_pi<T> >::do_nothing();
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index e51df69d4a..d5ab032c2f 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -103,7 +103,7 @@ void hyp0F0(T& H0F0, const T& x)
typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
BOOST_ASSERT(&H0F0 != &x);
- long tol = boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ long tol = boost::multiprecision::detail::digits2<number<T, et_on> >::value();
T t;
T x_pow_n_div_n_fact(x);
@@ -117,9 +117,9 @@ void hyp0F0(T& H0F0, const T& x)
ui_type n;
- static const unsigned series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ const unsigned series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_0f0(; ; x).
for(n = 2; n < series_limit; ++n)
{
@@ -158,16 +158,16 @@ void hyp1F0(T& H1F0, const T& a, const T& x)
eval_multiply(H1F0, pochham_a, x_pow_n_div_n_fact);
eval_add(H1F0, si_type(1));
T lim;
- eval_ldexp(lim, H1F0, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ eval_ldexp(lim, H1F0, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
if(eval_get_sign(lim) < 0)
lim.negate();
si_type n;
T term, part;
- static const si_type series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ const si_type series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_1f0(a; ; x).
for(n = 2; n < series_limit; n++)
{
@@ -237,7 +237,14 @@ void eval_exp(T& result, const T& x)
//
// Use series for exp(x) - 1:
//
- T lim = std::numeric_limits<number<T, et_on> >::epsilon().backend();
+ T lim;
+ if(std::numeric_limits<number<T, et_on> >::is_specialized)
+ lim = std::numeric_limits<number<T, et_on> >::epsilon().backend();
+ else
+ {
+ result = ui_type(1);
+ eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
+ }
unsigned k = 2;
exp_series = xx;
result = si_type(1);
@@ -286,7 +293,7 @@ void eval_exp(T& result, const T& x)
eval_convert_to(&n, result);
// The scaling is 2^11 = 2048.
- static const si_type p2 = static_cast<si_type>(si_type(1) << 11);
+ const si_type p2 = static_cast<si_type>(si_type(1) << 11);
eval_multiply(exp_series, get_constant_ln2<T>(), static_cast<canonical_exp_type>(n));
eval_subtract(exp_series, xx);
@@ -346,7 +353,10 @@ void eval_log(T& result, const T& arg)
else
eval_subtract(result, t);
- eval_multiply(lim, result, std::numeric_limits<number<T, et_on> >::epsilon().backend());
+ if(std::numeric_limits<number<T, et_on> >::is_specialized)
+ eval_multiply(lim, result, std::numeric_limits<number<T, et_on> >::epsilon().backend());
+ else
+ eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
if(eval_get_sign(lim) < 0)
lim.negate();
INSTRUMENT_BACKEND(lim);
@@ -369,14 +379,17 @@ void eval_log(T& result, const T& arg)
template <class T>
const T& get_constant_log10()
{
- static T result;
- static bool b = false;
- if(!b)
+ static BOOST_MP_THREAD_LOCAL T result;
+ static BOOST_MP_THREAD_LOCAL bool b = false;
+ static BOOST_MP_THREAD_LOCAL long digits = boost::multiprecision::detail::digits2<number<T> >::value();
+ if(!b || (digits != boost::multiprecision::detail::digits2<number<T> >::value()))
{
typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
T ten;
ten = ui_type(10u);
eval_log(result, ten);
+ b = true;
+ digits = boost::multiprecision::detail::digits2<number<T> >::value();
}
constant_initializer<T, &get_constant_log10<T> >::do_nothing();
@@ -606,7 +619,7 @@ namespace detail{
ui_type k = 1;
T lim(x);
- eval_ldexp(lim, lim, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ eval_ldexp(lim, lim, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
do
{
diff --git a/boost/multiprecision/detail/functions/trig.hpp b/boost/multiprecision/detail/functions/trig.hpp
index be2a9deb77..c84a639418 100644
--- a/boost/multiprecision/detail/functions/trig.hpp
+++ b/boost/multiprecision/detail/functions/trig.hpp
@@ -38,15 +38,15 @@ void hyp0F1(T& result, const T& b, const T& x)
T tol;
tol = ui_type(1);
- eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
eval_multiply(tol, result);
if(eval_get_sign(tol) < 0)
tol.negate();
T term;
- static const int series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ const int series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_0f1(; b; x).
for(n = 2; n < series_limit; ++n)
{
@@ -365,7 +365,7 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x)
eval_add(result, ui_type(1));
T lim;
- eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value);
+ eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
if(eval_get_sign(lim) < 0)
lim.negate();
@@ -373,9 +373,9 @@ void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x)
ui_type n;
T term;
- static const unsigned series_limit =
- boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100
- ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ const unsigned series_limit =
+ boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
+ ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
// Series expansion of hyperg_2f1(a, b; c; x).
for(n = 2; n < series_limit; ++n)
{
@@ -497,11 +497,16 @@ void eval_asin(T& result, const T& x)
result = (guess_type)(std::asin(dd));
- unsigned current_digits = std::numeric_limits<guess_type>::digits - 5;
- unsigned target_precision = boost::multiprecision::detail::digits2<number<T, et_on> >::value;
+ // Newton-Raphson iteration, we should double our precision with each iteration,
+ // in practice this seems to not quite work in all cases... so terminate when we
+ // have at least 2/3 of the digits correct on the assumption that the correction
+ // we've just added will finish the job...
+
+ boost::intmax_t current_precision = eval_ilogb(result);
+ boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3;
// Newton-Raphson iteration
- while(current_digits < target_precision)
+ while(current_precision > target_precision)
{
T sine, cosine;
eval_sin(sine, result);
@@ -509,18 +514,11 @@ void eval_asin(T& result, const T& x)
eval_subtract(sine, xx);
eval_divide(sine, cosine);
eval_subtract(result, sine);
-
- current_digits *= 2;
- /*
- T lim;
- eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value);
- if(eval_get_sign(s) < 0)
- s.negate();
- if(eval_get_sign(lim) < 0)
- lim.negate();
- if(lim.compare(s) >= 0)
+ current_precision = eval_ilogb(sine);
+#ifdef FP_ILOGB0
+ if(current_precision == FP_ILOGB0)
break;
- */
+#endif
}
if(b_neg)
result.negate();
@@ -646,11 +644,16 @@ void eval_atan(T& result, const T& x)
eval_convert_to(&d, xx);
result = fp_type(std::atan(d));
- // Newton-Raphson iteration
- static const boost::int32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3;
+ // Newton-Raphson iteration, we should double our precision with each iteration,
+ // in practice this seems to not quite work in all cases... so terminate when we
+ // have at least 2/3 of the digits correct on the assumption that the correction
+ // we've just added will finish the job...
+
+ boost::intmax_t current_precision = eval_ilogb(result);
+ boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3;
T s, c, t;
- for(boost::int32_t digits = double_digits10_minus_a_few; digits <= std::numeric_limits<number<T, et_on> >::digits10; digits *= 2)
+ while(current_precision > target_precision)
{
eval_sin(s, result);
eval_cos(c, result);
@@ -658,6 +661,11 @@ void eval_atan(T& result, const T& x)
eval_subtract(t, s);
eval_multiply(s, t, c);
eval_add(result, s);
+ current_precision = eval_ilogb(s);
+#ifdef FP_ILOGB0
+ if(current_precision == FP_ILOGB0)
+ break;
+#endif
}
if(b_neg)
result.negate();
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index d1fa028d30..6a840f8544 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -35,36 +35,37 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
using default_ops::eval_right_shift;
using default_ops::eval_ldexp;
using default_ops::eval_add;
+ using default_ops::eval_is_zero;
// smallest unsigned type handled natively by "From" is likely to be it's limb_type:
- typedef typename canonical<unsigned char, From>::type limb_type;
+ typedef typename canonical<unsigned char, From>::type l_limb_type;
// get the corresponding type that we can assign to "To":
- typedef typename canonical<limb_type, To>::type to_type;
+ typedef typename canonical<l_limb_type, To>::type to_type;
From t(from);
bool is_neg = eval_get_sign(t) < 0;
if(is_neg)
t.negate();
// Pick off the first limb:
- limb_type limb;
- limb_type mask = ~static_cast<limb_type>(0);
+ l_limb_type limb;
+ l_limb_type mask = static_cast<l_limb_type>(~static_cast<l_limb_type>(0));
From fl;
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
to = static_cast<to_type>(limb);
- eval_right_shift(t, std::numeric_limits<limb_type>::digits);
+ eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
//
// Then keep picking off more limbs until "t" is zero:
//
To l;
- unsigned shift = std::numeric_limits<limb_type>::digits;
+ unsigned shift = std::numeric_limits<l_limb_type>::digits;
while(!eval_is_zero(t))
{
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
l = static_cast<to_type>(limb);
- eval_right_shift(t, std::numeric_limits<limb_type>::digits);
+ eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
eval_ldexp(l, l, shift);
eval_add(to, l);
- shift += std::numeric_limits<limb_type>::digits;
+ shift += std::numeric_limits<l_limb_type>::digits;
}
//
// Finish off by setting the sign:
@@ -310,7 +311,7 @@ typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
num = -num;
}
int denom_bits = msb(denom);
- int shift = std::numeric_limits<To>::digits + denom_bits - msb(num) + 1;
+ int shift = std::numeric_limits<To>::digits + denom_bits - msb(num);
if(shift > 0)
num <<= shift;
else if(shift < 0)
@@ -318,7 +319,7 @@ typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
Integer q, r;
divide_qr(num, denom, q, r);
int q_bits = msb(q);
- if(q_bits == std::numeric_limits<To>::digits)
+ if(q_bits == std::numeric_limits<To>::digits - 1)
{
//
// Round up if 2 * r > denom:
@@ -334,7 +335,7 @@ typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
}
else
{
- BOOST_ASSERT(q_bits == 1 + std::numeric_limits<To>::digits);
+ BOOST_ASSERT(q_bits == std::numeric_limits<To>::digits);
//
// We basically already have the rounding info:
//
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index f229914c79..5911b3a28b 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -26,16 +26,25 @@
# define BOOST_MP_FORCEINLINE inline
#endif
-#if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || defined(__SUNPRO_CC)
+#if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
# define BOOST_MP_NOEXCEPT_IF(x)
#else
# define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
#endif
-#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || defined(__SUNPRO_CC)
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
#define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#endif
+//
+// Thread local storage:
+//
+#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL)
+# define BOOST_MP_THREAD_LOCAL thread_local
+#else
+# define BOOST_MP_THREAD_LOCAL
+#endif
+
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:6326)
@@ -402,7 +411,11 @@ struct expression<tag, Arg1, void, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
+ template <class T
+#ifndef __SUNPRO_CC
+, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+#endif
+>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -412,7 +425,9 @@ struct expression<tag, Arg1, void, void, void>
result_type r(*this);
return static_cast<bool>(r);
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
operator unmentionable_type()const
@@ -466,7 +481,11 @@ struct expression<terminal, Arg1, void, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
+ template <class T
+#ifndef __SUNPRO_CC
+, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+#endif
+>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -476,7 +495,9 @@ struct expression<terminal, Arg1, void, void, void>
result_type r(*this);
return static_cast<bool>(r);
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
operator unmentionable_type()const
@@ -534,7 +555,11 @@ struct expression<tag, Arg1, Arg2, void, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
+ template <class T
+#ifndef __SUNPRO_CC
+, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+#endif
+>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -544,7 +569,9 @@ struct expression<tag, Arg1, Arg2, void, void>
result_type r(*this);
return static_cast<bool>(r);
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
operator unmentionable_type()const
@@ -613,7 +640,11 @@ struct expression<tag, Arg1, Arg2, Arg3, void>
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
+ template <class T
+#ifndef __SUNPRO_CC
+, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+#endif
+>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -623,7 +654,9 @@ struct expression<tag, Arg1, Arg2, Arg3, void>
result_type r(*this);
return static_cast<bool>(r);
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
operator unmentionable_type()const
@@ -701,7 +734,11 @@ struct expression
return static_cast<T>(static_cast<result_type>(*this));
}
# else
- template <class T, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0>
+ template <class T
+#ifndef __SUNPRO_CC
+, typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
+#endif
+>
explicit operator T()const
{
return static_cast<T>(static_cast<result_type>(*this));
@@ -711,7 +748,9 @@ struct expression
result_type r(*this);
return static_cast<bool>(r);
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
operator unmentionable_type()const
@@ -751,7 +790,8 @@ struct digits2
BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
// If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
- static const long value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
+ static const long m_value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
+ static inline BOOST_CONSTEXPR long value()BOOST_NOEXCEPT { return m_value; }
};
#ifndef BOOST_MP_MIN_EXPONENT_DIGITS
diff --git a/boost/multiprecision/detail/ublas_interop.hpp b/boost/multiprecision/detail/ublas_interop.hpp
index d1aae4dc6e..cf56dc9fb8 100644
--- a/boost/multiprecision/detail/ublas_interop.hpp
+++ b/boost/multiprecision/detail/ublas_interop.hpp
@@ -32,6 +32,18 @@ struct promote_traits<boost::multiprecision::number<Backend1, ExpressionTemplate
>::type promote_type;
};
+template <class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1, class Arithmetic>
+struct promote_traits<boost::multiprecision::number<Backend1, ExpressionTemplates1>, Arithmetic>
+{
+ typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> promote_type;
+};
+
+template <class Arithmetic, class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1>
+struct promote_traits<Arithmetic, boost::multiprecision::number<Backend1, ExpressionTemplates1> >
+{
+ typedef boost::multiprecision::number<Backend1, ExpressionTemplates1> promote_type;
+};
+
template <class Backend1, boost::multiprecision::expression_template_option ExpressionTemplates1, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
struct promote_traits<boost::multiprecision::number<Backend1, ExpressionTemplates1>, boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
{
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index 979666a393..035b670228 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -8,6 +8,7 @@
#include <boost/config.hpp>
#include <boost/scoped_array.hpp>
+#include <boost/functional/hash.hpp>
#include <boost/multiprecision/number.hpp>
#if defined(BOOST_INTEL) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
@@ -489,6 +490,11 @@ inline void eval_atan2(float128_backend& result, const float128_backend& a, cons
result.value() = atan2q(a.value(), b.value());
}
+inline std::size_t hash_value(const float128_backend& val)
+{
+ return boost::hash_value(static_cast<double>(val.value()));
+}
+
} // namespace backends
}} // namespaces
@@ -547,7 +553,26 @@ void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& v
float128_detail::do_serialize(ar, val, load_tag(), binary_tag());
}
-}}
+} // namepsace multiprecision
+
+namespace math{
+
+template <multiprecision::expression_template_option ExpressionTemplates>
+inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& arg)
+{
+ return ::signbitq(arg.backend().value());
+}
+
+template <multiprecision::expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
+{
+ return ::copysignq(a.backend().value(), b.backend().value());
+}
+
+
+} // namespace math
+
+} // namespace boost
namespace std{
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index f7d4e90961..7f01682a2a 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -7,11 +7,13 @@
#define BOOST_MATH_ER_GMP_BACKEND_HPP
#include <boost/multiprecision/number.hpp>
+#include <boost/multiprecision/debug_adaptor.hpp>
#include <boost/multiprecision/detail/integer_ops.hpp>
#include <boost/multiprecision/detail/big_lanczos.hpp>
#include <boost/multiprecision/detail/digits.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
+#include <boost/functional/hash_fwd.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4127)
@@ -20,6 +22,13 @@
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
+
+#if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL)
+# define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL)
+#else
+# define BOOST_MP_MPIR_VERSION 0
+#endif
+
#include <cmath>
#include <limits>
#include <climits>
@@ -564,7 +573,7 @@ struct gmp_float<0> : public detail::gmp_float_imp<0>
}
unsigned precision()const BOOST_NOEXCEPT
{
- return multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data));
+ return static_cast<unsigned>(multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data)));
}
void precision(unsigned digits10) BOOST_NOEXCEPT
{
@@ -971,16 +980,39 @@ inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& v
template <unsigned Digits10>
inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
{
+#if BOOST_MP_MPIR_VERSION >= 20600
+ mpir_si v;
+ mpf_get_d_2exp(&v, val.data());
+#else
long v;
mpf_get_d_2exp(&v, val.data());
+#endif
*e = v;
eval_ldexp(result, val, -v);
}
template <unsigned Digits10>
inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
{
+#if BOOST_MP_MPIR_VERSION >= 20600
+ mpir_si v;
+ mpf_get_d_2exp(&v, val.data());
+ *e = v;
+ eval_ldexp(result, val, -v);
+#else
mpf_get_d_2exp(e, val.data());
eval_ldexp(result, val, -*e);
+#endif
+}
+
+template <unsigned Digits10>
+inline std::size_t hash_value(const gmp_float<Digits10>& val)
+{
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_exp);
+ boost::hash_combine(result, val.data()[0]._mp_size);
+ return result;
}
struct gmp_int
@@ -1637,7 +1669,7 @@ inline unsigned eval_lsb(const gmp_int& val)
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- return mpz_scan1(val.data(), 0);
+ return static_cast<unsigned>(mpz_scan1(val.data(), 0));
}
inline unsigned eval_msb(const gmp_int& val)
@@ -1651,7 +1683,7 @@ inline unsigned eval_msb(const gmp_int& val)
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- return mpz_sizeinbase(val.data(), 2) - 1;
+ return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1);
}
inline bool eval_bit_test(const gmp_int& val, unsigned index)
@@ -1731,6 +1763,16 @@ inline typename enable_if<
mpz_powm_ui(result.data(), base.data(), p, m.data());
}
+inline std::size_t hash_value(const gmp_int& val)
+{
+ // We should really use mpz_limbs_read here, but that's unsupported on older versions:
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_size);
+ return result;
+}
+
struct gmp_rational;
void eval_add(gmp_rational& t, const gmp_rational& o);
@@ -2094,6 +2136,17 @@ inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int c
mpq_canonicalize(result.data());
}
+inline std::size_t hash_value(const gmp_rational& val)
+{
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]);
+ for(int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_num._mp_size);
+ return result;
+}
+
//
// Some member functions that are dependent upon previous code go here:
//
@@ -2212,10 +2265,10 @@ inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
return result;
}
-#ifdef BOOST_NO_SFINAE_EXPR
-
namespace detail{
+#ifdef BOOST_NO_SFINAE_EXPR
+
template<>
struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
template<>
@@ -2227,10 +2280,46 @@ struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_ {};
template<unsigned D1, unsigned D2>
struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_ {};
-}
-
#endif
+template <>
+struct digits2<number<gmp_float<0>, et_on> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<gmp_float<0>, et_off> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+}
+
template<>
struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer>{};
template<>
@@ -2247,7 +2336,113 @@ typedef number<gmp_float<0> > mpf_float;
typedef number<gmp_int > mpz_int;
typedef number<gmp_rational > mpq_rational;
-}} // namespaces
+} // namespace multiprecision
+
+namespace math { namespace tools{
+
+ template <>
+ inline int digits<boost::multiprecision::mpf_float>()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
+ }
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
+ }
+
+ template <>
+ inline boost::multiprecision::mpf_float
+ max_value<boost::multiprecision::mpf_float>()
+ {
+ boost::multiprecision::mpf_float result(0.5);
+ mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::mpf_float
+ min_value<boost::multiprecision::mpf_float>()
+ {
+ boost::multiprecision::mpf_float result(0.5);
+ mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::min)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
+ max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+ {
+ boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
+ mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
+ min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+ {
+ boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
+ mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
+ }
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
+ max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+ {
+ return max_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
+ min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+ {
+ return min_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
+ max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+ {
+ return max_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
+ min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+ {
+ return min_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+
+}} // namespaces math::tools
+
+
+} // namespace boost
namespace std{
diff --git a/boost/multiprecision/logged_adaptor.hpp b/boost/multiprecision/logged_adaptor.hpp
index 8d430c7d20..2f916dd101 100644
--- a/boost/multiprecision/logged_adaptor.hpp
+++ b/boost/multiprecision/logged_adaptor.hpp
@@ -139,6 +139,22 @@ public:
ar & m_value;
log_postfix_event(m_value, "serialize");
}
+ static unsigned default_precision() BOOST_NOEXCEPT
+ {
+ return Backend::default_precision();
+ }
+ static void default_precision(unsigned v) BOOST_NOEXCEPT
+ {
+ Backend::default_precision(v);
+ }
+ unsigned precision()const BOOST_NOEXCEPT
+ {
+ return value().precision();
+ }
+ void precision(unsigned digits10) BOOST_NOEXCEPT
+ {
+ value().precision(digits10);
+ }
};
template <class T>
@@ -490,6 +506,12 @@ NON_MEMBER_OP3(fmod, "fmod");
NON_MEMBER_OP3(pow, "pow");
NON_MEMBER_OP3(atan2, "atan2");
+template <class Backend>
+std::size_t hash_value(const logged_adaptor<Backend>& val)
+{
+ return hash_value(val.value());
+}
+
} // namespace backends
using backends::logged_adaptor;
diff --git a/boost/multiprecision/miller_rabin.hpp b/boost/multiprecision/miller_rabin.hpp
index 96dac04df5..156f9b852b 100644
--- a/boost/multiprecision/miller_rabin.hpp
+++ b/boost/multiprecision/miller_rabin.hpp
@@ -6,7 +6,7 @@
#ifndef BOOST_MP_MR_HPP
#define BOOST_MP_MR_HPP
-#include <boost/multiprecision/random.hpp>
+#include <boost/random.hpp>
#include <boost/multiprecision/integer.hpp>
namespace boost{
diff --git a/boost/multiprecision/mpfi.hpp b/boost/multiprecision/mpfi.hpp
index 1ac7d1b5b9..00a692981c 100644
--- a/boost/multiprecision/mpfi.hpp
+++ b/boost/multiprecision/mpfi.hpp
@@ -12,11 +12,17 @@
#include <boost/multiprecision/detail/big_lanczos.hpp>
#include <boost/multiprecision/detail/digits.hpp>
#include <boost/multiprecision/mpfr.hpp>
+#include <boost/multiprecision/logged_adaptor.hpp>
#include <boost/math/constants/constants.hpp>
+#include <boost/functional/hash_fwd.hpp>
#include <mpfi.h>
#include <cmath>
#include <algorithm>
+#ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION
+# define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20
+#endif
+
namespace boost{
namespace multiprecision{
namespace backends{
@@ -315,7 +321,7 @@ protected:
mpfi_t m_data;
static unsigned& get_default_precision() BOOST_NOEXCEPT
{
- static unsigned val = 50;
+ static unsigned val = BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION;
return val;
}
};
@@ -1015,6 +1021,28 @@ inline void eval_tanh(mpfi_float_backend<Digits10>& result, const mpfi_float_bac
mpfi_tanh(result.data(), arg.data());
}
+template <unsigned Digits10>
+inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
+{
+ std::size_t result = 0;
+ std::size_t len = val.left_data()[0]._mpfr_prec / mp_bits_per_limb;
+ if(val.left_data()[0]._mpfr_prec % mp_bits_per_limb)
+ ++len;
+ for(int i = 0; i < len; ++i)
+ boost::hash_combine(result, val.left_data()[0]._mpfr_d[i]);
+ boost::hash_combine(result, val.left_data()[0]._mpfr_exp);
+ boost::hash_combine(result, val.left_data()[0]._mpfr_sign);
+
+ len = val.right_data()[0]._mpfr_prec / mp_bits_per_limb;
+ if(val.right_data()[0]._mpfr_prec % mp_bits_per_limb)
+ ++len;
+ for(int i = 0; i < len; ++i)
+ boost::hash_combine(result, val.right_data()[0]._mpfr_d[i]);
+ boost::hash_combine(result, val.right_data()[0]._mpfr_exp);
+ boost::hash_combine(result, val.right_data()[0]._mpfr_sign);
+ return result;
+}
+
} // namespace backends
#ifdef BOOST_NO_SFINAE_EXPR
@@ -1153,7 +1181,7 @@ inline int digits<boost::multiprecision::mpfi_float>()
BOOST_NOEXCEPT
#endif
{
- return boost::multiprecision::backends::detail::get_default_precision();
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::default_precision());
}
template <>
inline int digits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
@@ -1161,9 +1189,109 @@ inline int digits<boost::multiprecision::number<boost::multiprecision::mpfi_floa
BOOST_NOEXCEPT
#endif
{
- return boost::multiprecision::backends::detail::get_default_precision();
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::default_precision());
+}
+
+template <>
+inline boost::multiprecision::mpfi_float
+max_value<boost::multiprecision::mpfi_float>()
+{
+ boost::multiprecision::mpfi_float result(0.5);
+ mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+template <>
+inline boost::multiprecision::mpfi_float
+min_value<boost::multiprecision::mpfi_float>()
+{
+ boost::multiprecision::mpfi_float result(0.5);
+ mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
+max_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
+ mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
+min_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
+ mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+// mpfi gets used with logged_adaptor fairly often, so specialize for that use case as well:
+typedef boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> logged_type1;
+typedef boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off> logged_type2;
+
+template <>
+inline int digits<logged_type1>()
+#ifdef BOOST_MATH_NOEXCEPT
+BOOST_NOEXCEPT
+#endif
+{
+ return multiprecision::detail::digits10_2_2(logged_type1::default_precision());
+}
+template <>
+inline int digits<logged_type2 >()
+#ifdef BOOST_MATH_NOEXCEPT
+BOOST_NOEXCEPT
+#endif
+{
+ return multiprecision::detail::digits10_2_2(logged_type1::default_precision());
+}
+
+template <>
+inline logged_type1
+max_value<logged_type1>()
+{
+ logged_type1 result(0.5);
+ mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+template <>
+inline logged_type1
+min_value<logged_type1>()
+{
+ logged_type1 result(0.5);
+ mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
+
+template <>
+inline logged_type2
+max_value<logged_type2 >()
+{
+ logged_type2 result(0.5);
+ mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
}
+template <>
+inline logged_type2
+min_value<logged_type2 >()
+{
+ logged_type2 result(0.5);
+ mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
+ //BOOST_ASSERT(mpfi_number_p(result.backend().data()));
+ return result;
+}
} // namespace tools
namespace constants{ namespace detail{
@@ -1217,13 +1345,19 @@ struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfi_flo
}
return result;
}
+ static inline result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfi_const_pi(result.backend().data());
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
{
typedef boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result_type;
template<int N>
- static inline result_type const& get(const mpl::int_<N>&)
+ static inline result_type get(const mpl::int_<N>&)
{
mpfi_initializer<result_type>::force_instantiate();
static result_type result;
@@ -1235,6 +1369,12 @@ struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi
}
return result;
}
+ static inline result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfi_const_log2(result.backend().data());
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
@@ -1253,6 +1393,12 @@ struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfi_
}
return result;
}
+ static inline result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfi_const_euler(result.backend().data());
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
@@ -1271,6 +1417,12 @@ struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpf
}
return result;
}
+ static inline result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfi_const_catalan(result.backend().data());
+ return result;
+ }
};
}} // namespaces
diff --git a/boost/multiprecision/mpfr.hpp b/boost/multiprecision/mpfr.hpp
index 299de4a587..e6ccc18abb 100644
--- a/boost/multiprecision/mpfr.hpp
+++ b/boost/multiprecision/mpfr.hpp
@@ -7,6 +7,7 @@
#define BOOST_MATH_BN_MPFR_HPP
#include <boost/multiprecision/number.hpp>
+#include <boost/multiprecision/debug_adaptor.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
@@ -16,6 +17,10 @@
#include <cmath>
#include <algorithm>
+#ifndef BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION
+# define BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION 20
+#endif
+
namespace boost{
namespace multiprecision{
@@ -30,6 +35,9 @@ namespace backends{
template <unsigned digits10, mpfr_allocation_type AllocationType = allocate_dynamic>
struct mpfr_float_backend;
+template <>
+struct mpfr_float_backend<0, allocate_stack>;
+
} // namespace backends
template <unsigned digits10, mpfr_allocation_type AllocationType>
@@ -55,7 +63,6 @@ struct mpfr_cleanup
template <bool b>
typename mpfr_cleanup<b>::initializer const mpfr_cleanup<b>::init;
-inline long get_default_precision() { return 50; }
template <unsigned digits10, mpfr_allocation_type AllocationType>
struct mpfr_float_imp;
@@ -311,7 +318,7 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
}
~mpfr_float_imp() BOOST_NOEXCEPT
{
- if(m_data[0]._mpfr_d)
+ if(m_data[0]._mpfr_d)
mpfr_clear(m_data);
detail::mpfr_cleanup<true>::force_instantiate();
}
@@ -357,7 +364,7 @@ protected:
mpfr_t m_data;
static unsigned& get_default_precision() BOOST_NOEXCEPT
{
- static unsigned val = 50;
+ static unsigned val = BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION;
return val;
}
};
@@ -1425,6 +1432,40 @@ inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const
mpfr_tanh(result.data(), arg.data(), GMP_RNDN);
}
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_modf(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg, mpfr_float_backend<Digits10, AllocateType>* pipart)
+{
+ if(0 == pipart)
+ {
+ mpfr_float_backend<Digits10, AllocateType> ipart;
+ mpfr_modf(ipart.data(), result.data(), arg.data(), GMP_RNDN);
+ }
+ else
+ {
+ mpfr_modf(pipart->data(), result.data(), arg.data(), GMP_RNDN);
+ }
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_fmod(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
+{
+ mpfr_fmod(result.data(), a.data(), b.data(), GMP_RNDN);
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
+{
+ std::size_t result = 0;
+ std::size_t len = val.data()[0]._mpfr_prec / mp_bits_per_limb;
+ if(val.data()[0]._mpfr_prec % mp_bits_per_limb)
+ ++len;
+ for(int i = 0; i < len; ++i)
+ boost::hash_combine(result, val.data()[0]._mpfr_d[i]);
+ boost::hash_combine(result, val.data()[0]._mpfr_exp);
+ boost::hash_combine(result, val.data()[0]._mpfr_sign);
+ return result;
+}
+
} // namespace backends
#ifdef BOOST_NO_SFINAE_EXPR
@@ -1464,7 +1505,7 @@ inline int digits<boost::multiprecision::mpfr_float>()
BOOST_NOEXCEPT
#endif
{
- return boost::multiprecision::backends::detail::get_default_precision();
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::default_precision());
}
template <>
inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
@@ -1472,7 +1513,7 @@ inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_floa
BOOST_NOEXCEPT
#endif
{
- return boost::multiprecision::backends::detail::get_default_precision();
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::default_precision());
}
template <>
@@ -1515,6 +1556,51 @@ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0
return result;
}
+template <>
+inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
+#ifdef BOOST_MATH_NOEXCEPT
+BOOST_NOEXCEPT
+#endif
+{
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision());
+}
+template <>
+inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
+#ifdef BOOST_MATH_NOEXCEPT
+BOOST_NOEXCEPT
+#endif
+{
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision());
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
+max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
+{
+ return max_value<boost::multiprecision::mpfr_float>().backend();
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
+min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
+{
+ return min_value<boost::multiprecision::mpfr_float>().backend();
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
+max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
+{
+ return max_value<boost::multiprecision::mpfr_float>().backend();
+}
+
+template <>
+inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
+min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
+{
+ return min_value<boost::multiprecision::mpfr_float>().backend();
+}
+
} // namespace tools
namespace constants{ namespace detail{
@@ -1567,6 +1653,12 @@ struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_flo
}
return result;
}
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_pi(result.backend().data(), GMP_RNDN);
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
@@ -1585,6 +1677,12 @@ struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr
}
return result;
}
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_log2(result.backend().data(), GMP_RNDN);
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
@@ -1603,6 +1701,12 @@ struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_
}
return result;
}
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_euler(result.backend().data(), GMP_RNDN);
+ return result;
+ }
};
template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
@@ -1621,11 +1725,144 @@ struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpf
}
return result;
}
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_catalan(result.backend().data(), GMP_RNDN);
+ return result;
+ }
+};
+
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
+ template<int N>
+ static inline const result_type& get(const mpl::int_<N>&)
+ {
+ detail::mpfr_constant_initializer<constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
+ static result_type result;
+ static bool has_init = false;
+ if(!has_init)
+ {
+ mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
+ has_init = true;
+ }
+ return result;
+ }
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
+ return result;
+ }
+};
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
+ template<int N>
+ static inline const result_type& get(const mpl::int_<N>&)
+ {
+ detail::mpfr_constant_initializer<constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
+ static result_type result;
+ static bool init = false;
+ if(!init)
+ {
+ mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
+ init = true;
+ }
+ return result;
+ }
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
+ return result;
+ }
+};
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
+ template<int N>
+ static inline const result_type& get(const mpl::int_<N>&)
+ {
+ detail::mpfr_constant_initializer<constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
+ static result_type result;
+ static bool init = false;
+ if(!init)
+ {
+ mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
+ init = true;
+ }
+ return result;
+ }
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
+ return result;
+ }
+};
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+struct constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
+{
+ typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
+ template<int N>
+ static inline const result_type& get(const mpl::int_<N>&)
+ {
+ detail::mpfr_constant_initializer<constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
+ static result_type result;
+ static bool init = false;
+ if(!init)
+ {
+ mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
+ init = true;
+ }
+ return result;
+ }
+ static inline const result_type get(const mpl::int_<0>&)
+ {
+ result_type result;
+ mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
+ return result;
+ }
};
}} // namespaces
-}} // namespaces
+} // namespace multiprecision
+
+namespace math{
+
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+{
+ return (arg.backend().data()[0]._mpfr_sign < 0) ? 1 : 0;
+}
+
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& b)
+{
+ return (boost::math::signbit)(a) != (boost::math::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
+}
+
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
+{
+ return (arg.backend().value().data()[0]._mpfr_sign < 0) ? 1 : 0;
+}
+
+template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& b)
+{
+ return (boost::math::signbit)(a) != (boost::math::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>(-a) : a;
+}
+
+} // namespace math
+
+} // namespace boost
namespace std{
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index fca63661e3..15af7ef846 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -632,7 +632,9 @@ public:
{
return !is_zero();
}
- explicit operator void()const {}
+#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
+ BOOST_MP_FORCEINLINE explicit operator void()const {}
+#endif
# endif
#else
typedef bool (self_type::*unmentionable_type)()const;
@@ -759,7 +761,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if(bl && br)
+ {
+ self_type temp(e);
+ temp.m_backend.swap(this->m_backend);
+ }
+ else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_add(e.right(), typename right_type::tag_type());
@@ -769,11 +776,6 @@ private:
// Ignore the right node, it's *this, just add the left:
do_add(e.left(), typename left_type::tag_type());
}
- else if(bl && br)
- {
- self_type temp(e);
- temp.m_backend.swap(this->m_backend);
- }
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
@@ -797,7 +799,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if(bl && br)
+ {
+ self_type temp(e);
+ temp.m_backend.swap(this->m_backend);
+ }
+ else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just subtract the right:
do_subtract(e.right(), typename right_type::tag_type());
@@ -808,11 +815,6 @@ private:
do_subtract(e.left(), typename left_type::tag_type());
m_backend.negate();
}
- else if(bl && br)
- {
- self_type temp(e);
- temp.m_backend.swap(this->m_backend);
- }
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
@@ -837,7 +839,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
- if(bl && is_self(e.left()))
+ if(bl && br)
+ {
+ self_type temp(e);
+ temp.m_backend.swap(this->m_backend);
+ }
+ else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_multiplies(e.right(), typename right_type::tag_type());
@@ -847,11 +854,6 @@ private:
// Ignore the right node, it's *this, just add the left:
do_multiplies(e.left(), typename left_type::tag_type());
}
- else if(bl && br)
- {
- self_type temp(e);
- temp.m_backend.swap(this->m_backend);
- }
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
@@ -1793,6 +1795,14 @@ BOOST_MP_FORCEINLINE void swap(number<Backend, ExpressionTemplates>& a, number<B
{
a.swap(b);
}
+//
+// Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
+//
+template <class Backend, expression_template_option ExpressionTemplates>
+inline std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
+{
+ return hash_value(val.backend());
+}
} // namespace multiprecision
@@ -1945,6 +1955,22 @@ struct component_type<boost::rational<I> >
} // namespaces
+#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
+
+#include <functional>
+
+namespace std {
+
+ template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
+ struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
+ {
+ std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val)const { return hash_value(val); }
+ };
+
+}
+
+#endif
+
#include <boost/multiprecision/detail/ublas_interop.hpp>
#endif
diff --git a/boost/multiprecision/rational_adaptor.hpp b/boost/multiprecision/rational_adaptor.hpp
index e3cec0e482..334238c92f 100644
--- a/boost/multiprecision/rational_adaptor.hpp
+++ b/boost/multiprecision/rational_adaptor.hpp
@@ -10,6 +10,7 @@
#include <iomanip>
#include <sstream>
#include <boost/cstdint.hpp>
+#include <boost/functional/hash_fwd.hpp>
#include <boost/multiprecision/number.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
@@ -277,6 +278,15 @@ inline void assign_components(rational_adaptor<IntBackend>& result, const V& v1,
result.data().assign(v1, v2);
}
+template <class IntBackend>
+inline std::size_t hash_value(const rational_adaptor<IntBackend>& val)
+{
+ std::size_t result = hash_value(val.data().numerator());
+ boost::hash_combine(result, val.data().denominator());
+ return result;
+}
+
+
} // namespace backends
template<class IntBackend>
diff --git a/boost/multiprecision/tommath.hpp b/boost/multiprecision/tommath.hpp
index 3d576051ae..38a112fe9f 100644
--- a/boost/multiprecision/tommath.hpp
+++ b/boost/multiprecision/tommath.hpp
@@ -12,6 +12,7 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
#include <boost/scoped_array.hpp>
+#include <boost/functional/hash_fwd.hpp>
#include <tommath.h>
#include <cmath>
#include <limits>
@@ -651,6 +652,16 @@ inline typename enable_if<is_signed<Integer>, Integer>::type eval_integer_modulu
return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
}
+inline std::size_t hash_value(const tommath_int& val)
+{
+ std::size_t result = 0;
+ std::size_t len = val.data().used;
+ for(std::size_t i = 0; i < len; ++i)
+ boost::hash_combine(result, val.data().dp[i]);
+ boost::hash_combine(result, val.data().sign);
+ return result;
+}
+
} // namespace backends
using boost::multiprecision::backends::tommath_int;
diff --git a/boost/multiprecision/traits/explicit_conversion.hpp b/boost/multiprecision/traits/explicit_conversion.hpp
index b4cd8215e0..0a14f03442 100644
--- a/boost/multiprecision/traits/explicit_conversion.hpp
+++ b/boost/multiprecision/traits/explicit_conversion.hpp
@@ -11,69 +11,79 @@
#include <boost/utility/declval.hpp>
-namespace boost{ namespace multiprecision{ namespace detail{
+namespace boost {
+ namespace multiprecision {
+ namespace detail {
-template <int N>
-struct dummy_size{};
+ template <int N>
+ struct dummy_size {};
-template<typename S, typename T>
-struct has_generic_interconversion
-{
- typedef typename mpl::if_c<
- is_number<S>::value && is_number<T>::value,
- typename mpl::if_c<
- number_category<S>::value == number_kind_integer,
- typename mpl::if_c<
- number_category<T>::value == number_kind_integer
- || number_category<T>::value == number_kind_floating_point
- || number_category<T>::value == number_kind_rational
- || number_category<T>::value == number_kind_fixed_point,
- mpl::true_,
- mpl::false_
- >::type,
- typename mpl::if_c<
- number_category<S>::value == number_kind_rational,
- typename mpl::if_c<
+ template<typename S, typename T>
+ struct has_generic_interconversion
+ {
+ typedef typename mpl::if_c <
+ is_number<S>::value && is_number<T>::value,
+ typename mpl::if_c <
+ number_category<S>::value == number_kind_integer,
+ typename mpl::if_c<
+ number_category<T>::value == number_kind_integer
+ || number_category<T>::value == number_kind_floating_point
+ || number_category<T>::value == number_kind_rational
+ || number_category<T>::value == number_kind_fixed_point,
+ mpl::true_,
+ mpl::false_
+ >::type,
+ typename mpl::if_c<
+ number_category<S>::value == number_kind_rational,
+ typename mpl::if_c<
number_category<T>::value == number_kind_rational
|| number_category<T>::value == number_kind_rational,
mpl::true_,
mpl::false_
- >::type,
- typename mpl::if_c<
+ >::type,
+ typename mpl::if_c<
number_category<T>::value == number_kind_floating_point,
mpl::true_,
mpl::false_
- >::type
- >::type
- >::type,
- mpl::false_
- >::type type;
-};
+ >::type
+ >::type
+ > ::type,
+ mpl::false_
+ > ::type type;
+ };
-template<typename S, typename T>
-struct is_explicitly_convertible_imp
-{
+ template<typename S, typename T>
+ struct is_explicitly_convertible_imp
+ {
#ifndef BOOST_NO_SFINAE_EXPR
- template<typename S1, typename T1>
- static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
+ template<typename S1, typename T1>
+ static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
- template<typename S1, typename T1>
- static type_traits::no_type selector(...);
+ template<typename S1, typename T1>
+ static type_traits::no_type selector(...);
- static const bool value = sizeof(selector<S,T>(0)) == sizeof(type_traits::yes_type);
+ static const bool value = sizeof(selector<S, T>(0)) == sizeof(type_traits::yes_type);
- typedef boost::integral_constant<bool,value> type;
+ typedef boost::integral_constant<bool, value> type;
#else
- typedef typename has_generic_interconversion<S, T>::type gen_type;
- typedef mpl::bool_<boost::is_convertible<S, T>::value || gen_type::value> type;
+ typedef typename has_generic_interconversion<S, T>::type gen_type;
+ typedef mpl::bool_<boost::is_convertible<S, T>::value || gen_type::value> type;
#endif
-};
+ };
template<typename From, typename To>
struct is_explicitly_convertible : public is_explicitly_convertible_imp<From, To>::type
{
};
+#ifdef BOOST_NO_SFINAE_EXPR
+template<class Backend1, expression_template_option ExpressionTemplates1, class Backend2, expression_template_option ExpressionTemplates2>
+struct is_explicitly_convertible<number<Backend1, ExpressionTemplates1>, number<Backend2, ExpressionTemplates2> >
+ : public is_explicitly_convertible<Backend1, Backend2>
+{
+};
+#endif
+
}}} // namespaces
#endif