summaryrefslogtreecommitdiff
path: root/boost/multiprecision
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:22:41 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:22:41 +0900
commit3c1df2168531ad5580076ae08d529054689aeedd (patch)
tree941aff6f86393eecacddfec252a8508c7e8351c9 /boost/multiprecision
parentd6a306e745acfee00e81ccaf3324a2a03516db41 (diff)
downloadboost-3c1df2168531ad5580076ae08d529054689aeedd.tar.gz
boost-3c1df2168531ad5580076ae08d529054689aeedd.tar.bz2
boost-3c1df2168531ad5580076ae08d529054689aeedd.zip
Imported Upstream version 1.70.0upstream/1.70.0
Diffstat (limited to 'boost/multiprecision')
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp65
-rw-r--r--boost/multiprecision/cpp_bin_float/transcendental.hpp8
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp10
-rw-r--r--boost/multiprecision/cpp_int.hpp2
-rw-r--r--boost/multiprecision/cpp_int/serialize.hpp28
-rw-r--r--boost/multiprecision/debug_adaptor.hpp2
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp1
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp10
-rw-r--r--boost/multiprecision/detail/number_base.hpp19
-rw-r--r--boost/multiprecision/detail/precision.hpp75
-rw-r--r--boost/multiprecision/float128.hpp4
-rw-r--r--boost/multiprecision/gmp.hpp11
-rw-r--r--boost/multiprecision/logged_adaptor.hpp2
-rw-r--r--boost/multiprecision/mpfr.hpp246
-rw-r--r--boost/multiprecision/number.hpp134
-rw-r--r--boost/multiprecision/rational_adaptor.hpp8
-rw-r--r--boost/multiprecision/traits/explicit_conversion.hpp45
-rw-r--r--boost/multiprecision/traits/is_byte_container.hpp9
18 files changed, 514 insertions, 165 deletions
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index 03daf96fe4..3d8369500d 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -45,6 +45,43 @@ inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) {
template <class S>
inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
+template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
+struct is_cpp_bin_float_implicitly_constructible_from_type
+{
+ static const bool value = false;
+};
+
+template <class Float, int bit_count>
+struct is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count, true>
+{
+ static const bool value = (std::numeric_limits<Float>::digits <= (int)bit_count)
+ && (std::numeric_limits<Float>::radix == 2)
+ && std::numeric_limits<Float>::is_specialized
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<Float, __float128>::value
+#endif
+ && (is_floating_point<Float>::value || is_number<Float>::value)
+ ;
+};
+
+template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
+struct is_cpp_bin_float_explicitly_constructible_from_type
+{
+ static const bool value = false;
+};
+
+template <class Float, int bit_count>
+struct is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count, true>
+{
+ static const bool value = (std::numeric_limits<Float>::digits > (int)bit_count)
+ && (std::numeric_limits<Float>::radix == 2)
+ && std::numeric_limits<Float>::is_specialized
+#ifdef BOOST_HAS_FLOAT128
+ && !boost::is_same<Float, __float128>::value
+#endif
+ ;
+};
+
}
template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
@@ -99,15 +136,7 @@ public:
}
template <class Float>
cpp_bin_float(const Float& f,
- typename boost::enable_if_c<
- (number_category<Float>::value == number_kind_floating_point)
- && (std::numeric_limits<Float>::digits <= (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2)
- && (std::numeric_limits<Float>::is_specialized)
-#ifdef BOOST_HAS_FLOAT128
- && !boost::is_same<Float, __float128>::value
-#endif
- >::type const* = 0)
+ typename boost::enable_if_c<detail::is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
: m_data(), m_exponent(0), m_sign(false)
{
this->assign_float(f);
@@ -115,15 +144,7 @@ public:
template <class Float>
explicit cpp_bin_float(const Float& f,
- typename boost::enable_if_c<
- (number_category<Float>::value == number_kind_floating_point)
- && (std::numeric_limits<Float>::digits > (int)bit_count)
- && (std::numeric_limits<Float>::radix == 2)
- && (std::numeric_limits<Float>::is_specialized)
-#ifdef BOOST_HAS_FLOAT128
- && !boost::is_same<Float, __float128>::value
-#endif
->::type const* = 0)
+ typename boost::enable_if_c<detail::is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
: m_data(), m_exponent(0), m_sign(false)
{
this->assign_float(f);
@@ -330,7 +351,7 @@ public:
typename boost::enable_if_c<
(number_category<Float>::value == number_kind_floating_point)
&& !boost::is_floating_point<Float>::value
- /*&& (std::numeric_limits<number<Float> >::radix == 2)*/,
+ && is_number<Float>::value,
cpp_bin_float&>::type assign_float(Float f)
{
BOOST_MATH_STD_USING
@@ -507,9 +528,9 @@ public:
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/)
{
- ar & m_data;
- ar & m_exponent;
- ar & m_sign;
+ ar & boost::serialization::make_nvp("data", m_data);
+ ar & boost::serialization::make_nvp("exponent", m_exponent);
+ ar & boost::serialization::make_nvp("sign", m_sign);
}
};
diff --git a/boost/multiprecision/cpp_bin_float/transcendental.hpp b/boost/multiprecision/cpp_bin_float/transcendental.hpp
index 5c969716a5..5c1842dc7e 100644
--- a/boost/multiprecision/cpp_bin_float/transcendental.hpp
+++ b/boost/multiprecision/cpp_bin_float/transcendental.hpp
@@ -64,6 +64,7 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
using default_ops::eval_subtract;
using default_ops::eval_add;
using default_ops::eval_convert_to;
+ using default_ops::eval_increment;
int type = eval_fpclassify(arg);
bool isneg = eval_get_sign(arg) < 0;
@@ -104,6 +105,13 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>
eval_multiply(t, n, default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >());
eval_subtract(t, arg);
t.negate();
+ if (t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) > 0)
+ {
+ // There are some rare cases where the multiply rounds down leaving a remainder > ln2
+ // See https://github.com/boostorg/multiprecision/issues/120
+ eval_increment(n);
+ t = limb_type(0);
+ }
if(eval_get_sign(t) < 0)
{
// There are some very rare cases where arg/ln2 is an integer, and the subsequent multiply
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index 9149029b8f..c09ddee5e3 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -608,11 +608,11 @@ public:
void serialize(Archive & ar, const unsigned int /*version*/)
{
for(unsigned i = 0; i < data.size(); ++i)
- ar & data[i];
- ar & exp;
- ar & neg;
- ar & fpclass;
- ar & prec_elem;
+ ar & boost::serialization::make_nvp("digit", data[i]);
+ ar & boost::serialization::make_nvp("exponent", exp);
+ ar & boost::serialization::make_nvp("sign", neg);
+ ar & boost::serialization::make_nvp("class-type", fpclass);
+ ar & boost::serialization::make_nvp("precision", prec_elem);
}
private:
diff --git a/boost/multiprecision/cpp_int.hpp b/boost/multiprecision/cpp_int.hpp
index d81831b8a6..6af30fd9ec 100644
--- a/boost/multiprecision/cpp_int.hpp
+++ b/boost/multiprecision/cpp_int.hpp
@@ -830,7 +830,7 @@ public:
m_sign = false;
}
}
- BOOST_MP_FORCEINLINE void resize(unsigned new_size, unsigned min_size)
+ BOOST_MP_FORCEINLINE void resize(unsigned /* new_size */, unsigned min_size)
{
detail::verify_new_size(2, min_size, checked_type());
}
diff --git a/boost/multiprecision/cpp_int/serialize.hpp b/boost/multiprecision/cpp_int/serialize.hpp
index 042a9f89f7..ad0031b9de 100644
--- a/boost/multiprecision/cpp_int/serialize.hpp
+++ b/boost/multiprecision/cpp_int/serialize.hpp
@@ -44,11 +44,12 @@ void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&,
// Non-trivial.
// Non binary.
+ using boost::serialization::make_nvp;
bool s;
- ar & s;
+ ar & make_nvp("sign", s);
std::size_t limb_count;
std::size_t byte_count;
- ar & byte_count;
+ ar & make_nvp("byte-count", byte_count);
limb_count = byte_count / sizeof(limb_type) + ((byte_count % sizeof(limb_type)) ? 1 : 0);
val.resize(limb_count, limb_count);
limb_type* pl = val.limbs();
@@ -58,7 +59,7 @@ void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&,
for(std::size_t j = 0; (j < sizeof(limb_type)) && byte_count; ++j)
{
unsigned char byte;
- ar & byte;
+ ar & make_nvp("byte", byte);
pl[i] |= static_cast<limb_type>(byte) << (j * CHAR_BIT);
--byte_count;
}
@@ -74,12 +75,13 @@ void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&,
// Non-trivial.
// Non binary.
+ using boost::serialization::make_nvp;
bool s = val.sign();
- ar & s;
+ ar & make_nvp("sign", s);
limb_type* pl = val.limbs();
std::size_t limb_count = val.size();
std::size_t byte_count = limb_count * sizeof(limb_type);
- ar & byte_count;
+ ar & make_nvp("byte-count", byte_count);
for(std::size_t i = 0; i < limb_count; ++i)
{
@@ -87,7 +89,7 @@ void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&,
for(std::size_t j = 0; j < sizeof(limb_type); ++j)
{
unsigned char byte = static_cast<unsigned char>((l >> (j * CHAR_BIT)) & ((1u << CHAR_BIT) - 1));
- ar & byte;
+ ar & make_nvp("byte", byte);
}
}
}
@@ -97,15 +99,16 @@ void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::true_ const&,
// Load.
// Trivial.
// Non binary.
+ using boost::serialization::make_nvp;
bool s;
typename Int::local_limb_type l = 0;
- ar & s;
+ ar & make_nvp("sign", s);
std::size_t byte_count;
- ar & byte_count;
+ ar & make_nvp("byte-count", byte_count);
for(std::size_t i = 0; i < byte_count; ++i)
{
unsigned char b;
- ar & b;
+ ar & make_nvp("byte", b);
l |= static_cast<typename Int::local_limb_type>(b) << (i * CHAR_BIT);
}
*val.limbs() = l;
@@ -118,15 +121,16 @@ void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::true_ const&, m
// Store.
// Trivial.
// Non binary.
+ using boost::serialization::make_nvp;
bool s = val.sign();
typename Int::local_limb_type l = *val.limbs();
- ar & s;
+ ar & make_nvp("sign", s);
std::size_t limb_count = sizeof(l);
- ar & limb_count;
+ ar & make_nvp("byte-count", limb_count);
for(std::size_t i = 0; i < limb_count; ++i)
{
unsigned char b = static_cast<unsigned char>(static_cast<typename Int::local_limb_type>(l >> (i * CHAR_BIT)) & static_cast<typename Int::local_limb_type>((1u << CHAR_BIT) - 1));
- ar & b;
+ ar & make_nvp("byte", b);
}
}
template <class Archive, class Int>
diff --git a/boost/multiprecision/debug_adaptor.hpp b/boost/multiprecision/debug_adaptor.hpp
index cb61c5b59b..505bea1df1 100644
--- a/boost/multiprecision/debug_adaptor.hpp
+++ b/boost/multiprecision/debug_adaptor.hpp
@@ -120,7 +120,7 @@ public:
template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/)
{
- ar & m_value;
+ ar & boost::serialization::make_nvp("value", m_value);
typedef typename Archive::is_loading tag;
if(tag::value)
update_view();
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index 1abc705a9a..8fd6f1f953 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -537,6 +537,7 @@ inline void eval_pow(T& result, const T& x, const T& a)
{
// fallthrough..
}
+ BOOST_FALLTHROUGH;
}
default:
if(eval_signbit(a))
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index 730f45cc3a..783ddca6e2 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -481,9 +481,15 @@ void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>
number<To> num(0u);
number<From> val(from);
val = frexp(val, &e);
+ bool neg = false;
+ if (val.sign() < 0)
+ {
+ val.backend().negate();
+ neg = true;
+ }
while(e > 0)
{
- int s = (std::min)(e, shift);
+ exponent_type s = (std::min)(e, shift);
val = ldexp(val, s);
e -= s;
boost::long_long_type ll = boost::math::lltrunc(val);
@@ -492,6 +498,8 @@ void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>
num += ll;
}
to = num.backend();
+ if (neg)
+ to.negate();
}
template <class To, class From, int Radix>
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index 9665a825a0..cb29515706 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -53,6 +53,15 @@
#endif
namespace boost{
+
+ namespace serialization
+ {
+ template <class T>
+ struct nvp;
+ template<class T>
+ const nvp< T > make_nvp(const char * name, T & t);
+ }
+
namespace multiprecision{
enum expression_template_option
@@ -1540,8 +1549,12 @@ enum number_category_type
number_kind_complex = 4
};
+template <class Num, bool, bool>
+struct number_category_base : public mpl::int_<number_kind_unknown> {};
+template <class Num>
+struct number_category_base<Num, true, false> : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)> {};
template <class Num>
-struct number_category : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)> {};
+struct number_category : public number_category_base<Num, boost::is_class<Num>::value || boost::is_arithmetic<Num>::value, boost::is_abstract<Num>::value> {};
template <class Backend, expression_template_option ExpressionTemplates>
struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{};
template <class tag, class A1, class A2, class A3, class A4>
@@ -1551,9 +1564,9 @@ struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number
//
#ifdef BOOST_HAS_INT128
template <>
-struct number_category<__int128> : public mpl::int_<number_kind_integer> {};
+struct number_category<boost::int128_type> : public mpl::int_<number_kind_integer> {};
template <>
-struct number_category<unsigned __int128> : public mpl::int_<number_kind_integer> {};
+struct number_category<boost::uint128_type> : public mpl::int_<number_kind_integer> {};
#endif
#ifdef BOOST_HAS_FLOAT128
template <>
diff --git a/boost/multiprecision/detail/precision.hpp b/boost/multiprecision/detail/precision.hpp
index f5963abf69..c5d373a33d 100644
--- a/boost/multiprecision/detail/precision.hpp
+++ b/boost/multiprecision/detail/precision.hpp
@@ -8,18 +8,42 @@
#include <boost/multiprecision/traits/is_variable_precision.hpp>
#include <boost/multiprecision/detail/number_base.hpp>
+#include <boost/multiprecision/detail/digits.hpp>
namespace boost{ namespace multiprecision{ namespace detail{
template <class B, boost::multiprecision::expression_template_option ET>
+ inline BOOST_CONSTEXPR unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>&, const mpl::false_&)
+ {
+ return std::numeric_limits<boost::multiprecision::number<B, ET> >::digits10;
+ }
+ template <class B, boost::multiprecision::expression_template_option ET>
+ inline unsigned current_precision_of_last_chance_imp(const boost::multiprecision::number<B, ET>& val, const mpl::true_&)
+ {
+ //
+ // We have an arbitrary precision integer, take it's "precision" as the
+ // location of the most-significant-bit less the location of the
+ // least-significant-bit, ie the number of bits required to represent the
+ // the value assuming we will have an exponent to shift things by:
+ //
+ return val.is_zero() ? 1 : digits2_2_10(msb(abs(val)) - lsb(abs(val)) + 1);
+ }
+
+
+ template <class B, boost::multiprecision::expression_template_option ET>
inline unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const mpl::true_&)
{
return n.precision();
}
template <class B, boost::multiprecision::expression_template_option ET>
- inline BOOST_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>&, const mpl::false_&)
+ inline BOOST_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& val, const mpl::false_&)
{
- return std::numeric_limits<boost::multiprecision::number<B, ET> >::digits10;
+ return current_precision_of_last_chance_imp(val,
+ mpl::bool_<
+ std::numeric_limits<boost::multiprecision::number<B, ET> >::is_specialized
+ && std::numeric_limits<boost::multiprecision::number<B, ET> >::is_integer
+ && std::numeric_limits<boost::multiprecision::number<B, ET> >::is_exact
+ && !std::numeric_limits<boost::multiprecision::number<B, ET> >::is_modulo>());
}
template <class Terminal>
@@ -64,47 +88,74 @@ namespace boost{ namespace multiprecision{ namespace detail{
return (std::max)((std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_ref())), current_precision_of(expr.middle_ref()));
}
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4130)
+#endif
+
template <class R, bool = boost::multiprecision::detail::is_variable_precision<R>::value>
struct scoped_default_precision
{
template <class T>
- scoped_default_precision(const T&) {}
+ BOOST_CONSTEXPR scoped_default_precision(const T&) {}
template <class T, class U>
- scoped_default_precision(const T&, const U&) {}
+ BOOST_CONSTEXPR scoped_default_precision(const T&, const U&) {}
template <class T, class U, class V>
- scoped_default_precision(const T&, const U&, const V&) {}
+ BOOST_CONSTEXPR scoped_default_precision(const T&, const U&, const V&) {}
+
+ //
+ // This function is never called: in C++17 it won't be compiled either:
+ //
+ unsigned precision()const
+ {
+ BOOST_ASSERT("This function should never be called!!" == 0);
+ return 0;
+ }
};
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
template <class R>
struct scoped_default_precision<R, true>
{
template <class T>
- scoped_default_precision(const T& a)
+ BOOST_CXX14_CONSTEXPR scoped_default_precision(const T& a)
{
init(current_precision_of(a));
}
template <class T, class U>
- scoped_default_precision(const T& a, const U& b)
+ BOOST_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b)
{
init((std::max)(current_precision_of(a), current_precision_of(b)));
}
template <class T, class U, class V>
- scoped_default_precision(const T& a, const U& b, const V& c)
+ BOOST_CXX14_CONSTEXPR scoped_default_precision(const T& a, const U& b, const V& c)
{
init((std::max)((std::max)(current_precision_of(a), current_precision_of(b)), current_precision_of(c)));
}
~scoped_default_precision()
{
- R::default_precision(m_prec);
+ R::default_precision(m_old_prec);
+ }
+ BOOST_CXX14_CONSTEXPR unsigned precision()const
+ {
+ return m_new_prec;
}
private:
- void init(unsigned p)
+ BOOST_CXX14_CONSTEXPR void init(unsigned p)
{
- m_prec = R::default_precision();
+ m_old_prec = R::default_precision();
if (p)
+ {
R::default_precision(p);
+ m_new_prec = p;
+ }
+ else
+ m_new_prec = m_old_prec;
}
- unsigned m_prec;
+ unsigned m_old_prec, m_new_prec;
};
template <class T>
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index b4b16c5974..dd216c66db 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -668,7 +668,7 @@ void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend
// saving
// non-binary
std::string s(val.str(0, std::ios_base::scientific));
- ar & s;
+ ar & boost::serialization::make_nvp("value", s);
}
template <class Archive>
void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::false_&)
@@ -676,7 +676,7 @@ void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend
// loading
// non-binary
std::string s;
- ar & s;
+ ar & boost::serialization::make_nvp("value", s);
val = s.c_str();
}
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index d08e7080e5..0f5800ed3d 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -342,8 +342,19 @@ struct gmp_float_imp
}
else if(digits > 0)
{
+ mp_exp_t old_e = e;
ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
--e; // To match with what our formatter expects.
+ if (old_e > e)
+ {
+ // in some cases, when we ask for more digits of precision, it will
+ // change the number of digits to the left of the decimal, if that
+ // happens, account for it here.
+ // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
+ digits -= old_e - e;
+ ps = mpf_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data);
+ --e; // To match with what our formatter expects.
+ }
}
else
{
diff --git a/boost/multiprecision/logged_adaptor.hpp b/boost/multiprecision/logged_adaptor.hpp
index a08ca43c28..596d13ed74 100644
--- a/boost/multiprecision/logged_adaptor.hpp
+++ b/boost/multiprecision/logged_adaptor.hpp
@@ -157,7 +157,7 @@ public:
void serialize(Archive& ar, const unsigned int /*version*/)
{
log_prefix_event(m_value, "serialize");
- ar & m_value;
+ ar & boost::serialization::make_nvp("value", m_value);
log_postfix_event(m_value, "serialize");
}
static unsigned default_precision() BOOST_NOEXCEPT
diff --git a/boost/multiprecision/mpfr.hpp b/boost/multiprecision/mpfr.hpp
index 36aee83d80..112a275a46 100644
--- a/boost/multiprecision/mpfr.hpp
+++ b/boost/multiprecision/mpfr.hpp
@@ -320,8 +320,19 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
}
else if(digits > 0)
{
+ mp_exp_t old_e = e;
ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
--e; // To match with what our formatter expects.
+ if (old_e > e)
+ {
+ // in some cases, when we ask for more digits of precision, it will
+ // change the number of digits to the left of the decimal, if that
+ // happens, account for it here.
+ // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
+ digits -= old_e - e;
+ ps = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
+ --e; // To match with what our formatter expects.
+ }
}
else
{
@@ -2058,6 +2069,241 @@ namespace multiprecision {
}
+namespace math {
+ //
+ // Overloaded special functions which call native mpfr routines:
+ //
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("asinh<%1%>(%1%)", 0, Policy());
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("asinh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
+ return result;
+ }
+ 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> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return asinh(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("acosh<%1%>(%1%)", 0, Policy());
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("acosh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
+ return result;
+ }
+ 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> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return acosh(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("atanh<%1%>(%1%)", 0, Policy());
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("atanh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
+ return result;
+ }
+ 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> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return atanh(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("cbrt<%1%>(%1%)", 0, Policy());
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("cbrt<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
+ return result;
+ }
+ 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> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return cbrt(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erf<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("erf<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return erf(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erfc<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("erfc<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return erfc(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("expm1<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("expm1<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> exm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return expm1(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> arg, int* sign, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ if (arg > 0)
+ {
+ mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (sign)
+ *sign = 1;
+ }
+ else
+ {
+ if (floor(arg) == arg)
+ return policies::raise_pole_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >(
+ "lgamma<%1%>", "Evaluation of lgamma at a negative integer %1%.", arg, pol);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> t = detail::sinpx(arg);
+ arg = -arg;
+ if (t < 0)
+ {
+ t = -t;
+ }
+ result = log(boost::math::constants::pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >()) - lgamma(arg, 0, pol) - log(t);
+ if (sign)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> phase = 1 - arg;
+ phase = floor(phase) / 2;
+ if (floor(phase) == phase)
+ *sign = -1;
+ else
+ *sign = 1;
+ }
+ }
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("lgamma<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("lgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, int* sign)
+ {
+ return lgamma(arg, sign, policies::policy<>());
+ }
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ return lgamma(arg, 0, pol);
+ }
+ 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> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return lgamma(arg, 0, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline typename boost::enable_if_c<boost::math::policies::is_policy<Policy>::value, boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("tgamma<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("tgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return tgamma(arg, policies::policy<>());
+ }
+
+ template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
+ inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
+ {
+ boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
+
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ if (mpfr_inf_p(result.backend().data()))
+ return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("log1p<%1%>(%1%)", 0, pol);
+ if (mpfr_nan_p(result.backend().data()))
+ return policies::raise_evaluation_error("log1p<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
+ return result;
+ }
+ 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> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ return log1p(arg, policies::policy<>());
+ }
+
+
+}
+
} // namespace boost
namespace std{
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index 42c6a8fa5d..892996b397 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -224,11 +224,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(e);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_assign(e, tag_type());
return *this;
}
@@ -247,12 +247,12 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t;
- t.assign(e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t;
+ t.assign(e);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_assign(e, tag_type());
return *this;
}
@@ -305,11 +305,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(v) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(v);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(v);
+ return *this = BOOST_MP_MOVE(t);
+ }
generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
return *this;
}
@@ -317,22 +317,9 @@ public:
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
{
- detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
//
- // If the current precision of *this differs from that of expression e, then we
- // create a temporary (which will have the correct precision thanks to precision_guard)
- // and then move the result into *this. In C++17 we add a leading "if constexpr"
- // which causes this code to be eliminated in the common case that this type is
- // not actually variable precision. Pre C++17 this code should still be mostly
- // optimised away, but we can't prevent instantiation of the dead code leading
- // to longer build and possibly link times.
+ // No preicsion guard here, we already have one in operator=
//
- BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(e);
- *this = BOOST_MP_MOVE(t);
- }
*this = e;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
@@ -340,22 +327,9 @@ public:
typename boost::enable_if_c<!is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value
&& boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
{
- detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
//
- // If the current precision of *this differs from that of expression e, then we
- // create a temporary (which will have the correct precision thanks to precision_guard)
- // and then move the result into *this. In C++17 we add a leading "if constexpr"
- // which causes this code to be eliminated in the common case that this type is
- // not actually variable precision. Pre C++17 this code should still be mostly
- // optimised away, but we can't prevent instantiation of the dead code leading
- // to longer build and possibly link times.
+ // No precision guard as assign has one already:
//
- BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(e);
- *this = BOOST_MP_MOVE(t);
- }
assign(e);
}
@@ -383,11 +357,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(val) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this + val);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this + val);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
return *this;
}
@@ -424,11 +398,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this + e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this + e);
+ return *this = BOOST_MP_MOVE(t);
+ }
//
// Fused multiply-add:
//
@@ -459,11 +433,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(val) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this - val);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this - val);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
return *this;
}
@@ -508,11 +482,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this - e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this - e);
+ return *this = BOOST_MP_MOVE(t);
+ }
//
// Fused multiply-subtract:
//
@@ -535,11 +509,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this * e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this * e);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
@@ -585,11 +559,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this % e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this % e);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
@@ -689,11 +663,11 @@ public:
// to longer build and possibly link times.
//
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (boost::multiprecision::detail::current_precision_of(e) != boost::multiprecision::detail::current_precision_of(*this))
- {
- number t(*this / e);
- return *this = BOOST_MP_MOVE(t);
- }
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of(*this))
+ {
+ number t(*this / e);
+ return *this = BOOST_MP_MOVE(t);
+ }
do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
return *this;
}
@@ -856,7 +830,7 @@ public:
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/)
{
- ar & m_backend;
+ ar & boost::serialization::make_nvp("backend", m_backend);
}
private:
template <class T>
diff --git a/boost/multiprecision/rational_adaptor.hpp b/boost/multiprecision/rational_adaptor.hpp
index b06a157010..860a43bfa8 100644
--- a/boost/multiprecision/rational_adaptor.hpp
+++ b/boost/multiprecision/rational_adaptor.hpp
@@ -186,16 +186,16 @@ struct rational_adaptor
{
// Saving
integer_type n(m_value.numerator()), d(m_value.denominator());
- ar & n;
- ar & d;
+ ar & boost::serialization::make_nvp("numerator", n);
+ ar & boost::serialization::make_nvp("denominator", d);
}
template <class Archive>
void serialize(Archive& ar, const mpl::false_&)
{
// Loading
integer_type n, d;
- ar & n;
- ar & d;
+ ar & boost::serialization::make_nvp("numerator", n);
+ ar & boost::serialization::make_nvp("denominator", d);
m_value.assign(n, d);
}
template <class Archive>
diff --git a/boost/multiprecision/traits/explicit_conversion.hpp b/boost/multiprecision/traits/explicit_conversion.hpp
index 0a14f03442..9ebec6a93b 100644
--- a/boost/multiprecision/traits/explicit_conversion.hpp
+++ b/boost/multiprecision/traits/explicit_conversion.hpp
@@ -7,48 +7,51 @@
#ifndef BOOST_MP_EXPLICIT_CONVERTIBLE_HPP
#define BOOST_MP_EXPLICIT_CONVERTIBLE_HPP
+#include <boost/config.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_convertible.hpp>
-#include <boost/utility/declval.hpp>
-
+#include <boost/type_traits/declval.hpp>
+#include <boost/multiprecision/detail/number_base.hpp> // number_category
namespace boost {
namespace multiprecision {
namespace detail {
- template <int N>
+ template <unsigned int N>
struct dummy_size {};
template<typename S, typename T>
struct has_generic_interconversion
{
- typedef typename mpl::if_c <
+ typedef typename boost::conditional <
is_number<S>::value && is_number<T>::value,
- typename mpl::if_c <
+ typename boost::conditional <
number_category<S>::value == number_kind_integer,
- typename mpl::if_c<
+ typename boost::conditional<
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_
+ boost::true_type,
+ boost::false_type
>::type,
- typename mpl::if_c<
+ typename boost::conditional<
number_category<S>::value == number_kind_rational,
- typename mpl::if_c<
+ typename boost::conditional<
number_category<T>::value == number_kind_rational
|| number_category<T>::value == number_kind_rational,
- mpl::true_,
- mpl::false_
+ boost::true_type,
+ boost::false_type
>::type,
- typename mpl::if_c<
+ typename boost::conditional<
number_category<T>::value == number_kind_floating_point,
- mpl::true_,
- mpl::false_
+ boost::true_type,
+ boost::false_type
>::type
>::type
> ::type,
- mpl::false_
+ boost::false_type
> ::type type;
};
@@ -57,7 +60,13 @@ namespace boost {
{
#ifndef BOOST_NO_SFINAE_EXPR
template<typename S1, typename T1>
- static type_traits::yes_type selector(dummy_size<sizeof(static_cast<T1>(declval<S1>()))>*);
+ static type_traits::yes_type selector(dummy_size<sizeof(new T1(boost::declval<
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ S1
+#else
+ S1 const&
+#endif
+ >()))>*);
template<typename S1, typename T1>
static type_traits::no_type selector(...);
@@ -67,7 +76,7 @@ namespace boost {
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 boost::integral_constant<bool, boost::is_convertible<S, T>::value || gen_type::value> type;
#endif
};
diff --git a/boost/multiprecision/traits/is_byte_container.hpp b/boost/multiprecision/traits/is_byte_container.hpp
index d97428f0f2..64999800a7 100644
--- a/boost/multiprecision/traits/is_byte_container.hpp
+++ b/boost/multiprecision/traits/is_byte_container.hpp
@@ -6,25 +6,28 @@
#ifndef BOOST_IS_BYTE_CONTAINER_HPP
#define BOOST_IS_BYTE_CONTAINER_HPP
+#include <iterator>
#include <boost/mpl/has_xxx.hpp>
#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/remove_cv.hpp>
namespace boost{ namespace multiprecision{ namespace detail{
- BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false)
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false)
template <class C, bool b>
struct is_byte_container_imp
{
- static const bool value = boost::is_integral<typename C::value_type>::value && (sizeof(typename C::value_type) == 1);
+ // Note: Don't use C::value_type as this is a rather widespread typedef, even for non-range types
+ typedef typename boost::remove_cv<typename std::iterator_traits<typename C::const_iterator>::value_type>::type container_value_type;
+ static const bool value = boost::is_integral<container_value_type>::value && (sizeof(container_value_type) == 1);
};
template <class C>
struct is_byte_container_imp<C, false> : public boost::false_type {};
template <class C>
- struct is_byte_container : public is_byte_container_imp<C, has_member_value_type<C>::value && has_member_const_iterator<C>::value> {};
+ struct is_byte_container : public is_byte_container_imp<C, has_member_const_iterator<C>::value> {};
}}} // namespaces