summaryrefslogtreecommitdiff
path: root/boost/multiprecision
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision')
-rw-r--r--boost/multiprecision/cpp_bin_float.hpp58
-rw-r--r--boost/multiprecision/cpp_bin_float/transcendental.hpp11
-rw-r--r--boost/multiprecision/cpp_dec_float.hpp8
-rw-r--r--boost/multiprecision/cpp_int/multiply.hpp22
-rw-r--r--boost/multiprecision/detail/bitscan.hpp11
-rw-r--r--boost/multiprecision/detail/default_ops.hpp13
-rw-r--r--boost/multiprecision/detail/functions/constants.hpp17
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp10
-rw-r--r--boost/multiprecision/detail/functions/trig.hpp23
-rw-r--r--boost/multiprecision/detail/number_base.hpp29
-rw-r--r--boost/multiprecision/float128.hpp2
-rw-r--r--boost/multiprecision/gmp.hpp2
-rw-r--r--boost/multiprecision/number.hpp3
-rw-r--r--boost/multiprecision/traits/is_backend.hpp6
-rw-r--r--boost/multiprecision/traits/is_byte_container.hpp4
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