summaryrefslogtreecommitdiff
path: root/boost/multiprecision/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/detail')
-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
6 files changed, 93 insertions, 10 deletions
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;