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_BN_MPFI_HPP Chris@16: #define BOOST_MATH_BN_MPFI_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include 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: template Chris@16: struct mpfi_float_backend; Chris@16: Chris@16: } // namespace backends Chris@16: Chris@16: template Chris@16: struct number_category > : public mpl::int_{}; Chris@16: Chris@16: struct interval_error : public std::runtime_error Chris@16: { Chris@16: interval_error(const std::string& s) : std::runtime_error(s) {} Chris@16: }; Chris@16: Chris@16: namespace backends{ Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: inline int mpfi_sgn(mpfi_srcptr p) Chris@16: { Chris@16: if(mpfi_is_zero(p)) Chris@16: return 0; Chris@16: if(mpfi_is_strictly_pos(p)) Chris@16: return 1; Chris@16: if(mpfi_is_strictly_neg(p)) Chris@16: return -1; Chris@16: BOOST_THROW_EXCEPTION(interval_error("Sign of interval is ambiguous.")); Chris@16: } Chris@16: Chris@16: template Chris@16: struct mpfi_float_imp; Chris@16: Chris@16: template Chris@16: struct mpfi_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: mpfi_float_imp() Chris@16: { Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: } Chris@16: mpfi_float_imp(unsigned prec) Chris@16: { Chris@16: mpfi_init2(m_data, prec); Chris@16: } Chris@16: Chris@16: mpfi_float_imp(const mpfi_float_imp& o) Chris@16: { Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: if(o.m_data[0].left._mpfr_d) Chris@16: mpfi_set(m_data, o.m_data); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_imp(mpfi_float_imp&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: m_data[0] = o.m_data[0]; Chris@16: o.m_data[0].left._mpfr_d = 0; Chris@16: } Chris@16: #endif Chris@16: mpfi_float_imp& operator = (const mpfi_float_imp& o) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: if(o.m_data[0].left._mpfr_d) Chris@16: mpfi_set(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_imp& operator = (mpfi_float_imp&& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpfi_swap(m_data, o.m_data); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: #ifdef _MPFR_H_HAVE_INTMAX_T Chris@16: mpfi_float_imp& operator = (unsigned long long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfr_set_uj(left_data(), i, GMP_RNDD); Chris@16: mpfr_set_uj(right_data(), i, GMP_RNDU); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (long long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfr_set_sj(left_data(), i, GMP_RNDD); Chris@16: mpfr_set_sj(right_data(), i, GMP_RNDU); Chris@16: return *this; Chris@16: } Chris@16: #else Chris@16: mpfi_float_imp& operator = (unsigned long long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_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: mpfi_t t; Chris@16: mpfi_init2(t, (std::max)(static_cast(std::numeric_limits::digits), static_cast(multiprecision::detail::digits10_2_2(digits10)))); Chris@16: mpfi_set_ui(m_data, 0); Chris@16: while(i) Chris@16: { Chris@16: mpfi_set_ui(t, static_cast(i & mask)); Chris@16: if(shift) Chris@16: mpfi_mul_2exp(t, t, shift); Chris@16: mpfi_add(m_data, m_data, t); Chris@16: shift += std::numeric_limits::digits; Chris@16: i >>= std::numeric_limits::digits; Chris@16: } Chris@16: mpfi_clear(t); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (long long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: bool neg = i < 0; Chris@101: *this = boost::multiprecision::detail::unsigned_abs(i); Chris@16: if(neg) Chris@16: mpfi_neg(m_data, m_data); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: mpfi_float_imp& operator = (unsigned long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfi_set_ui(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (long i) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfi_set_si(m_data, i); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (double d) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfi_set_d(m_data, d); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (long double a) Chris@16: { Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: mpfr_set_ld(left_data(), a, GMP_RNDD); Chris@16: mpfr_set_ld(right_data(), a, GMP_RNDU); Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_imp& operator = (const char* s) Chris@16: { Chris@101: using default_ops::eval_fpclassify; Chris@101: Chris@16: if(m_data[0].left._mpfr_d == 0) Chris@16: mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision())); Chris@16: Chris@16: if(s && (*s == '{')) Chris@16: { Chris@16: mpfr_float_backend a, b; Chris@16: std::string part; Chris@16: const char* p = ++s; Chris@16: while(*p && (*p != ',') && (*p != '}')) Chris@16: ++p; Chris@16: part.assign(s + 1, p); Chris@16: a = part.c_str(); Chris@16: s = p; Chris@16: if(*p && (*p != '}')) Chris@16: { Chris@16: ++p; Chris@16: while(*p && (*p != ',') && (*p != '}')) Chris@16: ++p; Chris@16: part.assign(s + 1, p); Chris@16: } Chris@16: else Chris@16: part.erase(); Chris@16: b = part.c_str(); Chris@16: Chris@101: if(eval_fpclassify(a) == (int)FP_NAN) Chris@101: { Chris@101: mpfi_set_fr(this->data(), a.data()); Chris@101: } Chris@101: else if(eval_fpclassify(b) == (int)FP_NAN) Chris@101: { Chris@101: mpfi_set_fr(this->data(), b.data()); Chris@101: } Chris@101: else Chris@101: { Chris@101: if(a.compare(b) > 0) Chris@101: { Chris@101: BOOST_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end).")); Chris@101: } Chris@101: mpfi_interv_fr(m_data, a.data(), b.data()); Chris@101: } Chris@16: } Chris@16: else if(mpfi_set_str(m_data, s, 10) != 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number."))); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: void swap(mpfi_float_imp& o) BOOST_NOEXCEPT Chris@16: { Chris@16: mpfi_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].left._mpfr_d); Chris@16: Chris@16: mpfr_float_backend a, b; Chris@16: Chris@16: mpfi_get_left(a.data(), m_data); Chris@16: mpfi_get_right(b.data(), m_data); Chris@16: Chris@16: if(a.compare(b) == 0) Chris@16: return a.str(digits, f); Chris@16: Chris@16: return "{" + a.str(digits, f) + "," + b.str(digits, f) + "}"; Chris@16: } Chris@16: ~mpfi_float_imp() BOOST_NOEXCEPT Chris@16: { Chris@16: if(m_data[0].left._mpfr_d) Chris@16: mpfi_clear(m_data); Chris@16: } Chris@16: void negate() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: mpfi_neg(m_data, m_data); Chris@16: } Chris@16: int compare(const mpfi_float_imp& o)const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d && o.m_data[0].left._mpfr_d); Chris@16: if(mpfr_cmp(right_data(), o.left_data()) < 0) Chris@16: return -1; Chris@16: if(mpfr_cmp(left_data(), o.right_data()) > 0) Chris@16: return 1; Chris@16: if((mpfr_cmp(left_data(), o.left_data()) == 0) && (mpfr_cmp(right_data(), o.right_data()) == 0)) Chris@16: return 0; Chris@16: BOOST_THROW_EXCEPTION(interval_error("Ambiguous comparison between two values.")); Chris@16: return 0; Chris@16: } Chris@16: template Chris@16: int compare(V v)const BOOST_NOEXCEPT Chris@16: { Chris@16: mpfi_float_imp d; Chris@16: d = v; Chris@16: return compare(d); Chris@16: } Chris@16: mpfi_t& data() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return m_data; Chris@16: } Chris@16: const mpfi_t& data()const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return m_data; Chris@16: } Chris@16: mpfr_ptr left_data() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return &(m_data[0].left); Chris@16: } Chris@16: mpfr_srcptr left_data()const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return &(m_data[0].left); Chris@16: } Chris@16: mpfr_ptr right_data() BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return &(m_data[0].right); Chris@16: } Chris@16: mpfr_srcptr right_data()const BOOST_NOEXCEPT Chris@16: { Chris@16: BOOST_ASSERT(m_data[0].left._mpfr_d); Chris@16: return &(m_data[0].right); Chris@16: } Chris@16: protected: Chris@16: mpfi_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: template Chris@16: struct mpfi_float_backend : public detail::mpfi_float_imp Chris@16: { Chris@16: mpfi_float_backend() : detail::mpfi_float_imp() {} Chris@16: mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp(o) {} Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_backend(mpfi_float_backend&& o) : detail::mpfi_float_imp(static_cast&&>(o)) {} Chris@16: #endif Chris@16: template Chris@16: mpfi_float_backend(const mpfi_float_backend& val, typename enable_if_c::type* = 0) Chris@16: : detail::mpfi_float_imp() Chris@16: { Chris@16: mpfi_set(this->m_data, val.data()); Chris@16: } Chris@16: template Chris@16: explicit mpfi_float_backend(const mpfi_float_backend& val, typename disable_if_c::type* = 0) Chris@16: : detail::mpfi_float_imp() Chris@16: { Chris@16: mpfi_set(this->m_data, val.data()); Chris@16: } Chris@16: mpfi_float_backend(const mpfi_t val) Chris@16: : detail::mpfi_float_imp() Chris@16: { Chris@16: mpfi_set(this->m_data, val); Chris@16: } Chris@16: mpfi_float_backend& operator=(const mpfi_float_backend& o) Chris@16: { Chris@16: *static_cast*>(this) = static_cast const&>(o); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: mpfi_float_backend(const mpfr_float_backend& val, typename enable_if_c::type* = 0) Chris@16: : detail::mpfi_float_imp() Chris@16: { Chris@16: mpfi_set_fr(this->m_data, val.data()); Chris@16: } Chris@16: template Chris@16: mpfi_float_backend& operator=(const mpfr_float_backend& val) Chris@16: { Chris@16: mpfi_set_fr(this->m_data, val.data()); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: explicit mpfi_float_backend(const mpfr_float_backend& val, typename disable_if_c::type* = 0) Chris@16: : detail::mpfi_float_imp() Chris@16: { Chris@16: mpfi_set_fr(this->m_data, val.data()); Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_backend& operator=(mpfi_float_backend&& 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: mpfi_float_backend& operator=(const V& v) Chris@16: { Chris@16: *static_cast*>(this) = v; Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_backend& operator=(const mpfi_t val) Chris@16: { Chris@16: mpfi_set(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: // We don't change our precision here, this is a fixed precision type: Chris@16: template Chris@16: mpfi_float_backend& operator=(const mpfi_float_backend& val) Chris@16: { Chris@16: mpfi_set(this->m_data, val.data()); Chris@16: return *this; Chris@16: } Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct mpfi_float_backend<0> : public detail::mpfi_float_imp<0> Chris@16: { Chris@16: mpfi_float_backend() : detail::mpfi_float_imp<0>() {} Chris@16: mpfi_float_backend(const mpfi_t val) Chris@16: : detail::mpfi_float_imp<0>(mpfi_get_prec(val)) Chris@16: { Chris@16: mpfi_set(this->m_data, val); Chris@16: } Chris@16: mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<0>(o) {} Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_backend(mpfi_float_backend&& o) BOOST_NOEXCEPT : detail::mpfi_float_imp<0>(static_cast&&>(o)) {} Chris@16: #endif Chris@16: mpfi_float_backend(const mpfi_float_backend& o, unsigned digits10) Chris@16: : detail::mpfi_float_imp<0>(digits10) Chris@16: { Chris@16: *this = o; Chris@16: } Chris@16: template Chris@16: mpfi_float_backend(const mpfi_float_backend& val) Chris@16: : detail::mpfi_float_imp<0>(mpfi_get_prec(val.data())) Chris@16: { Chris@16: mpfi_set(this->m_data, val.data()); Chris@16: } Chris@16: mpfi_float_backend& operator=(const mpfi_float_backend& o) Chris@16: { Chris@16: mpfi_set_prec(this->m_data, mpfi_get_prec(o.data())); Chris@16: mpfi_set(this->m_data, o.data()); Chris@16: return *this; Chris@16: } Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: mpfi_float_backend& operator=(mpfi_float_backend&& 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: mpfi_float_backend& operator=(const V& v) Chris@16: { Chris@16: *static_cast*>(this) = v; Chris@16: return *this; Chris@16: } Chris@16: mpfi_float_backend& operator=(const mpfi_t val) Chris@16: { Chris@16: mpfi_set_prec(this->m_data, mpfi_get_prec(val)); Chris@16: mpfi_set(this->m_data, val); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: mpfi_float_backend& operator=(const mpfi_float_backend& val) Chris@16: { Chris@16: mpfi_set_prec(this->m_data, mpfi_get_prec(val.data())); Chris@16: mpfi_set(this->m_data, val.data()); 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(mpfi_get_prec(this->m_data)); Chris@16: } Chris@16: void precision(unsigned digits10) BOOST_NOEXCEPT Chris@16: { Chris@16: mpfi_set_prec(this->m_data, multiprecision::detail::digits2_2_10((digits10))); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline typename enable_if, bool>::type eval_eq(const mpfi_float_backend& 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, bool>::type eval_lt(const mpfi_float_backend& 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, bool>::type eval_gt(const mpfi_float_backend& 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(mpfi_float_backend& result, const mpfi_float_backend& o) Chris@16: { Chris@16: mpfi_add(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& result, const mpfi_float_backend& o) Chris@16: { Chris@16: mpfi_sub(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& result, const mpfi_float_backend& o) Chris@16: { Chris@16: if((void*)&result == (void*)&o) Chris@16: mpfi_sqr(result.data(), o.data()); Chris@16: else Chris@16: mpfi_mul(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& result, const mpfi_float_backend& o) Chris@16: { Chris@16: mpfi_div(result.data(), result.data(), o.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& result, unsigned long i) Chris@16: { Chris@16: mpfi_add_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& result, unsigned long i) Chris@16: { Chris@16: mpfi_sub_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& result, unsigned long i) Chris@16: { Chris@16: mpfi_mul_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& result, unsigned long i) Chris@16: { Chris@16: mpfi_div_ui(result.data(), result.data(), i); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& result, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpfi_add_ui(result.data(), result.data(), i); Chris@16: else Chris@101: mpfi_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& result, long i) Chris@16: { Chris@16: if(i > 0) Chris@16: mpfi_sub_ui(result.data(), result.data(), i); Chris@16: else Chris@101: mpfi_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& result, long i) Chris@16: { Chris@101: mpfi_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: if(i < 0) Chris@16: mpfi_neg(result.data(), result.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& result, long i) Chris@16: { Chris@101: mpfi_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); Chris@16: if(i < 0) Chris@16: mpfi_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(mpfi_float_backend& a, const mpfi_float_backend& x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_add(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& a, const mpfi_float_backend& x, unsigned long y) Chris@16: { Chris@16: mpfi_add_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& a, const mpfi_float_backend& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@101: mpfi_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: else Chris@16: mpfi_add_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& a, unsigned long x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_add_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_add(mpfi_float_backend& a, long x, const mpfi_float_backend& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpfi_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); Chris@16: mpfi_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpfi_add_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& a, const mpfi_float_backend& x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_sub(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& a, const mpfi_float_backend& x, unsigned long y) Chris@16: { Chris@16: mpfi_sub_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& a, const mpfi_float_backend& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@101: mpfi_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: else Chris@16: mpfi_sub_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& a, unsigned long x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_ui_sub(a.data(), x, y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_subtract(mpfi_float_backend& a, long x, const mpfi_float_backend& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpfi_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); Chris@16: mpfi_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpfi_ui_sub(a.data(), x, y.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& a, const mpfi_float_backend& x, const mpfi_float_backend& y) Chris@16: { Chris@16: if((void*)&x == (void*)&y) Chris@16: mpfi_sqr(a.data(), x.data()); Chris@16: else Chris@16: mpfi_mul(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& a, const mpfi_float_backend& x, unsigned long y) Chris@16: { Chris@16: mpfi_mul_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& a, const mpfi_float_backend& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@16: { Chris@101: mpfi_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: a.negate(); Chris@16: } Chris@16: else Chris@16: mpfi_mul_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& a, unsigned long x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_mul_ui(a.data(), y.data(), x); Chris@16: } Chris@16: template Chris@16: inline void eval_multiply(mpfi_float_backend& a, long x, const mpfi_float_backend& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpfi_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); Chris@16: mpfi_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpfi_mul_ui(a.data(), y.data(), x); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& a, const mpfi_float_backend& x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_div(a.data(), x.data(), y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& a, const mpfi_float_backend& x, unsigned long y) Chris@16: { Chris@16: mpfi_div_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& a, const mpfi_float_backend& x, long y) Chris@16: { Chris@16: if(y < 0) Chris@16: { Chris@101: mpfi_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); Chris@16: a.negate(); Chris@16: } Chris@16: else Chris@16: mpfi_div_ui(a.data(), x.data(), y); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& a, unsigned long x, const mpfi_float_backend& y) Chris@16: { Chris@16: mpfi_ui_div(a.data(), x, y.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_divide(mpfi_float_backend& a, long x, const mpfi_float_backend& y) Chris@16: { Chris@16: if(x < 0) Chris@16: { Chris@101: mpfi_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); Chris@16: mpfi_neg(a.data(), a.data()); Chris@16: } Chris@16: else Chris@16: mpfi_ui_div(a.data(), x, y.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool eval_is_zero(const mpfi_float_backend& val) BOOST_NOEXCEPT Chris@16: { Chris@16: return 0 != mpfi_is_zero(val.data()); Chris@16: } Chris@16: template Chris@16: inline int eval_get_sign(const mpfi_float_backend& val) Chris@16: { Chris@16: return detail::mpfi_sgn(val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_convert_to(unsigned long* result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend t; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_convert_to(result, t); Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(long* result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend t; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_convert_to(result, t); Chris@16: } Chris@16: #ifdef _MPFR_H_HAVE_INTMAX_T Chris@16: template Chris@16: inline void eval_convert_to(unsigned long long* result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend t; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_convert_to(result, t); Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(long long* result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend t; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_convert_to(result, t); Chris@16: } Chris@16: #endif Chris@16: template Chris@16: inline void eval_convert_to(double* result, const mpfi_float_backend& val) BOOST_NOEXCEPT Chris@16: { Chris@16: *result = mpfi_get_d(val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_convert_to(long double* result, const mpfi_float_backend& val) BOOST_NOEXCEPT Chris@16: { Chris@16: mpfr_float_backend t; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_convert_to(result, t); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void assign_components(mpfi_float_backend& result, const mpfr_float_backend& a, const mpfr_float_backend& b) Chris@16: { Chris@101: using default_ops::eval_fpclassify; Chris@101: if(eval_fpclassify(a) == (int)FP_NAN) Chris@101: { Chris@101: mpfi_set_fr(result.data(), a.data()); Chris@101: } Chris@101: else if(eval_fpclassify(b) == (int)FP_NAN) Chris@101: { Chris@101: mpfi_set_fr(result.data(), b.data()); Chris@101: } Chris@101: else Chris@101: { Chris@101: if(a.compare(b) > 0) Chris@101: { Chris@101: BOOST_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end).")); Chris@101: } Chris@101: mpfi_interv_fr(result.data(), a.data(), b.data()); Chris@101: } Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename enable_if_c, et_on> >::value >::type Chris@16: assign_components(mpfi_float_backend& result, const V& a, const V& b) Chris@16: { Chris@16: number, et_on> x(a), y(b); Chris@16: assign_components(result, x.backend(), y.backend()); Chris@16: } Chris@16: Chris@16: // Chris@16: // Native non-member operations: Chris@16: // Chris@16: template Chris@16: inline void eval_sqrt(mpfi_float_backend& result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfi_sqrt(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_abs(mpfi_float_backend& result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfi_abs(result.data(), val.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_fabs(mpfi_float_backend& result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfi_abs(result.data(), val.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_ceil(mpfi_float_backend& result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend a, b; Chris@16: mpfr_set(a.data(), val.left_data(), GMP_RNDN); Chris@16: mpfr_set(b.data(), val.right_data(), GMP_RNDN); Chris@16: eval_ceil(a, a); Chris@16: eval_ceil(b, b); Chris@16: if(a.compare(b) != 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(interval_error("Attempt to take the ceil of a value that straddles an integer boundary.")); Chris@16: } Chris@16: mpfi_set_fr(result.data(), a.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_floor(mpfi_float_backend& result, const mpfi_float_backend& val) Chris@16: { Chris@16: mpfr_float_backend a, b; Chris@16: mpfr_set(a.data(), val.left_data(), GMP_RNDN); Chris@16: mpfr_set(b.data(), val.right_data(), GMP_RNDN); Chris@16: eval_floor(a, a); Chris@16: eval_floor(b, b); Chris@16: if(a.compare(b) != 0) Chris@16: { Chris@16: BOOST_THROW_EXCEPTION(interval_error("Attempt to take the floor of a value that straddles an integer boundary.")); Chris@16: } Chris@16: mpfi_set_fr(result.data(), a.data()); Chris@16: } Chris@16: template Chris@16: inline void eval_ldexp(mpfi_float_backend& result, const mpfi_float_backend& val, long e) Chris@16: { Chris@16: if(e > 0) Chris@16: mpfi_mul_2exp(result.data(), val.data(), e); Chris@16: else if(e < 0) Chris@16: mpfi_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(mpfi_float_backend& result, const mpfi_float_backend& val, int* e) Chris@16: { Chris@16: mpfr_float_backend t, rt; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_frexp(rt, t, e); Chris@16: eval_ldexp(result, val, -*e); Chris@16: } Chris@16: template Chris@16: inline void eval_frexp(mpfi_float_backend& result, const mpfi_float_backend& val, long* e) Chris@16: { Chris@16: mpfr_float_backend t, rt; Chris@16: mpfi_mid(t.data(), val.data()); Chris@16: eval_frexp(rt, t, e); Chris@16: eval_ldexp(result, val, -*e); Chris@16: } Chris@16: Chris@16: template Chris@16: inline int eval_fpclassify(const mpfi_float_backend& val) BOOST_NOEXCEPT Chris@16: { Chris@16: return mpfi_inf_p(val.data()) ? FP_INFINITE : mpfi_nan_p(val.data()) ? FP_NAN : mpfi_is_zero(val.data()) ? FP_ZERO : FP_NORMAL; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_pow(mpfi_float_backend& result, const mpfi_float_backend& b, const mpfi_float_backend& e) Chris@16: { Chris@16: typedef typename boost::multiprecision::detail::canonical >::type ui_type; Chris@16: using default_ops::eval_get_sign; Chris@16: int s = eval_get_sign(b); Chris@16: if(s == 0) Chris@16: { Chris@16: if(eval_get_sign(e) == 0) Chris@16: { Chris@16: result = ui_type(1); Chris@16: } Chris@16: else Chris@16: { Chris@16: result = ui_type(0); Chris@16: } Chris@16: return; Chris@16: } Chris@16: if(s < 0) Chris@16: { Chris@16: if(eval_get_sign(e) < 0) Chris@16: { Chris@16: mpfi_float_backend t1, t2; Chris@16: t1 = e; Chris@16: t1.negate(); Chris@16: eval_pow(t2, b, t1); Chris@16: t1 = ui_type(1); Chris@16: eval_divide(result, t1, t2); Chris@16: return; Chris@16: } Chris@16: typename boost::multiprecision::detail::canonical >::type an; Chris@16: try Chris@16: { Chris@16: using default_ops::eval_convert_to; Chris@16: eval_convert_to(&an, e); Chris@16: if(e.compare(an) == 0) Chris@16: { Chris@16: mpfi_float_backend pb(b); Chris@16: pb.negate(); Chris@16: eval_pow(result, pb, e); Chris@16: if(an & 1u) Chris@16: result.negate(); Chris@16: return; Chris@16: } Chris@16: } Chris@16: catch(const std::exception&) Chris@16: { Chris@16: // conversion failed, just fall through, value is not an integer. Chris@16: } Chris@16: result = std::numeric_limits, et_on> >::quiet_NaN().backend(); Chris@16: return; Chris@16: } Chris@16: mpfi_log(result.data(), b.data()); Chris@16: mpfi_mul(result.data(), result.data(), e.data()); Chris@16: mpfi_exp(result.data(), result.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_exp(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_exp(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_log(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_log(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_log10(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_log10(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_sin(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_sin(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_cos(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_cos(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_tan(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_tan(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_asin(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_asin(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_acos(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_acos(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_atan(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_atan(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_atan2(mpfi_float_backend& result, const mpfi_float_backend& arg1, const mpfi_float_backend& arg2) Chris@16: { Chris@16: mpfi_atan2(result.data(), arg1.data(), arg2.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_sinh(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_sinh(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_cosh(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_cosh(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void eval_tanh(mpfi_float_backend& result, const mpfi_float_backend& arg) Chris@16: { Chris@16: mpfi_tanh(result.data(), arg.data()); Chris@16: } Chris@16: Chris@16: } // namespace backends 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, backends::mpfi_float_backend > : 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 is_interval_number > : public mpl::true_ {}; Chris@16: Chris@16: using boost::multiprecision::backends::mpfi_float_backend; Chris@16: Chris@16: typedef number > mpfi_float_50; Chris@16: typedef number > mpfi_float_100; Chris@16: typedef number > mpfi_float_500; Chris@16: typedef number > mpfi_float_1000; Chris@16: typedef number > mpfi_float; Chris@16: Chris@16: // Chris@16: // Special interval specific functions: Chris@16: // Chris@16: template Chris@16: inline number, ExpressionTemplates> lower(const number, ExpressionTemplates>& val) Chris@16: { Chris@16: number > result; Chris@16: mpfr_set(result.backend().data(), val.backend().left_data(), GMP_RNDN); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline number, ExpressionTemplates> upper(const number, ExpressionTemplates>& val) Chris@16: { Chris@16: number > result; Chris@16: mpfr_set(result.backend().data(), val.backend().right_data(), GMP_RNDN); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline number, ExpressionTemplates> median(const number, ExpressionTemplates>& val) Chris@16: { Chris@16: number > result; Chris@16: mpfi_mid(result.backend().data(), val.backend().data()); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline number, ExpressionTemplates> width(const number, ExpressionTemplates>& val) Chris@16: { Chris@16: number > result; Chris@16: mpfi_diam_abs(result.backend().data(), val.backend().data()); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline number, ExpressionTemplates> intersect(const number, ExpressionTemplates>& a, const number, ExpressionTemplates>& b) Chris@16: { Chris@16: number, ExpressionTemplates> result; Chris@16: mpfi_intersect(result.backend().data(), a.backend().data(), b.backend().data()); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline number, ExpressionTemplates> hull(const number, ExpressionTemplates>& a, const number, ExpressionTemplates>& b) Chris@16: { Chris@16: number, ExpressionTemplates> result; Chris@16: mpfi_union(result.backend().data(), a.backend().data(), b.backend().data()); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool overlap(const number, ExpressionTemplates>& a, const number, ExpressionTemplates>& b) Chris@16: { Chris@16: return (lower(a) <= lower(b) && lower(b) <= upper(a)) || Chris@16: (lower(b) <= lower(a) && lower(a) <= upper(b)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool in(const number, ExpressionTemplates1>& a, const number, ExpressionTemplates2>& b) Chris@16: { Chris@16: return mpfi_is_inside_fr(a.backend().data(), b.backend().data()) != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool zero_in(const number, ExpressionTemplates>& a) Chris@16: { Chris@16: return mpfi_has_zero(a.backend().data()) != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool subset(const number, ExpressionTemplates>& a, const number, ExpressionTemplates>& b) Chris@16: { Chris@16: return mpfi_is_inside(a.backend().data(), b.backend().data()) != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool proper_subset(const number, ExpressionTemplates>& a, const number, ExpressionTemplates>& b) Chris@16: { Chris@16: return mpfi_is_strictly_inside(a.backend().data(), b.backend().data()) != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool empty(const number, ExpressionTemplates>& a) Chris@16: { Chris@16: return mpfi_is_empty(a.backend().data()) != 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool singleton(const number, ExpressionTemplates>& a) Chris@16: { Chris@16: return mpfr_cmp(a.backend().left_data(), a.backend().right_data()) == 0; Chris@16: } Chris@16: Chris@16: template Chris@16: struct component_type, ExpressionTemplates> > Chris@16: { Chris@16: typedef number, ExpressionTemplates> type; Chris@16: }; Chris@16: Chris@16: } // namespace multiprecision Chris@16: Chris@16: namespace math{ Chris@16: Chris@16: namespace tools{ Chris@16: Chris@16: template <> Chris@16: inline int digits() Chris@16: { Chris@16: return boost::multiprecision::backends::detail::get_default_precision(); Chris@16: } Chris@16: template <> Chris@16: inline int digits, boost::multiprecision::et_off> >() Chris@16: { Chris@16: return boost::multiprecision::backends::detail::get_default_precision(); Chris@16: } Chris@16: Chris@16: } // namespace tools Chris@16: Chris@16: namespace constants{ namespace detail{ Chris@16: Chris@16: template struct constant_pi; Chris@16: template struct constant_ln_two; Chris@16: template struct constant_euler; Chris@16: template struct constant_catalan; Chris@16: Chris@16: // Chris@16: // Initializer: ensure all our constants are initialized prior to the first call of main: Chris@16: // Chris@16: template Chris@16: struct mpfi_initializer Chris@16: { Chris@16: struct init Chris@16: { Chris@16: init() Chris@16: { Chris@16: boost::math::constants::pi(); Chris@16: boost::math::constants::ln_two(); Chris@16: boost::math::constants::euler(); Chris@16: boost::math::constants::catalan(); Chris@16: } Chris@16: void force_instantiate()const{} Chris@16: }; Chris@16: static const init initializer; Chris@16: static void force_instantiate() Chris@16: { Chris@16: initializer.force_instantiate(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename mpfi_initializer::init mpfi_initializer::initializer; Chris@16: Chris@16: template Chris@16: struct constant_pi, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> result_type; Chris@16: template Chris@16: static inline result_type const& get(const mpl::int_&) Chris@16: { Chris@16: mpfi_initializer::force_instantiate(); Chris@16: static result_type result; Chris@16: static bool has_init = false; Chris@16: if(!has_init) Chris@16: { Chris@16: has_init = true; Chris@16: mpfi_const_pi(result.backend().data()); Chris@16: } Chris@16: return result; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct constant_ln_two, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> result_type; Chris@16: template Chris@16: static inline result_type const& get(const mpl::int_&) Chris@16: { Chris@16: mpfi_initializer::force_instantiate(); Chris@16: static result_type result; Chris@16: static bool has_init = false; Chris@16: if(!has_init) Chris@16: { Chris@16: has_init = true; Chris@16: mpfi_const_log2(result.backend().data()); Chris@16: } Chris@16: return result; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct constant_euler, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> result_type; Chris@16: template Chris@16: static inline result_type const& get(const mpl::int_&) Chris@16: { Chris@16: mpfi_initializer::force_instantiate(); Chris@16: static result_type result; Chris@16: static bool has_init = false; Chris@16: if(!has_init) Chris@16: { Chris@16: has_init = true; Chris@16: mpfi_const_euler(result.backend().data()); Chris@16: } Chris@16: return result; Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct constant_catalan, ExpressionTemplates> > Chris@16: { Chris@16: typedef boost::multiprecision::number, ExpressionTemplates> result_type; Chris@16: template Chris@16: static inline result_type const& get(const mpl::int_&) Chris@16: { Chris@16: mpfi_initializer::force_instantiate(); Chris@16: static result_type result; Chris@16: static bool has_init = false; Chris@16: if(!has_init) Chris@16: { Chris@16: has_init = true; Chris@16: mpfi_const_catalan(result.backend().data()); Chris@16: } Chris@16: return result; Chris@16: } Chris@16: }; Chris@16: Chris@16: }} // namespaces 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: 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 = 0.5; Chris@16: mpfi_div_2exp(value.second.backend().data(), value.second.backend().data(), -mpfr_get_emin()); 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 = 0.5; Chris@16: mpfi_mul_2exp(value.second.backend().data(), value.second.backend().data(), mpfr_get_emax()); 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) % 301 ? 2 : 1)); Chris@16: BOOST_STATIC_CONSTEXPR int digits10 = Digits10; Chris@16: // Is this really correct??? 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 = 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: mpfi_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: mpfi_div_2exp(value.second.backend().data(), value.second.backend().data(), 1); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR long min_exponent = MPFR_EMIN_DEFAULT; Chris@16: BOOST_STATIC_CONSTEXPR long min_exponent10 = (MPFR_EMIN_DEFAULT / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR long max_exponent = MPFR_EMAX_DEFAULT; Chris@16: BOOST_STATIC_CONSTEXPR long max_exponent10 = (MPFR_EMAX_DEFAULT / 1000) * 301L; Chris@16: BOOST_STATIC_CONSTEXPR bool has_infinity = true; Chris@16: BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; 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() Chris@16: { Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: boost::multiprecision::mpfr_float_backend t; Chris@16: mpfr_set_inf(t.data(), 1); Chris@16: value.first = true; Chris@16: mpfi_set_fr(value.second.backend().data(), t.data()); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: static number_type quiet_NaN() Chris@16: { Chris@16: initializer.do_nothing(); Chris@16: static std::pair value; Chris@16: if(!value.first) Chris@16: { Chris@16: boost::multiprecision::mpfr_float_backend t; Chris@16: mpfr_set_nan(t.data()); Chris@16: value.first = true; Chris@16: mpfi_set_fr(value.second.backend().data(), t.data()); Chris@16: } Chris@16: return value.second; Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR number_type signaling_NaN() Chris@16: { Chris@16: return number_type(0); Chris@16: } Chris@16: BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); } 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_to_nearest; 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: std::numeric_limits > >::infinity(); Chris@16: std::numeric_limits > >::quiet_NaN(); 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@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 long numeric_limits, ExpressionTemplates> >::min_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::min_exponent10; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST long numeric_limits, ExpressionTemplates> >::max_exponent; Chris@16: template Chris@16: BOOST_CONSTEXPR_OR_CONST long 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: 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(0); } Chris@16: static number_type (max)() { return number_type(0); } Chris@16: static number_type lowest() { return number_type(0); } 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(0); } Chris@16: static number_type round_error() { return number_type(0); } 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(0); } Chris@16: static number_type quiet_NaN() { return number_type(0); } Chris@16: static number_type signaling_NaN() { return number_type(0); } Chris@16: static number_type denorm_min() { return number_type(0); } 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, 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: } // namespace std Chris@16: #endif