diff options
Diffstat (limited to 'boost/multiprecision')
-rw-r--r-- | boost/multiprecision/cpp_bin_float.hpp | 58 | ||||
-rw-r--r-- | boost/multiprecision/cpp_bin_float/transcendental.hpp | 11 | ||||
-rw-r--r-- | boost/multiprecision/cpp_dec_float.hpp | 8 | ||||
-rw-r--r-- | boost/multiprecision/cpp_int/multiply.hpp | 22 | ||||
-rw-r--r-- | boost/multiprecision/detail/bitscan.hpp | 11 | ||||
-rw-r--r-- | boost/multiprecision/detail/default_ops.hpp | 13 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/constants.hpp | 17 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/pow.hpp | 10 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/trig.hpp | 23 | ||||
-rw-r--r-- | boost/multiprecision/detail/number_base.hpp | 29 | ||||
-rw-r--r-- | boost/multiprecision/float128.hpp | 2 | ||||
-rw-r--r-- | boost/multiprecision/gmp.hpp | 2 | ||||
-rw-r--r-- | boost/multiprecision/number.hpp | 3 | ||||
-rw-r--r-- | boost/multiprecision/traits/is_backend.hpp | 6 | ||||
-rw-r--r-- | boost/multiprecision/traits/is_byte_container.hpp | 4 |
15 files changed, 185 insertions, 34 deletions
diff --git a/boost/multiprecision/cpp_bin_float.hpp b/boost/multiprecision/cpp_bin_float.hpp index f3e593a142..c8cf06bc50 100644 --- a/boost/multiprecision/cpp_bin_float.hpp +++ b/boost/multiprecision/cpp_bin_float.hpp @@ -103,6 +103,10 @@ public: (number_category<Float>::value == number_kind_floating_point) && (std::numeric_limits<Float>::digits <= (int)bit_count) && (std::numeric_limits<Float>::radix == 2) + && (std::numeric_limits<Float>::is_specialized) +#ifdef BOOST_HAS_FLOAT128 + && !boost::is_same<Float, __float128>::value +#endif >::type const* = 0) : m_data(), m_exponent(0), m_sign(false) { @@ -113,14 +117,39 @@ public: explicit cpp_bin_float(const Float& f, typename boost::enable_if_c< (number_category<Float>::value == number_kind_floating_point) - && (std::numeric_limits<Float>::digits > (int)bit_count) - && (std::numeric_limits<Float>::radix == 2) + && (std::numeric_limits<Float>::digits > (int)bit_count) + && (std::numeric_limits<Float>::radix == 2) + && (std::numeric_limits<Float>::is_specialized) +#ifdef BOOST_HAS_FLOAT128 + && !boost::is_same<Float, __float128>::value +#endif +>::type const* = 0) + : m_data(), m_exponent(0), m_sign(false) + { + this->assign_float(f); + } +#ifdef BOOST_HAS_FLOAT128 + template <class Float> + cpp_bin_float(const Float& f, + typename boost::enable_if_c< + boost::is_same<Float, __float128>::value + && ((int)bit_count >= 113) >::type const* = 0) : m_data(), m_exponent(0), m_sign(false) { this->assign_float(f); } - + template <class Float> + explicit cpp_bin_float(const Float& f, + typename boost::enable_if_c< + boost::is_same<Float, __float128>::value + && ((int)bit_count < 113) + >::type const* = 0) + : m_data(), m_exponent(0), m_sign(false) + { + this->assign_float(f); + } +#endif cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>())) { m_data = o.m_data; @@ -157,22 +186,31 @@ public: } return *this; } - +#ifdef BOOST_HAS_FLOAT128 + template <class Float> + typename boost::enable_if_c< + (number_category<Float>::value == number_kind_floating_point) + //&& (std::numeric_limits<Float>::digits <= (int)bit_count) + && ((std::numeric_limits<Float>::radix == 2) || (boost::is_same<Float, __float128>::value)), cpp_bin_float&>::type + operator=(const Float& f) +#else template <class Float> typename boost::enable_if_c< (number_category<Float>::value == number_kind_floating_point) //&& (std::numeric_limits<Float>::digits <= (int)bit_count) - && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f) + && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type + operator=(const Float& f) +#endif { return assign_float(f); } #ifdef BOOST_HAS_FLOAT128 - cpp_bin_float& operator=(__float128 f) + template <class Float> + typename boost::enable_if_c<boost::is_same<Float, __float128>::value, cpp_bin_float& >::type assign_float(Float f) { using default_ops::eval_add; typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type; - if(f == 0) { m_data = limb_type(0); @@ -224,9 +262,13 @@ public: return *this; } #endif - +#ifdef BOOST_HAS_FLOAT128 + template <class Float> + typename boost::enable_if_c<is_floating_point<Float>::value && !is_same<Float, __float128>::value, cpp_bin_float&>::type assign_float(Float f) +#else template <class Float> typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f) +#endif { BOOST_MATH_STD_USING using default_ops::eval_add; diff --git a/boost/multiprecision/cpp_bin_float/transcendental.hpp b/boost/multiprecision/cpp_bin_float/transcendental.hpp index 066bc458e4..604ed85159 100644 --- a/boost/multiprecision/cpp_bin_float/transcendental.hpp +++ b/boost/multiprecision/cpp_bin_float/transcendental.hpp @@ -110,10 +110,19 @@ void eval_exp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> // rounds up, in that situation t ends up negative at this point which breaks our invariants below: t = limb_type(0); } - BOOST_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0); Exponent k, nn; eval_convert_to(&nn, n); + + if (nn == (std::numeric_limits<Exponent>::max)()) + { + // The result will necessarily oveflow: + res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); + return; + } + + BOOST_ASSERT(t.compare(default_ops::get_constant_ln2<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >()) < 0); + k = nn ? Exponent(1) << (msb(nn) / 2) : 0; eval_ldexp(t, t, -k); diff --git a/boost/multiprecision/cpp_dec_float.hpp b/boost/multiprecision/cpp_dec_float.hpp index f9e6a22189..6e1509289d 100644 --- a/boost/multiprecision/cpp_dec_float.hpp +++ b/boost/multiprecision/cpp_dec_float.hpp @@ -255,7 +255,11 @@ public: } template <class F> - cpp_dec_float(const F val, typename enable_if<is_floating_point<F> >::type* = 0) : + cpp_dec_float(const F val, typename enable_if_c<is_floating_point<F>::value +#ifdef BOOST_HAS_FLOAT128 + && !boost::is_same<F, __float128>::value +#endif + >::type* = 0) : data(), exp (static_cast<ExponentType>(0)), neg (false), @@ -2892,7 +2896,7 @@ template <unsigned Digits10, class ExponentType, class Allocator, class ArgType> inline void eval_scalbn(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val, ArgType e_) { using default_ops::eval_multiply; - const ExponentType e = e_; + const ExponentType e = static_cast<ExponentType>(e_); cpp_dec_float<Digits10, ExponentType, Allocator> t(1.0, e); eval_multiply(result, val, t); } diff --git a/boost/multiprecision/cpp_int/multiply.hpp b/boost/multiprecision/cpp_int/multiply.hpp index afe1db7a9f..151b2294c7 100644 --- a/boost/multiprecision/cpp_int/multiply.hpp +++ b/boost/multiprecision/cpp_int/multiply.hpp @@ -64,10 +64,10 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& /*result*/, unsigned /*required*/){} -template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> -inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, void>& result, unsigned required) +template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, class Allocator1> +inline void resize_for_carry(cpp_int_backend<MinBits1, MaxBits1, SignType1, checked, Allocator1>& result, unsigned required) { - if(result.size() != required) + if(result.size() < required) result.resize(required, required); } @@ -136,7 +136,8 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit for(unsigned i = 0; i < as; ++i) { unsigned inner_limit = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::variable ? bs : (std::min)(result.size() - i, bs); - for(unsigned j = 0; j < inner_limit; ++j) + unsigned j; + for(j = 0; j < inner_limit; ++j) { BOOST_ASSERT(i+j < result.size()); #if (!defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || !BOOST_WORKAROUND(BOOST_GCC_VERSION, <= 50100) @@ -156,9 +157,16 @@ inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBit carry >>= cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; BOOST_ASSERT(carry <= (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)); } - resize_for_carry(result, as + bs); // May throw if checking is enabled - if(i + bs < result.size()) - pr[i + bs] = static_cast<limb_type>(carry); + if(carry) + { + resize_for_carry(result, i + j + 1); // May throw if checking is enabled + if(i + j < result.size()) +#ifdef __MSVC_RUNTIME_CHECKS + pr[i + j] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0)); +#else + pr[i + j] = static_cast<limb_type>(carry); +#endif + } carry = 0; } result.normalize(); diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp index 21e8b8a3a9..c12606551f 100644 --- a/boost/multiprecision/detail/bitscan.hpp +++ b/boost/multiprecision/detail/bitscan.hpp @@ -143,9 +143,12 @@ BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> co return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask); } #ifdef BOOST_HAS_INT128 -BOOST_FORCEINLINE unsigned find_msb(unsigned __int128 mask, mpl::int_<0> const&) + +__extension__ typedef unsigned __int128 uint128_type; + +BOOST_FORCEINLINE unsigned find_msb(uint128_type mask, mpl::int_<0> const&) { - union { unsigned __int128 v; boost::uint64_t sv[2]; } val; + union { uint128_type v; boost::uint64_t sv[2]; } val; val.v = mask; #ifdef BOOST_LITTLE_ENDIAN if(val.sv[1]) @@ -157,9 +160,9 @@ BOOST_FORCEINLINE unsigned find_msb(unsigned __int128 mask, mpl::int_<0> const&) return find_msb(val.sv[1], mpl::int_<3>()); #endif } -BOOST_FORCEINLINE unsigned find_lsb(unsigned __int128 mask, mpl::int_<0> const&) +BOOST_FORCEINLINE unsigned find_lsb(uint128_type mask, mpl::int_<0> const&) { - union { unsigned __int128 v; boost::uint64_t sv[2]; } val; + union { uint128_type v; boost::uint64_t sv[2]; } val; val.v = mask; #ifdef BOOST_LITTLE_ENDIAN if(val.sv[0] == 0) diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp index 334db06a64..bfdb8bd368 100644 --- a/boost/multiprecision/detail/default_ops.hpp +++ b/boost/multiprecision/detail/default_ops.hpp @@ -1479,7 +1479,7 @@ inline typename B::exponent_type eval_ilogb(const B& val) { case FP_NAN: #ifdef FP_ILOGBNAN - return FP_ILOGBNAN; + return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)(); #else return (std::numeric_limits<typename B::exponent_type>::max)(); #endif @@ -3201,10 +3201,21 @@ inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multi return BOOST_MP_MOVE(boost::math::sinhc_pi(x)); } +using boost::multiprecision::gcd; +using boost::multiprecision::lcm; + #ifdef BOOST_MSVC #pragma warning(pop) #endif } // namespace math + +namespace integer { + +using boost::multiprecision::gcd; +using boost::multiprecision::lcm; + +} + } // namespace boost // diff --git a/boost/multiprecision/detail/functions/constants.hpp b/boost/multiprecision/detail/functions/constants.hpp index e0a2ff5fcf..48b4a5c29a 100644 --- a/boost/multiprecision/detail/functions/constants.hpp +++ b/boost/multiprecision/detail/functions/constants.hpp @@ -295,3 +295,20 @@ const T& get_constant_pi() return result; } +template <class T> +const T& get_constant_one_over_epsilon() +{ + static const bool is_init = false; + static T result; + if (is_init == false) + { + typedef typename mpl::front<typename T::unsigned_types>::type ui_type; + result = static_cast<ui_type>(1u); + eval_divide(result, std::numeric_limits<number<T> >::epsilon().backend()); + } + + constant_initializer<T, &get_constant_one_over_epsilon<T> >::do_nothing(); + + return result; +} + diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp index 460658e034..179e37f400 100644 --- a/boost/multiprecision/detail/functions/pow.hpp +++ b/boost/multiprecision/detail/functions/pow.hpp @@ -303,6 +303,16 @@ void eval_exp(T& result, const T& x) exp_type n; eval_convert_to(&n, result); + if (n == (std::numeric_limits<exp_type>::max)()) + { + // Exponent is too large to fit in our exponent type: + if (isneg) + result = ui_type(0); + else + result = std::numeric_limits<number<T> >::has_infinity ? std::numeric_limits<number<T> >::infinity().backend() : (std::numeric_limits<number<T> >::max)().backend(); + return; + } + // The scaling is 2^11 = 2048. const si_type p2 = static_cast<si_type>(si_type(1) << 11); diff --git a/boost/multiprecision/detail/functions/trig.hpp b/boost/multiprecision/detail/functions/trig.hpp index 319b708b0c..c001f955c9 100644 --- a/boost/multiprecision/detail/functions/trig.hpp +++ b/boost/multiprecision/detail/functions/trig.hpp @@ -128,7 +128,13 @@ void eval_sin(T& result, const T& x) eval_fmod(t, n_pi, t); const bool b_n_pi_is_even = eval_get_sign(t) == 0; eval_multiply(n_pi, get_constant_pi<T>()); - eval_subtract(xx, n_pi); + if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0) + { + result = ui_type(0); + return; + } + else + eval_subtract(xx, n_pi); BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific)); @@ -276,7 +282,20 @@ void eval_cos(T& result, const T& x) BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific)); eval_multiply(t, n_pi, get_constant_pi<T>()); BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific)); - eval_subtract(xx, t); + // + // If t is so large that all digits cancel the result of this subtraction + // is completely meaningless, just assume the result is zero for now... + // + // TODO We should of course do much better, see: + // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS" K C Ng 1992 + // + if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0) + { + result = ui_type(1); + return; + } + else + eval_subtract(xx, t); BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific)); // Adjust signs if the multiple of pi is not even. diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp index 9b10dd82d7..ca065bb569 100644 --- a/boost/multiprecision/detail/number_base.hpp +++ b/boost/multiprecision/detail/number_base.hpp @@ -38,8 +38,9 @@ // // Thread local storage: +// Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/ // -#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) +#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__) # define BOOST_MP_THREAD_LOCAL thread_local #else # define BOOST_MP_THREAD_LOCAL @@ -364,13 +365,22 @@ struct unmentionable typedef unmentionable* (unmentionable::*unmentionable_type)(); -template <class T> -struct expression_storage +template <class T, bool b> +struct expression_storage_base { typedef const T& type; }; template <class T> +struct expression_storage_base<T, true> +{ + typedef T type; +}; + +template <class T> +struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value> {}; + +template <class T> struct expression_storage<T*> { typedef T* type; @@ -988,6 +998,19 @@ template <class Backend, expression_template_option ExpressionTemplates> struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{}; template <class tag, class A1, class A2, class A3, class A4> struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{}; +// +// Specializations for types which do not always have numberic_limits specializations: +// +#ifdef BOOST_HAS_INT128 +template <> +struct number_category<__int128> : public mpl::int_<number_kind_integer> {}; +template <> +struct number_category<unsigned __int128> : public mpl::int_<number_kind_integer> {}; +#endif +#ifdef BOOST_HAS_FLOAT128 +template <> +struct number_category<__float128> : public mpl::int_<number_kind_floating_point> {}; +#endif template <class T> struct component_type; diff --git a/boost/multiprecision/float128.hpp b/boost/multiprecision/float128.hpp index 8de3af6519..a729523881 100644 --- a/boost/multiprecision/float128.hpp +++ b/boost/multiprecision/float128.hpp @@ -119,8 +119,10 @@ using backends::float128_backend; template<> struct number_category<backends::float128_backend> : public mpl::int_<number_kind_floating_point> {}; +#if defined(BOOST_MP_USE_QUAD) template<> struct number_category<float128_type> : public mpl::int_<number_kind_floating_point> {}; +#endif typedef number<float128_backend, et_off> float128; diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp index 266aff2285..6fd6204c4c 100644 --- a/boost/multiprecision/gmp.hpp +++ b/boost/multiprecision/gmp.hpp @@ -865,7 +865,7 @@ inline void eval_convert_to(long* result, const gmp_float<digits10>& val) BOOST_ { if(0 == mpf_fits_slong_p(val.data())) { - *result = (std::numeric_limits<unsigned long>::max)(); + *result = (std::numeric_limits<long>::max)(); *result *= mpf_sgn(val.data()); } else diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp index c3819dc561..dc61d696f2 100644 --- a/boost/multiprecision/number.hpp +++ b/boost/multiprecision/number.hpp @@ -48,6 +48,9 @@ public: (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value) && !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value +#ifdef BOOST_HAS_FLOAT128 + && !boost::is_same<V, __float128>::value +#endif >::type* = 0) { m_backend = canonical_value(v); diff --git a/boost/multiprecision/traits/is_backend.hpp b/boost/multiprecision/traits/is_backend.hpp index 9b23c86665..2a26b19df0 100644 --- a/boost/multiprecision/traits/is_backend.hpp +++ b/boost/multiprecision/traits/is_backend.hpp @@ -13,9 +13,9 @@ namespace boost{ namespace multiprecision{ namespace detail{ - BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types); - BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types); - BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types); + BOOST_MPL_HAS_XXX_TRAIT_DEF(signed_types) + BOOST_MPL_HAS_XXX_TRAIT_DEF(unsigned_types) + BOOST_MPL_HAS_XXX_TRAIT_DEF(float_types) template <class T> struct is_backend diff --git a/boost/multiprecision/traits/is_byte_container.hpp b/boost/multiprecision/traits/is_byte_container.hpp index 1efda2930e..d97428f0f2 100644 --- a/boost/multiprecision/traits/is_byte_container.hpp +++ b/boost/multiprecision/traits/is_byte_container.hpp @@ -11,8 +11,8 @@ namespace boost{ namespace multiprecision{ namespace detail{ - BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false); - BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false); + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_value_type, value_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_member_const_iterator, const_iterator, false) template <class C, bool b> struct is_byte_container_imp |