diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:41:18 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:43:11 +0900 |
commit | f763a99a501650eff2c60288aa6f10ef916d769e (patch) | |
tree | 02af7e13f9a38c888ebf340fe764cbe7dae99da9 /boost/multiprecision/gmp.hpp | |
parent | 5cde13f21d36c7224b0e13d11c4b49379ae5210d (diff) | |
download | boost-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.hpp | 211 |
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{ |