summaryrefslogtreecommitdiff
path: root/boost/multiprecision/gmp.hpp
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:41:18 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2016-10-06 10:43:11 +0900
commitf763a99a501650eff2c60288aa6f10ef916d769e (patch)
tree02af7e13f9a38c888ebf340fe764cbe7dae99da9 /boost/multiprecision/gmp.hpp
parent5cde13f21d36c7224b0e13d11c4b49379ae5210d (diff)
downloadboost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.gz
boost-f763a99a501650eff2c60288aa6f10ef916d769e.tar.bz2
boost-f763a99a501650eff2c60288aa6f10ef916d769e.zip
Imported Upstream version 1.62.0upstream/1.62.0
Change-Id: I9d4c1ddb7b7d8f0069217ecc582700f9fda6dd4c Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/multiprecision/gmp.hpp')
-rw-r--r--boost/multiprecision/gmp.hpp211
1 files changed, 203 insertions, 8 deletions
diff --git a/boost/multiprecision/gmp.hpp b/boost/multiprecision/gmp.hpp
index f7d4e90961..7f01682a2a 100644
--- a/boost/multiprecision/gmp.hpp
+++ b/boost/multiprecision/gmp.hpp
@@ -7,11 +7,13 @@
#define BOOST_MATH_ER_GMP_BACKEND_HPP
#include <boost/multiprecision/number.hpp>
+#include <boost/multiprecision/debug_adaptor.hpp>
#include <boost/multiprecision/detail/integer_ops.hpp>
#include <boost/multiprecision/detail/big_lanczos.hpp>
#include <boost/multiprecision/detail/digits.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/cstdint.hpp>
+#include <boost/functional/hash_fwd.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4127)
@@ -20,6 +22,13 @@
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
+
+#if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL)
+# define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL)
+#else
+# define BOOST_MP_MPIR_VERSION 0
+#endif
+
#include <cmath>
#include <limits>
#include <climits>
@@ -564,7 +573,7 @@ struct gmp_float<0> : public detail::gmp_float_imp<0>
}
unsigned precision()const BOOST_NOEXCEPT
{
- return multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data));
+ return static_cast<unsigned>(multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data)));
}
void precision(unsigned digits10) BOOST_NOEXCEPT
{
@@ -971,16 +980,39 @@ inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& v
template <unsigned Digits10>
inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
{
+#if BOOST_MP_MPIR_VERSION >= 20600
+ mpir_si v;
+ mpf_get_d_2exp(&v, val.data());
+#else
long v;
mpf_get_d_2exp(&v, val.data());
+#endif
*e = v;
eval_ldexp(result, val, -v);
}
template <unsigned Digits10>
inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
{
+#if BOOST_MP_MPIR_VERSION >= 20600
+ mpir_si v;
+ mpf_get_d_2exp(&v, val.data());
+ *e = v;
+ eval_ldexp(result, val, -v);
+#else
mpf_get_d_2exp(e, val.data());
eval_ldexp(result, val, -*e);
+#endif
+}
+
+template <unsigned Digits10>
+inline std::size_t hash_value(const gmp_float<Digits10>& val)
+{
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_exp);
+ boost::hash_combine(result, val.data()[0]._mp_size);
+ return result;
}
struct gmp_int
@@ -1637,7 +1669,7 @@ inline unsigned eval_lsb(const gmp_int& val)
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- return mpz_scan1(val.data(), 0);
+ return static_cast<unsigned>(mpz_scan1(val.data(), 0));
}
inline unsigned eval_msb(const gmp_int& val)
@@ -1651,7 +1683,7 @@ inline unsigned eval_msb(const gmp_int& val)
{
BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
}
- return mpz_sizeinbase(val.data(), 2) - 1;
+ return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1);
}
inline bool eval_bit_test(const gmp_int& val, unsigned index)
@@ -1731,6 +1763,16 @@ inline typename enable_if<
mpz_powm_ui(result.data(), base.data(), p, m.data());
}
+inline std::size_t hash_value(const gmp_int& val)
+{
+ // We should really use mpz_limbs_read here, but that's unsupported on older versions:
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_size);
+ return result;
+}
+
struct gmp_rational;
void eval_add(gmp_rational& t, const gmp_rational& o);
@@ -2094,6 +2136,17 @@ inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int c
mpq_canonicalize(result.data());
}
+inline std::size_t hash_value(const gmp_rational& val)
+{
+ std::size_t result = 0;
+ for(int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]);
+ for(int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i)
+ boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]);
+ boost::hash_combine(result, val.data()[0]._mp_num._mp_size);
+ return result;
+}
+
//
// Some member functions that are dependent upon previous code go here:
//
@@ -2212,10 +2265,10 @@ inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
return result;
}
-#ifdef BOOST_NO_SFINAE_EXPR
-
namespace detail{
+#ifdef BOOST_NO_SFINAE_EXPR
+
template<>
struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
template<>
@@ -2227,10 +2280,46 @@ struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_ {};
template<unsigned D1, unsigned D2>
struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_ {};
-}
-
#endif
+template <>
+struct digits2<number<gmp_float<0>, et_on> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<gmp_float<0>, et_off> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+template <>
+struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> >
+{
+ static long value()
+ {
+ return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
+ }
+};
+
+}
+
template<>
struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer>{};
template<>
@@ -2247,7 +2336,113 @@ typedef number<gmp_float<0> > mpf_float;
typedef number<gmp_int > mpz_int;
typedef number<gmp_rational > mpq_rational;
-}} // namespaces
+} // namespace multiprecision
+
+namespace math { namespace tools{
+
+ template <>
+ inline int digits<boost::multiprecision::mpf_float>()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
+ }
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
+ }
+
+ template <>
+ inline boost::multiprecision::mpf_float
+ max_value<boost::multiprecision::mpf_float>()
+ {
+ boost::multiprecision::mpf_float result(0.5);
+ mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::mpf_float
+ min_value<boost::multiprecision::mpf_float>()
+ {
+ boost::multiprecision::mpf_float result(0.5);
+ mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::min)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
+ max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+ {
+ boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
+ mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
+ min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
+ {
+ boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
+ mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
+ return result;
+ }
+
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
+ }
+ template <>
+ inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+#ifdef BOOST_MATH_NOEXCEPT
+ BOOST_NOEXCEPT
+#endif
+ {
+ return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
+ max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+ {
+ return max_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
+ min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
+ {
+ return min_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
+ max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+ {
+ return max_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+ template <>
+ inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
+ min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
+ {
+ return min_value<boost::multiprecision::mpf_float>().backend();
+ }
+
+
+}} // namespaces math::tools
+
+
+} // namespace boost
namespace std{