Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Copyright 2011 John Maddock. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP Chris@16: #define BOOST_MATH_ER_GMP_BACKEND_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable:4127) Chris@16: #endif Chris@16: #include Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost{ Chris@16: namespace multiprecision{ Chris@16: namespace backends{ Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: // warning C4127: conditional expression is constant Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4127) Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct gmp_float; Chris@16: struct gmp_int; Chris@16: struct gmp_rational; Chris@16: Chris@16: } // namespace backends Chris@16: Chris@16: template<> Chris@16: struct number_category : public mpl::int_{}; Chris@16: template<> Chris@16: struct number_category : public mpl::int_{}; Chris@16: template Chris@16: struct number_category > : public mpl::int_{}; Chris@16: Chris@16: namespace backends{ Chris@16: // Chris@16: // Within this file, the only functions we mark as noexcept are those that manipulate Chris@16: // (but don't create) an mpf_t. All other types may allocate at pretty much any time Chris@16: // via a user-supplied allocator, and therefore throw. Chris@16: // Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: struct gmp_float_imp Chris@16: { Chris@16: typedef mpl::list signed_types; Chris@16: typedef mpl::list unsigned_types; Chris@16: typedef mpl::list float_types; Chris@16: typedef long exponent_type; Chris@16: Chris@16: gmp_float_imp() BOOST_NOEXCEPT {} Chris@16: Chris@16: gmp_float_imp(const gmp_float_imp& o) Chris@16: { Chris@16: // Chris@16: // We have to do an init followed by a set here, otherwise *this may be at Chris@16: // a lower precision than o: seems like mpf_init_set copies just enough bits Chris@16: // to get the right value, but if it's then used in further calculations Chris@16: // things go badly wrong!! Chris@16: // Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: if(o.m_data[0]._mp_d) Chris@16: mpf_set(m_data, o.m_data); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: m_data[0] = o.m_data[0]; Chris@16: o.m_data[0]._mp_d = 0; Chris@16: } Chris@16: #endif Chris@16: gmp_float_imp& operator = (const gmp_float_imp& o) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: if(o.m_data[0]._mp_d) Chris@16: mpf_set(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float_imp& operator = (gmp_float_imp&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpf_swap(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: gmp_float_imp& operator = (unsigned long long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); Chris@16: unsigned shift = 0; Chris@16: mpf_t t; Chris@16: mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpf_set_ui(m_data, 0); Chris@16: while(i) Chris@16: { Chris@16: mpf_set_ui(t, static_cast(i & mask)); Chris@16: if(shift) Chris@16: mpf_mul_2exp(t, t, shift); Chris@16: mpf_add(m_data, m_data, t); Chris@16: shift += std::numeric_limits::digits; Chris@16: i >>= std::numeric_limits::digits; Chris@16: } Chris@16: mpf_clear(t); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (long long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: bool neg = i < 0; Chris@101: *this = static_cast(boost::multiprecision::detail::unsigned_abs(i)); Chris@16: if(neg) Chris@16: mpf_neg(m_data, m_data); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (unsigned long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpf_set_ui(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpf_set_si(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (double d) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpf_set_d(m_data, d); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (long double a) Chris@16: { Chris@16: using std::frexp; Chris@16: using std::ldexp; Chris@16: using std::floor; Chris@16: Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: Chris@16: if (a == 0) { Chris@16: mpf_set_si(m_data, 0); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: if (a == 1) { Chris@16: mpf_set_si(m_data, 1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: BOOST_ASSERT(!(boost::math::isinf)(a)); Chris@16: BOOST_ASSERT(!(boost::math::isnan)(a)); Chris@16: Chris@16: int e; Chris@16: long double f, term; Chris@16: mpf_set_ui(m_data, 0u); Chris@16: Chris@16: f = frexp(a, &e); Chris@16: Chris@16: static const int shift = std::numeric_limits::digits - 1; Chris@16: Chris@16: while(f) Chris@16: { Chris@16: // extract int sized bits from f: Chris@16: f = ldexp(f, shift); Chris@16: term = floor(f); Chris@16: e -= shift; Chris@16: mpf_mul_2exp(m_data, m_data, shift); Chris@16: if(term > 0) Chris@16: mpf_add_ui(m_data, m_data, static_cast(term)); Chris@16: else Chris@16: mpf_sub_ui(m_data, m_data, static_cast(-term)); Chris@16: f -= term; Chris@16: } Chris@16: if(e > 0) Chris@16: mpf_mul_2exp(m_data, m_data, e); Chris@16: else if(e < 0) Chris@16: mpf_div_2exp(m_data, m_data, -e); Chris@16: return *this; Chris@16: } Chris@16: gmp_float_imp& operator = (const char* s) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: if(0 != mpf_set_str(m_data, s, 10)) Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number."))); Chris@16: return *this; Chris@16: } Chris@16: void swap(gmp_float_imp& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpf_swap(m_data, o.m_data); Chris@16: } Chris@16: std::string str(std::streamsize digits, std::ios_base::fmtflags f)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: Chris@16: bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; Chris@16: bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; Chris@16: std::streamsize org_digits(digits); Chris@16: Chris@16: if(scientific && digits) Chris@16: ++digits; Chris@16: Chris@16: std::string result; Chris@16: mp_exp_t e; Chris@16: void *(*alloc_func_ptr) (size_t); Chris@16: void *(*realloc_func_ptr) (void *, size_t, size_t); Chris@16: void (*free_func_ptr) (void *, size_t); Chris@16: mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); Chris@16: Chris@16: if(mpf_sgn(m_data) == 0) Chris@16: { Chris@16: e = 0; Chris@16: result = "0"; Chris@16: if(fixed && digits) Chris@16: ++digits; Chris@16: } Chris@16: else Chris@16: { Chris@16: char* ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); Chris@16: --e; // To match with what our formatter expects. Chris@16: if(fixed && e != -1) Chris@16: { Chris@16: // Oops we actually need a different number of digits to what we asked for: Chris@16: (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); Chris@16: digits += e + 1; Chris@16: if(digits == 0) Chris@16: { Chris@16: // We need to get *all* the digits and then possibly round up, Chris@16: // we end up with either "0" or "1" as the result. Chris@16: ps = mpf_get_str (0, &e, 10, 0, m_data); Chris@16: --e; Chris@16: unsigned offset = *ps == '-' ? 1 : 0; Chris@16: if(ps[offset] > '5') Chris@16: { Chris@16: ++e; Chris@16: ps[offset] = '1'; Chris@16: ps[offset + 1] = 0; Chris@16: } Chris@16: else if(ps[offset] == '5') Chris@16: { Chris@16: unsigned i = offset + 1; Chris@16: bool round_up = false; Chris@16: while(ps[i] != 0) Chris@16: { Chris@16: if(ps[i] != '0') Chris@16: { Chris@16: round_up = true; Chris@16: break; Chris@16: } Chris@16: } Chris@16: if(round_up) Chris@16: { Chris@16: ++e; Chris@16: ps[offset] = '1'; Chris@16: ps[offset + 1] = 0; Chris@16: } Chris@16: else Chris@16: { Chris@16: ps[offset] = '0'; Chris@16: ps[offset + 1] = 0; Chris@16: } Chris@16: } Chris@16: else Chris@16: { Chris@16: ps[offset] = '0'; Chris@16: ps[offset + 1] = 0; Chris@16: } Chris@16: } Chris@16: else if(digits > 0) Chris@16: { Chris@16: ps = mpf_get_str (0, &e, 10, static_cast(digits), m_data); Chris@16: --e; // To match with what our formatter expects. Chris@16: } Chris@16: else Chris@16: { Chris@16: ps = mpf_get_str (0, &e, 10, 1, m_data); Chris@16: --e; Chris@16: unsigned offset = *ps == '-' ? 1 : 0; Chris@16: ps[offset] = '0'; Chris@16: ps[offset + 1] = 0; Chris@16: } Chris@16: } Chris@16: result = ps; Chris@16: (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); Chris@16: } Chris@16: boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0); Chris@16: return result; Chris@16: } Chris@16: ~gmp_float_imp() BOOST_NOEXCEPT Chris@16: { Chris@16: if(m_data[0]._mp_d) Chris@16: mpf_clear(m_data); Chris@16: } Chris@16: void negate() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: mpf_neg(m_data, m_data); Chris@16: } Chris@16: int compare(const gmp_float& o)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); Chris@16: return mpf_cmp(m_data, o.m_data); Chris@16: } Chris@16: int compare(long i)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return mpf_cmp_si(m_data, i); Chris@16: } Chris@16: int compare(unsigned long i)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return mpf_cmp_ui(m_data, i); Chris@16: } Chris@16: template Chris@16: typename enable_if, int>::type compare(V v)const Chris@16: { Chris@16: gmp_float d; Chris@16: d = v; Chris@16: return compare(d); Chris@16: } Chris@16: mpf_t& data() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: const mpf_t& data()const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: protected: Chris@16: mpf_t m_data; Chris@16: static unsigned& get_default_precision() BOOST_NOEXCEPT Chris@16: { Chris@16: static unsigned val = 50; Chris@16: return val; Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: struct gmp_int; Chris@16: struct gmp_rational; Chris@16: Chris@16: template Chris@16: struct gmp_float : public detail::gmp_float_imp Chris@16: { Chris@16: gmp_float() Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: } Chris@16: gmp_float(const gmp_float& o) : detail::gmp_float_imp(o) {} Chris@16: template Chris@16: gmp_float(const gmp_float& o, typename enable_if_c::type* = 0); Chris@16: template Chris@16: explicit gmp_float(const gmp_float& o, typename disable_if_c::type* = 0); Chris@16: gmp_float(const gmp_int& o); Chris@16: gmp_float(const gmp_rational& o); Chris@16: gmp_float(const mpf_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set(this->m_data, val); Chris@16: } Chris@16: gmp_float(const mpz_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set_z(this->m_data, val); Chris@16: } Chris@16: gmp_float(const mpq_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set_q(this->m_data, val); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp(static_cast&&>(o)) {} Chris@16: #endif Chris@16: gmp_float& operator=(const gmp_float& o) Chris@16: { Chris@16: *static_cast*>(this) = static_cast const&>(o); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: *static_cast*>(this) = static_cast&&>(o); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: template Chris@16: gmp_float& operator=(const gmp_float& o); Chris@16: gmp_float& operator=(const gmp_int& o); Chris@16: gmp_float& operator=(const gmp_rational& o); Chris@16: gmp_float& operator=(const mpf_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_float& operator=(const mpz_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set_z(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_float& operator=(const mpq_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set_q(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: gmp_float& operator=(const V& v) Chris@16: { Chris@16: *static_cast*>(this) = v; Chris@16: return *this; Chris@16: } Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct gmp_float<0> : public detail::gmp_float_imp<0> Chris@16: { Chris@16: gmp_float() Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: } Chris@16: gmp_float(const mpf_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set(this->m_data, val); Chris@16: } Chris@16: gmp_float(const mpz_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_z(this->m_data, val); Chris@16: } Chris@16: gmp_float(const mpq_t val) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_q(this->m_data, val); Chris@16: } Chris@16: gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o) {} Chris@16: template Chris@16: gmp_float(const gmp_float& o) Chris@16: { Chris@16: mpf_init2(this->m_data, mpf_get_prec(o.data())); Chris@16: mpf_set(this->m_data, o.data()); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast&&>(o)) {} Chris@16: #endif Chris@16: gmp_float(const gmp_int& o); Chris@16: gmp_float(const gmp_rational& o); Chris@16: gmp_float(const gmp_float& o, unsigned digits10) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: mpf_set(this->m_data, o.data()); Chris@16: } Chris@16: Chris@16: gmp_float& operator=(const gmp_float& o) Chris@16: { Chris@16: *static_cast*>(this) = static_cast const&>(o); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: *static_cast*>(this) = static_cast &&>(o); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: template Chris@16: gmp_float& operator=(const gmp_float& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: { Chris@16: mpf_init2(this->m_data, mpf_get_prec(o.data())); Chris@16: } Chris@16: else Chris@16: { Chris@16: mpf_set_prec(this->m_data, mpf_get_prec(o.data())); Chris@16: } Chris@16: mpf_set(this->m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: gmp_float& operator=(const gmp_int& o); Chris@16: gmp_float& operator=(const gmp_rational& o); Chris@16: gmp_float& operator=(const mpf_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_float& operator=(const mpz_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_z(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_float& operator=(const mpq_t val) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_q(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: gmp_float& operator=(const V& v) Chris@16: { Chris@16: *static_cast*>(this) = v; Chris@16: return *this; Chris@16: } Chris@16: static unsigned default_precision() BOOST_NOEXCEPT Chris@16: { Chris@16: return get_default_precision(); Chris@16: } Chris@16: static void default_precision(unsigned v) BOOST_NOEXCEPT Chris@16: { Chris@16: get_default_precision() = v; Chris@16: } Chris@16: unsigned precision()const BOOST_NOEXCEPT Chris@16: { Chris@16: return multiprecision::detail::digits2_2_10(mpf_get_prec(this->m_data)); Chris@16: } Chris@16: void precision(unsigned digits10) BOOST_NOEXCEPT Chris@16: { Chris@16: mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(digits10)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline typename enable_if_c::value, bool>::type eval_eq(const gmp_float& a, const T& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return a.compare(b) == 0; Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c::value, bool>::type eval_lt(const gmp_float& a, const T& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return a.compare(b) < 0; Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c::value, bool>::type eval_gt(const gmp_float& a, const T& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return a.compare(b) > 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_add(gmp_float& result, const gmp_float& o) Chris@16: { Chris@16: mpf_add(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& result, const gmp_float& o) Chris@16: { Chris@16: mpf_sub(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& result, const gmp_float& o) Chris@16: { Chris@16: mpf_mul(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline bool eval_is_zero(const gmp_float& val) BOOST_NOEXCEPT Chris@16: { Chris@16: return mpf_sgn(val.data()) == 0; Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& result, const gmp_float& o) Chris@16: { Chris@16: if(eval_is_zero(o)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_div(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& result, unsigned long i) Chris@16: { Chris@16: mpf_add_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& result, unsigned long i) Chris@16: { Chris@16: mpf_sub_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& result, unsigned long i) Chris@16: { Chris@16: mpf_mul_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& result, unsigned long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_div_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& result, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpf_add_ui(result.data(), result.data(), i); Chris@16: else Chris@16: mpf_sub_ui(result.data(), result.data(), std::abs(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& result, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpf_sub_ui(result.data(), result.data(), i); Chris@16: else Chris@16: mpf_add_ui(result.data(), result.data(), std::abs(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& result, long i) Chris@16: { Chris@16: mpf_mul_ui(result.data(), result.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpf_neg(result.data(), result.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& result, long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_div_ui(result.data(), result.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpf_neg(result.data(), result.data()); Chris@16: } Chris@16: // Chris@16: // Specialised 3 arg versions of the basic operators: Chris@16: // Chris@16: template Chris@16: inline void eval_add(gmp_float& a, const gmp_float& x, const gmp_float& y) Chris@16: { Chris@16: mpf_add(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& a, const gmp_float& x, unsigned long y) Chris@16: { Chris@16: mpf_add_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& a, const gmp_float& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@101: mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: else Chris@16: mpf_add_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& a, unsigned long x, const gmp_float& y) Chris@16: { Chris@16: mpf_add_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_add(gmp_float& a, long x, const gmp_float& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); Chris@16: mpf_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpf_add_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& a, const gmp_float& x, const gmp_float& y) Chris@16: { Chris@16: mpf_sub(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& a, const gmp_float& x, unsigned long y) Chris@16: { Chris@16: mpf_sub_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& a, const gmp_float& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@101: mpf_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: else Chris@16: mpf_sub_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& a, unsigned long x, const gmp_float& y) Chris@16: { Chris@16: mpf_ui_sub(a.data(), x, y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(gmp_float& a, long x, const gmp_float& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpf_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); Chris@16: mpf_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpf_ui_sub(a.data(), x, y.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_multiply(gmp_float& a, const gmp_float& x, const gmp_float& y) Chris@16: { Chris@16: mpf_mul(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& a, const gmp_float& x, unsigned long y) Chris@16: { Chris@16: mpf_mul_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& a, const gmp_float& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@16: { Chris@101: mpf_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: a.negate(); Chris@16: } Chris@16: else Chris@16: mpf_mul_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& a, unsigned long x, const gmp_float& y) Chris@16: { Chris@16: mpf_mul_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(gmp_float& a, long x, const gmp_float& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpf_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); Chris@16: mpf_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpf_mul_ui(a.data(), y.data(), x); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_divide(gmp_float& a, const gmp_float& x, const gmp_float& y) Chris@16: { Chris@16: if(eval_is_zero(y)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_div(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& a, const gmp_float& x, unsigned long y) Chris@16: { Chris@16: if(y == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_div_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& a, const gmp_float& x, long y) Chris@16: { Chris@16: if(y == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: if(y < 0) Chris@16: { Chris@101: mpf_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: a.negate(); Chris@16: } Chris@16: else Chris@16: mpf_div_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& a, unsigned long x, const gmp_float& y) Chris@16: { Chris@16: if(eval_is_zero(y)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpf_ui_div(a.data(), x, y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(gmp_float& a, long x, const gmp_float& y) Chris@16: { Chris@16: if(eval_is_zero(y)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: if(x < 0) Chris@16: { Chris@101: mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); Chris@16: mpf_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpf_ui_div(a.data(), x, y.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline int eval_get_sign(const gmp_float& val) BOOST_NOEXCEPT Chris@16: { Chris@16: return mpf_sgn(val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_convert_to(unsigned long* result, const gmp_float& val) BOOST_NOEXCEPT Chris@16: { Chris@16: if(0 == mpf_fits_ulong_p(val.data())) Chris@16: *result = (std::numeric_limits::max)(); Chris@16: else Chris@16: *result = mpf_get_ui(val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(long* result, const gmp_float& val) BOOST_NOEXCEPT Chris@16: { Chris@16: if(0 == mpf_fits_slong_p(val.data())) Chris@16: { Chris@16: *result = (std::numeric_limits::max)(); Chris@16: *result *= mpf_sgn(val.data()); Chris@16: } Chris@16: else Chris@16: *result = mpf_get_si(val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(double* result, const gmp_float& val) BOOST_NOEXCEPT Chris@16: { Chris@16: *result = mpf_get_d(val.data()); Chris@16: } Chris@16: #ifdef BOOST_HAS_LONG_LONG Chris@16: template Chris@16: inline void eval_convert_to(long long* result, const gmp_float& val) Chris@16: { Chris@16: gmp_float t(val); Chris@16: if(eval_get_sign(t) < 0) Chris@16: t.negate(); Chris@16: Chris@16: long digits = std::numeric_limits::digits - std::numeric_limits::digits; Chris@16: Chris@16: if(digits > 0) Chris@16: mpf_div_2exp(t.data(), t.data(), digits); Chris@16: Chris@16: if(!mpf_fits_slong_p(t.data())) Chris@16: { Chris@16: if(eval_get_sign(val) < 0) Chris@16: *result = (std::numeric_limits::min)(); Chris@16: else Chris@16: *result = (std::numeric_limits::max)(); Chris@16: return; Chris@16: }; Chris@16: Chris@16: *result = mpf_get_si(t.data()); Chris@16: while(digits > 0) Chris@16: { Chris@16: *result <<= digits; Chris@16: digits -= std::numeric_limits::digits; Chris@16: mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); Chris@16: unsigned long l = mpf_get_ui(t.data()); Chris@16: if(digits < 0) Chris@16: l >>= -digits; Chris@16: *result |= l; Chris@16: } Chris@16: if(eval_get_sign(val) < 0) Chris@16: *result = -*result; Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(unsigned long long* result, const gmp_float& val) Chris@16: { Chris@16: gmp_float t(val); Chris@16: Chris@16: long digits = std::numeric_limits::digits - std::numeric_limits::digits; Chris@16: Chris@16: if(digits > 0) Chris@16: mpf_div_2exp(t.data(), t.data(), digits); Chris@16: Chris@16: if(!mpf_fits_ulong_p(t.data())) Chris@16: { Chris@16: *result = (std::numeric_limits::max)(); Chris@16: return; Chris@16: } Chris@16: Chris@16: *result = mpf_get_ui(t.data()); Chris@16: while(digits > 0) Chris@16: { Chris@16: *result <<= digits; Chris@16: digits -= std::numeric_limits::digits; Chris@16: mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits::digits : std::numeric_limits::digits + digits); Chris@16: unsigned long l = mpf_get_ui(t.data()); Chris@16: if(digits < 0) Chris@16: l >>= -digits; Chris@16: *result |= l; Chris@16: } Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Chris@16: // Native non-member operations: Chris@16: // Chris@16: template Chris@16: inline void eval_sqrt(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_sqrt(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_abs(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_abs(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_fabs(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_abs(result.data(), val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_ceil(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_ceil(result.data(), val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_floor(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_floor(result.data(), val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_trunc(gmp_float& result, const gmp_float& val) Chris@16: { Chris@16: mpf_trunc(result.data(), val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_ldexp(gmp_float& result, const gmp_float& val, long e) Chris@16: { Chris@16: if(e > 0) Chris@16: mpf_mul_2exp(result.data(), val.data(), e); Chris@16: else if(e < 0) Chris@16: mpf_div_2exp(result.data(), val.data(), -e); Chris@16: else Chris@16: result = val; Chris@16: } Chris@16: template Chris@16: inline void eval_frexp(gmp_float& result, const gmp_float& val, int* e) Chris@16: { Chris@16: long v; Chris@16: mpf_get_d_2exp(&v, val.data()); Chris@16: *e = v; Chris@16: eval_ldexp(result, val, -v); Chris@16: } Chris@16: template Chris@16: inline void eval_frexp(gmp_float& result, const gmp_float& val, long* e) Chris@16: { Chris@16: mpf_get_d_2exp(e, val.data()); Chris@16: eval_ldexp(result, val, -*e); Chris@16: } Chris@16: Chris@16: struct gmp_int Chris@16: { Chris@16: typedef mpl::list signed_types; Chris@16: typedef mpl::list unsigned_types; Chris@16: typedef mpl::list float_types; Chris@16: Chris@16: gmp_int() Chris@16: { Chris@16: mpz_init(this->m_data); Chris@16: } Chris@16: gmp_int(const gmp_int& o) Chris@16: { Chris@16: if(o.m_data[0]._mp_d) Chris@16: mpz_init_set(m_data, o.m_data); Chris@16: else Chris@16: mpz_init(this->m_data); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_int(gmp_int&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: m_data[0] = o.m_data[0]; Chris@16: o.m_data[0]._mp_d = 0; Chris@16: } Chris@16: #endif Chris@16: explicit gmp_int(const mpf_t val) Chris@16: { Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_f(this->m_data, val); Chris@16: } Chris@16: gmp_int(const mpz_t val) Chris@16: { Chris@16: mpz_init_set(this->m_data, val); Chris@16: } Chris@16: explicit gmp_int(const mpq_t val) Chris@16: { Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_q(this->m_data, val); Chris@16: } Chris@16: template Chris@16: explicit gmp_int(const gmp_float& o) Chris@16: { Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_f(this->m_data, o.data()); Chris@16: } Chris@16: explicit gmp_int(const gmp_rational& o); Chris@16: gmp_int& operator = (const gmp_int& o) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_int& operator = (gmp_int&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpz_swap(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: gmp_int& operator = (unsigned long long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); Chris@16: unsigned shift = 0; Chris@16: mpz_t t; Chris@16: mpz_set_ui(m_data, 0); Chris@16: mpz_init_set_ui(t, 0); Chris@16: while(i) Chris@16: { Chris@16: mpz_set_ui(t, static_cast(i & mask)); Chris@16: if(shift) Chris@16: mpz_mul_2exp(t, t, shift); Chris@16: mpz_add(m_data, m_data, t); Chris@16: shift += std::numeric_limits::digits; Chris@16: i >>= std::numeric_limits::digits; Chris@16: } Chris@16: mpz_clear(t); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (long long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: bool neg = i < 0; Chris@101: *this = boost::multiprecision::detail::unsigned_abs(i); Chris@16: if(neg) Chris@16: mpz_neg(m_data, m_data); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (unsigned long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_ui(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (long i) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_si(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (double d) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_d(m_data, d); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (long double a) Chris@16: { Chris@16: using std::frexp; Chris@16: using std::ldexp; Chris@16: using std::floor; Chris@16: Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: Chris@16: if (a == 0) { Chris@16: mpz_set_si(m_data, 0); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: if (a == 1) { Chris@16: mpz_set_si(m_data, 1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: BOOST_ASSERT(!(boost::math::isinf)(a)); Chris@16: BOOST_ASSERT(!(boost::math::isnan)(a)); Chris@16: Chris@16: int e; Chris@16: long double f, term; Chris@16: mpz_set_ui(m_data, 0u); Chris@16: Chris@16: f = frexp(a, &e); Chris@16: Chris@16: static const int shift = std::numeric_limits::digits - 1; Chris@16: Chris@16: while(f) Chris@16: { Chris@16: // extract int sized bits from f: Chris@16: f = ldexp(f, shift); Chris@16: term = floor(f); Chris@16: e -= shift; Chris@16: mpz_mul_2exp(m_data, m_data, shift); Chris@16: if(term > 0) Chris@16: mpz_add_ui(m_data, m_data, static_cast(term)); Chris@16: else Chris@16: mpz_sub_ui(m_data, m_data, static_cast(-term)); Chris@16: f -= term; Chris@16: } Chris@16: if(e > 0) Chris@16: mpz_mul_2exp(m_data, m_data, e); Chris@16: else if(e < 0) Chris@16: mpz_div_2exp(m_data, m_data, -e); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator = (const char* s) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: std::size_t n = s ? std::strlen(s) : 0; Chris@16: int radix = 10; Chris@16: if(n && (*s == '0')) Chris@16: { Chris@16: if((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) Chris@16: { Chris@16: radix = 16; Chris@16: s +=2; Chris@16: n -= 2; Chris@16: } Chris@16: else Chris@16: { Chris@16: radix = 8; Chris@16: n -= 1; Chris@16: } Chris@16: } Chris@16: if(n) Chris@16: { Chris@16: if(0 != mpz_set_str(m_data, s, radix)) Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer."))); Chris@16: } Chris@16: else Chris@16: mpz_set_ui(m_data, 0); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator=(const mpf_t val) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_f(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator=(const mpz_t val) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator=(const mpq_t val) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_q(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: gmp_int& operator=(const gmp_float& o) Chris@16: { Chris@16: if(m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_f(this->m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: gmp_int& operator=(const gmp_rational& o); Chris@16: void swap(gmp_int& o) Chris@16: { Chris@16: mpz_swap(m_data, o.m_data); Chris@16: } Chris@16: std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: Chris@16: int base = 10; Chris@16: if((f & std::ios_base::oct) == std::ios_base::oct) Chris@16: base = 8; Chris@16: else if((f & std::ios_base::hex) == std::ios_base::hex) Chris@16: base = 16; Chris@16: // Chris@16: // sanity check, bases 8 and 16 are only available for positive numbers: Chris@16: // Chris@16: if((base != 10) && (mpz_sgn(m_data) < 0)) Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); Chris@16: void *(*alloc_func_ptr) (size_t); Chris@16: void *(*realloc_func_ptr) (void *, size_t, size_t); Chris@16: void (*free_func_ptr) (void *, size_t); Chris@16: const char* ps = mpz_get_str (0, base, m_data); Chris@16: std::string s = ps; Chris@16: mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); Chris@16: (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); Chris@16: Chris@16: if((base != 10) && (f & std::ios_base::showbase)) Chris@16: { Chris@16: int pos = s[0] == '-' ? 1 : 0; Chris@16: const char* pp = base == 8 ? "0" : "0x"; Chris@101: s.insert(static_cast(pos), pp); Chris@16: } Chris@16: if((f & std::ios_base::showpos) && (s[0] != '-')) Chris@101: s.insert(static_cast(0), 1, '+'); Chris@16: Chris@16: return s; Chris@16: } Chris@16: ~gmp_int() BOOST_NOEXCEPT Chris@16: { Chris@16: if(m_data[0]._mp_d) Chris@16: mpz_clear(m_data); Chris@16: } Chris@16: void negate() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: mpz_neg(m_data, m_data); Chris@16: } Chris@16: int compare(const gmp_int& o)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); Chris@16: return mpz_cmp(m_data, o.m_data); Chris@16: } Chris@16: int compare(long i)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return mpz_cmp_si(m_data, i); Chris@16: } Chris@16: int compare(unsigned long i)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return mpz_cmp_ui(m_data, i); Chris@16: } Chris@16: template Chris@16: int compare(V v)const Chris@16: { Chris@16: gmp_int d; Chris@16: d = v; Chris@16: return compare(d); Chris@16: } Chris@16: mpz_t& data() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: const mpz_t& data()const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: protected: Chris@16: mpz_t m_data; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline typename enable_if, bool>::type eval_eq(const gmp_int& a, const T& b) Chris@16: { Chris@16: return a.compare(b) == 0; Chris@16: } Chris@16: template Chris@16: inline typename enable_if, bool>::type eval_lt(const gmp_int& a, const T& b) Chris@16: { Chris@16: return a.compare(b) < 0; Chris@16: } Chris@16: template Chris@16: inline typename enable_if, bool>::type eval_gt(const gmp_int& a, const T& b) Chris@16: { Chris@16: return a.compare(b) > 0; Chris@16: } Chris@16: Chris@16: inline bool eval_is_zero(const gmp_int& val) Chris@16: { Chris@16: return mpz_sgn(val.data()) == 0; Chris@16: } Chris@16: inline void eval_add(gmp_int& t, const gmp_int& o) Chris@16: { Chris@16: mpz_add(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b) Chris@16: { Chris@16: mpz_addmul(t.data(), a.data(), b.data()); Chris@16: } Chris@16: inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b) Chris@16: { Chris@16: mpz_submul(t.data(), a.data(), b.data()); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, const gmp_int& o) Chris@16: { Chris@16: mpz_sub(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, const gmp_int& o) Chris@16: { Chris@16: mpz_mul(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, const gmp_int& o) Chris@16: { Chris@16: if(eval_is_zero(o)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, const gmp_int& o) Chris@16: { Chris@16: mpz_tdiv_r(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_add(gmp_int& t, unsigned long i) Chris@16: { Chris@16: mpz_add_ui(t.data(), t.data(), i); Chris@16: } Chris@16: inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i) Chris@16: { Chris@16: mpz_addmul_ui(t.data(), a.data(), i); Chris@16: } Chris@16: inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i) Chris@16: { Chris@16: mpz_submul_ui(t.data(), a.data(), i); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, unsigned long i) Chris@16: { Chris@16: mpz_sub_ui(t.data(), t.data(), i); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, unsigned long i) Chris@16: { Chris@16: mpz_mul_ui(t.data(), t.data(), i); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, unsigned long i) Chris@16: { Chris@16: mpz_tdiv_r_ui(t.data(), t.data(), i); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, unsigned long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q_ui(t.data(), t.data(), i); Chris@16: } Chris@16: inline void eval_add(gmp_int& t, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_add_ui(t.data(), t.data(), i); Chris@16: else Chris@101: mpz_sub_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_addmul_ui(t.data(), a.data(), i); Chris@16: else Chris@101: mpz_submul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_submul_ui(t.data(), a.data(), i); Chris@16: else Chris@101: mpz_addmul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_sub_ui(t.data(), t.data(), i); Chris@16: else Chris@101: mpz_add_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, long i) Chris@16: { Chris@16: mpz_mul_ui(t.data(), t.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpz_neg(t.data(), t.data()); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, long i) Chris@16: { Chris@16: mpz_tdiv_r_ui(t.data(), t.data(), std::abs(i)); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q_ui(t.data(), t.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpz_neg(t.data(), t.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_left_shift(gmp_int& t, UI i) Chris@16: { Chris@16: mpz_mul_2exp(t.data(), t.data(), static_cast(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_right_shift(gmp_int& t, UI i) Chris@16: { Chris@16: mpz_fdiv_q_2exp(t.data(), t.data(), static_cast(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i) Chris@16: { Chris@16: mpz_mul_2exp(t.data(), v.data(), static_cast(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i) Chris@16: { Chris@16: mpz_fdiv_q_2exp(t.data(), v.data(), static_cast(i)); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_and(gmp_int& result, const gmp_int& v) Chris@16: { Chris@16: mpz_and(result.data(), result.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_or(gmp_int& result, const gmp_int& v) Chris@16: { Chris@16: mpz_ior(result.data(), result.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v) Chris@16: { Chris@16: mpz_xor(result.data(), result.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o) Chris@16: { Chris@16: mpz_add(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o) Chris@16: { Chris@16: mpz_sub(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o) Chris@16: { Chris@16: mpz_mul(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o) Chris@16: { Chris@16: if(eval_is_zero(o)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o) Chris@16: { Chris@16: mpz_tdiv_r(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i) Chris@16: { Chris@16: mpz_add_ui(t.data(), p.data(), i); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i) Chris@16: { Chris@16: mpz_sub_ui(t.data(), p.data(), i); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i) Chris@16: { Chris@16: mpz_mul_ui(t.data(), p.data(), i); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i) Chris@16: { Chris@16: mpz_tdiv_r_ui(t.data(), p.data(), i); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q_ui(t.data(), p.data(), i); Chris@16: } Chris@16: inline void eval_add(gmp_int& t, const gmp_int& p, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_add_ui(t.data(), p.data(), i); Chris@16: else Chris@101: mpz_sub_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_subtract(gmp_int& t, const gmp_int& p, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpz_sub_ui(t.data(), p.data(), i); Chris@16: else Chris@101: mpz_add_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: inline void eval_multiply(gmp_int& t, const gmp_int& p, long i) Chris@16: { Chris@16: mpz_mul_ui(t.data(), p.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpz_neg(t.data(), t.data()); Chris@16: } Chris@16: inline void eval_modulus(gmp_int& t, const gmp_int& p, long i) Chris@16: { Chris@16: mpz_tdiv_r_ui(t.data(), p.data(), std::abs(i)); Chris@16: } Chris@16: inline void eval_divide(gmp_int& t, const gmp_int& p, long i) Chris@16: { Chris@16: if(i == 0) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpz_tdiv_q_ui(t.data(), p.data(), std::abs(i)); Chris@16: if(i < 0) Chris@16: mpz_neg(t.data(), t.data()); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v) Chris@16: { Chris@16: mpz_and(result.data(), u.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v) Chris@16: { Chris@16: mpz_ior(result.data(), u.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v) Chris@16: { Chris@16: mpz_xor(result.data(), u.data(), v.data()); Chris@16: } Chris@16: Chris@16: inline void eval_complement(gmp_int& result, const gmp_int& u) Chris@16: { Chris@16: mpz_com(result.data(), u.data()); Chris@16: } Chris@16: Chris@16: inline int eval_get_sign(const gmp_int& val) Chris@16: { Chris@16: return mpz_sgn(val.data()); Chris@16: } Chris@16: inline void eval_convert_to(unsigned long* result, const gmp_int& val) Chris@16: { Chris@16: if(0 == mpz_fits_ulong_p(val.data())) Chris@16: { Chris@16: *result = (std::numeric_limits::max)(); Chris@16: } Chris@16: else Chris@16: *result = mpz_get_ui(val.data()); Chris@16: } Chris@16: inline void eval_convert_to(long* result, const gmp_int& val) Chris@16: { Chris@16: if(0 == mpz_fits_slong_p(val.data())) Chris@16: { Chris@16: *result = (std::numeric_limits::max)(); Chris@16: *result *= mpz_sgn(val.data()); Chris@16: } Chris@16: else Chris@16: *result = mpz_get_si(val.data()); Chris@16: } Chris@16: inline void eval_convert_to(double* result, const gmp_int& val) Chris@16: { Chris@16: *result = mpz_get_d(val.data()); Chris@16: } Chris@16: Chris@16: inline void eval_abs(gmp_int& result, const gmp_int& val) Chris@16: { Chris@16: mpz_abs(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b) Chris@16: { Chris@16: mpz_gcd(result.data(), a.data(), b.data()); Chris@16: } Chris@16: inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b) Chris@16: { Chris@16: mpz_lcm(result.data(), a.data(), b.data()); Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) Chris@16: { Chris@16: mpz_gcd_ui(result.data(), a.data(), b); Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c<(is_unsigned::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) Chris@16: { Chris@16: mpz_lcm_ui(result.data(), a.data(), b); Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c<(is_signed::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) Chris@16: { Chris@16: mpz_gcd_ui(result.data(), a.data(), std::abs(b)); Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) Chris@16: { Chris@16: mpz_lcm_ui(result.data(), a.data(), std::abs(b)); Chris@16: } Chris@16: Chris@16: inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x) Chris@16: { Chris@16: mpz_sqrtrem(s.data(), r.data(), x.data()); Chris@16: } Chris@16: Chris@16: inline unsigned eval_lsb(const gmp_int& val) Chris@16: { Chris@16: int c = eval_get_sign(val); Chris@16: if(c == 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); Chris@16: } Chris@16: if(c < 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); Chris@16: } Chris@16: return mpz_scan1(val.data(), 0); Chris@16: } Chris@16: Chris@16: inline unsigned eval_msb(const gmp_int& val) Chris@16: { Chris@16: int c = eval_get_sign(val); Chris@16: if(c == 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); Chris@16: } Chris@16: if(c < 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); Chris@16: } Chris@16: return mpz_sizeinbase(val.data(), 2) - 1; Chris@16: } Chris@16: Chris@16: inline bool eval_bit_test(const gmp_int& val, unsigned index) Chris@16: { Chris@16: return mpz_tstbit(val.data(), index) ? true : false; Chris@16: } Chris@16: Chris@16: inline void eval_bit_set(gmp_int& val, unsigned index) Chris@16: { Chris@16: mpz_setbit(val.data(), index); Chris@16: } Chris@16: Chris@16: inline void eval_bit_unset(gmp_int& val, unsigned index) Chris@16: { Chris@16: mpz_clrbit(val.data(), index); Chris@16: } Chris@16: Chris@16: inline void eval_bit_flip(gmp_int& val, unsigned index) Chris@16: { Chris@16: mpz_combit(val.data(), index); Chris@16: } Chris@16: Chris@16: inline void eval_qr(const gmp_int& x, const gmp_int& y, Chris@16: gmp_int& q, gmp_int& r) Chris@16: { Chris@16: mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) Chris@16: { Chris@16: if((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits::max)())) Chris@16: { Chris@16: return mpz_tdiv_ui(x.data(), val); Chris@16: } Chris@16: else Chris@16: { Chris@16: return default_ops::eval_integer_modulus(x, val); Chris@16: } Chris@16: } Chris@16: template Chris@16: inline typename enable_if, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) Chris@16: { Chris@16: typedef typename make_unsigned::type unsigned_type; Chris@16: return eval_integer_modulus(x, static_cast(std::abs(val))); Chris@16: } Chris@16: inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m) Chris@16: { Chris@16: if(eval_get_sign(p) < 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); Chris@16: } Chris@16: mpz_powm(result.data(), base.data(), p.data(), m.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename enable_if< Chris@16: mpl::and_< Chris@16: is_unsigned, Chris@16: mpl::bool_ Chris@16: > Chris@16: >::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) Chris@16: { Chris@16: mpz_powm_ui(result.data(), base.data(), p, m.data()); Chris@16: } Chris@16: template Chris@16: inline typename enable_if< Chris@16: mpl::and_< Chris@16: is_signed, Chris@16: mpl::bool_ Chris@16: > Chris@16: >::type eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) Chris@16: { Chris@16: if(p < 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); Chris@16: } Chris@16: mpz_powm_ui(result.data(), base.data(), p, m.data()); Chris@16: } Chris@16: Chris@16: struct gmp_rational; Chris@16: void eval_add(gmp_rational& t, const gmp_rational& o); Chris@16: Chris@16: struct gmp_rational Chris@16: { Chris@16: typedef mpl::list signed_types; Chris@16: typedef mpl::list unsigned_types; Chris@16: typedef mpl::list float_types; Chris@16: Chris@16: gmp_rational() Chris@16: { Chris@16: mpq_init(this->m_data); Chris@16: } Chris@16: gmp_rational(const gmp_rational& o) Chris@16: { Chris@16: mpq_init(m_data); Chris@16: if(o.m_data[0]._mp_num._mp_d) Chris@16: mpq_set(m_data, o.m_data); Chris@16: } Chris@16: gmp_rational(const gmp_int& o) Chris@16: { Chris@16: mpq_init(m_data); Chris@16: mpq_set_z(m_data, o.data()); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT Chris@16: { Chris@101: m_data[0] = o.m_data[0]; Chris@16: o.m_data[0]._mp_num._mp_d = 0; Chris@16: o.m_data[0]._mp_den._mp_d = 0; Chris@16: } Chris@16: #endif Chris@16: gmp_rational(const mpq_t o) Chris@16: { Chris@16: mpq_init(m_data); Chris@16: mpq_set(m_data, o); Chris@16: } Chris@16: gmp_rational(const mpz_t o) Chris@16: { Chris@16: mpq_init(m_data); Chris@16: mpq_set_z(m_data, o); Chris@16: } Chris@16: gmp_rational& operator = (const gmp_rational& o) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: gmp_rational& operator = (gmp_rational&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpq_swap(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: gmp_rational& operator = (unsigned long long i) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: unsigned long long mask = ((1uLL << std::numeric_limits::digits) - 1); Chris@16: unsigned shift = 0; Chris@16: mpq_t t; Chris@16: mpq_set_ui(m_data, 0, 1); Chris@16: mpq_init(t); Chris@16: while(i) Chris@16: { Chris@16: mpq_set_ui(t, static_cast(i & mask), 1); Chris@16: if(shift) Chris@16: mpq_mul_2exp(t, t, shift); Chris@16: mpq_add(m_data, m_data, t); Chris@16: shift += std::numeric_limits::digits; Chris@16: i >>= std::numeric_limits::digits; Chris@16: } Chris@16: mpq_clear(t); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (long long i) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: bool neg = i < 0; Chris@101: *this = boost::multiprecision::detail::unsigned_abs(i); Chris@16: if(neg) Chris@16: mpq_neg(m_data, m_data); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (unsigned long i) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set_ui(m_data, i, 1); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (long i) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set_si(m_data, i, 1); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (double d) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set_d(m_data, d); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (long double a) Chris@16: { Chris@16: using std::frexp; Chris@16: using std::ldexp; Chris@16: using std::floor; Chris@16: using default_ops::eval_add; Chris@16: using default_ops::eval_subtract; Chris@16: Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: Chris@16: if (a == 0) { Chris@16: mpq_set_si(m_data, 0, 1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: if (a == 1) { Chris@16: mpq_set_si(m_data, 1, 1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: BOOST_ASSERT(!(boost::math::isinf)(a)); Chris@16: BOOST_ASSERT(!(boost::math::isnan)(a)); Chris@16: Chris@16: int e; Chris@16: long double f, term; Chris@16: mpq_set_ui(m_data, 0, 1); Chris@16: mpq_set_ui(m_data, 0u, 1); Chris@16: gmp_rational t; Chris@16: Chris@16: f = frexp(a, &e); Chris@16: Chris@16: static const int shift = std::numeric_limits::digits - 1; Chris@16: Chris@16: while(f) Chris@16: { Chris@16: // extract int sized bits from f: Chris@16: f = ldexp(f, shift); Chris@16: term = floor(f); Chris@16: e -= shift; Chris@16: mpq_mul_2exp(m_data, m_data, shift); Chris@16: t = static_cast(term); Chris@16: eval_add(*this, t); Chris@16: f -= term; Chris@16: } Chris@16: if(e > 0) Chris@16: mpq_mul_2exp(m_data, m_data, e); Chris@16: else if(e < 0) Chris@16: mpq_div_2exp(m_data, m_data, -e); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator = (const char* s) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: if(0 != mpq_set_str(m_data, s, 10)) Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number."))); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator=(const gmp_int& o) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set_z(m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator=(const mpq_t o) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set(m_data, o); Chris@16: return *this; Chris@16: } Chris@16: gmp_rational& operator=(const mpz_t o) Chris@16: { Chris@16: if(m_data[0]._mp_den._mp_d == 0) Chris@16: mpq_init(m_data); Chris@16: mpq_set_z(m_data, o); Chris@16: return *this; Chris@16: } Chris@16: void swap(gmp_rational& o) Chris@16: { Chris@16: mpq_swap(m_data, o.m_data); Chris@16: } Chris@16: std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: // TODO make a better job of this including handling of f!! Chris@16: void *(*alloc_func_ptr) (size_t); Chris@16: void *(*realloc_func_ptr) (void *, size_t, size_t); Chris@16: void (*free_func_ptr) (void *, size_t); Chris@16: const char* ps = mpq_get_str (0, 10, m_data); Chris@16: std::string s = ps; Chris@16: mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); Chris@16: (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); Chris@16: return s; Chris@16: } Chris@16: ~gmp_rational() Chris@16: { Chris@16: if(m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d) Chris@16: mpq_clear(m_data); Chris@16: } Chris@16: void negate() Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: mpq_neg(m_data, m_data); Chris@16: } Chris@16: int compare(const gmp_rational& o)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d); Chris@16: return mpq_cmp(m_data, o.m_data); Chris@16: } Chris@16: template Chris@16: int compare(V v)const Chris@16: { Chris@16: gmp_rational d; Chris@16: d = v; Chris@16: return compare(d); Chris@16: } Chris@16: int compare(unsigned long v)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: return mpq_cmp_ui(m_data, v, 1); Chris@16: } Chris@16: int compare(long v)const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: return mpq_cmp_si(m_data, v, 1); Chris@16: } Chris@16: mpq_t& data() Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: const mpq_t& data()const Chris@16: { Chris@16: BOOST_ASSERT(m_data[0]._mp_num._mp_d); Chris@16: return m_data; Chris@16: } Chris@16: protected: Chris@16: mpq_t m_data; Chris@16: }; Chris@16: Chris@16: inline bool eval_is_zero(const gmp_rational& val) Chris@16: { Chris@16: return mpq_sgn(val.data()) == 0; Chris@16: } Chris@16: template Chris@16: inline bool eval_eq(gmp_rational& a, const T& b) Chris@16: { Chris@16: return a.compare(b) == 0; Chris@16: } Chris@16: template Chris@16: inline bool eval_lt(gmp_rational& a, const T& b) Chris@16: { Chris@16: return a.compare(b) < 0; Chris@16: } Chris@16: template Chris@16: inline bool eval_gt(gmp_rational& a, const T& b) Chris@16: { Chris@16: return a.compare(b) > 0; Chris@16: } Chris@16: Chris@16: inline void eval_add(gmp_rational& t, const gmp_rational& o) Chris@16: { Chris@16: mpq_add(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_subtract(gmp_rational& t, const gmp_rational& o) Chris@16: { Chris@16: mpq_sub(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_multiply(gmp_rational& t, const gmp_rational& o) Chris@16: { Chris@16: mpq_mul(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_divide(gmp_rational& t, const gmp_rational& o) Chris@16: { Chris@16: if(eval_is_zero(o)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpq_div(t.data(), t.data(), o.data()); Chris@16: } Chris@16: inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) Chris@16: { Chris@16: mpq_add(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) Chris@16: { Chris@16: mpq_sub(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) Chris@16: { Chris@16: mpq_mul(t.data(), p.data(), o.data()); Chris@16: } Chris@16: inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) Chris@16: { Chris@16: if(eval_is_zero(o)) Chris@16: BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); Chris@16: mpq_div(t.data(), p.data(), o.data()); Chris@16: } Chris@16: Chris@16: inline int eval_get_sign(const gmp_rational& val) Chris@16: { Chris@16: return mpq_sgn(val.data()); Chris@16: } Chris@16: inline void eval_convert_to(double* result, const gmp_rational& val) Chris@16: { Chris@101: // Chris@101: // This does not round correctly: Chris@101: // Chris@101: //*result = mpq_get_d(val.data()); Chris@101: // Chris@101: // This does: Chris@101: // Chris@101: boost::multiprecision::detail::generic_convert_rational_to_float(*result, val); Chris@16: } Chris@16: Chris@16: inline void eval_convert_to(long* result, const gmp_rational& val) Chris@16: { Chris@16: double r; Chris@16: eval_convert_to(&r, val); Chris@16: *result = static_cast(r); Chris@16: } Chris@16: Chris@16: inline void eval_convert_to(unsigned long* result, const gmp_rational& val) Chris@16: { Chris@16: double r; Chris@16: eval_convert_to(&r, val); Chris@16: *result = static_cast(r); Chris@16: } Chris@16: Chris@16: inline void eval_abs(gmp_rational& result, const gmp_rational& val) Chris@16: { Chris@16: mpq_abs(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2) Chris@16: { Chris@16: mpq_set_ui(result.data(), v1, v2); Chris@16: mpq_canonicalize(result.data()); Chris@16: } Chris@16: inline void assign_components(gmp_rational& result, long v1, long v2) Chris@16: { Chris@16: mpq_set_si(result.data(), v1, v2); Chris@16: mpq_canonicalize(result.data()); Chris@16: } Chris@16: inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2) Chris@16: { Chris@16: mpz_set(mpq_numref(result.data()), v1.data()); Chris@16: mpz_set(mpq_denref(result.data()), v2.data()); Chris@16: mpq_canonicalize(result.data()); Chris@16: } Chris@16: Chris@16: // Chris@16: // Some member functions that are dependent upon previous code go here: Chris@16: // Chris@16: template Chris@16: template Chris@16: inline gmp_float::gmp_float(const gmp_float& o, typename enable_if_c::type*) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set(this->m_data, o.data()); Chris@16: } Chris@16: template Chris@16: template Chris@16: inline gmp_float::gmp_float(const gmp_float& o, typename disable_if_c::type*) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set(this->m_data, o.data()); Chris@16: } Chris@16: template Chris@16: inline gmp_float::gmp_float(const gmp_int& o) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set_z(this->data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline gmp_float::gmp_float(const gmp_rational& o) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set_q(this->data(), o.data()); Chris@16: } Chris@16: template Chris@16: template Chris@16: inline gmp_float& gmp_float::operator=(const gmp_float& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set(this->m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: inline gmp_float& gmp_float::operator=(const gmp_int& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set_z(this->data(), o.data()); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: inline gmp_float& gmp_float::operator=(const gmp_rational& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : this->get_default_precision())); Chris@16: mpf_set_q(this->data(), o.data()); Chris@16: return *this; Chris@16: } Chris@16: inline gmp_float<0>::gmp_float(const gmp_int& o) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_z(this->data(), o.data()); Chris@16: } Chris@16: inline gmp_float<0>::gmp_float(const gmp_rational& o) Chris@16: { Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision())); Chris@16: mpf_set_q(this->data(), o.data()); Chris@16: } Chris@16: inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); Chris@16: mpf_set_z(this->data(), o.data()); Chris@16: return *this; Chris@16: } Chris@16: inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(this->get_default_precision())); Chris@16: mpf_set_q(this->data(), o.data()); Chris@16: return *this; Chris@16: } Chris@16: inline gmp_int::gmp_int(const gmp_rational& o) Chris@16: { Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_q(this->m_data, o.data()); Chris@16: } Chris@16: inline gmp_int& gmp_int::operator=(const gmp_rational& o) Chris@16: { Chris@16: if(this->m_data[0]._mp_d == 0) Chris@16: mpz_init(this->m_data); Chris@16: mpz_set_q(this->m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: } //namespace backends Chris@16: Chris@16: using boost::multiprecision::backends::gmp_int; Chris@16: using boost::multiprecision::backends::gmp_rational; Chris@16: using boost::multiprecision::backends::gmp_float; Chris@16: Chris@16: template <> Chris@16: struct component_type > Chris@16: { Chris@16: typedef number type; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline number numerator(const number& val) Chris@16: { Chris@16: number result; Chris@16: mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); Chris@16: return result; Chris@16: } Chris@16: template Chris@16: inline number denominator(const number& val) Chris@16: { Chris@16: number result; Chris@16: mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); Chris@16: return result; Chris@16: } Chris@16: Chris@16: #ifdef BOOST_NO_SFINAE_EXPR Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template<> Chris@16: struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; Chris@16: template<> Chris@16: struct is_explicitly_convertible::type, gmp_int> : public mpl::true_ {}; Chris@16: template Chris@16: struct is_explicitly_convertible, gmp_int> : public mpl::true_ {}; Chris@16: template<> Chris@16: struct is_explicitly_convertible : public mpl::true_ {}; Chris@16: template Chris@16: struct is_explicitly_convertible, gmp_float > : public mpl::true_ {}; Chris@16: Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: template<> Chris@16: struct number_category::type> : public mpl::int_{}; Chris@16: template<> Chris@16: struct number_category::type> : public mpl::int_{}; Chris@16: template<> Chris@16: struct number_category >::type> : public mpl::int_{}; Chris@16: Chris@16: Chris@16: typedef number > mpf_float_50; Chris@16: typedef number > mpf_float_100; Chris@16: typedef number > mpf_float_500; Chris@16: typedef number > mpf_float_1000; Chris@16: typedef number > mpf_float; Chris@16: typedef number mpz_int; Chris@16: typedef number mpq_rational; Chris@16: Chris@16: }} // namespaces Chris@16: Chris@16: namespace std{ Chris@16: Chris@16: // Chris@16: // numeric_limits [partial] specializations for the types declared in this header: Chris@16: // Chris@16: template Chris@16: class numeric_limits, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> number_type; Chris@16: public: Chris@16: BOOST_STATIC_CONSTEXPR bool is_specialized = true; Chris@16: // Chris@16: // min and max values chosen so as to not cause segfaults when calling Chris@16: // mpf_get_str on 64-bit Linux builds. Possibly we could use larger Chris@16: // exponent values elsewhere. Chris@16: // Chris@16: static number_type (min)() Chris@16: { Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: value.first = true; Chris@16: value.second = 1; Chris@16: mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: static number_type (max)() Chris@16: { Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: value.first = true; Chris@16: value.second = 1; Chris@16: mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits::max)() / 64 + 1); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR number_type lowest() Chris@16: { Chris@16: return -(max)(); Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR int digits = static_cast((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1)); Chris@16: BOOST_STATIC_CONSTEXPR int digits10 = Digits10; Chris@16: // Have to allow for a possible extra limb inside the gmp data structure: Chris@16: BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 2 + ((GMP_LIMB_BITS * 301L) / 1000L); Chris@16: BOOST_STATIC_CONSTEXPR bool is_signed = true; Chris@16: BOOST_STATIC_CONSTEXPR bool is_integer = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_exact = false; Chris@16: BOOST_STATIC_CONSTEXPR int radix = 2; Chris@16: static number_type epsilon() Chris@16: { Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: value.first = true; Chris@16: value.second = 1; Chris@16: mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits::digits - 1); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: // What value should this be???? Chris@16: static number_type round_error() Chris@16: { Chris@16: // returns epsilon/2 Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: value.first = true; Chris@16: value.second = 1; Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN; Chris@16: BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX; Chris@16: BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR bool has_infinity = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; Chris@16: BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; Chris@16: BOOST_STATIC_CONSTEXPR number_type infinity() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR bool is_iec559 = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_bounded = true; Chris@16: BOOST_STATIC_CONSTEXPR bool is_modulo = false; Chris@16: BOOST_STATIC_CONSTEXPR bool traps = true; Chris@16: BOOST_STATIC_CONSTEXPR bool tinyness_before = false; Chris@16: BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; Chris@16: Chris@16: private: Chris@16: struct data_initializer Chris@16: { Chris@16: data_initializer() Chris@16: { Chris@16: std::numeric_limits > >::epsilon(); Chris@16: std::numeric_limits > >::round_error(); Chris@16: (std::numeric_limits > >::min)(); Chris@16: (std::numeric_limits > >::max)(); Chris@16: } Chris@16: void do_nothing()const{} Chris@16: }; Chris@16: static const data_initializer initializer; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename numeric_limits, ExpressionTemplates> >::data_initializer numeric_limits, ExpressionTemplates> >::initializer; Chris@16: Chris@101: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@101: Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent10; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent10; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; Chris@101: template Chris@101: BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; Chris@101: Chris@101: #endif Chris@101: Chris@16: template Chris@16: class numeric_limits, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> number_type; Chris@16: public: Chris@16: BOOST_STATIC_CONSTEXPR bool is_specialized = false; Chris@16: static number_type (min)() { return number_type(); } Chris@16: static number_type (max)() { return number_type(); } Chris@16: static number_type lowest() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR int digits = 0; Chris@16: BOOST_STATIC_CONSTEXPR int digits10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_digits10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR bool is_signed = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_integer = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_exact = false; Chris@16: BOOST_STATIC_CONSTEXPR int radix = 0; Chris@16: static number_type epsilon() { return number_type(); } Chris@16: static number_type round_error() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR bool has_infinity = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; Chris@16: BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; Chris@16: static number_type infinity() { return number_type(); } Chris@16: static number_type quiet_NaN() { return number_type(); } Chris@16: static number_type signaling_NaN() { return number_type(); } Chris@16: static number_type denorm_min() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR bool is_iec559 = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_bounded = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_modulo = false; Chris@16: BOOST_STATIC_CONSTEXPR bool traps = false; Chris@16: BOOST_STATIC_CONSTEXPR bool tinyness_before = false; Chris@16: BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_signed; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_integer; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_exact; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::radix; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::min_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits, ExpressionTemplates> >::max_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_infinity; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_quiet_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_signaling_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits, ExpressionTemplates> >::has_denorm; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::has_denorm_loss; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_iec559; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_bounded; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::is_modulo; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::traps; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits, ExpressionTemplates> >::tinyness_before; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits, ExpressionTemplates> >::round_style; Chris@16: Chris@16: #endif Chris@16: Chris@16: template Chris@16: class numeric_limits > Chris@16: { Chris@16: typedef boost::multiprecision::number number_type; Chris@16: public: Chris@16: BOOST_STATIC_CONSTEXPR bool is_specialized = true; Chris@16: // Chris@16: // Largest and smallest numbers are bounded only by available memory, set Chris@16: // to zero: Chris@16: // Chris@16: static number_type (min)() Chris@16: { Chris@16: return number_type(); Chris@16: } Chris@16: static number_type (max)() Chris@16: { Chris@16: return number_type(); Chris@16: } Chris@16: static number_type lowest() { return (min)(); } Chris@16: BOOST_STATIC_CONSTEXPR int digits = INT_MAX; Chris@16: BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; Chris@16: BOOST_STATIC_CONSTEXPR bool is_signed = true; Chris@16: BOOST_STATIC_CONSTEXPR bool is_integer = true; Chris@16: BOOST_STATIC_CONSTEXPR bool is_exact = true; Chris@16: BOOST_STATIC_CONSTEXPR int radix = 2; Chris@16: static number_type epsilon() { return number_type(); } Chris@16: static number_type round_error() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR bool has_infinity = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; Chris@16: BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; Chris@16: static number_type infinity() { return number_type(); } Chris@16: static number_type quiet_NaN() { return number_type(); } Chris@16: static number_type signaling_NaN() { return number_type(); } Chris@16: static number_type denorm_min() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR bool is_iec559 = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_bounded = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_modulo = false; Chris@16: BOOST_STATIC_CONSTEXPR bool traps = false; Chris@16: BOOST_STATIC_CONSTEXPR bool tinyness_before = false; Chris@16: BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; Chris@16: Chris@16: #endif Chris@16: Chris@16: template Chris@16: class numeric_limits > Chris@16: { Chris@16: typedef boost::multiprecision::number number_type; Chris@16: public: Chris@16: BOOST_STATIC_CONSTEXPR bool is_specialized = true; Chris@16: // Chris@16: // Largest and smallest numbers are bounded only by available memory, set Chris@16: // to zero: Chris@16: // Chris@16: static number_type (min)() Chris@16: { Chris@16: return number_type(); Chris@16: } Chris@16: static number_type (max)() Chris@16: { Chris@16: return number_type(); Chris@16: } Chris@16: static number_type lowest() { return (min)(); } Chris@16: // Digits are unbounded, use zero for now: Chris@16: BOOST_STATIC_CONSTEXPR int digits = INT_MAX; Chris@16: BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2; Chris@16: BOOST_STATIC_CONSTEXPR bool is_signed = true; Chris@16: BOOST_STATIC_CONSTEXPR bool is_integer = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_exact = true; Chris@16: BOOST_STATIC_CONSTEXPR int radix = 2; Chris@16: static number_type epsilon() { return number_type(); } Chris@16: static number_type round_error() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent = 0; Chris@16: BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; Chris@16: BOOST_STATIC_CONSTEXPR bool has_infinity = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; Chris@16: BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; Chris@16: BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; Chris@16: static number_type infinity() { return number_type(); } Chris@16: static number_type quiet_NaN() { return number_type(); } Chris@16: static number_type signaling_NaN() { return number_type(); } Chris@16: static number_type denorm_min() { return number_type(); } Chris@16: BOOST_STATIC_CONSTEXPR bool is_iec559 = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_bounded = false; Chris@16: BOOST_STATIC_CONSTEXPR bool is_modulo = false; Chris@16: BOOST_STATIC_CONSTEXPR bool traps = false; Chris@16: BOOST_STATIC_CONSTEXPR bool tinyness_before = false; Chris@16: BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_digits10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_signed; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_integer; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_exact; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::radix; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::min_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST int numeric_limits >::max_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_infinity; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_quiet_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_signaling_NaN; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits >::has_denorm; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::has_denorm_loss; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_iec559; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_bounded; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::is_modulo; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::traps; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST bool numeric_limits >::tinyness_before; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits >::round_style; Chris@16: Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: } // namespace std Chris@16: Chris@16: #endif