Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:48:49

0001 ///////////////////////////////////////////////////////////////////////////////
0002 //  Copyright 2011 John Maddock. Distributed under the Boost
0003 //  Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_MP_MPFI_HPP
0007 #define BOOST_MP_MPFI_HPP
0008 
0009 #include <algorithm>
0010 #include <cmath>
0011 #include <cstdint>
0012 #include <type_traits>
0013 #include <string>
0014 #include <boost/multiprecision/detail/standalone_config.hpp>
0015 #include <boost/multiprecision/detail/fpclassify.hpp>
0016 #include <boost/multiprecision/number.hpp>
0017 #include <boost/multiprecision/detail/digits.hpp>
0018 #include <boost/multiprecision/detail/precision.hpp>
0019 #include <boost/multiprecision/detail/atomic.hpp>
0020 #include <boost/multiprecision/traits/max_digits10.hpp>
0021 #include <boost/multiprecision/mpfr.hpp>
0022 #include <boost/multiprecision/logged_adaptor.hpp>
0023 #include <boost/multiprecision/detail/hash.hpp>
0024 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0025 #include <boost/multiprecision/detail/assert.hpp>
0026 #include <mpfi.h>
0027 
0028 #ifdef BOOST_MP_MATH_AVAILABLE
0029 #include <boost/math/constants/constants.hpp>
0030 #endif
0031 
0032 #ifndef BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION
0033 #define BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION 20
0034 #endif
0035 
0036 namespace boost {
0037 namespace multiprecision {
0038 
0039 template <unsigned digits10>
0040 struct number_category<backends::mpfi_float_backend<digits10> > : public std::integral_constant<int, number_kind_floating_point>
0041 {};
0042 
0043 struct interval_error : public std::runtime_error
0044 {
0045    interval_error(const std::string& s) : std::runtime_error(s) {}
0046 };
0047 
0048 namespace detail {
0049    template <>
0050    struct is_variable_precision<backends::mpfi_float_backend<0> > : public std::integral_constant<bool, true>
0051    {};
0052 } // namespace detail
0053 
0054 
0055 namespace backends {
0056 
0057 namespace detail {
0058 
0059 inline int mpfi_sgn(mpfi_srcptr p)
0060 {
0061    if (mpfi_is_zero(p))
0062       return 0;
0063    if (mpfi_is_strictly_pos(p))
0064       return 1;
0065    if (mpfi_is_strictly_neg(p))
0066       return -1;
0067    BOOST_MP_THROW_EXCEPTION(interval_error("Sign of interval is ambiguous."));
0068 }
0069 
0070 template <unsigned digits10>
0071 struct mpfi_float_imp;
0072 
0073 template <unsigned digits10>
0074 struct mpfi_float_imp
0075 {
0076 #ifdef BOOST_HAS_LONG_LONG
0077    using signed_types = std::tuple<long, long long>          ;
0078    using unsigned_types = std::tuple<unsigned long, unsigned long long>;
0079 #else
0080    using signed_types = std::tuple<long>         ;
0081    using unsigned_types = std::tuple<unsigned long>;
0082 #endif
0083    using float_types = std::tuple<double, long double>;
0084    using exponent_type = long                          ;
0085 
0086    mpfi_float_imp()
0087    {
0088       mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0089       mpfi_set_ui(m_data, 0u);
0090    }
0091    mpfi_float_imp(unsigned prec)
0092    {
0093       mpfi_init2(m_data, prec);
0094       mpfi_set_ui(m_data, 0u);
0095    }
0096 
0097    mpfi_float_imp(const mpfi_float_imp& o)
0098    {
0099       mpfi_init2(m_data, preserve_source_precision() ? mpfi_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0100       if (o.m_data[0].left._mpfr_d)
0101          mpfi_set(m_data, o.m_data);
0102    }
0103    template <unsigned D, mpfr_allocation_type AllocationType>
0104    mpfi_float_imp(const mpfr_float_imp<D, AllocationType>& o)
0105    {
0106       mpfi_init2(m_data, (D == 0 ? preserve_component_precision() : preserve_related_precision()) ? mpfr_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0107       if (o.data()[0]._mpfr_d)
0108          mpfi_set_fr(m_data, o.data());
0109    }
0110    // rvalue copy
0111    mpfi_float_imp(mpfi_float_imp&& o) noexcept
0112    {
0113       mpfr_prec_t binary_default_precision = boost::multiprecision::detail::digits10_2_2(get_default_precision());
0114       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfi_get_prec(o.data()) == binary_default_precision))
0115       {
0116          m_data[0]                = o.m_data[0];
0117          o.m_data[0].left._mpfr_d = nullptr;
0118       }
0119       else
0120       {
0121          // NOTE: C allocation interface must not throw:
0122          mpfi_init2(m_data, binary_default_precision);
0123          mpfi_set(m_data, o.m_data);
0124       }
0125    }
0126    mpfi_float_imp& operator=(const mpfi_float_imp& o)
0127    {
0128       if (this != &o)
0129       {
0130          if (m_data[0].left._mpfr_d == nullptr)
0131             mpfi_init2(m_data, preserve_source_precision() ? mpfi_get_prec(o.m_data) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0132          else if (preserve_source_precision() && (mpfi_get_prec(o.data()) != mpfi_get_prec(data())))
0133          {
0134             mpfi_set_prec(m_data, mpfi_get_prec(o.m_data));
0135          }
0136          mpfi_set(m_data, o.m_data);
0137       }
0138       return *this;
0139    }
0140    // rvalue assign
0141    mpfi_float_imp& operator=(mpfi_float_imp&& o) noexcept
0142    {
0143       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfi_get_prec(o.data()) == mpfi_get_prec(data())))
0144          mpfi_swap(m_data, o.m_data);
0145       else
0146          *this = static_cast<const mpfi_float_imp&>(o);
0147       return *this;
0148    }
0149 #ifdef BOOST_HAS_LONG_LONG
0150 #ifdef _MPFR_H_HAVE_INTMAX_T
0151    mpfi_float_imp& operator=(unsigned long long i)
0152    {
0153       if (m_data[0].left._mpfr_d == nullptr)
0154          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0155       mpfr_set_uj(left_data(), i, GMP_RNDD);
0156       mpfr_set_uj(right_data(), i, GMP_RNDU);
0157       return *this;
0158    }
0159    mpfi_float_imp& operator=(long long i)
0160    {
0161       if (m_data[0].left._mpfr_d == nullptr)
0162          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0163       mpfr_set_sj(left_data(), i, GMP_RNDD);
0164       mpfr_set_sj(right_data(), i, GMP_RNDU);
0165       return *this;
0166    }
0167 #else
0168    mpfi_float_imp& operator=(unsigned long long i)
0169    {
0170       if (m_data[0].left._mpfr_d == nullptr)
0171          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0172       unsigned long long mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1u);
0173       unsigned               shift = 0;
0174       mpfi_t                 t;
0175       mpfi_init2(t, (std::max)(static_cast<mpfr_prec_t>(std::numeric_limits<unsigned long long>::digits), static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10))));
0176       mpfi_set_ui(m_data, 0);
0177       while (i)
0178       {
0179          mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
0180          if (shift)
0181             mpfi_mul_2exp(t, t, shift);
0182          mpfi_add(m_data, m_data, t);
0183          shift += std::numeric_limits<unsigned long>::digits;
0184          i >>= std::numeric_limits<unsigned long>::digits;
0185       }
0186       mpfi_clear(t);
0187       return *this;
0188    }
0189    mpfi_float_imp& operator=(long long i)
0190    {
0191       if (m_data[0].left._mpfr_d == nullptr)
0192          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0193       bool neg = i < 0;
0194       *this    = boost::multiprecision::detail::unsigned_abs(i);
0195       if (neg)
0196          mpfi_neg(m_data, m_data);
0197       return *this;
0198    }
0199 #endif
0200 #endif
0201 #ifdef BOOST_HAS_INT128
0202    mpfi_float_imp& operator=(uint128_type i)
0203    {
0204       if (m_data[0].left._mpfr_d == nullptr)
0205          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0206       constexpr uint128_type mask = ((((static_cast<uint128_type>(1u) << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1u);
0207       unsigned               shift = 0;
0208       mpfi_t                 t;
0209       mpfi_init2(t, (std::max)(static_cast<mpfr_prec_t>(128), static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10))));
0210       mpfi_set_ui(m_data, 0);
0211       while (i)
0212       {
0213          mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
0214          if (shift)
0215             mpfi_mul_2exp(t, t, shift);
0216          mpfi_add(m_data, m_data, t);
0217          shift += std::numeric_limits<unsigned long>::digits;
0218          i >>= std::numeric_limits<unsigned long>::digits;
0219       }
0220       mpfi_clear(t);
0221       return *this;
0222    }
0223    mpfi_float_imp& operator=(int128_type i)
0224    {
0225       if (m_data[0].left._mpfr_d == nullptr)
0226          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0227       bool neg = i < 0;
0228       *this = boost::multiprecision::detail::unsigned_abs(i);
0229       if (neg)
0230          mpfi_neg(m_data, m_data);
0231       return *this;
0232    }
0233 #endif
0234    mpfi_float_imp& operator=(unsigned long i)
0235    {
0236       if (m_data[0].left._mpfr_d == nullptr)
0237          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0238       mpfi_set_ui(m_data, i);
0239       return *this;
0240    }
0241    mpfi_float_imp& operator=(long i)
0242    {
0243       if (m_data[0].left._mpfr_d == nullptr)
0244          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0245       mpfi_set_si(m_data, i);
0246       return *this;
0247    }
0248    mpfi_float_imp& operator=(double d)
0249    {
0250       if (m_data[0].left._mpfr_d == nullptr)
0251          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0252       mpfi_set_d(m_data, d);
0253       return *this;
0254    }
0255    mpfi_float_imp& operator=(long double a)
0256    {
0257       if (m_data[0].left._mpfr_d == nullptr)
0258          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0259       mpfr_set_ld(left_data(), a, GMP_RNDD);
0260       mpfr_set_ld(right_data(), a, GMP_RNDU);
0261       return *this;
0262    }
0263 #ifdef BOOST_HAS_FLOAT128
0264    mpfi_float_imp& operator=(float128_type a)
0265    {
0266       BOOST_MP_FLOAT128_USING
0267       if (m_data[0].left._mpfr_d == nullptr)
0268          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0269 
0270       if (a == 0)
0271       {
0272          mpfi_set_si(m_data, 0);
0273          return *this;
0274       }
0275 
0276       if (a == 1)
0277       {
0278          mpfi_set_si(m_data, 1);
0279          return *this;
0280       }
0281 
0282       BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
0283       BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
0284 
0285       int        e;
0286       float128_type f, term;
0287       mpfi_set_ui(m_data, 0u);
0288 
0289       f = frexp(a, &e);
0290 
0291       constexpr const int shift = std::numeric_limits<int>::digits - 1;
0292 
0293       while (f)
0294       {
0295          // extract int sized bits from f:
0296          f = ldexp(f, shift);
0297          term = floor(f);
0298          e -= shift;
0299          mpfi_mul_2exp(m_data, m_data, shift);
0300          if (term > 0)
0301             mpfi_add_ui(m_data, m_data, static_cast<unsigned>(term));
0302          else
0303             mpfi_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
0304          f -= term;
0305       }
0306       if (e > 0)
0307          mpfi_mul_2exp(m_data, m_data, e);
0308       else if (e < 0)
0309          mpfi_div_2exp(m_data, m_data, -e);
0310       return *this;
0311    }
0312 #endif
0313    mpfi_float_imp& operator=(const char* s)
0314    {
0315       using default_ops::eval_fpclassify;
0316 
0317       if (m_data[0].left._mpfr_d == nullptr)
0318          mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0319 
0320       if (s && (*s == '{'))
0321       {
0322          mpfr_float_backend<digits10> a, b;
0323          std::string                  part;
0324          const char*                  p = ++s;
0325          while (*p && (*p != ',') && (*p != '}'))
0326             ++p;
0327          part.assign(s, p);
0328          a = part.c_str();
0329          s = p;
0330          if (*p && (*p != '}'))
0331          {
0332             ++p;
0333             while (*p && (*p != ',') && (*p != '}'))
0334                ++p;
0335             part.assign(s + 1, p);
0336          }
0337          else
0338             part.erase();
0339          b = part.c_str();
0340 
0341          if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
0342          {
0343             mpfi_set_fr(this->data(), a.data());
0344          }
0345          else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
0346          {
0347             mpfi_set_fr(this->data(), b.data());
0348          }
0349          else
0350          {
0351             if (a.compare(b) > 0)
0352             {
0353                BOOST_MP_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
0354             }
0355             mpfi_interv_fr(m_data, a.data(), b.data());
0356          }
0357       }
0358       else if (mpfi_set_str(m_data, s, 10) != 0)
0359       {
0360          BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
0361       }
0362       return *this;
0363    }
0364    void swap(mpfi_float_imp& o) noexcept
0365    {
0366       mpfi_swap(m_data, o.m_data);
0367    }
0368    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0369    {
0370       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0371 
0372       mpfr_float_backend<digits10> a, b;
0373 
0374       mpfi_get_left(a.data(), m_data);
0375       mpfi_get_right(b.data(), m_data);
0376 
0377       if (a.compare(b) == 0)
0378          return a.str(digits, f);
0379 
0380       return "{" + a.str(digits, f) + "," + b.str(digits, f) + "}";
0381    }
0382    ~mpfi_float_imp() noexcept
0383    {
0384       if (m_data[0].left._mpfr_d)
0385          mpfi_clear(m_data);
0386    }
0387    void negate() noexcept
0388    {
0389       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0390       mpfi_neg(m_data, m_data);
0391    }
0392    int compare(const mpfi_float_imp& o) const noexcept
0393    {
0394       BOOST_MP_ASSERT(m_data[0].left._mpfr_d && o.m_data[0].left._mpfr_d);
0395       if (mpfr_cmp(right_data(), o.left_data()) < 0)
0396          return -1;
0397       if (mpfr_cmp(left_data(), o.right_data()) > 0)
0398          return 1;
0399       if ((mpfr_cmp(left_data(), o.left_data()) == 0) && (mpfr_cmp(right_data(), o.right_data()) == 0))
0400          return 0;
0401       BOOST_MP_THROW_EXCEPTION(interval_error("Ambiguous comparison between two values."));
0402       return 0;
0403    }
0404    template <class V>
0405    int compare(V v) const noexcept
0406    {
0407       mpfi_float_imp d;
0408       d = v;
0409       return compare(d);
0410    }
0411    mpfi_t& data() noexcept
0412    {
0413       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0414       return m_data;
0415    }
0416    const mpfi_t& data() const noexcept
0417    {
0418       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0419       return m_data;
0420    }
0421    mpfr_ptr left_data() noexcept
0422    {
0423       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0424       return &(m_data[0].left);
0425    }
0426    mpfr_srcptr left_data() const noexcept
0427    {
0428       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0429       return &(m_data[0].left);
0430    }
0431    mpfr_ptr right_data() noexcept
0432    {
0433       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0434       return &(m_data[0].right);
0435    }
0436    mpfr_srcptr right_data() const noexcept
0437    {
0438       BOOST_MP_ASSERT(m_data[0].left._mpfr_d);
0439       return &(m_data[0].right);
0440    }
0441 
0442  protected:
0443    mpfi_t           m_data;
0444    static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
0445    {
0446       static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFI_DEFAULT_PRECISION);
0447       return val;
0448    }
0449    static unsigned& get_default_precision() noexcept
0450    {
0451       static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
0452       return val;
0453    }
0454 #ifndef BOOST_MT_NO_ATOMIC_INT
0455    static std::atomic<variable_precision_options>& get_global_default_options() noexcept
0456 #else
0457    static variable_precision_options& get_global_default_options() noexcept
0458 #endif
0459    {
0460 #ifndef BOOST_MT_NO_ATOMIC_INT
0461       static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
0462 #else
0463       static variable_precision_optionss val{variable_precision_options::preserve_related_precision};
0464 #endif
0465       return val;
0466    }
0467    static variable_precision_options& get_default_options() noexcept
0468    {
0469       static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
0470       return val;
0471    }
0472    static bool preserve_source_precision() noexcept
0473    {
0474       return get_default_options() >= variable_precision_options::preserve_source_precision;
0475    }
0476    static bool preserve_component_precision() noexcept
0477    {
0478       return get_default_options() >= variable_precision_options::preserve_component_precision;
0479    }
0480    static bool preserve_related_precision() noexcept
0481    {
0482       return get_default_options() >= variable_precision_options::preserve_related_precision;
0483    }
0484    static bool preserve_all_precision() noexcept
0485    {
0486       return get_default_options() >= variable_precision_options::preserve_all_precision;
0487    }
0488 };
0489 
0490 } // namespace detail
0491 
0492 template <unsigned digits10>
0493 struct mpfi_float_backend : public detail::mpfi_float_imp<digits10>
0494 {
0495    mpfi_float_backend() : detail::mpfi_float_imp<digits10>() {}
0496    mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<digits10>(o) {}
0497    // rvalue copy
0498    mpfi_float_backend(mpfi_float_backend&& o) : detail::mpfi_float_imp<digits10>(static_cast<detail::mpfi_float_imp<digits10>&&>(o))
0499    {}
0500    template <unsigned D>
0501    mpfi_float_backend(const mpfi_float_backend<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0502        : detail::mpfi_float_imp<digits10>()
0503    {
0504       mpfi_set(this->m_data, val.data());
0505    }
0506    template <unsigned D, mpfr_allocation_type AllocationType>
0507    mpfi_float_backend(const mpfr_float_backend<D, AllocationType>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0508        : detail::mpfi_float_imp<digits10>(val) {}
0509 
0510    template <unsigned D>
0511    explicit mpfi_float_backend(const mpfi_float_backend<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0512        : detail::mpfi_float_imp<digits10>()
0513    {
0514       mpfi_set(this->m_data, val.data());
0515    }
0516    mpfi_float_backend(const mpfi_t val)
0517        : detail::mpfi_float_imp<digits10>()
0518    {
0519       mpfi_set(this->m_data, val);
0520    }
0521    mpfi_float_backend& operator=(const mpfi_float_backend& o)
0522    {
0523       *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10> const&>(o);
0524       return *this;
0525    }
0526    template <unsigned D>
0527    mpfi_float_backend(const mpfr_float_backend<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0528        : detail::mpfi_float_imp<digits10>()
0529    {
0530       mpfi_set_fr(this->m_data, val.data());
0531    }
0532    template <unsigned D>
0533    mpfi_float_backend& operator=(const mpfr_float_backend<D>& val)
0534    {
0535       mpfi_set_fr(this->m_data, val.data());
0536       return *this;
0537    }
0538    template <unsigned D>
0539    explicit mpfi_float_backend(const mpfr_float_backend<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0540        : detail::mpfi_float_imp<digits10>()
0541    {
0542       mpfi_set_fr(this->m_data, val.data());
0543    }
0544    // rvalue copy
0545    mpfi_float_backend& operator=(mpfi_float_backend&& o) noexcept
0546    {
0547       *static_cast<detail::mpfi_float_imp<digits10>*>(this) = static_cast<detail::mpfi_float_imp<digits10>&&>(o);
0548       return *this;
0549    }
0550    template <class V>
0551    typename std::enable_if<std::is_assignable<detail::mpfi_float_imp<digits10>, V>::value, mpfi_float_backend&>::type operator=(const V& v)
0552    {
0553       *static_cast<detail::mpfi_float_imp<digits10>*>(this) = v;
0554       return *this;
0555    }
0556    mpfi_float_backend& operator=(const mpfi_t val)
0557    {
0558       mpfi_set(this->m_data, val);
0559       return *this;
0560    }
0561    // We don't change our precision here, this is a fixed precision type:
0562    template <unsigned D>
0563    mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
0564    {
0565       mpfi_set(this->m_data, val.data());
0566       return *this;
0567    }
0568 };
0569 
0570 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
0571 void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b);
0572 
0573 template <unsigned Digits10, class V>
0574 typename std::enable_if<std::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || std::is_convertible<V, const char*>::value>::type
0575 assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b);
0576 
0577 template <>
0578 struct mpfi_float_backend<0> : public detail::mpfi_float_imp<0>
0579 {
0580    mpfi_float_backend() : detail::mpfi_float_imp<0>() {}
0581    mpfi_float_backend(const mpfi_t val)
0582        : detail::mpfi_float_imp<0>(mpfi_get_prec(val))
0583    {
0584       mpfi_set(this->m_data, val);
0585    }
0586    mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<0>(o) {}
0587 
0588    template <unsigned D, mpfr_allocation_type AllocationType>
0589    mpfi_float_backend(const mpfr_float_backend<D, AllocationType>& val)
0590        : detail::mpfi_float_imp<0>(val) {}
0591 
0592    // rvalue copy
0593    mpfi_float_backend(mpfi_float_backend&& o) noexcept : detail::mpfi_float_imp<0>(static_cast<detail::mpfi_float_imp<0>&&>(o))
0594    {}
0595    mpfi_float_backend(const mpfi_float_backend& o, unsigned digits10)
0596        : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
0597    {
0598       mpfi_set(this->m_data, o.data());
0599    }
0600    template <class V>
0601    mpfi_float_backend(const V& a, const V& b, unsigned digits10)
0602        : detail::mpfi_float_imp<0>(multiprecision::detail::digits10_2_2(digits10))
0603    {
0604       boost::multiprecision::detail::scoped_target_precision<mpfi_float_backend<0> > opts;
0605       assign_components(*this, a, b);
0606    }
0607 
0608    template <unsigned D>
0609    mpfi_float_backend(const mpfi_float_backend<D>& val)
0610        : detail::mpfi_float_imp<0>(mpfi_get_prec(val.data()))
0611    {
0612       mpfi_set(this->m_data, val.data());
0613    }
0614    mpfi_float_backend& operator=(const mpfi_float_backend& o) = default;
0615    // rvalue assign
0616    mpfi_float_backend& operator=(mpfi_float_backend&& o) noexcept = default;
0617 
0618    template <class V>
0619    mpfi_float_backend& operator=(const V& v)
0620    {
0621       constexpr unsigned d10 = std::is_floating_point<V>::value ?
0622          std::numeric_limits<V>::digits10 :
0623          std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
0624          1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
0625 
0626       if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
0627       {
0628          BOOST_IF_CONSTEXPR(std::is_floating_point<V>::value)
0629          {
0630             if (std::numeric_limits<V>::digits > mpfi_get_prec(this->data()))
0631                mpfi_set_prec(this->data(), std::numeric_limits<V>::digits);
0632          }
0633          else
0634          {
0635             if (precision() < d10)
0636                this->precision(d10);
0637          }
0638       }
0639 
0640       *static_cast<detail::mpfi_float_imp<0>*>(this) = v;
0641       return *this;
0642    }
0643    mpfi_float_backend& operator=(const mpfi_t val)
0644    {
0645       mpfi_set_prec(this->m_data, mpfi_get_prec(val));
0646       mpfi_set(this->m_data, val);
0647       return *this;
0648    }
0649    template <unsigned D>
0650    mpfi_float_backend& operator=(const mpfi_float_backend<D>& val)
0651    {
0652       mpfi_set_prec(this->m_data, mpfi_get_prec(val.data()));
0653       mpfi_set(this->m_data, val.data());
0654       return *this;
0655    }
0656    static unsigned thread_default_precision() noexcept
0657    {
0658       return get_default_precision();
0659    }
0660    static void thread_default_precision(unsigned v) noexcept
0661    {
0662       get_default_precision() = v;
0663    }
0664    static unsigned default_precision() noexcept
0665    {
0666       return get_global_default_precision();
0667    }
0668    static void default_precision(unsigned v) noexcept
0669    {
0670       get_global_default_precision() = v;
0671    }
0672    unsigned precision() const noexcept
0673    {
0674       return multiprecision::detail::digits2_2_10(mpfi_get_prec(this->m_data));
0675    }
0676    void precision(unsigned digits10) noexcept
0677    {
0678       mpfi_float_backend t(*this, digits10);
0679       this->swap(t);
0680    }
0681    //
0682    // Variable precision options:
0683    //
0684    static variable_precision_options default_variable_precision_options() noexcept
0685    {
0686       return get_global_default_options();
0687    }
0688    static variable_precision_options thread_default_variable_precision_options() noexcept
0689    {
0690       return get_default_options();
0691    }
0692    static void default_variable_precision_options(variable_precision_options opts)
0693    {
0694       get_global_default_options() = opts;
0695    }
0696    static void thread_default_variable_precision_options(variable_precision_options opts)
0697    {
0698       get_default_options() = opts;
0699    }
0700 };
0701 
0702 template <unsigned digits10, class T>
0703 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const mpfi_float_backend<digits10>& a, const T& b) noexcept
0704 {
0705    return a.compare(b) == 0;
0706 }
0707 template <unsigned digits10, class T>
0708 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const mpfi_float_backend<digits10>& a, const T& b) noexcept
0709 {
0710    return a.compare(b) < 0;
0711 }
0712 template <unsigned digits10, class T>
0713 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const mpfi_float_backend<digits10>& a, const T& b) noexcept
0714 {
0715    return a.compare(b) > 0;
0716 }
0717 
0718 template <unsigned D1, unsigned D2>
0719 inline void eval_add(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
0720 {
0721    mpfi_add(result.data(), result.data(), o.data());
0722 }
0723 template <unsigned D1, unsigned D2>
0724 inline void eval_subtract(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
0725 {
0726    mpfi_sub(result.data(), result.data(), o.data());
0727 }
0728 template <unsigned D1, unsigned D2>
0729 inline void eval_multiply(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
0730 {
0731    if ((void*)&result == (void*)&o)
0732       mpfi_sqr(result.data(), o.data());
0733    else
0734       mpfi_mul(result.data(), result.data(), o.data());
0735 }
0736 template <unsigned D1, unsigned D2>
0737 inline void eval_divide(mpfi_float_backend<D1>& result, const mpfi_float_backend<D2>& o)
0738 {
0739    mpfi_div(result.data(), result.data(), o.data());
0740 }
0741 template <unsigned digits10>
0742 inline void eval_add(mpfi_float_backend<digits10>& result, unsigned long i)
0743 {
0744    mpfi_add_ui(result.data(), result.data(), i);
0745 }
0746 template <unsigned digits10>
0747 inline void eval_subtract(mpfi_float_backend<digits10>& result, unsigned long i)
0748 {
0749    mpfi_sub_ui(result.data(), result.data(), i);
0750 }
0751 template <unsigned digits10>
0752 inline void eval_multiply(mpfi_float_backend<digits10>& result, unsigned long i)
0753 {
0754    mpfi_mul_ui(result.data(), result.data(), i);
0755 }
0756 template <unsigned digits10>
0757 inline void eval_divide(mpfi_float_backend<digits10>& result, unsigned long i)
0758 {
0759    mpfi_div_ui(result.data(), result.data(), i);
0760 }
0761 template <unsigned digits10>
0762 inline void eval_add(mpfi_float_backend<digits10>& result, long i)
0763 {
0764    if (i > 0)
0765       mpfi_add_ui(result.data(), result.data(), i);
0766    else
0767       mpfi_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
0768 }
0769 template <unsigned digits10>
0770 inline void eval_subtract(mpfi_float_backend<digits10>& result, long i)
0771 {
0772    if (i > 0)
0773       mpfi_sub_ui(result.data(), result.data(), i);
0774    else
0775       mpfi_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
0776 }
0777 template <unsigned digits10>
0778 inline void eval_multiply(mpfi_float_backend<digits10>& result, long i)
0779 {
0780    mpfi_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
0781    if (i < 0)
0782       mpfi_neg(result.data(), result.data());
0783 }
0784 template <unsigned digits10>
0785 inline void eval_divide(mpfi_float_backend<digits10>& result, long i)
0786 {
0787    mpfi_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
0788    if (i < 0)
0789       mpfi_neg(result.data(), result.data());
0790 }
0791 //
0792 // Specialised 3 arg versions of the basic operators:
0793 //
0794 template <unsigned D1, unsigned D2, unsigned D3>
0795 inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
0796 {
0797    mpfi_add(a.data(), x.data(), y.data());
0798 }
0799 template <unsigned D1, unsigned D2>
0800 inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
0801 {
0802    mpfi_add_ui(a.data(), x.data(), y);
0803 }
0804 template <unsigned D1, unsigned D2>
0805 inline void eval_add(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
0806 {
0807    if (y < 0)
0808       mpfi_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
0809    else
0810       mpfi_add_ui(a.data(), x.data(), y);
0811 }
0812 template <unsigned D1, unsigned D2>
0813 inline void eval_add(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
0814 {
0815    mpfi_add_ui(a.data(), y.data(), x);
0816 }
0817 template <unsigned D1, unsigned D2>
0818 inline void eval_add(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
0819 {
0820    if (x < 0)
0821    {
0822       mpfi_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
0823       mpfi_neg(a.data(), a.data());
0824    }
0825    else
0826       mpfi_add_ui(a.data(), y.data(), x);
0827 }
0828 template <unsigned D1, unsigned D2, unsigned D3>
0829 inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
0830 {
0831    mpfi_sub(a.data(), x.data(), y.data());
0832 }
0833 template <unsigned D1, unsigned D2>
0834 inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
0835 {
0836    mpfi_sub_ui(a.data(), x.data(), y);
0837 }
0838 template <unsigned D1, unsigned D2>
0839 inline void eval_subtract(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
0840 {
0841    if (y < 0)
0842       mpfi_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
0843    else
0844       mpfi_sub_ui(a.data(), x.data(), y);
0845 }
0846 template <unsigned D1, unsigned D2>
0847 inline void eval_subtract(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
0848 {
0849    mpfi_ui_sub(a.data(), x, y.data());
0850 }
0851 template <unsigned D1, unsigned D2>
0852 inline void eval_subtract(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
0853 {
0854    if (x < 0)
0855    {
0856       mpfi_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
0857       mpfi_neg(a.data(), a.data());
0858    }
0859    else
0860       mpfi_ui_sub(a.data(), x, y.data());
0861 }
0862 
0863 template <unsigned D1, unsigned D2, unsigned D3>
0864 inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
0865 {
0866    if ((void*)&x == (void*)&y)
0867       mpfi_sqr(a.data(), x.data());
0868    else
0869       mpfi_mul(a.data(), x.data(), y.data());
0870 }
0871 template <unsigned D1, unsigned D2>
0872 inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
0873 {
0874    mpfi_mul_ui(a.data(), x.data(), y);
0875 }
0876 template <unsigned D1, unsigned D2>
0877 inline void eval_multiply(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
0878 {
0879    if (y < 0)
0880    {
0881       mpfi_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
0882       a.negate();
0883    }
0884    else
0885       mpfi_mul_ui(a.data(), x.data(), y);
0886 }
0887 template <unsigned D1, unsigned D2>
0888 inline void eval_multiply(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
0889 {
0890    mpfi_mul_ui(a.data(), y.data(), x);
0891 }
0892 template <unsigned D1, unsigned D2>
0893 inline void eval_multiply(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
0894 {
0895    if (x < 0)
0896    {
0897       mpfi_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
0898       mpfi_neg(a.data(), a.data());
0899    }
0900    else
0901       mpfi_mul_ui(a.data(), y.data(), x);
0902 }
0903 
0904 template <unsigned D1, unsigned D2, unsigned D3>
0905 inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, const mpfi_float_backend<D3>& y)
0906 {
0907    mpfi_div(a.data(), x.data(), y.data());
0908 }
0909 template <unsigned D1, unsigned D2>
0910 inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, unsigned long y)
0911 {
0912    mpfi_div_ui(a.data(), x.data(), y);
0913 }
0914 template <unsigned D1, unsigned D2>
0915 inline void eval_divide(mpfi_float_backend<D1>& a, const mpfi_float_backend<D2>& x, long y)
0916 {
0917    if (y < 0)
0918    {
0919       mpfi_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
0920       a.negate();
0921    }
0922    else
0923       mpfi_div_ui(a.data(), x.data(), y);
0924 }
0925 template <unsigned D1, unsigned D2>
0926 inline void eval_divide(mpfi_float_backend<D1>& a, unsigned long x, const mpfi_float_backend<D2>& y)
0927 {
0928    mpfi_ui_div(a.data(), x, y.data());
0929 }
0930 template <unsigned D1, unsigned D2>
0931 inline void eval_divide(mpfi_float_backend<D1>& a, long x, const mpfi_float_backend<D2>& y)
0932 {
0933    if (x < 0)
0934    {
0935       mpfi_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
0936       mpfi_neg(a.data(), a.data());
0937    }
0938    else
0939       mpfi_ui_div(a.data(), x, y.data());
0940 }
0941 
0942 template <unsigned digits10>
0943 inline bool eval_is_zero(const mpfi_float_backend<digits10>& val) noexcept
0944 {
0945    return 0 != mpfi_is_zero(val.data());
0946 }
0947 template <unsigned digits10>
0948 inline int eval_get_sign(const mpfi_float_backend<digits10>& val)
0949 {
0950    return detail::mpfi_sgn(val.data());
0951 }
0952 
0953 template <unsigned digits10>
0954 inline void eval_convert_to(unsigned long* result, const mpfi_float_backend<digits10>& val)
0955 {
0956    mpfr_float_backend<digits10> t;
0957    mpfi_mid(t.data(), val.data());
0958    eval_convert_to(result, t);
0959 }
0960 template <unsigned digits10>
0961 inline void eval_convert_to(long* result, const mpfi_float_backend<digits10>& val)
0962 {
0963    mpfr_float_backend<digits10> t;
0964    mpfi_mid(t.data(), val.data());
0965    eval_convert_to(result, t);
0966 }
0967 #ifdef _MPFR_H_HAVE_INTMAX_T
0968 template <unsigned digits10>
0969 inline void eval_convert_to(unsigned long long* result, const mpfi_float_backend<digits10>& val)
0970 {
0971    mpfr_float_backend<digits10> t;
0972    mpfi_mid(t.data(), val.data());
0973    eval_convert_to(result, t);
0974 }
0975 template <unsigned digits10>
0976 inline void eval_convert_to(long long* result, const mpfi_float_backend<digits10>& val)
0977 {
0978    mpfr_float_backend<digits10> t;
0979    mpfi_mid(t.data(), val.data());
0980    eval_convert_to(result, t);
0981 }
0982 #endif
0983 #ifdef BOOST_HAS_INT128
0984 template <unsigned digits10>
0985 inline void eval_convert_to(uint128_type* result, const mpfi_float_backend<digits10>& val)
0986 {
0987    mpfr_float_backend<digits10> t;
0988    mpfi_mid(t.data(), val.data());
0989    eval_convert_to(result, t);
0990 }
0991 template <unsigned digits10>
0992 inline void eval_convert_to(int128_type* result, const mpfi_float_backend<digits10>& val)
0993 {
0994    mpfr_float_backend<digits10> t;
0995    mpfi_mid(t.data(), val.data());
0996    eval_convert_to(result, t);
0997 }
0998 #endif
0999 template <unsigned digits10>
1000 inline void eval_convert_to(double* result, const mpfi_float_backend<digits10>& val) noexcept
1001 {
1002    *result = mpfi_get_d(val.data());
1003 }
1004 template <unsigned digits10>
1005 inline void eval_convert_to(long double* result, const mpfi_float_backend<digits10>& val) noexcept
1006 {
1007    mpfr_float_backend<digits10> t;
1008    mpfi_mid(t.data(), val.data());
1009    eval_convert_to(result, t);
1010 }
1011 #ifdef BOOST_HAS_FLOAT128
1012 template <unsigned digits10>
1013 inline void eval_convert_to(float128_type* result, const mpfi_float_backend<digits10>& val)
1014 {
1015    mpfr_float_backend<digits10> t;
1016    mpfi_mid(t.data(), val.data());
1017    eval_convert_to(result, t);
1018 }
1019 #endif
1020 template <mpfr_allocation_type AllocationType>
1021 inline void assign_components_set_precision(mpfi_float_backend<0>& result, const mpfr_float_backend<0, AllocationType>& a, const mpfr_float_backend<0, AllocationType>& b)
1022 {
1023    if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_component_precision)
1024    {
1025       unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
1026       mpfi_set_prec(result.data(), prec);
1027    }
1028 }
1029 template <unsigned D2, mpfr_allocation_type AllocationType>
1030 inline void assign_components_set_precision(mpfi_float_backend<0>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
1031 {
1032    if (result.thread_default_variable_precision_options() >= variable_precision_options::preserve_related_precision)
1033    {
1034       unsigned long prec = (std::max)(mpfr_get_prec(a.data()), mpfr_get_prec(b.data()));
1035       mpfi_set_prec(result.data(), prec);
1036    }
1037 }
1038 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1039 inline void assign_components_set_precision(mpfi_float_backend<D1>&, const mpfr_float_backend<D2, AllocationType>&, const mpfr_float_backend<D2, AllocationType>&)
1040 {
1041 }
1042 
1043 
1044 template <unsigned D1, unsigned D2, mpfr_allocation_type AllocationType>
1045 inline void assign_components(mpfi_float_backend<D1>& result, const mpfr_float_backend<D2, AllocationType>& a, const mpfr_float_backend<D2, AllocationType>& b)
1046 {
1047    //
1048    // This is called from class number's constructors, so if we have variable
1049    // precision, then copy the precision of the source variables.
1050    //
1051    assign_components_set_precision(result, a, b);
1052 
1053    using default_ops::eval_fpclassify;
1054    if (eval_fpclassify(a) == static_cast<int>(FP_NAN))
1055    {
1056       mpfi_set_fr(result.data(), a.data());
1057    }
1058    else if (eval_fpclassify(b) == static_cast<int>(FP_NAN))
1059    {
1060       mpfi_set_fr(result.data(), b.data());
1061    }
1062    else
1063    {
1064       if (a.compare(b) > 0)
1065       {
1066          BOOST_MP_THROW_EXCEPTION(std::runtime_error("Attempt to create interval with invalid range (start is greater than end)."));
1067       }
1068       mpfi_interv_fr(result.data(), a.data(), b.data());
1069    }
1070 }
1071 
1072 template <unsigned Digits10, class V>
1073 inline typename std::enable_if<std::is_constructible<number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on>, V>::value || std::is_convertible<V, const char*>::value>::type
1074 assign_components(mpfi_float_backend<Digits10>& result, const V& a, const V& b)
1075 {
1076    number<mpfr_float_backend<Digits10, allocate_dynamic>, et_on> x(a), y(b);
1077    assign_components(result, x.backend(), y.backend());
1078 }
1079 
1080 //
1081 // Native non-member operations:
1082 //
1083 template <unsigned Digits10>
1084 inline void eval_sqrt(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
1085 {
1086    mpfi_sqrt(result.data(), val.data());
1087 }
1088 
1089 template <unsigned Digits10>
1090 inline void eval_abs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
1091 {
1092    mpfi_abs(result.data(), val.data());
1093 }
1094 
1095 template <unsigned Digits10>
1096 inline void eval_fabs(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
1097 {
1098    mpfi_abs(result.data(), val.data());
1099 }
1100 template <unsigned Digits10>
1101 inline void eval_ceil(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
1102 {
1103    mpfr_float_backend<Digits10> a, b;
1104    mpfr_set(a.data(), val.left_data(), GMP_RNDN);
1105    mpfr_set(b.data(), val.right_data(), GMP_RNDN);
1106    eval_ceil(a, a);
1107    eval_ceil(b, b);
1108    if (a.compare(b) != 0)
1109    {
1110       BOOST_MP_THROW_EXCEPTION(interval_error("Attempt to take the ceil of a value that straddles an integer boundary."));
1111    }
1112    mpfi_set_fr(result.data(), a.data());
1113 }
1114 template <unsigned Digits10>
1115 inline void eval_floor(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val)
1116 {
1117    mpfr_float_backend<Digits10> a, b;
1118    mpfr_set(a.data(), val.left_data(), GMP_RNDN);
1119    mpfr_set(b.data(), val.right_data(), GMP_RNDN);
1120    eval_floor(a, a);
1121    eval_floor(b, b);
1122    if (a.compare(b) != 0)
1123    {
1124       BOOST_MP_THROW_EXCEPTION(interval_error("Attempt to take the floor of a value that straddles an integer boundary."));
1125    }
1126    mpfi_set_fr(result.data(), a.data());
1127 }
1128 template <unsigned Digits10>
1129 inline void eval_ldexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long e)
1130 {
1131    if (e > 0)
1132       mpfi_mul_2exp(result.data(), val.data(), e);
1133    else if (e < 0)
1134       mpfi_div_2exp(result.data(), val.data(), -e);
1135    else
1136       result = val;
1137 }
1138 template <unsigned Digits10>
1139 inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, int* e)
1140 {
1141    mpfr_float_backend<Digits10> t, rt;
1142    mpfi_mid(t.data(), val.data());
1143    eval_frexp(rt, t, e);
1144    eval_ldexp(result, val, -*e);
1145 }
1146 template <unsigned Digits10>
1147 inline void eval_frexp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& val, long* e)
1148 {
1149    mpfr_float_backend<Digits10> t, rt;
1150    mpfi_mid(t.data(), val.data());
1151    eval_frexp(rt, t, e);
1152    eval_ldexp(result, val, -*e);
1153 }
1154 
1155 template <unsigned Digits10>
1156 inline int eval_fpclassify(const mpfi_float_backend<Digits10>& val) noexcept
1157 {
1158    return mpfi_inf_p(val.data()) ? FP_INFINITE : mpfi_nan_p(val.data()) ? FP_NAN : mpfi_is_zero(val.data()) ? FP_ZERO : FP_NORMAL;
1159 }
1160 
1161 template <unsigned Digits10>
1162 inline void eval_pow(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& b, const mpfi_float_backend<Digits10>& e)
1163 {
1164    using ui_type = typename boost::multiprecision::detail::canonical<unsigned, mpfi_float_backend<Digits10> >::type;
1165    using default_ops::eval_get_sign;
1166    int s = eval_get_sign(b);
1167    if (s == 0)
1168    {
1169       if (eval_get_sign(e) == 0)
1170       {
1171          result = ui_type(1);
1172       }
1173       else
1174       {
1175          result = ui_type(0);
1176       }
1177       return;
1178    }
1179    if (s < 0)
1180    {
1181       if (eval_get_sign(e) < 0)
1182       {
1183          mpfi_float_backend<Digits10> t1, t2;
1184          t1 = e;
1185          t1.negate();
1186          eval_pow(t2, b, t1);
1187          t1 = ui_type(1);
1188          eval_divide(result, t1, t2);
1189          return;
1190       }
1191       typename boost::multiprecision::detail::canonical<std::uintmax_t, mpfi_float_backend<Digits10> >::type an;
1192 #ifndef BOOST_NO_EXCEPTIONS
1193       try
1194       {
1195 #endif
1196          using default_ops::eval_convert_to;
1197          eval_convert_to(&an, e);
1198          if (e.compare(an) == 0)
1199          {
1200             mpfi_float_backend<Digits10> pb(b);
1201             pb.negate();
1202             eval_pow(result, pb, e);
1203             if (an & 1u)
1204                result.negate();
1205             return;
1206          }
1207 #ifndef BOOST_NO_EXCEPTIONS
1208       }
1209       catch (const std::exception&)
1210       {
1211          // conversion failed, just fall through, value is not an integer.
1212       }
1213 #endif
1214       result = std::numeric_limits<number<mpfi_float_backend<Digits10>, et_on> >::quiet_NaN().backend();
1215       return;
1216    }
1217    mpfi_log(result.data(), b.data());
1218    mpfi_mul(result.data(), result.data(), e.data());
1219    mpfi_exp(result.data(), result.data());
1220 }
1221 
1222 template <unsigned Digits10>
1223 inline void eval_exp(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1224 {
1225    mpfi_exp(result.data(), arg.data());
1226 }
1227 
1228 template <unsigned Digits10>
1229 inline void eval_exp2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1230 {
1231    mpfi_exp2(result.data(), arg.data());
1232 }
1233 
1234 template <unsigned Digits10>
1235 inline void eval_log(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1236 {
1237    mpfi_log(result.data(), arg.data());
1238 }
1239 
1240 template <unsigned Digits10>
1241 inline void eval_log10(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1242 {
1243    mpfi_log10(result.data(), arg.data());
1244 }
1245 
1246 template <unsigned Digits10>
1247 inline void eval_sin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1248 {
1249    mpfi_sin(result.data(), arg.data());
1250 }
1251 
1252 template <unsigned Digits10>
1253 inline void eval_cos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1254 {
1255    mpfi_cos(result.data(), arg.data());
1256 }
1257 
1258 template <unsigned Digits10>
1259 inline void eval_tan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1260 {
1261    mpfi_tan(result.data(), arg.data());
1262 }
1263 
1264 template <unsigned Digits10>
1265 inline void eval_asin(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1266 {
1267    mpfi_asin(result.data(), arg.data());
1268 }
1269 
1270 template <unsigned Digits10>
1271 inline void eval_acos(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1272 {
1273    mpfi_acos(result.data(), arg.data());
1274 }
1275 
1276 template <unsigned Digits10>
1277 inline void eval_atan(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1278 {
1279    mpfi_atan(result.data(), arg.data());
1280 }
1281 
1282 template <unsigned Digits10>
1283 inline void eval_atan2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg1, const mpfi_float_backend<Digits10>& arg2)
1284 {
1285    mpfi_atan2(result.data(), arg1.data(), arg2.data());
1286 }
1287 
1288 template <unsigned Digits10>
1289 inline void eval_sinh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1290 {
1291    mpfi_sinh(result.data(), arg.data());
1292 }
1293 
1294 template <unsigned Digits10>
1295 inline void eval_cosh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1296 {
1297    mpfi_cosh(result.data(), arg.data());
1298 }
1299 
1300 template <unsigned Digits10>
1301 inline void eval_tanh(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1302 {
1303    mpfi_tanh(result.data(), arg.data());
1304 }
1305 
1306 template <unsigned Digits10>
1307 inline void eval_log2(mpfi_float_backend<Digits10>& result, const mpfi_float_backend<Digits10>& arg)
1308 {
1309    mpfi_log2(result.data(), arg.data());
1310 }
1311 
1312 template <unsigned Digits10>
1313 inline std::size_t hash_value(const mpfi_float_backend<Digits10>& val)
1314 {
1315    std::size_t result = 0;
1316    std::size_t len    = val.left_data()[0]._mpfr_prec / mp_bits_per_limb;
1317    if (val.left_data()[0]._mpfr_prec % mp_bits_per_limb)
1318       ++len;
1319    for (std::size_t i = 0; i < len; ++i)
1320       boost::multiprecision::detail::hash_combine(result, val.left_data()[0]._mpfr_d[i]);
1321    boost::multiprecision::detail::hash_combine(result, val.left_data()[0]._mpfr_exp, val.left_data()[0]._mpfr_sign);
1322 
1323    len = val.right_data()[0]._mpfr_prec / mp_bits_per_limb;
1324    if (val.right_data()[0]._mpfr_prec % mp_bits_per_limb)
1325       ++len;
1326    for (std::size_t i = 0; i < len; ++i)
1327       boost::multiprecision::detail::hash_combine(result, val.right_data()[0]._mpfr_d[i]);
1328    boost::multiprecision::detail::hash_combine(result, val.right_data()[0]._mpfr_exp, val.right_data()[0]._mpfr_sign);
1329    return result;
1330 }
1331 
1332 template <class To, unsigned D>
1333 void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_integer>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
1334 {
1335    using boost::multiprecision::detail::generic_interconvert;
1336    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
1337    mpfr_float_backend<D> t;
1338    mpfi_mid(t.data(), from.data());
1339    generic_interconvert(to, t, to_type, from_type);
1340 }
1341 
1342 template <class To, unsigned D>
1343 void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_rational>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
1344 {
1345    using boost::multiprecision::detail::generic_interconvert;
1346    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
1347    mpfr_float_backend<D> t;
1348    mpfi_mid(t.data(), from.data());
1349    generic_interconvert(to, t, to_type, from_type);
1350 }
1351 
1352 template <class To, unsigned D>
1353 void generic_interconvert(To& to, const mpfi_float_backend<D>& from, const std::integral_constant<int, number_kind_floating_point>& to_type, const std::integral_constant<int, number_kind_floating_point>& from_type)
1354 {
1355    using boost::multiprecision::detail::generic_interconvert;
1356    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<D>>> scoped(from);
1357    mpfr_float_backend<D> t;
1358    mpfi_mid(t.data(), from.data());
1359    generic_interconvert(to, t, to_type, from_type);
1360 }
1361 
1362 } // namespace backends
1363 
1364 template <>
1365 struct number_category<detail::canonical<mpfi_t, backends::mpfi_float_backend<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
1366 {};
1367 template <unsigned Digits10>
1368 struct is_interval_number<backends::mpfi_float_backend<Digits10> > : public std::integral_constant<bool, true>
1369 {};
1370 
1371 //
1372 // Special interval specific functions:
1373 //
1374 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1375 inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> lower(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
1376 {
1377    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
1378    number<mpfr_float_backend<Digits10> >                                                                               result;
1379    mpfr_set(result.backend().data(), val.backend().left_data(), GMP_RNDN);
1380    return result;
1381 }
1382 
1383 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1384 inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> upper(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
1385 {
1386    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
1387    number<mpfr_float_backend<Digits10> >                                                                               result;
1388    mpfr_set(result.backend().data(), val.backend().right_data(), GMP_RNDN);
1389    return result;
1390 }
1391 
1392 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1393 inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> median(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
1394 {
1395    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
1396    number<mpfr_float_backend<Digits10> >                                                                               result;
1397    mpfi_mid(result.backend().data(), val.backend().data());
1398    return result;
1399 }
1400 
1401 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1402 inline number<mpfr_float_backend<Digits10>, ExpressionTemplates> width(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& val)
1403 {
1404    boost::multiprecision::detail::scoped_precision_options<number<mpfr_float_backend<Digits10>, ExpressionTemplates> > precision_guard(val);
1405    number<mpfr_float_backend<Digits10> >                                                                               result;
1406    mpfi_diam_abs(result.backend().data(), val.backend().data());
1407    return result;
1408 }
1409 
1410 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1411 inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> intersect(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
1412 {
1413    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
1414    number<mpfi_float_backend<Digits10>, ExpressionTemplates>                                                           result;
1415    mpfi_intersect(result.backend().data(), a.backend().data(), b.backend().data());
1416    return result;
1417 }
1418 
1419 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1420 inline number<mpfi_float_backend<Digits10>, ExpressionTemplates> hull(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
1421 {
1422    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(a, b);
1423    number<mpfi_float_backend<Digits10>, ExpressionTemplates>                                                           result;
1424    mpfi_union(result.backend().data(), a.backend().data(), b.backend().data());
1425    return result;
1426 }
1427 
1428 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1429 inline bool overlap(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
1430 {
1431    return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
1432           (lower(b) <= lower(a) && lower(a) <= upper(b));
1433 }
1434 
1435 template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
1436 inline bool in(const number<mpfr_float_backend<Digits10>, ExpressionTemplates1>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates2>& b)
1437 {
1438    return mpfi_is_inside_fr(a.backend().data(), b.backend().data()) != 0;
1439 }
1440 
1441 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1442 inline bool zero_in(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
1443 {
1444    return mpfi_has_zero(a.backend().data()) != 0;
1445 }
1446 
1447 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1448 inline bool subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
1449 {
1450    return mpfi_is_inside(a.backend().data(), b.backend().data()) != 0;
1451 }
1452 
1453 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1454 inline bool proper_subset(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a, const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& b)
1455 {
1456    return mpfi_is_strictly_inside(a.backend().data(), b.backend().data()) != 0;
1457 }
1458 
1459 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1460 inline bool empty(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
1461 {
1462    return mpfi_is_empty(a.backend().data()) != 0;
1463 }
1464 
1465 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1466 inline bool singleton(const number<mpfi_float_backend<Digits10>, ExpressionTemplates>& a)
1467 {
1468    return mpfr_cmp(a.backend().left_data(), a.backend().right_data()) == 0;
1469 }
1470 
1471 //
1472 // Again with debug_adaptor:
1473 //
1474 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1475 inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> lower(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1476 {
1477    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1478    number<debug_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1479    mpfr_set(result.backend().value().data(), val.backend().value().left_data(), GMP_RNDN);
1480    return result;
1481 }
1482 
1483 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1484 inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> upper(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1485 {
1486    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1487    number<debug_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1488    mpfr_set(result.backend().value().data(), val.backend().value().right_data(), GMP_RNDN);
1489    return result;
1490 }
1491 
1492 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1493 inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> median(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1494 {
1495    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1496    number<debug_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1497    mpfi_mid(result.backend().value().data(), val.backend().value().data());
1498    return result;
1499 }
1500 
1501 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1502 inline number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> width(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1503 {
1504    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1505    number<debug_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1506    mpfi_diam_abs(result.backend().value().data(), val.backend().value().data());
1507    return result;
1508 }
1509 
1510 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1511 inline number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> intersect(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1512 {
1513    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
1514    number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>                                                           result;
1515    mpfi_intersect(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
1516    return result;
1517 }
1518 
1519 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1520 inline number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> hull(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1521 {
1522    boost::multiprecision::detail::scoped_default_precision<number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
1523    number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>                                                           result;
1524    mpfi_union(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
1525    return result;
1526 }
1527 
1528 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1529 inline bool overlap(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1530 {
1531    return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
1532           (lower(b) <= lower(a) && lower(a) <= upper(b));
1533 }
1534 
1535 template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
1536 inline bool in(const number<debug_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates1>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates2>& b)
1537 {
1538    return mpfi_is_inside_fr(a.backend().value().data(), b.backend().value().data()) != 0;
1539 }
1540 
1541 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1542 inline bool zero_in(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1543 {
1544    return mpfi_has_zero(a.backend().value().data()) != 0;
1545 }
1546 
1547 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1548 inline bool subset(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1549 {
1550    return mpfi_is_inside(a.backend().value().data(), b.backend().value().data()) != 0;
1551 }
1552 
1553 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1554 inline bool proper_subset(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1555 {
1556    return mpfi_is_strictly_inside(a.backend().value().data(), b.backend().value().data()) != 0;
1557 }
1558 
1559 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1560 inline bool empty(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1561 {
1562    return mpfi_is_empty(a.backend().value().data()) != 0;
1563 }
1564 
1565 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1566 inline bool singleton(const number<debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1567 {
1568    return mpfr_cmp(a.backend().value().left_data(), a.backend().value().right_data()) == 0;
1569 }
1570 //
1571 // Again with logged_adaptor:
1572 //
1573 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1574 inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> lower(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1575 {
1576    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1577    number<logged_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1578    mpfr_set(result.backend().value().data(), val.backend().value().left_data(), GMP_RNDN);
1579    return result;
1580 }
1581 
1582 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1583 inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> upper(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1584 {
1585    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1586    number<logged_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1587    mpfr_set(result.backend().value().data(), val.backend().value().right_data(), GMP_RNDN);
1588    return result;
1589 }
1590 
1591 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1592 inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> median(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1593 {
1594    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1595    number<logged_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1596    mpfi_mid(result.backend().value().data(), val.backend().value().data());
1597    return result;
1598 }
1599 
1600 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1601 inline number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> width(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& val)
1602 {
1603    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(val);
1604    number<logged_adaptor<mpfr_float_backend<Digits10> > >                                                                               result;
1605    mpfi_diam_abs(result.backend().value().data(), val.backend().value().data());
1606    return result;
1607 }
1608 
1609 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1610 inline number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> intersect(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1611 {
1612    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
1613    number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>                                                           result;
1614    mpfi_intersect(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
1615    return result;
1616 }
1617 
1618 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1619 inline number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> hull(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1620 {
1621    boost::multiprecision::detail::scoped_default_precision<number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(a, b);
1622    number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>                                                           result;
1623    mpfi_union(result.backend().value().data(), a.backend().value().data(), b.backend().value().data());
1624    return result;
1625 }
1626 
1627 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1628 inline bool overlap(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1629 {
1630    return (lower(a) <= lower(b) && lower(b) <= upper(a)) ||
1631           (lower(b) <= lower(a) && lower(a) <= upper(b));
1632 }
1633 
1634 template <unsigned Digits10, expression_template_option ExpressionTemplates1, expression_template_option ExpressionTemplates2>
1635 inline bool in(const number<logged_adaptor<mpfr_float_backend<Digits10> >, ExpressionTemplates1>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates2>& b)
1636 {
1637    return mpfi_is_inside_fr(a.backend().value().data(), b.backend().value().data()) != 0;
1638 }
1639 
1640 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1641 inline bool zero_in(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1642 {
1643    return mpfi_has_zero(a.backend().value().data()) != 0;
1644 }
1645 
1646 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1647 inline bool subset(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1648 {
1649    return mpfi_is_inside(a.backend().value().data(), b.backend().value().data()) != 0;
1650 }
1651 
1652 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1653 inline bool proper_subset(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a, const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& b)
1654 {
1655    return mpfi_is_strictly_inside(a.backend().value().data(), b.backend().value().data()) != 0;
1656 }
1657 
1658 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1659 inline bool empty(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1660 {
1661    return mpfi_is_empty(a.backend().value().data()) != 0;
1662 }
1663 
1664 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1665 inline bool singleton(const number<logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates>& a)
1666 {
1667    return mpfr_cmp(a.backend().value().left_data(), a.backend().value().right_data()) == 0;
1668 }
1669 //
1670 // component_type specialization:
1671 //
1672 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1673 struct component_type<number<mpfi_float_backend<Digits10>, ExpressionTemplates> >
1674 {
1675    using type = number<mpfr_float_backend<Digits10>, ExpressionTemplates>;
1676 };
1677 
1678 //
1679 // Overloaded special functions which call native mpfr routines:
1680 //
1681 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1682 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1683 {
1684    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1685 
1686    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1687    mpfi_asinh(result.backend().data(), arg.backend().data());
1688    return result;
1689 }
1690 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1691 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1692 {
1693    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1694 
1695    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1696    mpfi_acosh(result.backend().data(), arg.backend().data());
1697    return result;
1698 }
1699 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1700 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1701 {
1702    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1703 
1704    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1705    mpfi_atanh(result.backend().data(), arg.backend().data());
1706    return result;
1707 }
1708 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1709 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1710 {
1711    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1712 
1713    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1714    mpfi_cbrt(result.backend().data(), arg.backend().data());
1715    return result;
1716 }
1717 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1718 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1719 {
1720    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1721 
1722    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1723    mpfi_expm1(result.backend().data(), arg.backend().data());
1724    return result;
1725 }
1726 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1727 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>& arg)
1728 {
1729    boost::multiprecision::detail::scoped_default_precision<number<mpfi_float_backend<Digits10>, ExpressionTemplates> > precision_guard(arg);
1730 
1731    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> result;
1732    mpfi_log1p(result.backend().data(), arg.backend().data());
1733    return result;
1734 }
1735 
1736 //
1737 // And again with debug_adaptor:
1738 //
1739 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1740 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1741 {
1742    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1743 
1744    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1745    mpfi_asinh(result.backend().value().data(), arg.backend().value().data());
1746    return result;
1747 }
1748 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1749 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1750 {
1751    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1752 
1753    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1754    mpfi_acosh(result.backend().value().data(), arg.backend().value().data());
1755    return result;
1756 }
1757 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1758 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1759 {
1760    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1761 
1762    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1763    mpfi_atanh(result.backend().value().data(), arg.backend().value().data());
1764    return result;
1765 }
1766 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1767 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1768 {
1769    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1770 
1771    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1772    mpfi_cbrt(result.backend().value().data(), arg.backend().value().data());
1773    return result;
1774 }
1775 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1776 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1777 {
1778    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1779 
1780    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1781    mpfi_expm1(result.backend().value().data(), arg.backend().value().data());
1782    return result;
1783 }
1784 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1785 inline boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1786 {
1787    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::debug_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1788 
1789    boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1790    mpfi_log1p(result.backend().value().data(), arg.backend().value().data());
1791    return result;
1792 }
1793 
1794 //
1795 // And again with logged_adaptor:
1796 //
1797 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1798 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1799 {
1800    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1801 
1802    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1803    mpfi_asinh(result.backend().value().data(), arg.backend().value().data());
1804    return result;
1805 }
1806 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1807 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1808 {
1809    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1810 
1811    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1812    mpfi_acosh(result.backend().value().data(), arg.backend().value().data());
1813    return result;
1814 }
1815 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1816 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1817 {
1818    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1819 
1820    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1821    mpfi_atanh(result.backend().value().data(), arg.backend().value().data());
1822    return result;
1823 }
1824 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1825 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1826 {
1827    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1828 
1829    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1830    mpfi_cbrt(result.backend().value().data(), arg.backend().value().data());
1831    return result;
1832 }
1833 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1834 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1835 {
1836    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1837 
1838    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1839    mpfi_expm1(result.backend().value().data(), arg.backend().value().data());
1840    return result;
1841 }
1842 template <unsigned Digits10, expression_template_option ExpressionTemplates>
1843 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>& arg)
1844 {
1845    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<mpfi_float_backend<Digits10> >, ExpressionTemplates> > precision_guard(arg);
1846 
1847    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> result;
1848    mpfi_log1p(result.backend().value().data(), arg.backend().value().data());
1849    return result;
1850 }
1851 
1852 } // namespace multiprecision
1853 
1854 namespace math {
1855 
1856 namespace tools {
1857 
1858 inline void set_output_precision(const boost::multiprecision::mpfi_float& val, std::ostream& os)
1859 {
1860    os << std::setprecision(val.precision());
1861 }
1862 
1863 template <>
1864 inline int digits<boost::multiprecision::mpfi_float>()
1865 #ifdef BOOST_MATH_NOEXCEPT
1866     noexcept
1867 #endif
1868 {
1869    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::thread_default_precision());
1870 }
1871 template <>
1872 inline int digits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
1873 #ifdef BOOST_MATH_NOEXCEPT
1874     noexcept
1875 #endif
1876 {
1877    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfi_float::thread_default_precision());
1878 }
1879 
1880 template <>
1881 inline boost::multiprecision::mpfi_float
1882 max_value<boost::multiprecision::mpfi_float>()
1883 {
1884    boost::multiprecision::mpfi_float result(0.5);
1885    mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
1886    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1887    return result;
1888 }
1889 
1890 template <>
1891 inline boost::multiprecision::mpfi_float
1892 min_value<boost::multiprecision::mpfi_float>()
1893 {
1894    boost::multiprecision::mpfi_float result(0.5);
1895    mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
1896    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1897    return result;
1898 }
1899 
1900 template <>
1901 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
1902 max_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
1903 {
1904    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
1905    mpfi_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax());
1906    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1907    return result;
1908 }
1909 
1910 template <>
1911 inline boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off>
1912 min_value<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> >()
1913 {
1914    boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, boost::multiprecision::et_off> result(0.5);
1915    mpfi_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin());
1916    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1917    return result;
1918 }
1919 
1920 // mpfi gets used with logged_adaptor fairly often, so specialize for that use case as well:
1921 using logged_type1 = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> ;
1922 using logged_type2 = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off>;
1923 
1924 template <>
1925 inline int digits<logged_type1>()
1926 #ifdef BOOST_MATH_NOEXCEPT
1927     noexcept
1928 #endif
1929 {
1930    return multiprecision::detail::digits10_2_2(logged_type1::thread_default_precision());
1931 }
1932 template <>
1933 inline int digits<logged_type2>()
1934 #ifdef BOOST_MATH_NOEXCEPT
1935     noexcept
1936 #endif
1937 {
1938    return multiprecision::detail::digits10_2_2(logged_type1::thread_default_precision());
1939 }
1940 
1941 template <>
1942 inline logged_type1
1943 max_value<logged_type1>()
1944 {
1945    logged_type1 result(0.5);
1946    mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
1947    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1948    return result;
1949 }
1950 
1951 template <>
1952 inline logged_type1
1953 min_value<logged_type1>()
1954 {
1955    logged_type1 result(0.5);
1956    mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
1957    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1958    return result;
1959 }
1960 
1961 template <>
1962 inline logged_type2
1963 max_value<logged_type2>()
1964 {
1965    logged_type2 result(0.5);
1966    mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
1967    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1968    return result;
1969 }
1970 
1971 template <>
1972 inline logged_type2
1973 min_value<logged_type2>()
1974 {
1975    logged_type2 result(0.5);
1976    mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
1977    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
1978    return result;
1979 }
1980 // mpfi gets used with debug_adaptor fairly often, so specialize for that use case as well:
1981 using debug_type1 = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_on> ;
1982 using debug_type2 = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float::backend_type>, boost::multiprecision::et_off>;
1983 
1984 template <>
1985 inline int digits<debug_type1>()
1986 #ifdef BOOST_MATH_NOEXCEPT
1987     noexcept
1988 #endif
1989 {
1990    return multiprecision::detail::digits10_2_2(debug_type1::default_precision());
1991 }
1992 template <>
1993 inline int digits<debug_type2>()
1994 #ifdef BOOST_MATH_NOEXCEPT
1995     noexcept
1996 #endif
1997 {
1998    return multiprecision::detail::digits10_2_2(debug_type1::default_precision());
1999 }
2000 
2001 template <>
2002 inline debug_type1
2003 max_value<debug_type1>()
2004 {
2005    debug_type1 result(0.5);
2006    mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
2007    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
2008    result.backend().update_view();
2009    return result;
2010 }
2011 
2012 template <>
2013 inline debug_type1
2014 min_value<debug_type1>()
2015 {
2016    debug_type1 result(0.5);
2017    mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
2018    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
2019    result.backend().update_view();
2020    return result;
2021 }
2022 
2023 template <>
2024 inline debug_type2
2025 max_value<debug_type2>()
2026 {
2027    debug_type2 result(0.5);
2028    mpfi_mul_2exp(result.backend().value().data(), result.backend().value().data(), mpfr_get_emax());
2029    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
2030    result.backend().update_view();
2031    return result;
2032 }
2033 
2034 template <>
2035 inline debug_type2
2036 min_value<debug_type2>()
2037 {
2038    debug_type2 result(0.5);
2039    mpfi_div_2exp(result.backend().value().data(), result.backend().value().data(), -mpfr_get_emin());
2040    //BOOST_MP_ASSERT(mpfi_number_p(result.backend().data()));
2041    result.backend().update_view();
2042    return result;
2043 }
2044 
2045 } // namespace tools
2046 
2047 namespace constants { namespace detail {
2048 
2049 template <class T>
2050 struct constant_pi;
2051 template <class T>
2052 struct constant_ln_two;
2053 template <class T>
2054 struct constant_euler;
2055 template <class T>
2056 struct constant_catalan;
2057 
2058 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2059 struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
2060 {
2061    using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
2062    template <int N>
2063    static inline const result_type& get(const std::integral_constant<int, N>&)
2064    {
2065       // Rely on C++11 thread safe initialization:
2066       static result_type result{get(std::integral_constant<int, 0>())};
2067       return result;
2068    }
2069    static inline result_type get(const std::integral_constant<int, 0>&)
2070    {
2071       result_type result;
2072       mpfi_const_pi(result.backend().data());
2073       return result;
2074    }
2075 };
2076 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2077 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
2078 {
2079    using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
2080    template <int N>
2081    static inline const result_type& get(const std::integral_constant<int, N>&)
2082    {
2083       // Rely on C++11 thread safe initialization:
2084       static result_type result{get(std::integral_constant<int, 0>())};
2085       return result;
2086    }
2087    static inline result_type get(const std::integral_constant<int, 0>&)
2088    {
2089       result_type result;
2090       mpfi_const_log2(result.backend().data());
2091       return result;
2092    }
2093 };
2094 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2095 struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
2096 {
2097    using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
2098    template <int N>
2099    static inline const result_type& get(const std::integral_constant<int, N>&)
2100    {
2101       // Rely on C++11 thread safe initialization:
2102       static result_type result{get(std::integral_constant<int, 0>())};
2103       return result;
2104    }
2105    static inline result_type get(const std::integral_constant<int, 0>&)
2106    {
2107       result_type result;
2108       mpfi_const_euler(result.backend().data());
2109       return result;
2110    }
2111 };
2112 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2113 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
2114 {
2115    using result_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
2116    template <int N>
2117    static inline const result_type& get(const std::integral_constant<int, N>&)
2118    {
2119       // Rely on C++11 thread safe initialization:
2120       static result_type result{get(std::integral_constant<int, 0>())};
2121       return result;
2122    }
2123    static inline result_type get(const std::integral_constant<int, 0>&)
2124    {
2125       result_type result;
2126       mpfi_const_catalan(result.backend().data());
2127       return result;
2128    }
2129 };
2130 //
2131 // And again with debug_adaptor:
2132 //
2133 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2134 struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2135 {
2136    using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2137    template <int N>
2138    static inline const result_type& get(const std::integral_constant<int, N>&)
2139    {
2140       // C++11 thread safe static initialization:
2141       static result_type result{get(std::integral_constant<int, 0>())};
2142       return result;
2143    }
2144    static inline result_type get(const std::integral_constant<int, 0>&)
2145    {
2146       result_type result;
2147       mpfi_const_pi(result.backend().value().data());
2148       result.backend().update_view();
2149       return result;
2150    }
2151 };
2152 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2153 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2154 {
2155    using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2156    template <int N>
2157    static inline const result_type& get(const std::integral_constant<int, N>&)
2158    {
2159       // C++11 thread safe static initialization:
2160       static result_type result{get(std::integral_constant<int, 0>())};
2161       return result;
2162    }
2163    static inline result_type get(const std::integral_constant<int, 0>&)
2164    {
2165       result_type result;
2166       mpfi_const_log2(result.backend().value().data());
2167       result.backend().update_view();
2168       return result;
2169    }
2170 };
2171 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2172 struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2173 {
2174    using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2175    template <int N>
2176    static inline const result_type& get(const std::integral_constant<int, N>&)
2177    {
2178       // C++11 thread safe static initialization:
2179       static result_type result{get(std::integral_constant<int, 0>())};
2180       return result;
2181    }
2182    static inline result_type get(const std::integral_constant<int, 0>&)
2183    {
2184       result_type result;
2185       mpfi_const_euler(result.backend().value().data());
2186       result.backend().update_view();
2187       return result;
2188    }
2189 };
2190 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2191 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2192 {
2193    using result_type = boost::multiprecision::number<boost::multiprecision::backends::debug_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2194    template <int N>
2195    static inline const result_type& get(const std::integral_constant<int, N>&)
2196    {
2197       // C++11 thread safe static initialization:
2198       static result_type result{get(std::integral_constant<int, 0>())};
2199       return result;
2200    }
2201    static inline result_type get(const std::integral_constant<int, 0>&)
2202    {
2203       result_type result;
2204       mpfi_const_catalan(result.backend().value().data());
2205       result.backend().update_view();
2206       return result;
2207    }
2208 };
2209 //
2210 // And again with logged_adaptor:
2211 //
2212 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2213 struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2214 {
2215    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2216    template <int N>
2217    static inline const result_type& get(const std::integral_constant<int, N>&)
2218    {
2219       // C++11 thread safe static initialization:
2220       static result_type result{get(std::integral_constant<int, 0>())};
2221       return result;
2222    }
2223    static inline result_type get(const std::integral_constant<int, 0>&)
2224    {
2225       result_type result;
2226       mpfi_const_pi(result.backend().value().data());
2227       return result;
2228    }
2229 };
2230 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2231 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2232 {
2233    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2234    template <int N>
2235    static inline const result_type& get(const std::integral_constant<int, N>&)
2236    {
2237       // C++11 thread safe static initialization:
2238       static result_type result{get(std::integral_constant<int, 0>())};
2239       return result;
2240    }
2241    static inline result_type get(const std::integral_constant<int, 0>&)
2242    {
2243       result_type result;
2244       mpfi_const_log2(result.backend().value().data());
2245       return result;
2246    }
2247 };
2248 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2249 struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2250 {
2251    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2252    template <int N>
2253    static inline const result_type& get(const std::integral_constant<int, N>&)
2254    {
2255       // C++11 thread safe static initialization:
2256       static result_type result{get(std::integral_constant<int, 0>())};
2257       return result;
2258    }
2259    static inline result_type get(const std::integral_constant<int, 0>&)
2260    {
2261       result_type result;
2262       mpfi_const_euler(result.backend().value().data());
2263       return result;
2264    }
2265 };
2266 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2267 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates> >
2268 {
2269    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfi_float_backend<Digits10> >, ExpressionTemplates>;
2270    template <int N>
2271    static inline const result_type& get(const std::integral_constant<int, N>&)
2272    {
2273       // C++11 thread safe static initialization:
2274       static result_type result{get(std::integral_constant<int, 0>())};
2275       return result;
2276    }
2277    static inline result_type get(const std::integral_constant<int, 0>&)
2278    {
2279       result_type result;
2280       mpfi_const_catalan(result.backend().value().data());
2281       return result;
2282    }
2283 };
2284 
2285 }} // namespace constants::detail
2286 
2287 } // namespace math
2288 } // namespace boost
2289 
2290 namespace std {
2291 
2292 //
2293 // numeric_limits [partial] specializations for the types declared in this header:
2294 //
2295 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2296 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >
2297 {
2298    using number_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates>;
2299    static number_type get_min()
2300    {
2301       number_type value(0.5);
2302       mpfi_div_2exp(value.backend().data(), value.backend().data(), -mpfr_get_emin());
2303       return value;
2304    }
2305    static number_type get_max()
2306    {
2307       number_type value(0.5);
2308       mpfi_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax());
2309       return value;
2310    }
2311    static number_type get_epsilon()
2312    {
2313       number_type value(1);
2314       mpfi_div_2exp(value.backend().data(), value.backend().data(), std::numeric_limits<number_type>::digits - 1);
2315       return value;
2316    }
2317    static number_type get_infinity()
2318    {
2319       number_type value;
2320       boost::multiprecision::mpfr_float_backend<Digits10> t;
2321       mpfr_set_inf(t.data(), 1);
2322       mpfi_set_fr(value.backend().data(), t.data());
2323       return value;
2324    }
2325    static number_type get_quiet_NaN()
2326    {
2327       number_type value;
2328       boost::multiprecision::mpfr_float_backend<Digits10> t;
2329       mpfr_set_nan(t.data());
2330       mpfi_set_fr(value.backend().data(), t.data());
2331       return value;
2332    }
2333 
2334  public:
2335    static constexpr bool is_specialized = true;
2336    static number_type(min)()
2337    {
2338       static number_type value{get_min()};
2339       return value;
2340    }
2341    static number_type(max)()
2342    {
2343       static number_type value{get_max()};
2344       return value;
2345    }
2346    static constexpr number_type lowest()
2347    {
2348       return -(max)();
2349    }
2350    static constexpr int digits   = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
2351    static constexpr int digits10 = Digits10;
2352    // Is this really correct???
2353    static constexpr int  max_digits10 = boost::multiprecision::detail::calc_max_digits10<digits>::value;
2354    static constexpr bool is_signed    = true;
2355    static constexpr bool is_integer   = false;
2356    static constexpr bool is_exact     = false;
2357    static constexpr int  radix        = 2;
2358    static number_type          epsilon()
2359    {
2360       static number_type value{get_epsilon()};
2361       return value;
2362    }
2363    // What value should this be????
2364    static number_type round_error()
2365    {
2366       return 0.5;
2367    }
2368    static constexpr long min_exponent                  = MPFR_EMIN_DEFAULT;
2369    static constexpr long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
2370    static constexpr long max_exponent                  = MPFR_EMAX_DEFAULT;
2371    static constexpr long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
2372    static constexpr bool has_infinity                  = true;
2373    static constexpr bool has_quiet_NaN                 = true;
2374    static constexpr bool has_signaling_NaN             = false;
2375    static constexpr float_denorm_style has_denorm      = denorm_absent;
2376    static constexpr bool               has_denorm_loss = false;
2377    static number_type                        infinity()
2378    {
2379       static number_type value{get_infinity()};
2380       return value;
2381    }
2382    static number_type quiet_NaN()
2383    {
2384       static number_type value{get_quiet_NaN()};
2385       return value;
2386    }
2387    static constexpr number_type signaling_NaN()
2388    {
2389       return number_type(0);
2390    }
2391    static constexpr number_type denorm_min() { return (min)(); }
2392    static constexpr bool        is_iec559         = false;
2393    static constexpr bool        is_bounded        = true;
2394    static constexpr bool        is_modulo         = false;
2395    static constexpr bool        traps             = true;
2396    static constexpr bool        tinyness_before   = false;
2397    static constexpr float_round_style round_style = round_to_nearest;
2398 };
2399 
2400 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2401 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits;
2402 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2403 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::digits10;
2404 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2405 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_digits10;
2406 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2407 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_signed;
2408 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2409 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_integer;
2410 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2411 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_exact;
2412 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2413 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::radix;
2414 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2415 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent;
2416 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2417 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::min_exponent10;
2418 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2419 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent;
2420 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2421 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::max_exponent10;
2422 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2423 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_infinity;
2424 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2425 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
2426 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2427 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
2428 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2429 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm;
2430 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2431 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::has_denorm_loss;
2432 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2433 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_iec559;
2434 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2435 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_bounded;
2436 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2437 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::is_modulo;
2438 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2439 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::traps;
2440 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2441 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::tinyness_before;
2442 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2443 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>, ExpressionTemplates> >::round_style;
2444 
2445 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2446 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >
2447 {
2448    using number_type = boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates>;
2449 
2450  public:
2451    static constexpr bool is_specialized = false;
2452    static number_type(min)() { return number_type(0); }
2453    static number_type(max)() { return number_type(0); }
2454    static number_type          lowest() { return number_type(0); }
2455    static constexpr int  digits       = 0;
2456    static constexpr int  digits10     = 0;
2457    static constexpr int  max_digits10 = 0;
2458    static constexpr bool is_signed    = false;
2459    static constexpr bool is_integer   = false;
2460    static constexpr bool is_exact     = false;
2461    static constexpr int  radix        = 0;
2462    static number_type          epsilon() { return number_type(0); }
2463    static number_type          round_error() { return number_type(0); }
2464    static constexpr int  min_exponent                  = 0;
2465    static constexpr int  min_exponent10                = 0;
2466    static constexpr int  max_exponent                  = 0;
2467    static constexpr int  max_exponent10                = 0;
2468    static constexpr bool has_infinity                  = false;
2469    static constexpr bool has_quiet_NaN                 = false;
2470    static constexpr bool has_signaling_NaN             = false;
2471    static constexpr float_denorm_style has_denorm      = denorm_absent;
2472    static constexpr bool               has_denorm_loss = false;
2473    static number_type                        infinity() { return number_type(0); }
2474    static number_type                        quiet_NaN() { return number_type(0); }
2475    static number_type                        signaling_NaN() { return number_type(0); }
2476    static number_type                        denorm_min() { return number_type(0); }
2477    static constexpr bool               is_iec559       = false;
2478    static constexpr bool               is_bounded      = false;
2479    static constexpr bool               is_modulo       = false;
2480    static constexpr bool               traps           = false;
2481    static constexpr bool               tinyness_before = false;
2482    static constexpr float_round_style round_style      = round_toward_zero;
2483 };
2484 
2485 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2486 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits;
2487 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2488 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::digits10;
2489 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2490 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_digits10;
2491 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2492 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_signed;
2493 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2494 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_integer;
2495 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2496 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_exact;
2497 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2498 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::radix;
2499 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2500 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent;
2501 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2502 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::min_exponent10;
2503 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2504 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent;
2505 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2506 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::max_exponent10;
2507 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2508 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_infinity;
2509 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2510 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
2511 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2512 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
2513 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2514 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm;
2515 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2516 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
2517 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2518 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_iec559;
2519 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2520 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_bounded;
2521 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2522 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::is_modulo;
2523 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2524 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::traps;
2525 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2526 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::tinyness_before;
2527 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2528 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<0>, ExpressionTemplates> >::round_style;
2529 
2530 } // namespace std
2531 #endif