summaryrefslogtreecommitdiff
path: root/boost/multiprecision
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:05:34 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 11:06:28 +0900
commit34bd32e225e2a8a94104489b31c42e5801cc1f4a (patch)
treed021b579a0c190354819974e1eaf0baa54b551f3 /boost/multiprecision
parentf763a99a501650eff2c60288aa6f10ef916d769e (diff)
downloadboost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.tar.gz
boost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.tar.bz2
boost-34bd32e225e2a8a94104489b31c42e5801cc1f4a.zip
Imported Upstream version 1.63.0upstream/1.63.0
Change-Id: Iac85556a04b7e58d63ba636dedb0986e3555714a Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/multiprecision')
-rw-r--r--boost/multiprecision/concepts/mp_number_archetypes.hpp1
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp89
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp9
-rw-r--r--boost/multiprecision/cpp_int/misc.hpp1
-rw-r--r--boost/multiprecision/detail/default_ops.hpp898
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp28
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp71
-rw-r--r--boost/multiprecision/detail/integer_ops.hpp14
-rw-r--r--boost/multiprecision/detail/number_base.hpp20
-rw-r--r--boost/multiprecision/detail/number_compare.hpp178
-rw-r--r--boost/multiprecision/float128.hpp106
-rw-r--r--boost/multiprecision/gmp.hpp12
-rw-r--r--boost/multiprecision/mpfi.hpp89
-rw-r--r--boost/multiprecision/mpfr.hpp178
-rw-r--r--boost/multiprecision/number.hpp26
-rw-r--r--boost/multiprecision/rational_adaptor.hpp1
16 files changed, 1581 insertions, 140 deletions
diff --git a/boost/multiprecision/concepts/mp_number_archetypes.hpp b/boost/multiprecision/concepts/mp_number_archetypes.hpp
index f26e0e0d18..b17eb121ae 100644
--- a/boost/multiprecision/concepts/mp_number_archetypes.hpp
+++ b/boost/multiprecision/concepts/mp_number_archetypes.hpp
@@ -33,6 +33,7 @@ struct number_backend_float_architype
number_backend_float_architype()
{
+ m_value = 0;
std::cout << "Default construct" << std::endl;
}
number_backend_float_architype(const number_backend_float_architype& o)
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp
index 453a406f28..38f5387528 100644
--- a/boost/multiprecision/cpp_bin_float.hpp
+++ b/boost/multiprecision/cpp_bin_float.hpp
@@ -11,6 +11,16 @@
#include <boost/math/special_functions/trunc.hpp>
#include <boost/multiprecision/detail/float_string_cvt.hpp>
+//
+// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
+//
+#include <boost/math/special_functions/asinh.hpp>
+#include <boost/math/special_functions/acosh.hpp>
+#include <boost/math/special_functions/atanh.hpp>
+#include <boost/math/special_functions/cbrt.hpp>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/gamma.hpp>
+
namespace boost{ namespace multiprecision{ namespace backends{
enum digit_base_type
@@ -67,7 +77,7 @@ private:
exponent_type m_exponent;
bool m_sign;
public:
- cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_nan), m_sign(false) {}
+ cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {}
cpp_bin_float(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval<const rep_type&>())))
: m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
@@ -574,7 +584,9 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
{
bool s = a.sign();
res = b;
- if(res.sign() == s)
+ if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
+ res.sign() = false;
+ else if(res.sign() == s)
res.negate();
}
return;
@@ -633,7 +645,9 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
}
copy_and_round(res, dt);
- if(res.sign() != s)
+ if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
+ res.sign() = false;
+ else if(res.sign() != s)
res.negate();
res.check_invariants();
}
@@ -1221,7 +1235,8 @@ inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_con
//
// Perform rounding first, then afterwards extract the digits:
//
- typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
+ typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
+ typedef typename common_type<typename conv_type::exponent_type, int>::type common_exp_type;
conv_type arg(original_arg);
switch(arg.exponent())
{
@@ -1239,13 +1254,26 @@ inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_con
*res = -*res;
return;
}
- typename conv_type::exponent_type e = arg.exponent();
+ common_exp_type e = arg.exponent();
+ static const common_exp_type min_exp_limit = std::numeric_limits<Float>::min_exponent
+ - (common_exp_type)cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - std::numeric_limits<Float>::digits - 2;
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);
+ if(e < min_exp_limit)
+ {
+ *res = 0;
+ return;
+ }
+ if(e > std::numeric_limits<Float>::max_exponent)
+ {
+ *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
+ return;
+ }
+
+ *res = std::ldexp(static_cast<Float>(*arg.bits().limbs()), static_cast<int>(e));
for(unsigned i = 1; i < arg.bits().size(); ++i)
{
e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
- *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[i]), e);
+ *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[i]), static_cast<int>(e));
}
if(arg.sign())
*res = -*res;
@@ -1471,7 +1499,9 @@ inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE
}
if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
{
+ bool s = arg.sign(); // takes care of signed zeros
res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
+ res.sign() = s;
return;
}
bool fractional = (int)eval_lsb(arg.bits()) < shift;
@@ -1514,6 +1544,22 @@ struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2,
}
#endif
+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;
+}
using backends::cpp_bin_float;
using backends::digit_base_2;
@@ -1540,23 +1586,8 @@ typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost:
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;
- }
-
+ using boost::multiprecision::signbit;
+ using boost::multiprecision::copysign;
} // namespace math
@@ -1649,7 +1680,6 @@ public:
BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
static number_type infinity()
{
- // returns epsilon/2
initializer.do_nothing();
static std::pair<bool, number_type> value;
if(!value.first)
@@ -1661,7 +1691,14 @@ public:
}
static number_type quiet_NaN()
{
- return number_type();
+ initializer.do_nothing();
+ static std::pair<bool, number_type> value;
+ if(!value.first)
+ {
+ value.first = true;
+ value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
+ }
+ return value.second;
}
BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
{
diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp
index ee14becf5d..9e0c2900ae 100644
--- a/boost/multiprecision/cpp_dec_float.hpp
+++ b/boost/multiprecision/cpp_dec_float.hpp
@@ -34,6 +34,15 @@
// Headers required for Boost.Math integration:
//
#include <boost/math/policies/policy.hpp>
+//
+// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
+//
+#include <boost/math/special_functions/asinh.hpp>
+#include <boost/math/special_functions/acosh.hpp>
+#include <boost/math/special_functions/atanh.hpp>
+#include <boost/math/special_functions/cbrt.hpp>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/gamma.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
diff --git a/boost/multiprecision/cpp_int/misc.hpp b/boost/multiprecision/cpp_int/misc.hpp
index 0412ff144e..1fbb63ff99 100644
--- a/boost/multiprecision/cpp_int/misc.hpp
+++ b/boost/multiprecision/cpp_int/misc.hpp
@@ -16,6 +16,7 @@
#pragma warning(push)
#pragma warning(disable:4702)
#pragma warning(disable:4127) // conditional expression is constant
+#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
#endif
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index d9fa19479b..fe8d5acd16 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -9,6 +9,7 @@
#include <boost/math/policies/error_handling.hpp>
#include <boost/multiprecision/detail/number_base.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
+#include <boost/math/special_functions/next.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/fold.hpp>
@@ -26,9 +27,12 @@
namespace boost{ namespace multiprecision{
-
+
namespace detail {
+ template <class T>
+ struct is_backend;
+
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>
@@ -42,7 +46,6 @@ namespace boost{ namespace multiprecision{
}
-
namespace default_ops{
#ifdef BOOST_MSVC
@@ -62,7 +65,7 @@ namespace default_ops{
// code even more....
//
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value >::type
+inline typename disable_if_c<is_convertible<V, T>::value >::type
eval_add(T& result, V const& v)
{
T t;
@@ -70,14 +73,14 @@ inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_c
eval_add(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value >::type
+inline typename enable_if_c<is_convertible<V, T>::value >::type
eval_add(T& result, V const& v)
{
T t(v);
eval_add(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
+inline typename disable_if_c<is_convertible<V, T>::value>::type
eval_subtract(T& result, V const& v)
{
T t;
@@ -85,14 +88,14 @@ inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_c
eval_subtract(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, T>::value>::type
eval_subtract(T& result, V const& v)
{
T t(v);
eval_subtract(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
+inline typename disable_if_c<is_convertible<V, T>::value>::type
eval_multiply(T& result, V const& v)
{
T t;
@@ -100,7 +103,7 @@ inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_c
eval_multiply(result, t);
}
template <class T, class V>
-inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
+inline typename enable_if_c<is_convertible<V, T>::value>::type
eval_multiply(T& result, V const& v)
{
T t(v);
@@ -405,7 +408,7 @@ inline void eval_multiply_default(T& t, const U& u, const V& v)
}
else
{
- t = u;
+ t = number<T>::canonical_value(u);
eval_multiply(t, v);
}
}
@@ -415,13 +418,13 @@ inline void eval_multiply(T& t, const U& u, const V& v)
eval_multiply_default(t, u, v);
}
-template <class T, class U, class V, class X>
-inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
+template <class T>
+inline void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
{
if((void*)&x == (void*)&t)
{
T z;
- z = x;
+ z = number<T>::canonical_value(x);
eval_multiply_add(t, u, v, z);
}
else
@@ -430,6 +433,25 @@ inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::typ
eval_add(t, x);
}
}
+
+template <class T, class U>
+inline typename boost::disable_if_c<boost::is_same<T, U>::value, T>::type make_T(const U& u)
+{
+ T t;
+ t = number<T>::canonical_value(u);
+ return BOOST_MP_MOVE(t);
+}
+template <class T>
+inline const T& make_T(const T& t)
+{
+ return t;
+}
+
+template <class T, class U, class V, class X>
+inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
+{
+ eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
+}
template <class T, class U, class V, class X>
inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
{
@@ -614,14 +636,14 @@ inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
}
}
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_bitwise_and_default(T& t, const T& u, const U& v)
+inline typename disable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
{
T vv;
vv = v;
eval_bitwise_and(t, u, vv);
}
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_bitwise_and_default(T& t, const T& u, const U& v)
+inline typename enable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
{
T vv(v);
eval_bitwise_and(t, u, vv);
@@ -632,17 +654,10 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type e
eval_bitwise_and(t, v, u);
}
template <class T, class U, class V>
-inline void eval_bitwise_and_default(T& t, const U& u, const V& v)
+inline typename disable_if_c<is_same<T, U>::value || is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
{
- if(is_same<T, V>::value && ((void*)&t == (void*)&v))
- {
- eval_bitwise_and(t, u);
- }
- else
- {
- t = u;
- eval_bitwise_and(t, v);
- }
+ t = u;
+ eval_bitwise_and(t, v);
}
template <class T, class U, class V>
inline void eval_bitwise_and(T& t, const U& u, const V& v)
@@ -998,6 +1013,152 @@ inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, con
}
template <class T>
+void eval_round(T& result, const T& a);
+
+template <class T>
+inline void eval_remquo(T& result, const T& a, const T& b, int* pi)
+{
+ BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
+ if((&result == &a) || (&result == &b))
+ {
+ T temp;
+ eval_remquo(temp, a, b, pi);
+ result = temp;
+ return;
+ }
+ T n;
+ eval_divide(result, a, b);
+ eval_round(n, result);
+ eval_convert_to(pi, n);
+ eval_multiply(n, b);
+ eval_subtract(result, a, n);
+}
+template<class T, class A>
+inline typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
+{
+ typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
+ typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
+ cast_type c;
+ c = a;
+ eval_remquo(result, x, c, pi);
+}
+template<class T, class A>
+inline typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
+{
+ typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
+ typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
+ cast_type c;
+ c = x;
+ eval_remquo(result, c, a, pi);
+}
+template <class T, class U, class V>
+inline void eval_remainder(T& result, const U& a, const V& b)
+{
+ int i;
+ eval_remquo(result, a, b, &i);
+}
+
+template <class B>
+bool eval_gt(const B& a, const B& b);
+template <class T, class U>
+bool eval_gt(const T& a, const U& b);
+template <class B>
+bool eval_lt(const B& a, const B& b);
+template <class T, class U>
+bool eval_lt(const T& a, const U& b);
+
+template<class T>
+inline void eval_fdim(T& result, const T& a, const T& b)
+{
+ typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
+ static const ui_type zero = 0u;
+ switch(eval_fpclassify(b))
+ {
+ case FP_NAN:
+ case FP_INFINITE:
+ result = zero;
+ return;
+ }
+ switch(eval_fpclassify(a))
+ {
+ case FP_NAN:
+ result = zero;
+ return;
+ case FP_INFINITE:
+ result = a;
+ return;
+ }
+ if(eval_gt(a, b))
+ {
+ eval_subtract(result, a, b);
+ }
+ else
+ result = zero;
+}
+
+template<class T, class A>
+inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
+{
+ typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
+ typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
+ static const ui_type zero = 0u;
+ arithmetic_type canonical_b = b;
+ switch((::boost::math::fpclassify)(b))
+ {
+ case FP_NAN:
+ case FP_INFINITE:
+ result = zero;
+ return;
+ }
+ switch(eval_fpclassify(a))
+ {
+ case FP_NAN:
+ result = zero;
+ return;
+ case FP_INFINITE:
+ result = a;
+ return;
+ }
+ if(eval_gt(a, canonical_b))
+ {
+ eval_subtract(result, a, canonical_b);
+ }
+ else
+ result = zero;
+}
+
+template<class T, class A>
+inline typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
+{
+ typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
+ typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
+ static const ui_type zero = 0u;
+ arithmetic_type canonical_a = a;
+ switch(eval_fpclassify(b))
+ {
+ case FP_NAN:
+ case FP_INFINITE:
+ result = zero;
+ return;
+ }
+ switch((::boost::math::fpclassify)(a))
+ {
+ case FP_NAN:
+ result = zero;
+ return;
+ case FP_INFINITE:
+ result = std::numeric_limits<number<T> >::infinity().backend();
+ return;
+ }
+ if(eval_gt(canonical_a, b))
+ {
+ eval_subtract(result, canonical_a, b);
+ }
+ else
+ result = zero;
+}
+
+template <class T>
inline void eval_trunc(T& result, const T& a)
{
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
@@ -1309,6 +1470,134 @@ inline void eval_scalbn(B& result, const B& val, A e)
BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
}
+template <class B, class A>
+inline void eval_scalbln(B& result, const B& val, A e)
+{
+ eval_scalbn(result, val, e);
+}
+
+template <class T>
+inline bool is_arg_nan(const T& val, mpl::true_ const&, const mpl::false_&)
+{
+ return eval_fpclassify(val) == FP_NAN;
+}
+template <class T>
+inline bool is_arg_nan(const T& val, mpl::false_ const&, const mpl::true_&)
+{
+ return (boost::math::isnan)(val);
+}
+template <class T>
+inline bool is_arg_nan(const T&, mpl::false_ const&, const mpl::false_&)
+{
+ return false;
+}
+
+template <class T>
+inline bool is_arg_nan(const T& val)
+{
+ return is_arg_nan(val, mpl::bool_<boost::multiprecision::detail::is_backend<T>::value>(), is_floating_point<T>());
+}
+
+template <class T, class U, class V>
+inline void eval_fmax(T& result, const U& a, const V& b)
+{
+ if(is_arg_nan(a))
+ result = number<T>::canonical_value(b);
+ else if(is_arg_nan(b))
+ result = number<T>::canonical_value(a);
+ else if(eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
+ result = number<T>::canonical_value(b);
+ else
+ result = number<T>::canonical_value(a);
+}
+template <class T, class U, class V>
+inline void eval_fmin(T& result, const U& a, const V& b)
+{
+ if(is_arg_nan(a))
+ result = number<T>::canonical_value(b);
+ else if(is_arg_nan(b))
+ result = number<T>::canonical_value(a);
+ else if(eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
+ result = number<T>::canonical_value(a);
+ else
+ result = number<T>::canonical_value(b);
+}
+
+template <class R, class T, class U>
+inline void eval_hypot(R& result, const T& a, const U& b)
+{
+ //
+ // Normalize x and y, so that both are positive and x >= y:
+ //
+ R x, y;
+ x = number<R>::canonical_value(a);
+ y = number<R>::canonical_value(b);
+ if(eval_get_sign(x) < 0)
+ x.negate();
+ if(eval_get_sign(y) < 0)
+ y.negate();
+
+ // Special case, see C99 Annex F.
+ // The order of the if's is important: do not change!
+ int c1 = eval_fpclassify(x);
+ int c2 = eval_fpclassify(y);
+
+ if(c1 == FP_ZERO)
+ {
+ result = y;
+ return;
+ }
+ if(c2 == FP_ZERO)
+ {
+ result = x;
+ return;
+ }
+ if(c1 == FP_INFINITE)
+ {
+ result = x;
+ return;
+ }
+ if((c2 == FP_INFINITE) || (c2 == FP_NAN))
+ {
+ result = y;
+ return;
+ }
+ if(c1 == FP_NAN)
+ {
+ result = x;
+ return;
+ }
+
+ if(eval_gt(y, x))
+ x.swap(y);
+
+ eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
+
+ if(eval_gt(result, y))
+ {
+ result = x;
+ return;
+ }
+
+ R rat;
+ eval_divide(rat, y, x);
+ eval_multiply(result, rat, rat);
+ eval_increment(result);
+ eval_sqrt(rat, result);
+ eval_multiply(result, rat, x);
+}
+
+template <class R, class T>
+inline void eval_nearbyint(R& result, const T& a)
+{
+ eval_round(result, a);
+}
+template <class R, class T>
+inline void eval_rint(R& result, const T& a)
+{
+ eval_nearbyint(result, a);
+}
+
//
// These functions are implemented in separate files, but expanded inline here,
// DO NOT CHANGE THE ORDER OF THESE INCLUDES:
@@ -1319,8 +1608,6 @@ inline void eval_scalbn(B& result, const B& val, A e)
}
-} // namespace multiprecision
-namespace math{
//
// Default versions of floating point classification routines:
//
@@ -1334,52 +1621,52 @@ template <class tag, class A1, class A2, class A3, class A4>
inline int fpclassify 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 (fpclassify)(value_type(arg));
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- int v = (fpclassify)(arg);
+ int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
}
template <class tag, class A1, class A2, class A3, class A4>
inline bool isfinite 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 (isfinite)(value_type(arg));
+ return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return (fpclassify)(arg) == (int)FP_NAN;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN;
}
template <class tag, class A1, class A2, class A3, class A4>
inline bool isnan 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 (isnan)(value_type(arg));
+ return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return (fpclassify)(arg) == (int)FP_INFINITE;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE;
}
template <class tag, class A1, class A2, class A3, class A4>
inline bool isinf 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 (isinf)(value_type(arg));
+ return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
{
- return (fpclassify)(arg) == (int)FP_NORMAL;
+ return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL;
}
template <class tag, class A1, class A2, class A3, class A4>
inline bool isnormal 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 (isnormal)(value_type(arg));
+ return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
// Default versions of sign manipulation functions, if individual backends can do better than this
@@ -1394,7 +1681,7 @@ 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));
+ return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
}
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
@@ -1406,24 +1693,246 @@ 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));
+ return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+{
+ return -arg;
+}
+template <class tag, class A1, class A2, class A3, class A4>
+inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign 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 changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
+}
+template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+{
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
+}
+template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
+inline multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+{
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
+}
+template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+{
+ typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
+ return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
}
-} // namespace math
+} // namespace multiprecision
-namespace multiprecision{
+namespace math {
//
- // Import Math functions here, so they can be found via ADL:
+ // Import Math functions here, so they can be found by Boost.Math:
//
- 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;
+ using boost::multiprecision::signbit;
+ using boost::multiprecision::sign;
+ using boost::multiprecision::copysign;
+ using boost::multiprecision::changesign;
+ using boost::multiprecision::fpclassify;
+ using boost::multiprecision::isinf;
+ using boost::multiprecision::isnan;
+ using boost::multiprecision::isnormal;
+ using boost::multiprecision::isfinite;
+
+}
+
+namespace multiprecision{
+
+ typedef ::boost::math::policies::policy<
+ ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
+ ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
+ ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
+ ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
+ ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>
+ > c99_error_policy;
+
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::asinh(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type asinh 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 asinh(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::acosh(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type acosh 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 acosh(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::atanh(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type atanh 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 atanh(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::cbrt(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt 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 cbrt(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::erf(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf 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 erf(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::erfc(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc 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 erfc(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::expm1(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 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 expm1(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::lgamma(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma 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 lgamma(value_type(arg));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::tgamma(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma 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 tgamma(value_type(arg));
+ }
+
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return lround(arg);
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+ {
+ return lround(arg);
+ }
+#ifndef BOOST_NO_LONG_LONG
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return llround(arg);
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
+ {
+ return llround(arg);
+ }
+#endif
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
+ {
+ return boost::math::log1p(arg, c99_error_policy());
+ }
+ template <class tag, class A1, class A2, class A3, class A4>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p 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 log1p(value_type(arg));
+ }
+
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+ {
+ return boost::math::nextafter(a, b, c99_error_policy());
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+ inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+ {
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
+ }
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+ {
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
+ }
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+ {
+ typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
+ return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+ {
+ return boost::math::nextafter(a, b, c99_error_policy());
+ }
+ template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
+ inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
+ {
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
+ }
+ template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
+ inline multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
+ {
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
+ }
+ template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
+ inline typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
+ {
+ typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
+ return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
+ }
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)
@@ -1781,6 +2290,286 @@ inline typename enable_if_c<number_category<B>::value == number_kind_integer, nu
eval_integer_sqrt(s.backend(), r.backend(), x.backend());
return s;
}
+//
+// fma:
+//
+
+namespace default_ops {
+
+ struct fma_func
+ {
+ template <class B, class T, class U, class V>
+ void operator()(B& result, const T& a, const U& b, const V& c)const
+ {
+ eval_multiply_add(result, a, b, c);
+ }
+ };
+
+
+}
+
+template <class Backend, class U, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
+ mpl::or_<
+ is_number<U>,
+ is_number_expression<U>,
+ is_arithmetic<U>
+ >,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>
+>::type
+fma(const number<Backend, et_on>& a, const U& b, const V& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
+ mpl::or_<
+ is_number<U>,
+ is_number_expression<U>,
+ is_arithmetic<U>
+ >,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>
+>::type
+fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class Backend, class U, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
+ mpl::or_<
+ is_number<U>,
+ is_number_expression<U>,
+ is_arithmetic<U>
+ >,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ number<Backend, et_off>
+>::type
+fma(const number<Backend, et_off>& a, const U& b, const V& c)
+{
+ using default_ops::eval_multiply_add;
+ number<Backend, et_off> result;
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
+ return BOOST_MP_MOVE(result);
+}
+
+template <class U, class Backend, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>
+>::type
+fma(const U& a, const number<Backend, et_on>& b, const V& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>
+>::type
+fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class U, class Backend, class V>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ mpl::or_<
+ is_number<V>,
+ is_number_expression<V>,
+ is_arithmetic<V>
+ >
+ >,
+ number<Backend, et_off>
+>::type
+fma(const U& a, const number<Backend, et_off>& b, const V& c)
+{
+ using default_ops::eval_multiply_add;
+ number<Backend, et_off> result;
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
+ return BOOST_MP_MOVE(result);
+}
+
+template <class U, class V, class Backend>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ is_arithmetic<V>
+ >,
+ detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >
+>::type
+fma(const U& a, const V& b, const number<Backend, et_on>& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ is_arithmetic<V>
+ >,
+ detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >
+>::type
+fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
+{
+ return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
+ default_ops::fma_func(), a, b, c);
+}
+
+template <class U, class V, class Backend>
+inline typename enable_if<
+ mpl::and_<
+ mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
+ is_arithmetic<U>,
+ is_arithmetic<V>
+ >,
+ number<Backend, et_off>
+>::type
+fma(const U& a, const V& b, const number<Backend, et_off>& c)
+{
+ using default_ops::eval_multiply_add;
+ number<Backend, et_off> result;
+ eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
+ return BOOST_MP_MOVE(result);
+}
+
+namespace default_ops {
+
+ struct remquo_func
+ {
+ template <class B, class T, class U>
+ void operator()(B& result, const T& a, const U& b, int* pi)const
+ {
+ eval_remquo(result, a, b, pi);
+ }
+ };
+
+}
+
+template <class Backend, class U>
+inline typename enable_if_c<
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
+ detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>
+>::type
+remquo(const number<Backend, et_on>& a, const U& b, int* pi)
+{
+ return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
+ default_ops::remquo_func(), a, b, pi);
+}
+
+template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
+inline typename enable_if_c<
+ number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point,
+ detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>
+>::type
+remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
+{
+ return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
+ default_ops::remquo_func(), a, b, pi);
+}
+
+template <class U, class Backend>
+inline typename enable_if_c<
+ (number_category<number<Backend, et_on> >::value == number_kind_floating_point)
+ && !is_number<U>::value && !is_number_expression<U>::value,
+ detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>
+>::type
+remquo(const U& a, const number<Backend, et_on>& b, int* pi)
+{
+ return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
+ default_ops::remquo_func(), a, b, pi);
+}
+
+template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
+inline typename enable_if_c<
+ (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type >::value == number_kind_floating_point)
+ && !is_number<U>::value && !is_number_expression<U>::value,
+ detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>
+>::type
+remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
+{
+ return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
+ default_ops::remquo_func(), a, b, pi);
+}
+
+template <class Backend, class U>
+inline typename enable_if_c<
+ number_category<number<Backend, et_on> >::value == number_kind_floating_point,
+ number<Backend, et_off>
+>::type
+remquo(const number<Backend, et_off>& a, const U& b, int* pi)
+{
+ using default_ops::eval_remquo;
+ number<Backend, et_off> result;
+ eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
+ return BOOST_MP_MOVE(result);
+}
+template <class U, class Backend>
+inline typename enable_if_c<
+(number_category<number<Backend, et_on> >::value == number_kind_floating_point)
+&& !is_number<U>::value && !is_number_expression<U>::value,
+number<Backend, et_off>
+>::type
+remquo(const U& a, const number<Backend, et_off>& b, int* pi)
+{
+ using default_ops::eval_remquo;
+ number<Backend, et_off> result;
+ eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
+ return BOOST_MP_MOVE(result);
+}
+
template <class B, expression_template_option ExpressionTemplates>
inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
@@ -2231,6 +3020,7 @@ UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
UNARY_OP_FUNCTOR(round, number_kind_floating_point)
UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
+UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
UNARY_OP_FUNCTOR(log, number_kind_floating_point)
UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
@@ -2242,6 +3032,9 @@ UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
+UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
+UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
+UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
//HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
@@ -2253,13 +3046,22 @@ HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_po
//HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point)
BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
+BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
+BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
+BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
+BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
+BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(scalbln, boost::long_long_type, number_kind_floating_point)
//
// Integer functions:
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index d5ab032c2f..b244a18c8b 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -405,6 +405,13 @@ void eval_log10(T& result, const T& arg)
eval_divide(result, get_constant_log10<T>());
}
+template <class R, class T>
+inline void eval_log2(R& result, const T& a)
+{
+ eval_log(result, a);
+ eval_divide(result, get_constant_ln2<R>());
+}
+
template<typename T>
inline void eval_pow(T& result, const T& x, const T& a)
{
@@ -603,6 +610,27 @@ inline typename enable_if<is_arithmetic<A>, void>::type eval_pow(T& result, cons
eval_pow(result, c, a);
}
+template <class T>
+void eval_exp2(T& result, const T& arg)
+{
+ BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
+
+ // Check for pure-integer arguments which can be either signed or unsigned.
+ typename boost::multiprecision::detail::canonical<typename T::exponent_type, T>::type i;
+ T temp;
+ eval_trunc(temp, arg);
+ eval_convert_to(&i, temp);
+ if(arg.compare(i) == 0)
+ {
+ temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(1u);
+ eval_ldexp(result, temp, i);
+ return;
+ }
+
+ temp = static_cast<typename mpl::front<typename T::unsigned_types>::type>(2u);
+ eval_pow(result, temp, arg);
+}
+
namespace detail{
template <class T>
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index 6a840f8544..e2d8487c87 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -147,6 +147,8 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
using default_ops::eval_add;
using default_ops::eval_subtract;
using default_ops::eval_convert_to;
+ using default_ops::eval_get_sign;
+ using default_ops::eval_is_zero;
//
// First classify the input, then handle the special cases:
@@ -425,7 +427,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
//
typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
typename From::exponent_type e;
- typename component_type<To>::type num, denom;
+ typename component_type<number<To> >::type num, denom;
number<From> val(from);
e = ilogb(val);
val = scalbn(val, -e);
@@ -446,7 +448,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
num *= denom;
denom = 1;
}
- assign_components(to, num, denom);
+ assign_components(to, num.backend(), denom.backend());
}
template <class To, class From>
@@ -455,7 +457,70 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
generic_interconvert_float2rational(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
}
-}}} // namespaces
+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_rational>& /*from_type*/)
+{
+ number<From> t(from);
+ number<To> result(numerator(t) / denominator(t));
+ to = result.backend();
+}
+
+template <class To, class From>
+void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<2>& /*radix*/)
+{
+ typedef typename From::exponent_type exponent_type;
+ static const exponent_type shift = std::numeric_limits<boost::long_long_type>::digits;
+ exponent_type e;
+ number<To> num(0u);
+ number<From> val(from);
+ val = frexp(val, &e);
+ while(e > 0)
+ {
+ int s = (std::min)(e, shift);
+ val = ldexp(val, s);
+ e -= s;
+ boost::long_long_type ll = boost::math::lltrunc(val);
+ val -= ll;
+ num <<= s;
+ num += ll;
+ }
+ to = num.backend();
+}
+
+template <class To, class From, int Radix>
+void generic_interconvert_float2int(To& to, const From& from, const mpl::int_<Radix>& /*radix*/)
+{
+ //
+ // This is almost the same as the binary case above, but we have to use
+ // scalbn and ilogb rather than ldexp and frexp, we also only extract
+ // one Radix digit at a time which is terribly inefficient!
+ //
+ typename From::exponent_type e;
+ number<To> num(0u);
+ number<From> val(from);
+ e = ilogb(val);
+ val = scalbn(val, -e);
+ while(e >= 0)
+ {
+ boost::long_long_type ll = boost::math::lltrunc(val);
+ val -= ll;
+ val = scalbn(val, 1);
+ num *= Radix;
+ num += ll;
+ --e;
+ }
+ to = num.backend();
+}
+
+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_floating_point>& /*from_type*/)
+{
+ generic_interconvert_float2int(to, from, mpl::int_<std::numeric_limits<number<From> >::radix>());
+}
+
+}
+}
+} // namespaces
#ifdef BOOST_MSVC
#pragma warning(pop)
diff --git a/boost/multiprecision/detail/integer_ops.hpp b/boost/multiprecision/detail/integer_ops.hpp
index 58b1d75c65..4b1a9d8bae 100644
--- a/boost/multiprecision/detail/integer_ops.hpp
+++ b/boost/multiprecision/detail/integer_ops.hpp
@@ -469,7 +469,19 @@ inline typename enable_if<
is_integral<V>
>
>,
- detail::expression<detail::function, default_ops::powm_func, T, U, V> >::type
+ typename mpl::if_<
+ is_no_et_number<T>,
+ T,
+ typename mpl::if_<
+ is_no_et_number<U>,
+ U,
+ typename mpl::if_<
+ is_no_et_number<V>,
+ V,
+ detail::expression<detail::function, default_ops::powm_func, T, U, V> >::type
+ >::type
+ >::type
+ >::type
powm(const T& b, const U& p, const V& mod)
{
return detail::expression<detail::function, default_ops::powm_func, T, U, V>(
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index 5911b3a28b..9b10dd82d7 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -74,6 +74,18 @@ struct is_number : public mpl::false_ {};
template <class Backend, expression_template_option ExpressionTemplates>
struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_ {};
+template <class T>
+struct is_et_number : public mpl::false_ {};
+
+template <class Backend>
+struct is_et_number<number<Backend, et_on> > : public mpl::true_ {};
+
+template <class T>
+struct is_no_et_number : public mpl::false_ {};
+
+template <class Backend>
+struct is_no_et_number<number<Backend, et_off> > : public mpl::true_ {};
+
namespace detail{
// Forward-declare an expression wrapper
@@ -696,11 +708,11 @@ struct expression
typedef typename right_middle_type::result_type right_middle_result_type;
typedef typename right_type::result_type right_result_type;
typedef typename combine_expression<
+ left_result_type,
typename combine_expression<
- typename combine_expression<left_result_type, left_middle_result_type>::type,
- right_middle_result_type
- >::type,
- right_result_type
+ left_middle_result_type,
+ typename combine_expression<right_middle_result_type, right_result_type>::type
+ >::type
>::type result_type;
typedef tag tag_type;
diff --git a/boost/multiprecision/detail/number_compare.hpp b/boost/multiprecision/detail/number_compare.hpp
index 3a36289d8b..adf034265c 100644
--- a/boost/multiprecision/detail/number_compare.hpp
+++ b/boost/multiprecision/detail/number_compare.hpp
@@ -475,6 +475,184 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
return !eval_lt(t.backend(), t2.backend());
}
+//
+// C99 comparison macros as functions:
+//
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+ isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a > b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+ isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a >= b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a <= b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a < b; }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
+{
+ if(detail::is_unordered_comparison(a, b)) return false;
+ return a != b;
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
+{
+ if(detail::is_unordered_comparison(a, b)) return false;
+ return a != b;
+}
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
+{
+ if(detail::is_unordered_comparison(a, b)) return false;
+ return a != b;
+}
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+}
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+}
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+ typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
+ return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
+}
+
+template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
+inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return detail::is_unordered_comparison(a, b); }
+
+template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
+
+template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
+inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
+isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
+
+template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
+ return detail::is_unordered_comparison(a, b);
+}
+
+template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
+inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
+isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+ return detail::is_unordered_comparison(a, b);
+}
+
+template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
+inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
+isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
+{
+ typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
+ typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
+ return detail::is_unordered_comparison(a, b);
+}
}} // namespaces
diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp
index 035b670228..702d488cd6 100644
--- a/boost/multiprecision/float128.hpp
+++ b/boost/multiprecision/float128.hpp
@@ -489,6 +489,10 @@ inline void eval_atan2(float128_backend& result, const float128_backend& a, cons
{
result.value() = atan2q(a.value(), b.value());
}
+inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
+{
+ result.value() = fmaq(a.value(), b.value(), c.value());
+}
inline std::size_t hash_value(const float128_backend& val)
{
@@ -497,7 +501,88 @@ inline std::size_t hash_value(const float128_backend& val)
} // namespace backends
-}} // namespaces
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return asinhq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return acoshq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return atanhq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return cbrtq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return erfq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return erfcq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return expm1q(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return lgammaq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return tgammaq(arg.backend().value());
+ }
+ template<boost::multiprecision::expression_template_option ExpressionTemplates>
+ inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
+ {
+ return log1pq(arg.backend().value());
+ }
+
+ 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());
+ }
+
+ inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
+ {
+ result.value() = remainderq(a.value(), b.value());
+ }
+ inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
+ {
+ result.value() = remquoq(a.value(), b.value(), pi);
+ }
+
+} // namespace multiprecision
+
+namespace math {
+
+ using boost::multiprecision::signbit;
+ using boost::multiprecision::copysign;
+
+} // namespace math
+
+} // namespace boost
namespace boost{
namespace archive{
@@ -553,24 +638,7 @@ 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
+} // namepsace archive
} // namespace boost
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index 7f01682a2a..266aff2285 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -14,6 +14,16 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
#include <boost/functional/hash_fwd.hpp>
+//
+// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
+//
+#include <boost/math/special_functions/asinh.hpp>
+#include <boost/math/special_functions/acosh.hpp>
+#include <boost/math/special_functions/atanh.hpp>
+#include <boost/math/special_functions/cbrt.hpp>
+#include <boost/math/special_functions/expm1.hpp>
+#include <boost/math/special_functions/gamma.hpp>
+
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4127)
@@ -573,7 +583,7 @@ struct gmp_float<0> : public detail::gmp_float_imp<0>
}
unsigned precision()const BOOST_NOEXCEPT
{
- return static_cast<unsigned>(multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data)));
+ return static_cast<unsigned>(multiprecision::detail::digits2_2_10(static_cast<unsigned long>(mpf_get_prec(this->m_data))));
}
void precision(unsigned digits10) BOOST_NOEXCEPT
{
diff --git a/boost/multiprecision/mpfi.hpp b/boost/multiprecision/mpfi.hpp
index 00a692981c..b863e31352 100644
--- a/boost/multiprecision/mpfi.hpp
+++ b/boost/multiprecision/mpfi.hpp
@@ -74,10 +74,12 @@ struct mpfi_float_imp
mpfi_float_imp()
{
mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
+ mpfi_set_ui(m_data, 0u);
}
mpfi_float_imp(unsigned prec)
{
mpfi_init2(m_data, prec);
+ mpfi_set_ui(m_data, 0u);
}
mpfi_float_imp(const mpfi_float_imp& o)
@@ -950,6 +952,12 @@ inline void eval_exp(mpfi_float_backend<Digits10>& result, const mpfi_float_back
}
template <unsigned Digits10>
+inline void eval_exp2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
+{
+ mpfi_exp2(result.data(), arg.data());
+}
+
+template <unsigned Digits10>
inline void eval_log(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
{
mpfi_log(result.data(), arg.data());
@@ -1022,6 +1030,12 @@ inline void eval_tanh(mpfi_float_backend<Digits10>& result, const mpfi_float_bac
}
template <unsigned Digits10>
+inline void eval_log2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
+{
+ mpfi_log2(result.data(), arg.data());
+}
+
+template <unsigned Digits10>
inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
{
std::size_t result = 0;
@@ -1043,6 +1057,33 @@ inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
return result;
}
+template <class To, unsigned D>
+void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_integer>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
+{
+ using boost::multiprecision::detail::generic_interconvert;
+ mpfr_float_backend<D> t;
+ mpfi_mid(t.data(), from.data());
+ generic_interconvert(to, t, to_type, from_type);
+}
+
+template <class To, unsigned D>
+void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_rational>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
+{
+ using boost::multiprecision::detail::generic_interconvert;
+ mpfr_float_backend<D> t;
+ mpfi_mid(t.data(), from.data());
+ generic_interconvert(to, t, to_type, from_type);
+}
+
+template <class To, unsigned D>
+void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const mpl::int_<number_kind_floating_point>& to_type, const mpl::int_<number_kind_floating_point>& from_type)
+{
+ using boost::multiprecision::detail::generic_interconvert;
+ mpfr_float_backend<D> t;
+ mpfi_mid(t.data(), from.data());
+ generic_interconvert(to, t, to_type, from_type);
+}
+
} // namespace backends
#ifdef BOOST_NO_SFINAE_EXPR
@@ -1053,7 +1094,6 @@ template<unsigned D1, unsigned D2>
struct is_explicitly_convertible<backends::mpfi_float_backend<D1>, backends::mpfi_float_backend<D2> > : public mpl::true_ {};
}
-
#endif
template<>
@@ -1169,6 +1209,53 @@ struct component_type<number<mpfi_float_backend<Digits10>, ExpressionTemplates>
typedef number<mpfr_float_backend<Digits10>, ExpressionTemplates> type;
};
+//
+// Overloaded special functions which call native mpfr routines:
+//
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_asinh(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_acosh(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_atanh(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_cbrt(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_expm1(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+template <unsigned Digits10, expression_template_option ExpressionTemplates>
+inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
+{
+ boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
+ mpfi_log1p(result.backend().data(), arg.backend().data());
+ return BOOST_MP_MOVE(result);
+}
+
+
} // namespace multiprecision
namespace math{
diff --git a/boost/multiprecision/mpfr.hpp b/boost/multiprecision/mpfr.hpp
index e6ccc18abb..440517ff86 100644
--- a/boost/multiprecision/mpfr.hpp
+++ b/boost/multiprecision/mpfr.hpp
@@ -83,10 +83,12 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
mpfr_float_imp()
{
mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
+ mpfr_set_ui(m_data, 0u, GMP_RNDN);
}
mpfr_float_imp(unsigned prec)
{
mpfr_init2(m_data, prec);
+ mpfr_set_ui(m_data, 0u, GMP_RNDN);
}
mpfr_float_imp(const mpfr_float_imp& o)
@@ -398,6 +400,7 @@ struct mpfr_float_imp<digits10, allocate_stack>
{
mpfr_custom_init(m_buffer, digits2);
mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
+ mpfr_set_ui(m_data, 0u, GMP_RNDN);
}
mpfr_float_imp(const mpfr_float_imp& o)
@@ -1361,6 +1364,12 @@ inline void eval_exp(mpfr_float_backend<Digits10, AllocateType>& result, const m
}
template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_exp2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
+{
+ mpfr_exp2(result.data(), arg.data(), GMP_RNDN);
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
inline void eval_log(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
{
mpfr_log(result.data(), arg.data(), GMP_RNDN);
@@ -1433,6 +1442,12 @@ inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const
}
template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_log2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
+{
+ mpfr_log2(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)
@@ -1445,6 +1460,18 @@ inline void eval_modf(mpfr_float_backend<Digits10, AllocateType>& result, const
mpfr_modf(pipart->data(), result.data(), arg.data(), GMP_RNDN);
}
}
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_remainder(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
+{
+ mpfr_remainder(result.data(), a.data(), b.data(), GMP_RNDN);
+}
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_remquo(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, int* pi)
+{
+ long l;
+ mpfr_remquo(result.data(), &l, a.data(), b.data(), GMP_RNDN);
+ if(pi) *pi = l;
+}
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)
@@ -1453,6 +1480,31 @@ inline void eval_fmod(mpfr_float_backend<Digits10, AllocateType>& result, const
}
template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_multiply_add(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
+{
+ mpfr_fma(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_multiply_add(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& c)
+{
+ mpfr_fma(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
+{
+ mpfr_fms(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
+ result.negate();
+}
+
+template <unsigned Digits10, mpfr_allocation_type AllocateType>
+inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& c)
+{
+ mpfr_fms(result.data(), a.data(), b.data(), c.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;
@@ -1493,10 +1545,37 @@ typedef number<mpfr_float_backend<0> > mpfr_float;
typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50;
typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
+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::multiprecision::signbit)(a) != (boost::multiprecision::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::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>(-a) : a;
+}
+
} // namespace multiprecision
namespace math{
+ using boost::multiprecision::signbit;
+ using boost::multiprecision::copysign;
+
namespace tools{
template <>
@@ -1834,34 +1913,83 @@ struct constant_catalan<boost::multiprecision::number<boost::multiprecision::deb
} // 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;
-}
+namespace multiprecision {
+ //
+ // Overloaded special functions which call native mpfr routines:
+ //
+ 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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(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)
+ {
+ boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
+ mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
+ return BOOST_MP_MOVE(result);
+ }
-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 15af7ef846..aaf6532e13 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -112,7 +112,8 @@ public:
//
// Attempt a generic interconvertion:
//
- detail::generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
+ using detail::generic_interconvert;
+ generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
}
template <class Other, expression_template_option ET>
explicit BOOST_MP_FORCEINLINE number(const number<Other, ET>& val, typename boost::enable_if_c<
@@ -178,7 +179,8 @@ public:
//
// Attempt a generic interconvertion:
//
- detail::generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
+ using detail::generic_interconvert;
+ generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
return *this;
}
@@ -213,7 +215,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
// Create a copy if e contains this, but not if we're just doing a
// x += x
@@ -256,7 +258,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
// Create a copy if e contains this:
if(contains_self(e))
@@ -299,7 +301,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
// Create a temporary if the RHS references *this, but not
// if we're just doing an x *= x;
@@ -331,7 +333,7 @@ public:
return *this;
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
// Create a temporary if the RHS references *this:
@@ -419,7 +421,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
// Create a temporary if the RHS references *this:
if(contains_self(e))
@@ -451,7 +453,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
// Create a temporary if the RHS references *this, but not
@@ -486,7 +488,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
// Create a temporary if the RHS references *this, but not
@@ -521,7 +523,7 @@ public:
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- number& operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
+ typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
if(contains_self(e))
@@ -585,7 +587,7 @@ private:
eval_convert_to(result, m_backend);
}
template <class B2, expression_template_option ET>
- typename enable_if_c<detail::is_explicitly_convertible<Backend, B2>::value>::type convert_to_imp(number<B2, ET>* result)const
+ void convert_to_imp(number<B2, ET>* result)const
{
result->assign(*this);
}
@@ -1737,7 +1739,7 @@ inline std::string read_string_while(std::istream& is, std::string const& permit
else if(permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
{
// Invalid numeric character, stop reading:
- is.rdbuf()->sputbackc(static_cast<char>(c));
+ //is.rdbuf()->sputbackc(static_cast<char>(c));
break;
}
else
diff --git a/boost/multiprecision/rational_adaptor.hpp b/boost/multiprecision/rational_adaptor.hpp
index 334238c92f..4ba5961a11 100644
--- a/boost/multiprecision/rational_adaptor.hpp
+++ b/boost/multiprecision/rational_adaptor.hpp
@@ -55,6 +55,7 @@ struct rational_adaptor
typename enable_if_c<(boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_arithmetic<U>::value), rational_adaptor&>::type operator = (const U& u)
{
m_value = IntBackend(u);
+ return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES