diff options
Diffstat (limited to 'boost/multiprecision')
-rw-r--r-- | boost/multiprecision/concepts/mp_number_archetypes.hpp | 1 | ||||
-rw-r--r-- | boost/multiprecision/cpp_bin_float.hpp | 89 | ||||
-rw-r--r-- | boost/multiprecision/cpp_dec_float.hpp | 9 | ||||
-rw-r--r-- | boost/multiprecision/cpp_int/misc.hpp | 1 | ||||
-rw-r--r-- | boost/multiprecision/detail/default_ops.hpp | 898 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/pow.hpp | 28 | ||||
-rw-r--r-- | boost/multiprecision/detail/generic_interconvert.hpp | 71 | ||||
-rw-r--r-- | boost/multiprecision/detail/integer_ops.hpp | 14 | ||||
-rw-r--r-- | boost/multiprecision/detail/number_base.hpp | 20 | ||||
-rw-r--r-- | boost/multiprecision/detail/number_compare.hpp | 178 | ||||
-rw-r--r-- | boost/multiprecision/float128.hpp | 106 | ||||
-rw-r--r-- | boost/multiprecision/gmp.hpp | 12 | ||||
-rw-r--r-- | boost/multiprecision/mpfi.hpp | 89 | ||||
-rw-r--r-- | boost/multiprecision/mpfr.hpp | 178 | ||||
-rw-r--r-- | boost/multiprecision/number.hpp | 26 | ||||
-rw-r--r-- | boost/multiprecision/rational_adaptor.hpp | 1 |
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 |