Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:36

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_MPFR_HPP
0007 #define BOOST_MP_MPFR_HPP
0008 
0009 #include <boost/multiprecision/detail/standalone_config.hpp>
0010 #include <boost/multiprecision/number.hpp>
0011 #include <boost/multiprecision/debug_adaptor.hpp>
0012 #include <boost/multiprecision/logged_adaptor.hpp>
0013 #include <boost/multiprecision/gmp.hpp>
0014 #include <boost/multiprecision/detail/digits.hpp>
0015 #include <boost/multiprecision/detail/float128_functions.hpp>
0016 #include <boost/multiprecision/detail/atomic.hpp>
0017 #include <boost/multiprecision/traits/max_digits10.hpp>
0018 #include <boost/multiprecision/detail/hash.hpp>
0019 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0020 #include <boost/multiprecision/detail/assert.hpp>
0021 #include <boost/multiprecision/detail/fpclassify.hpp>
0022 #include <mpfr.h>
0023 #include <cmath>
0024 #include <cstdint>
0025 #include <algorithm>
0026 #include <utility>
0027 #include <type_traits>
0028 #include <atomic>
0029 
0030 #ifdef BOOST_MP_MATH_AVAILABLE
0031 #include <boost/math/constants/constants.hpp>
0032 #include <boost/math/special_functions/gamma.hpp>
0033 #endif
0034 
0035 #ifndef BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION
0036 #define BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION 20
0037 #endif
0038 
0039 namespace boost {
0040 namespace multiprecision {
0041 
0042 template <unsigned digits10, mpfr_allocation_type AllocationType>
0043 struct number_category<backends::mpfr_float_backend<digits10, AllocationType> > : public std::integral_constant<int, number_kind_floating_point>
0044 {};
0045 
0046 namespace backends {
0047 
0048 namespace detail {
0049 
0050 template <bool b>
0051 struct mpfr_cleanup
0052 {
0053    //
0054    // There are 2 seperate cleanup objects here, one calls
0055    // mpfr_free_cache on destruction to perform global cleanup
0056    // the other is declared thread_local and calls
0057    // mpfr_free_cache2(MPFR_FREE_LOCAL_CACHE) to free thread local data.
0058    //
0059    struct initializer
0060    {
0061       initializer() {}
0062       ~initializer() { mpfr_free_cache(); }
0063       void force_instantiate() const {}
0064    };
0065 #if MPFR_VERSION_MAJOR >= 4
0066    struct thread_initializer
0067    {
0068       thread_initializer() {}
0069       ~thread_initializer() { mpfr_free_cache2(MPFR_FREE_LOCAL_CACHE); }
0070       void force_instantiate() const {}
0071    };
0072 #endif
0073    static const initializer init;
0074    static void              force_instantiate()
0075    {
0076 #if MPFR_VERSION_MAJOR >= 4
0077       static const BOOST_MP_THREAD_LOCAL thread_initializer thread_init;
0078       thread_init.force_instantiate();
0079 #endif
0080       init.force_instantiate();
0081    }
0082 };
0083 
0084 template <bool b>
0085 typename mpfr_cleanup<b>::initializer const mpfr_cleanup<b>::init;
0086 
0087 inline void mpfr_copy_precision(mpfr_t dest, const mpfr_t src)
0088 {
0089    mpfr_prec_t p_dest = mpfr_get_prec(dest);
0090    mpfr_prec_t p_src  = mpfr_get_prec(src);
0091    if (p_dest != p_src)
0092       mpfr_set_prec(dest, p_src);
0093 }
0094 inline void mpfr_copy_precision(mpfr_t dest, const mpfr_t src1, const mpfr_t src2)
0095 {
0096    mpfr_prec_t p_dest = mpfr_get_prec(dest);
0097    mpfr_prec_t p_src1 = mpfr_get_prec(src1);
0098    mpfr_prec_t p_src2 = mpfr_get_prec(src2);
0099    if (p_src2 > p_src1)
0100       p_src1 = p_src2;
0101    if (p_dest != p_src1)
0102       mpfr_set_prec(dest, p_src1);
0103 }
0104 
0105 template <unsigned digits10, mpfr_allocation_type AllocationType>
0106 struct mpfr_float_imp;
0107 
0108 template <unsigned digits10>
0109 struct mpfr_float_imp<digits10, allocate_dynamic>
0110 {
0111 #ifdef BOOST_HAS_LONG_LONG
0112    using signed_types = std::tuple<long, long long>          ;
0113    using unsigned_types = std::tuple<unsigned long, unsigned long long>;
0114 #else
0115    using signed_types = std::tuple<long>         ;
0116    using unsigned_types = std::tuple<unsigned long>;
0117 #endif
0118    using float_types = std::tuple<double, long double>;
0119    using exponent_type = long                          ;
0120 
0121    mpfr_float_imp()
0122    {
0123       mpfr_init2(m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision()))));
0124       mpfr_set_ui(m_data, 0u, GMP_RNDN);
0125    }
0126    mpfr_float_imp(unsigned digits2)
0127    {
0128       mpfr_init2(m_data, digits2);
0129       mpfr_set_ui(m_data, 0u, GMP_RNDN);
0130    }
0131 
0132    mpfr_float_imp(const mpfr_float_imp& o)
0133    {
0134       mpfr_init2(m_data, preserve_source_precision() ? mpfr_get_prec(o.data()) : static_cast<mpfr_prec_t>(boost::multiprecision::detail::digits10_2_2(get_default_precision())));
0135       if (o.m_data[0]._mpfr_d)
0136          mpfr_set(m_data, o.m_data, GMP_RNDN);
0137    }
0138    // rvalue copy
0139    mpfr_float_imp(mpfr_float_imp&& o) noexcept
0140    {
0141       mpfr_prec_t binary_default_precision = static_cast<mpfr_prec_t>(boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0142       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfr_get_prec(o.data()) == binary_default_precision))
0143       {
0144          m_data[0] = o.m_data[0];
0145          o.m_data[0]._mpfr_d = nullptr;
0146       }
0147       else
0148       {
0149          // NOTE: C allocation interface must not throw:
0150          mpfr_init2(m_data, binary_default_precision);
0151          if (o.m_data[0]._mpfr_d)
0152             mpfr_set(m_data, o.m_data, GMP_RNDN);
0153       }
0154    }
0155    mpfr_float_imp& operator=(const mpfr_float_imp& o)
0156    {
0157       if ((o.m_data[0]._mpfr_d) && (this != &o))
0158       {
0159          if (m_data[0]._mpfr_d == nullptr)
0160          {
0161             mpfr_init2(m_data, preserve_source_precision() ? static_cast<mpfr_prec_t>(mpfr_get_prec(o.m_data)) : static_cast<mpfr_prec_t>(boost::multiprecision::detail::digits10_2_2(get_default_precision())));
0162          }
0163          else if (preserve_source_precision() && (mpfr_get_prec(o.data()) != mpfr_get_prec(data())))
0164          {
0165             mpfr_set_prec(m_data, mpfr_get_prec(o.m_data));
0166          }
0167          mpfr_set(m_data, o.m_data, GMP_RNDN);
0168       }
0169       return *this;
0170    }
0171    // rvalue assign
0172    mpfr_float_imp& operator=(mpfr_float_imp&& o) noexcept
0173    {
0174       if ((this->get_default_options() != variable_precision_options::preserve_target_precision) || (mpfr_get_prec(o.data()) == mpfr_get_prec(data())))
0175          mpfr_swap(m_data, o.m_data);
0176       else
0177          *this = static_cast<const mpfr_float_imp&>(o);
0178       return *this;
0179    }
0180 #ifdef BOOST_HAS_LONG_LONG
0181 #ifdef _MPFR_H_HAVE_INTMAX_T
0182    mpfr_float_imp& operator=(unsigned long long i)
0183    {
0184       if (m_data[0]._mpfr_d == nullptr)
0185          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0186       mpfr_set_uj(m_data, i, GMP_RNDN);
0187       return *this;
0188    }
0189    mpfr_float_imp& operator=(long long i)
0190    {
0191       if (m_data[0]._mpfr_d == nullptr)
0192          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0193       mpfr_set_sj(m_data, i, GMP_RNDN);
0194       return *this;
0195    }
0196 #else
0197    mpfr_float_imp& operator=(unsigned long long i)
0198    {
0199       if (m_data[0]._mpfr_d == nullptr)
0200          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0201       unsigned long long mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
0202       unsigned               shift = 0;
0203       mpfr_t                 t;
0204       mpfr_init2(t, (std::max)(static_cast<mpfr_prec_t>(std::numeric_limits<unsigned long long>::digits), static_cast<mpfr_prec_t>(mpfr_get_prec(m_data))));
0205       mpfr_set_ui(m_data, 0, GMP_RNDN);
0206       while (i)
0207       {
0208          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
0209          if (shift)
0210             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
0211          mpfr_add(m_data, m_data, t, GMP_RNDN);
0212          shift += std::numeric_limits<unsigned long>::digits;
0213          i >>= std::numeric_limits<unsigned long>::digits;
0214       }
0215       mpfr_clear(t);
0216       return *this;
0217    }
0218    mpfr_float_imp& operator=(long long i)
0219    {
0220       if (m_data[0]._mpfr_d == nullptr)
0221          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0222       bool neg = i < 0;
0223       *this    = boost::multiprecision::detail::unsigned_abs(i);
0224       if (neg)
0225          mpfr_neg(m_data, m_data, GMP_RNDN);
0226       return *this;
0227    }
0228 #endif
0229 #endif
0230 #ifdef BOOST_HAS_INT128
0231    mpfr_float_imp& operator=(uint128_type i)
0232    {
0233       if (m_data[0]._mpfr_d == nullptr)
0234          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0235       unsigned long long mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
0236       unsigned           shift = 0;
0237       mpfr_t             t;
0238       mpfr_init2(t, (std::max)(static_cast<mpfr_prec_t>(std::numeric_limits<unsigned long long>::digits), static_cast<mpfr_prec_t>(mpfr_get_prec(m_data))));
0239       mpfr_set_ui(m_data, 0, GMP_RNDN);
0240       while (i)
0241       {
0242          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
0243          if (shift)
0244             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
0245          mpfr_add(m_data, m_data, t, GMP_RNDN);
0246          shift += std::numeric_limits<unsigned long>::digits;
0247          i >>= std::numeric_limits<unsigned long>::digits;
0248       }
0249       mpfr_clear(t);
0250       return *this;
0251    }
0252    mpfr_float_imp& operator=(int128_type i)
0253    {
0254       if (m_data[0]._mpfr_d == nullptr)
0255          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0256       bool neg = i < 0;
0257       *this    = boost::multiprecision::detail::unsigned_abs(i);
0258       if (neg)
0259          mpfr_neg(m_data, m_data, GMP_RNDN);
0260       return *this;
0261    }
0262 #endif
0263    mpfr_float_imp& operator=(unsigned long i)
0264    {
0265       if (m_data[0]._mpfr_d == nullptr)
0266          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0267       mpfr_set_ui(m_data, i, GMP_RNDN);
0268       return *this;
0269    }
0270    mpfr_float_imp& operator=(long i)
0271    {
0272       if (m_data[0]._mpfr_d == nullptr)
0273          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0274       mpfr_set_si(m_data, i, GMP_RNDN);
0275       return *this;
0276    }
0277    mpfr_float_imp& operator=(double d)
0278    {
0279       if (m_data[0]._mpfr_d == nullptr)
0280          mpfr_init2(m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision()))));
0281       mpfr_set_d(m_data, d, GMP_RNDN);
0282       return *this;
0283    }
0284    mpfr_float_imp& operator=(long double a)
0285    {
0286       if (m_data[0]._mpfr_d == nullptr)
0287          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0288       mpfr_set_ld(m_data, a, GMP_RNDN);
0289       return *this;
0290    }
0291 #ifdef BOOST_HAS_FLOAT128
0292    mpfr_float_imp& operator=(float128_type a)
0293    {
0294       BOOST_MP_FLOAT128_USING
0295       if (m_data[0]._mpfr_d == nullptr)
0296          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision())));
0297 
0298       if (a == 0)
0299       {
0300          mpfr_set_si(m_data, 0, GMP_RNDN);
0301          return *this;
0302       }
0303 
0304       if (a == 1)
0305       {
0306          mpfr_set_si(m_data, 1, GMP_RNDN);
0307          return *this;
0308       }
0309 
0310       if (BOOST_MP_ISINF(a))
0311       {
0312          mpfr_set_inf(m_data, a < 0 ? -1 : 1);
0313          return *this;
0314       }
0315       if (BOOST_MP_ISNAN(a))
0316       {
0317          mpfr_set_nan(m_data);
0318          return *this;
0319       }
0320 
0321       int        e;
0322       float128_type f, term;
0323       mpfr_set_ui(m_data, 0u, GMP_RNDN);
0324 
0325       f = frexp(a, &e);
0326 
0327       constexpr const int shift = std::numeric_limits<int>::digits - 1;
0328 
0329       while (f)
0330       {
0331          // extract int sized bits from f:
0332          f    = ldexp(f, shift);
0333          term = floor(f);
0334          e -= shift;
0335          mpfr_mul_2exp(m_data, m_data, shift, GMP_RNDN);
0336          if (term > 0)
0337             mpfr_add_ui(m_data, m_data, static_cast<unsigned>(term), GMP_RNDN);
0338          else
0339             mpfr_sub_ui(m_data, m_data, static_cast<unsigned>(-term), GMP_RNDN);
0340          f -= term;
0341       }
0342       if (e > 0)
0343          mpfr_mul_2exp(m_data, m_data, e, GMP_RNDN);
0344       else if (e < 0)
0345          mpfr_div_2exp(m_data, m_data, -e, GMP_RNDN);
0346       return *this;
0347    }
0348 #endif
0349    mpfr_float_imp& operator=(const char* s)
0350    {
0351       if (m_data[0]._mpfr_d == nullptr)
0352          mpfr_init2(m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(digits10 ? digits10 : static_cast<unsigned>(get_default_precision()))));
0353       if (mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
0354       {
0355          BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
0356       }
0357       return *this;
0358    }
0359    void swap(mpfr_float_imp& o) noexcept
0360    {
0361       mpfr_swap(m_data, o.m_data);
0362    }
0363    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0364    {
0365       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0366 
0367       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
0368       bool fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
0369 
0370       std::streamsize org_digits(digits);
0371 
0372       if (scientific && digits)
0373          ++digits;
0374 
0375       std::string result;
0376       mp_exp_t    e;
0377       if (mpfr_inf_p(m_data))
0378       {
0379          if (mpfr_sgn(m_data) < 0)
0380             result = "-inf";
0381          else if (f & std::ios_base::showpos)
0382             result = "+inf";
0383          else
0384             result = "inf";
0385          return result;
0386       }
0387       if (mpfr_nan_p(m_data))
0388       {
0389          result = "nan";
0390          return result;
0391       }
0392       if (mpfr_zero_p(m_data))
0393       {
0394          e      = 0;
0395          if (mpfr_signbit(m_data))
0396             result = "-0";
0397          else
0398             result = "0";
0399       }
0400       else if (fixed)
0401       {
0402          // We actually need a different number of digits to what one might expect:
0403          char* ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0404          --e;
0405          mpfr_free_str(ps);
0406          digits += e + 1;
0407          if (digits == 0)
0408          {
0409             // We need to get *all* the digits and then possibly round up,
0410             // we end up with either "0" or "1" as the result.
0411             ps = mpfr_get_str(nullptr, &e, 10, 0, m_data, GMP_RNDN);
0412             --e;
0413             unsigned offset = *ps == '-' ? 1 : 0;
0414             if (ps[offset] > '5')
0415             {
0416                ++e;
0417                ps[offset] = '1';
0418                ps[offset + 1] = 0;
0419             }
0420             else if (ps[offset] == '5')
0421             {
0422                unsigned i = offset + 1;
0423                bool     round_up = false;
0424                while (ps[i] != 0)
0425                {
0426                   if (ps[i] != '0')
0427                   {
0428                      round_up = true;
0429                      break;
0430                   }
0431                   ++i;
0432                }
0433                if (round_up)
0434                {
0435                   ++e;
0436                   ps[offset] = '1';
0437                   ps[offset + 1] = 0;
0438                }
0439                else
0440                {
0441                   ps[offset] = '0';
0442                   ps[offset + 1] = 0;
0443                }
0444             }
0445             else
0446             {
0447                ps[offset] = '0';
0448                ps[offset + 1] = 0;
0449             }
0450          }
0451          else if (digits > 0)
0452          {
0453             mp_exp_t old_e = e;
0454             ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0455             --e; // To match with what our formatter expects.
0456             if (old_e > e)
0457             {
0458                // in some cases, when we ask for more digits of precision, it will
0459                // change the number of digits to the left of the decimal, if that
0460                // happens, account for it here.
0461                // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
0462                mpfr_free_str(ps);
0463                digits -= old_e - e;
0464                ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0465                --e; // To match with what our formatter expects.
0466             }
0467          }
0468          else
0469          {
0470             ps = mpfr_get_str(nullptr, &e, 10, 1, m_data, GMP_RNDN);
0471             --e;
0472             unsigned offset = *ps == '-' ? 1 : 0;
0473             ps[offset] = '0';
0474             ps[offset + 1] = 0;
0475          }
0476          result = ps ? ps : "0";
0477          if (ps)
0478             mpfr_free_str(ps);
0479       }
0480       else
0481       {
0482          char* ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0483          --e; // To match with what our formatter expects.
0484          result = ps ? ps : "0";
0485          if (ps)
0486             mpfr_free_str(ps);
0487       }
0488       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
0489       return result;
0490    }
0491    ~mpfr_float_imp() noexcept
0492    {
0493       if (m_data[0]._mpfr_d)
0494          mpfr_clear(m_data);
0495       detail::mpfr_cleanup<true>::force_instantiate();
0496    }
0497    void negate() noexcept
0498    {
0499       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0500       mpfr_neg(m_data, m_data, GMP_RNDN);
0501    }
0502    template <mpfr_allocation_type AllocationType>
0503    int compare(const mpfr_float_backend<digits10, AllocationType>& o) const
0504    {
0505       BOOST_MP_ASSERT(m_data[0]._mpfr_d && o.m_data[0]._mpfr_d);
0506       return mpfr_cmp(m_data, o.m_data);
0507    }
0508    int compare(long i) const
0509    {
0510       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0511       return mpfr_cmp_si(m_data, i);
0512    }
0513    int compare(double i) const
0514    {
0515       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0516       return mpfr_cmp_d(m_data, i);
0517    }
0518    int compare(long double i) const
0519    {
0520       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0521       return mpfr_cmp_ld(m_data, i);
0522    }
0523    int compare(unsigned long i) const
0524    {
0525       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0526       return mpfr_cmp_ui(m_data, i);
0527    }
0528    template <class V>
0529    int compare(V v) const
0530    {
0531       mpfr_float_backend<digits10, allocate_dynamic> d(0uL, mpfr_get_prec(m_data));
0532       d = v;
0533       return compare(d);
0534    }
0535    mpfr_t& data() noexcept
0536    {
0537       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0538       return m_data;
0539    }
0540    const mpfr_t& data() const noexcept
0541    {
0542       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0543       return m_data;
0544    }
0545 
0546  protected:
0547    mpfr_t           m_data;
0548    static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
0549    {
0550       static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION);
0551       return val;
0552    }
0553    static unsigned& get_default_precision() noexcept
0554    {
0555       static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
0556       return val;
0557    }
0558 #ifndef BOOST_MT_NO_ATOMIC_INT
0559    static std::atomic<variable_precision_options>& get_global_default_options() noexcept
0560    {
0561       static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
0562       return val;
0563    }
0564 #else
0565    static variable_precision_options& get_global_default_options() noexcept
0566    {
0567       static variable_precision_options val{variable_precision_options::preserve_related_precision};
0568       return val;
0569    }
0570 #endif
0571    static variable_precision_options& get_default_options()noexcept
0572    {
0573       static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
0574       return val;
0575    }
0576    static bool preserve_source_precision() noexcept
0577    {
0578       return get_default_options() >= variable_precision_options::preserve_source_precision;
0579    }
0580 };
0581 
0582 #ifdef BOOST_MSVC
0583 #pragma warning(push)
0584 #pragma warning(disable : 4127) // Conditional expression is constant
0585 #endif
0586 
0587 template <unsigned digits10>
0588 struct mpfr_float_imp<digits10, allocate_stack>
0589 {
0590 #ifdef BOOST_HAS_LONG_LONG
0591    using signed_types = std::tuple<long, long long>          ;
0592    using unsigned_types = std::tuple<unsigned long, unsigned long long>;
0593 #else
0594    using signed_types = std::tuple<long>         ;
0595    using unsigned_types = std::tuple<unsigned long>;
0596 #endif
0597    using float_types = std::tuple<double, long double>;
0598    using exponent_type = long                          ;
0599 
0600    static constexpr const unsigned digits2    = (digits10 * 1000uL) / 301uL + ((digits10 * 1000uL) % 301 ? 2u : 1u);
0601    static constexpr const unsigned limb_count = mpfr_custom_get_size(digits2) / sizeof(mp_limb_t);
0602 
0603    ~mpfr_float_imp() noexcept
0604    {
0605       detail::mpfr_cleanup<true>::force_instantiate();
0606    }
0607    mpfr_float_imp()
0608    {
0609       mpfr_custom_init(m_buffer, digits2);
0610       mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
0611       mpfr_set_ui(m_data, 0u, GMP_RNDN);
0612    }
0613 
0614    mpfr_float_imp(const mpfr_float_imp& o)
0615    {
0616       mpfr_custom_init(m_buffer, digits2);
0617       mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
0618       mpfr_set(m_data, o.m_data, GMP_RNDN);
0619    }
0620    mpfr_float_imp& operator=(const mpfr_float_imp& o)
0621    {
0622       mpfr_set(m_data, o.m_data, GMP_RNDN);
0623       return *this;
0624    }
0625 #ifdef BOOST_HAS_LONG_LONG
0626 #ifdef _MPFR_H_HAVE_INTMAX_T
0627    mpfr_float_imp& operator=(unsigned long long i)
0628    {
0629       mpfr_set_uj(m_data, i, GMP_RNDN);
0630       return *this;
0631    }
0632    mpfr_float_imp& operator=(long long i)
0633    {
0634       mpfr_set_sj(m_data, i, GMP_RNDN);
0635       return *this;
0636    }
0637 #else
0638    mpfr_float_imp& operator=(unsigned long long i)
0639    {
0640       unsigned long long mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uL);
0641       unsigned               shift = 0;
0642       mpfr_t                 t;
0643       mp_limb_t              t_limbs[limb_count];
0644       mpfr_custom_init(t_limbs, digits2);
0645       mpfr_custom_init_set(t, MPFR_NAN_KIND, 0, digits2, t_limbs);
0646       mpfr_set_ui(m_data, 0, GMP_RNDN);
0647       while (i)
0648       {
0649          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
0650          if (shift)
0651             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
0652          mpfr_add(m_data, m_data, t, GMP_RNDN);
0653          shift += std::numeric_limits<unsigned long>::digits;
0654          i >>= std::numeric_limits<unsigned long>::digits;
0655       }
0656       return *this;
0657    }
0658    mpfr_float_imp& operator=(long long i)
0659    {
0660       bool neg = i < 0;
0661       *this    = boost::multiprecision::detail::unsigned_abs(i);
0662       if (neg)
0663          mpfr_neg(m_data, m_data, GMP_RNDN);
0664       return *this;
0665    }
0666 #endif
0667 #endif
0668 #ifdef BOOST_HAS_INT128
0669    mpfr_float_imp& operator=(uint128_type i)
0670    {
0671       unsigned long long mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uL);
0672       unsigned           shift = 0;
0673       mpfr_t             t;
0674       mp_limb_t          t_limbs[limb_count];
0675       mpfr_custom_init(t_limbs, digits2);
0676       mpfr_custom_init_set(t, MPFR_NAN_KIND, 0, digits2, t_limbs);
0677       mpfr_set_ui(m_data, 0, GMP_RNDN);
0678       while (i)
0679       {
0680          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
0681          if (shift)
0682             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
0683          mpfr_add(m_data, m_data, t, GMP_RNDN);
0684          shift += std::numeric_limits<unsigned long>::digits;
0685          i >>= std::numeric_limits<unsigned long>::digits;
0686       }
0687       return *this;
0688    }
0689    mpfr_float_imp& operator=(int128_type i)
0690    {
0691       bool neg = i < 0;
0692       *this    = boost::multiprecision::detail::unsigned_abs(i);
0693       if (neg)
0694          mpfr_neg(m_data, m_data, GMP_RNDN);
0695       return *this;
0696    }
0697 #endif
0698    mpfr_float_imp& operator=(unsigned long i)
0699    {
0700       mpfr_set_ui(m_data, i, GMP_RNDN);
0701       return *this;
0702    }
0703    mpfr_float_imp& operator=(long i)
0704    {
0705       mpfr_set_si(m_data, i, GMP_RNDN);
0706       return *this;
0707    }
0708    mpfr_float_imp& operator=(double d)
0709    {
0710       mpfr_set_d(m_data, d, GMP_RNDN);
0711       return *this;
0712    }
0713    mpfr_float_imp& operator=(long double a)
0714    {
0715       mpfr_set_ld(m_data, a, GMP_RNDN);
0716       return *this;
0717    }
0718 #ifdef BOOST_HAS_FLOAT128
0719    mpfr_float_imp& operator=(float128_type a)
0720    {
0721       BOOST_MP_FLOAT128_USING
0722       if (a == 0)
0723       {
0724          mpfr_set_si(m_data, 0, GMP_RNDN);
0725          return *this;
0726       }
0727 
0728       if (a == 1)
0729       {
0730          mpfr_set_si(m_data, 1, GMP_RNDN);
0731          return *this;
0732       }
0733 
0734       if (BOOST_MP_ISINF(a))
0735       {
0736          mpfr_set_inf(m_data, a < 0 ? -1 : 1);
0737          return *this;
0738       }
0739       if (BOOST_MP_ISNAN(a))
0740       {
0741          mpfr_set_nan(m_data);
0742          return *this;
0743       }
0744 
0745       int        e;
0746       float128_type f, term;
0747       mpfr_set_ui(m_data, 0u, GMP_RNDN);
0748 
0749       f = frexp(a, &e);
0750 
0751       constexpr const int shift = std::numeric_limits<int>::digits - 1;
0752 
0753       while (f)
0754       {
0755          // extract int sized bits from f:
0756          f    = ldexp(f, shift);
0757          term = floor(f);
0758          e -= shift;
0759          mpfr_mul_2exp(m_data, m_data, shift, GMP_RNDN);
0760          if (term > 0)
0761             mpfr_add_ui(m_data, m_data, static_cast<unsigned>(term), GMP_RNDN);
0762          else
0763             mpfr_sub_ui(m_data, m_data, static_cast<unsigned>(-term), GMP_RNDN);
0764          f -= term;
0765       }
0766       if (e > 0)
0767          mpfr_mul_2exp(m_data, m_data, e, GMP_RNDN);
0768       else if (e < 0)
0769          mpfr_div_2exp(m_data, m_data, -e, GMP_RNDN);
0770       return *this;
0771    }
0772 #endif
0773    mpfr_float_imp& operator=(const char* s)
0774    {
0775       if (mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
0776       {
0777          BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
0778       }
0779       return *this;
0780    }
0781    void swap(mpfr_float_imp& o) noexcept
0782    {
0783       // We have to swap by copying:
0784       mpfr_float_imp t(*this);
0785       *this = o;
0786       o     = t;
0787    }
0788    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0789    {
0790       BOOST_MP_ASSERT(m_data[0]._mpfr_d);
0791 
0792       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
0793       bool fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
0794 
0795       std::streamsize org_digits(digits);
0796 
0797       if (scientific && digits)
0798          ++digits;
0799 
0800       std::string result;
0801       mp_exp_t    e;
0802       if (mpfr_inf_p(m_data))
0803       {
0804          if (mpfr_sgn(m_data) < 0)
0805             result = "-inf";
0806          else if (f & std::ios_base::showpos)
0807             result = "+inf";
0808          else
0809             result = "inf";
0810          return result;
0811       }
0812       if (mpfr_nan_p(m_data))
0813       {
0814          result = "nan";
0815          return result;
0816       }
0817       if (mpfr_zero_p(m_data))
0818       {
0819          e      = 0;
0820          result = "0";
0821       }
0822       else
0823       {
0824          char* ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0825          --e; // To match with what our formatter expects.
0826          if (fixed && e != -1)
0827          {
0828             // Oops we actually need a different number of digits to what we asked for:
0829             mpfr_free_str(ps);
0830             digits += e + 1;
0831             if (digits == 0)
0832             {
0833                // We need to get *all* the digits and then possibly round up,
0834                // we end up with either "0" or "1" as the result.
0835                ps = mpfr_get_str(nullptr, &e, 10, 0, m_data, GMP_RNDN);
0836                --e;
0837                unsigned offset = *ps == '-' ? 1 : 0;
0838                if (ps[offset] > '5')
0839                {
0840                   ++e;
0841                   ps[offset]     = '1';
0842                   ps[offset + 1] = 0;
0843                }
0844                else if (ps[offset] == '5')
0845                {
0846                   unsigned i        = offset + 1;
0847                   bool     round_up = false;
0848                   while (ps[i] != 0)
0849                   {
0850                      if (ps[i] != '0')
0851                      {
0852                         round_up = true;
0853                         break;
0854                      }
0855                   }
0856                   if (round_up)
0857                   {
0858                      ++e;
0859                      ps[offset]     = '1';
0860                      ps[offset + 1] = 0;
0861                   }
0862                   else
0863                   {
0864                      ps[offset]     = '0';
0865                      ps[offset + 1] = 0;
0866                   }
0867                }
0868                else
0869                {
0870                   ps[offset]     = '0';
0871                   ps[offset + 1] = 0;
0872                }
0873             }
0874             else if (digits > 0)
0875             {
0876                ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0877                --e; // To match with what our formatter expects.
0878             }
0879             else
0880             {
0881                ps = mpfr_get_str(nullptr, &e, 10, 1, m_data, GMP_RNDN);
0882                --e;
0883                unsigned offset = *ps == '-' ? 1 : 0;
0884                ps[offset]      = '0';
0885                ps[offset + 1]  = 0;
0886             }
0887          }
0888          result = ps ? ps : "0";
0889          if (ps)
0890             mpfr_free_str(ps);
0891       }
0892       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
0893       return result;
0894    }
0895    void negate() noexcept
0896    {
0897       mpfr_neg(m_data, m_data, GMP_RNDN);
0898    }
0899    template <mpfr_allocation_type AllocationType>
0900    int compare(const mpfr_float_backend<digits10, AllocationType>& o) const
0901    {
0902       return mpfr_cmp(m_data, o.m_data);
0903    }
0904    int compare(long i) const
0905    {
0906       return mpfr_cmp_si(m_data, i);
0907    }
0908    int compare(unsigned long i) const
0909    {
0910       return mpfr_cmp_ui(m_data, i);
0911    }
0912    int compare(double i) const
0913    {
0914       return mpfr_cmp_d(m_data, i);
0915    }
0916    int compare(long double i) const
0917    {
0918       return mpfr_cmp_ld(m_data, i);
0919    }
0920    template <class V>
0921    int compare(V v) const
0922    {
0923       mpfr_float_backend<digits10, allocate_stack> d;
0924       d = v;
0925       return compare(d);
0926    }
0927    mpfr_t& data() noexcept
0928    {
0929       return m_data;
0930    }
0931    const mpfr_t& data() const noexcept
0932    {
0933       return m_data;
0934    }
0935 
0936  protected:
0937    mpfr_t    m_data;
0938    mp_limb_t m_buffer[limb_count];
0939 };
0940 
0941 #ifdef BOOST_MSVC
0942 #pragma warning(pop)
0943 #endif
0944 
0945 } // namespace detail
0946 
0947 template <unsigned digits10, mpfr_allocation_type AllocationType>
0948 struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationType>
0949 {
0950    mpfr_float_backend() : detail::mpfr_float_imp<digits10, AllocationType>() {}
0951    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<digits10, AllocationType>(o) {}
0952    // rvalue copy
0953    mpfr_float_backend(mpfr_float_backend&& o) noexcept : detail::mpfr_float_imp<digits10, AllocationType>(static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o))
0954    {}
0955    template <unsigned D, mpfr_allocation_type AT>
0956    mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0957        : detail::mpfr_float_imp<digits10, AllocationType>()
0958    {
0959       mpfr_set(this->m_data, val.data(), GMP_RNDN);
0960    }
0961    template <unsigned D, mpfr_allocation_type AT>
0962    explicit mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0963        : detail::mpfr_float_imp<digits10, AllocationType>()
0964    {
0965       mpfr_set(this->m_data, val.data(), GMP_RNDN);
0966    }
0967    template <unsigned D>
0968    mpfr_float_backend(const gmp_float<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0969        : detail::mpfr_float_imp<digits10, AllocationType>()
0970    {
0971       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
0972    }
0973    template <unsigned D>
0974    mpfr_float_backend(const gmp_float<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0975        : detail::mpfr_float_imp<digits10, AllocationType>()
0976    {
0977       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
0978    }
0979    mpfr_float_backend(const gmp_int& val)
0980        : detail::mpfr_float_imp<digits10, AllocationType>()
0981    {
0982       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
0983    }
0984    mpfr_float_backend(const gmp_rational& val)
0985        : detail::mpfr_float_imp<digits10, AllocationType>()
0986    {
0987       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
0988    }
0989    mpfr_float_backend(const mpfr_t val)
0990        : detail::mpfr_float_imp<digits10, AllocationType>()
0991    {
0992       mpfr_set(this->m_data, val, GMP_RNDN);
0993    }
0994    mpfr_float_backend(const mpf_t val)
0995        : detail::mpfr_float_imp<digits10, AllocationType>()
0996    {
0997       mpfr_set_f(this->m_data, val, GMP_RNDN);
0998    }
0999    mpfr_float_backend(const mpz_t val)
1000        : detail::mpfr_float_imp<digits10, AllocationType>()
1001    {
1002       mpfr_set_z(this->m_data, val, GMP_RNDN);
1003    }
1004    mpfr_float_backend(const mpq_t val)
1005        : detail::mpfr_float_imp<digits10, AllocationType>()
1006    {
1007       mpfr_set_q(this->m_data, val, GMP_RNDN);
1008    }
1009    // Construction with precision: we ignore the precision here.
1010    template <class V>
1011    mpfr_float_backend(const V& o, unsigned)
1012    {
1013       *this = o;
1014    }
1015    mpfr_float_backend& operator=(const mpfr_float_backend& o)
1016    {
1017       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType> const&>(o);
1018       return *this;
1019    }
1020    // rvalue assign
1021    mpfr_float_backend& operator=(mpfr_float_backend&& o) noexcept
1022    {
1023       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o);
1024       return *this;
1025    }
1026    template <class V>
1027    typename std::enable_if<std::is_assignable<detail::mpfr_float_imp<digits10, AllocationType>, V>::value, mpfr_float_backend&>::type operator=(const V& v)
1028    {
1029       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = v;
1030       return *this;
1031    }
1032    mpfr_float_backend& operator=(const mpfr_t val)
1033    {
1034       if (this->m_data[0]._mpfr_d == nullptr)
1035          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1036       mpfr_set(this->m_data, val, GMP_RNDN);
1037       return *this;
1038    }
1039    mpfr_float_backend& operator=(const mpf_t val)
1040    {
1041       if (this->m_data[0]._mpfr_d == nullptr)
1042          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1043       mpfr_set_f(this->m_data, val, GMP_RNDN);
1044       return *this;
1045    }
1046    mpfr_float_backend& operator=(const mpz_t val)
1047    {
1048       if (this->m_data[0]._mpfr_d == nullptr)
1049          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1050       mpfr_set_z(this->m_data, val, GMP_RNDN);
1051       return *this;
1052    }
1053    mpfr_float_backend& operator=(const mpq_t val)
1054    {
1055       if (this->m_data[0]._mpfr_d == nullptr)
1056          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1057       mpfr_set_q(this->m_data, val, GMP_RNDN);
1058       return *this;
1059    }
1060    // We don't change our precision here, this is a fixed precision type:
1061    template <unsigned D, mpfr_allocation_type AT>
1062    mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
1063    {
1064       if (this->m_data[0]._mpfr_d == nullptr)
1065          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1066       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1067       return *this;
1068    }
1069    template <unsigned D>
1070    mpfr_float_backend& operator=(const gmp_float<D>& val)
1071    {
1072       if (this->m_data[0]._mpfr_d == nullptr)
1073          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1074       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1075       return *this;
1076    }
1077    mpfr_float_backend& operator=(const gmp_int& val)
1078    {
1079       if (this->m_data[0]._mpfr_d == nullptr)
1080          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1081       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1082       return *this;
1083    }
1084    mpfr_float_backend& operator=(const gmp_rational& val)
1085    {
1086       if (this->m_data[0]._mpfr_d == nullptr)
1087          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1088       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1089       return *this;
1090    }
1091 };
1092 
1093 template <>
1094 struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0, allocate_dynamic>
1095 {
1096    mpfr_float_backend() : detail::mpfr_float_imp<0, allocate_dynamic>() {}
1097    mpfr_float_backend(const mpfr_t val)
1098        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_all_precision() ? static_cast<unsigned>(mpfr_get_prec(val)) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(get_default_precision())))
1099    {
1100       mpfr_set(this->m_data, val, GMP_RNDN);
1101    }
1102    mpfr_float_backend(const mpf_t val)
1103        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_all_precision() ? static_cast<unsigned>(mpf_get_prec(val)) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(get_default_precision())))
1104    {
1105       mpfr_set_f(this->m_data, val, GMP_RNDN);
1106    }
1107    mpfr_float_backend(const mpz_t val)
1108        : detail::mpfr_float_imp<0, allocate_dynamic>()
1109    {
1110       mpfr_set_z(this->m_data, val, GMP_RNDN);
1111    }
1112    mpfr_float_backend(const mpq_t val)
1113        : detail::mpfr_float_imp<0, allocate_dynamic>()
1114    {
1115       mpfr_set_q(this->m_data, val, GMP_RNDN);
1116    }
1117    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<0, allocate_dynamic>(o) {}
1118    // rvalue copy
1119    mpfr_float_backend(mpfr_float_backend&& o) noexcept : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<detail::mpfr_float_imp<0, allocate_dynamic>&&>(o))
1120    {}
1121    template <class V>
1122    mpfr_float_backend(const V& o, unsigned digits10)
1123        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1124    {
1125       *this = o;
1126    }
1127 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
1128    mpfr_float_backend(const std::string_view& o, unsigned digits10)
1129        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1130    {
1131       std::string s(o);
1132       *this = s.c_str();
1133    }
1134 #endif
1135    template <unsigned D>
1136    mpfr_float_backend(const gmp_float<D>& val, unsigned digits10)
1137        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1138    {
1139       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1140    }
1141    template <unsigned D>
1142    mpfr_float_backend(const mpfr_float_backend<D>& val, unsigned digits10)
1143        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1144    {
1145       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1146    }
1147    template <unsigned D>
1148    mpfr_float_backend(const mpfr_float_backend<D>& val)
1149        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_related_precision() ? static_cast<unsigned>(mpfr_get_prec(val.data())) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(get_default_precision())))
1150    {
1151       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1152    }
1153    template <unsigned D>
1154    mpfr_float_backend(const gmp_float<D>& val)
1155        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_all_precision() ? static_cast<unsigned>(mpf_get_prec(val.data())) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(get_default_precision())))
1156    {
1157       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1158    }
1159    mpfr_float_backend(const gmp_int& val)
1160        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_all_precision() ? static_cast<unsigned>(used_gmp_int_bits(val)) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(thread_default_precision())))
1161    {
1162       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1163    }
1164    mpfr_float_backend(const gmp_rational& val)
1165        : detail::mpfr_float_imp<0, allocate_dynamic>(preserve_all_precision() ? static_cast<unsigned>(used_gmp_rational_bits(val)) : static_cast<unsigned>(boost::multiprecision::detail::digits10_2_2(thread_default_precision())))
1166    {
1167       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1168    }
1169 
1170    mpfr_float_backend& operator=(const mpfr_float_backend& o) = default;
1171    // rvalue assign
1172    mpfr_float_backend& operator=(mpfr_float_backend&& o) noexcept = default;
1173 
1174    template <class V>
1175    typename std::enable_if<std::is_assignable<detail::mpfr_float_imp<0, allocate_dynamic>, V>::value, mpfr_float_backend&>::type operator=(const V& v)
1176    {
1177       constexpr unsigned d10 = std::is_floating_point<V>::value ?
1178          std::numeric_limits<V>::digits10 :
1179          std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
1180          1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
1181 
1182       if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1183       {
1184          BOOST_IF_CONSTEXPR(std::is_floating_point<V>::value)
1185          {
1186             if (std::numeric_limits<V>::digits > mpfr_get_prec(this->data()))
1187                mpfr_set_prec(this->data(), std::numeric_limits<V>::digits);
1188          }
1189          else
1190          {
1191             if(precision() < d10)
1192                this->precision(d10);
1193          }
1194       }
1195 
1196       *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = v;
1197       return *this;
1198    }
1199    mpfr_float_backend& operator=(const mpfr_t val)
1200    {
1201       if (this->m_data[0]._mpfr_d == nullptr)
1202          mpfr_init2(this->m_data, preserve_all_precision() ? static_cast<mpfr_prec_t>(mpfr_get_prec(val)) : static_cast<mpfr_prec_t>(boost::multiprecision::detail::digits10_2_2(get_default_precision())));
1203       else if(preserve_all_precision())
1204          mpfr_set_prec(this->m_data, mpfr_get_prec(val));
1205       mpfr_set(this->m_data, val, GMP_RNDN);
1206       return *this;
1207    }
1208    mpfr_float_backend& operator=(const mpf_t val)
1209    {
1210       if (this->m_data[0]._mpfr_d == nullptr)
1211          mpfr_init2(this->m_data, preserve_all_precision() ? static_cast<mpfr_prec_t>(mpf_get_prec(val)) : static_cast<mpfr_prec_t>(boost::multiprecision::detail::digits10_2_2(get_default_precision())));
1212       else if(preserve_all_precision())
1213          mpfr_set_prec(this->m_data, static_cast<mpfr_prec_t>(mpf_get_prec(val)));
1214       mpfr_set_f(this->m_data, val, GMP_RNDN);
1215       return *this;
1216    }
1217    mpfr_float_backend& operator=(const mpz_t val)
1218    {
1219       if (this->m_data[0]._mpfr_d == nullptr)
1220          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(get_default_precision())));
1221       mpfr_set_z(this->m_data, val, GMP_RNDN);
1222       return *this;
1223    }
1224    mpfr_float_backend& operator=(const mpq_t val)
1225    {
1226       if (this->m_data[0]._mpfr_d == nullptr)
1227          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(get_default_precision())));
1228       mpfr_set_q(this->m_data, val, GMP_RNDN);
1229       return *this;
1230    }
1231    template <unsigned D>
1232    mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
1233    {
1234       if (this->m_data[0]._mpfr_d == nullptr)
1235          mpfr_init2(this->m_data, preserve_related_precision() ? static_cast<mpfr_prec_t>(mpfr_get_prec(val.data())) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
1236       else if (preserve_related_precision())
1237          mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
1238       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1239       return *this;
1240    }
1241    template <unsigned D>
1242    mpfr_float_backend& operator=(const gmp_float<D>& val)
1243    {
1244       if (this->m_data[0]._mpfr_d == nullptr)
1245          mpfr_init2(this->m_data, preserve_all_precision() ? static_cast<mpfr_prec_t>(mpf_get_prec(val.data())) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
1246       else if (preserve_all_precision())
1247          mpfr_set_prec(this->m_data, static_cast<mpfr_prec_t>(mpf_get_prec(val.data())));
1248       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1249       return *this;
1250    }
1251    mpfr_float_backend& operator=(const gmp_int& val)
1252    {
1253       if (this->m_data[0]._mpfr_d == nullptr)
1254       {
1255          unsigned requested_precision = this->thread_default_precision();
1256          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1257          {
1258             unsigned d2  = static_cast<unsigned>(used_gmp_int_bits(val));
1259             unsigned d10 = static_cast<unsigned>(1ULL + multiprecision::detail::digits2_2_10(d2));
1260             if (d10 > requested_precision)
1261                requested_precision = d10;
1262          }
1263          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(requested_precision)));
1264       }
1265       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1266       {
1267          unsigned requested_precision = this->thread_default_precision();
1268          unsigned d2  = static_cast<unsigned>(used_gmp_int_bits(val));
1269          unsigned d10 = static_cast<unsigned>(1ULL + multiprecision::detail::digits2_2_10(d2));
1270          if (d10 > requested_precision)
1271             this->precision(d10);
1272       }
1273       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1274       return *this;
1275    }
1276    mpfr_float_backend& operator=(const gmp_rational& val)
1277    {
1278       if (this->m_data[0]._mpfr_d == nullptr)
1279       {
1280          unsigned requested_precision = this->get_default_precision();
1281          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1282          {
1283             unsigned d10 = static_cast<unsigned>(1u + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val)));
1284             if (d10 > requested_precision)
1285                requested_precision = d10;
1286          }
1287          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(requested_precision)));
1288       }
1289       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1290       {
1291          unsigned requested_precision = this->get_default_precision();
1292          unsigned d10 = static_cast<unsigned>(1u + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val)));
1293          if (d10 > requested_precision)
1294             this->precision(d10);
1295       }
1296       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1297       return *this;
1298    }
1299    static unsigned default_precision() noexcept
1300    {
1301       return get_global_default_precision();
1302    }
1303    static void default_precision(unsigned v) noexcept
1304    {
1305       get_global_default_precision() = v;
1306    }
1307    static unsigned thread_default_precision() noexcept
1308    {
1309       return get_default_precision();
1310    }
1311    static void thread_default_precision(unsigned v) noexcept
1312    {
1313       get_default_precision() = v;
1314    }
1315    unsigned precision() const noexcept
1316    {
1317       return static_cast<unsigned>(multiprecision::detail::digits2_2_10(static_cast<unsigned long>(mpfr_get_prec(this->m_data))));
1318    }
1319    void precision(unsigned digits10) noexcept
1320    {
1321       mpfr_prec_round(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2((digits10))), GMP_RNDN);
1322    }
1323    //
1324    // Variable precision options:
1325    //
1326    static variable_precision_options default_variable_precision_options()noexcept
1327    {
1328       return get_global_default_options();
1329    }
1330    static variable_precision_options thread_default_variable_precision_options()noexcept
1331    {
1332       return get_default_options();
1333    }
1334    static void default_variable_precision_options(variable_precision_options opts)
1335    {
1336       get_global_default_options() = opts;
1337    }
1338    static void thread_default_variable_precision_options(variable_precision_options opts)
1339    {
1340       get_default_options() = opts;
1341    }
1342    static bool preserve_source_precision()
1343    {
1344       return get_default_options() >= variable_precision_options::preserve_source_precision;
1345    }
1346    static bool preserve_related_precision()
1347    {
1348       return get_default_options() >= variable_precision_options::preserve_related_precision;
1349    }
1350    static bool preserve_all_precision()
1351    {
1352       return get_default_options() >= variable_precision_options::preserve_all_precision;
1353    }
1354 };
1355 
1356 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1357 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const mpfr_float_backend<digits10, AllocationType>& a, const T& b)
1358 {
1359    return a.compare(b) == 0;
1360 }
1361 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1362 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b)
1363 {
1364    return a.compare(b) < 0;
1365 }
1366 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1367 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b)
1368 {
1369    return a.compare(b) > 0;
1370 }
1371 
1372 template <unsigned digits10, mpfr_allocation_type AllocationType>
1373 inline bool eval_eq(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b)noexcept
1374 {
1375    return mpfr_equal_p(a.data(), b.data());
1376 }
1377 template <unsigned digits10, mpfr_allocation_type AllocationType>
1378 inline bool eval_lt(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b) noexcept
1379 {
1380    return mpfr_less_p(a.data(), b.data());
1381 }
1382 template <unsigned digits10, mpfr_allocation_type AllocationType>
1383 inline bool eval_gt(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b) noexcept
1384 {
1385    return mpfr_greater_p(a.data(), b.data());
1386 }
1387 
1388 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1389 inline void eval_add(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1390 {
1391    mpfr_add(result.data(), result.data(), o.data(), GMP_RNDN);
1392 }
1393 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1394 inline void eval_subtract(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1395 {
1396    mpfr_sub(result.data(), result.data(), o.data(), GMP_RNDN);
1397 }
1398 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1399 inline void eval_multiply(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1400 {
1401    if ((void*)&o == (void*)&result)
1402       mpfr_sqr(result.data(), o.data(), GMP_RNDN);
1403    else
1404       mpfr_mul(result.data(), result.data(), o.data(), GMP_RNDN);
1405 }
1406 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1407 inline void eval_divide(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1408 {
1409    mpfr_div(result.data(), result.data(), o.data(), GMP_RNDN);
1410 }
1411 template <unsigned digits10, mpfr_allocation_type AllocationType>
1412 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1413 {
1414    mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1415 }
1416 template <unsigned digits10, mpfr_allocation_type AllocationType>
1417 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1418 {
1419    mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
1420 }
1421 template <unsigned digits10, mpfr_allocation_type AllocationType>
1422 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1423 {
1424    mpfr_mul_ui(result.data(), result.data(), i, GMP_RNDN);
1425 }
1426 template <unsigned digits10, mpfr_allocation_type AllocationType>
1427 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1428 {
1429    mpfr_div_ui(result.data(), result.data(), i, GMP_RNDN);
1430 }
1431 template <unsigned digits10, mpfr_allocation_type AllocationType>
1432 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, long i)
1433 {
1434    if (i > 0)
1435       mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1436    else
1437       mpfr_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1438 }
1439 template <unsigned digits10, mpfr_allocation_type AllocationType>
1440 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, long i)
1441 {
1442    if (i > 0)
1443       mpfr_sub_ui(result.data(), result.data(), static_cast<typename std::make_unsigned<long>::type>(i), GMP_RNDN);
1444    else
1445       mpfr_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1446 }
1447 template <unsigned digits10, mpfr_allocation_type AllocationType>
1448 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, long i)
1449 {
1450    mpfr_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1451    if (i < 0)
1452       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1453 }
1454 template <unsigned digits10, mpfr_allocation_type AllocationType>
1455 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, long i)
1456 {
1457    mpfr_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1458    if (i < 0)
1459       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1460 }
1461 //
1462 // Specialised 3 arg versions of the basic operators:
1463 //
1464 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1465 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1466 {
1467    mpfr_add(a.data(), x.data(), y.data(), GMP_RNDN);
1468 }
1469 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1470 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1471 {
1472    mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1473 }
1474 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1475 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1476 {
1477    if (y < 0)
1478       mpfr_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1479    else
1480       mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1481 }
1482 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1483 inline void eval_add(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1484 {
1485    mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1486 }
1487 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1488 inline void eval_add(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1489 {
1490    if (x < 0)
1491    {
1492       mpfr_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1493       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1494    }
1495    else
1496       mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1497 }
1498 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1499 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1500 {
1501    mpfr_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1502 }
1503 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1504 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1505 {
1506    mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1507 }
1508 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1509 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1510 {
1511    if (y < 0)
1512       mpfr_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1513    else
1514       mpfr_sub_ui(a.data(), x.data(), static_cast<typename std::make_unsigned<long>::type>(y), GMP_RNDN);
1515 }
1516 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1517 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1518 {
1519    mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1520 }
1521 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1522 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1523 {
1524    if (x < 0)
1525    {
1526       mpfr_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1527       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1528    }
1529    else
1530       mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1531 }
1532 
1533 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1534 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1535 {
1536    if ((void*)&x == (void*)&y)
1537       mpfr_sqr(a.data(), x.data(), GMP_RNDN);
1538    else
1539       mpfr_mul(a.data(), x.data(), y.data(), GMP_RNDN);
1540 }
1541 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1542 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1543 {
1544    mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1545 }
1546 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1547 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1548 {
1549    if (y < 0)
1550    {
1551       mpfr_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1552       a.negate();
1553    }
1554    else
1555       mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1556 }
1557 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1558 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1559 {
1560    mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1561 }
1562 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1563 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1564 {
1565    if (x < 0)
1566    {
1567       mpfr_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1568       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1569    }
1570    else
1571       mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1572 }
1573 
1574 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1575 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1576 {
1577    mpfr_div(a.data(), x.data(), y.data(), GMP_RNDN);
1578 }
1579 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1580 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1581 {
1582    mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1583 }
1584 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1585 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1586 {
1587    if (y < 0)
1588    {
1589       mpfr_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1590       a.negate();
1591    }
1592    else
1593       mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1594 }
1595 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1596 inline void eval_divide(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1597 {
1598    mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1599 }
1600 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1601 inline void eval_divide(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1602 {
1603    if (x < 0)
1604    {
1605       mpfr_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1606       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1607    }
1608    else
1609       mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1610 }
1611 
1612 template <unsigned digits10, mpfr_allocation_type AllocationType>
1613 inline bool eval_is_zero(const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1614 {
1615    return 0 != mpfr_zero_p(val.data());
1616 }
1617 template <unsigned digits10, mpfr_allocation_type AllocationType>
1618 inline int eval_get_sign(const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1619 {
1620    return mpfr_sgn(val.data());
1621 }
1622 
1623 template <unsigned digits10, mpfr_allocation_type AllocationType>
1624 inline void eval_convert_to(unsigned long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1625 {
1626    if (mpfr_nan_p(val.data()))
1627    {
1628       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1629    }
1630    *result = mpfr_get_ui(val.data(), GMP_RNDZ);
1631 }
1632 template <unsigned digits10, mpfr_allocation_type AllocationType>
1633 inline void eval_convert_to(long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1634 {
1635    if (mpfr_nan_p(val.data()))
1636    {
1637       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1638    }
1639    *result = mpfr_get_si(val.data(), GMP_RNDZ);
1640 }
1641 #ifdef _MPFR_H_HAVE_INTMAX_T
1642 template <unsigned digits10, mpfr_allocation_type AllocationType>
1643 inline void eval_convert_to(unsigned long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1644 {
1645    if (mpfr_nan_p(val.data()))
1646    {
1647       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1648    }
1649    *result = mpfr_get_uj(val.data(), GMP_RNDZ);
1650 }
1651 template <unsigned digits10, mpfr_allocation_type AllocationType>
1652 inline void eval_convert_to(long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1653 {
1654    if (mpfr_nan_p(val.data()))
1655    {
1656       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1657    }
1658    *result = mpfr_get_sj(val.data(), GMP_RNDZ);
1659 }
1660 #endif
1661 template <unsigned digits10, mpfr_allocation_type AllocationType>
1662 inline void eval_convert_to(float* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1663 {
1664    *result = mpfr_get_flt(val.data(), GMP_RNDN);
1665 }
1666 template <unsigned digits10, mpfr_allocation_type AllocationType>
1667 inline void eval_convert_to(double* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1668 {
1669    *result = mpfr_get_d(val.data(), GMP_RNDN);
1670 }
1671 template <unsigned digits10, mpfr_allocation_type AllocationType>
1672 inline void eval_convert_to(long double* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1673 {
1674    *result = mpfr_get_ld(val.data(), GMP_RNDN);
1675 }
1676 
1677 #ifdef BOOST_HAS_INT128
1678 template <unsigned digits10, mpfr_allocation_type AllocationType>
1679 inline void eval_convert_to(int128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1680 {
1681    gmp_int i;
1682    mpfr_get_z(i.data(), val.data(), GMP_RNDN);
1683    eval_convert_to(result, i);
1684 }
1685 template <unsigned digits10, mpfr_allocation_type AllocationType>
1686 inline void eval_convert_to(uint128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1687 {
1688    gmp_int i;
1689    mpfr_get_z(i.data(), val.data(), GMP_RNDN);
1690    eval_convert_to(result, i);
1691 }
1692 #endif
1693 #if defined(BOOST_HAS_FLOAT128)
1694 template <unsigned digits10, mpfr_allocation_type AllocationType>
1695 inline void eval_convert_to(float128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1696 {
1697    *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr);
1698 }
1699 #endif
1700 
1701 //
1702 // Native non-member operations:
1703 //
1704 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1705 inline void eval_sqrt(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1706 {
1707    mpfr_sqrt(result.data(), val.data(), GMP_RNDN);
1708 }
1709 
1710 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1711 inline void eval_abs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1712 {
1713    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1714 }
1715 
1716 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1717 inline void eval_fabs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1718 {
1719    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1720 }
1721 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1722 inline void eval_ceil(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1723 {
1724    mpfr_ceil(result.data(), val.data());
1725 }
1726 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1727 inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1728 {
1729    mpfr_floor(result.data(), val.data());
1730 }
1731 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1732 inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1733 {
1734    mpfr_trunc(result.data(), val.data());
1735 }
1736 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1737 inline void eval_ldexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long e)
1738 {
1739    using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1740 
1741    if (e > 0)
1742       mpfr_mul_2exp(result.data(), val.data(), static_cast<local_uint_type>(e), GMP_RNDN);
1743    else if (e < 0)
1744       mpfr_div_2exp(result.data(), val.data(), static_cast<local_uint_type>(-e), GMP_RNDN);
1745    else
1746       result = val;
1747 }
1748 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1749 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, int* e)
1750 {
1751    if (mpfr_zero_p(val.data()))
1752    {
1753       *e = 0;
1754       result = val;
1755       return;
1756    }
1757    mp_exp_t v = mpfr_get_exp(val.data());
1758    *e = static_cast<int>(v);
1759    if (v)
1760       eval_ldexp(result, val, -v);
1761    else
1762       result = val;
1763 }
1764 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1765 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long* e)
1766 {
1767    if (mpfr_zero_p(val.data()))
1768    {
1769       *e = 0;
1770       result = val;
1771       return;
1772    }
1773    mp_exp_t v = mpfr_get_exp(val.data());
1774    *e = v;
1775    if(v)
1776       eval_ldexp(result, val, -v);
1777    else
1778       result = val;
1779 }
1780 
1781 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1782 inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val) noexcept
1783 {
1784    return mpfr_inf_p(val.data()) ? FP_INFINITE : mpfr_nan_p(val.data()) ? FP_NAN : mpfr_zero_p(val.data()) ? FP_ZERO : FP_NORMAL;
1785 }
1786 
1787 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1788 inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
1789 {
1790    if (mpfr_zero_p(b.data()) && mpfr_integer_p(e.data()) && (mpfr_signbit(e.data()) == 0) && mpfr_fits_ulong_p(e.data(), GMP_RNDN) && (mpfr_get_ui(e.data(), GMP_RNDN) & 1))
1791    {
1792       mpfr_set(result.data(), b.data(), GMP_RNDN);
1793    }
1794    else
1795       mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
1796 }
1797 
1798 #ifdef BOOST_MSVC
1799 //
1800 // The enable_if usage below doesn't work with msvc - but only when
1801 // certain other enable_if usages are defined first.  It's a capricious
1802 // and rather annoying compiler bug in other words....
1803 //
1804 #define BOOST_MP_ENABLE_IF_WORKAROUND (Digits10 || !Digits10)&&
1805 #else
1806 #define BOOST_MP_ENABLE_IF_WORKAROUND
1807 #endif
1808 
1809 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1810 inline typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && (BOOST_MP_ENABLE_IF_WORKAROUND(sizeof(Integer) <= sizeof(long)))>::type
1811 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1812 {
1813    mpfr_pow_si(result.data(), b.data(), e, GMP_RNDN);
1814 }
1815 
1816 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1817 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && (BOOST_MP_ENABLE_IF_WORKAROUND(sizeof(Integer) <= sizeof(long)))>::type
1818 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1819 {
1820    mpfr_pow_ui(result.data(), b.data(), e, GMP_RNDN);
1821 }
1822 
1823 #undef BOOST_MP_ENABLE_IF_WORKAROUND
1824 
1825 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1826 inline void eval_exp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1827 {
1828    mpfr_exp(result.data(), arg.data(), GMP_RNDN);
1829 }
1830 
1831 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1832 inline void eval_exp2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1833 {
1834    mpfr_exp2(result.data(), arg.data(), GMP_RNDN);
1835 }
1836 
1837 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1838 inline void eval_log(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1839 {
1840    mpfr_log(result.data(), arg.data(), GMP_RNDN);
1841 }
1842 
1843 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1844 inline void eval_log10(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1845 {
1846    mpfr_log10(result.data(), arg.data(), GMP_RNDN);
1847 }
1848 
1849 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1850 inline void eval_sin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1851 {
1852    mpfr_sin(result.data(), arg.data(), GMP_RNDN);
1853 }
1854 
1855 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1856 inline void eval_cos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1857 {
1858    mpfr_cos(result.data(), arg.data(), GMP_RNDN);
1859 }
1860 
1861 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1862 inline void eval_tan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1863 {
1864    mpfr_tan(result.data(), arg.data(), GMP_RNDN);
1865 }
1866 
1867 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1868 inline void eval_asin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1869 {
1870    mpfr_asin(result.data(), arg.data(), GMP_RNDN);
1871 }
1872 
1873 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1874 inline void eval_acos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1875 {
1876    mpfr_acos(result.data(), arg.data(), GMP_RNDN);
1877 }
1878 
1879 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1880 inline void eval_atan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1881 {
1882    mpfr_atan(result.data(), arg.data(), GMP_RNDN);
1883 }
1884 
1885 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1886 inline void eval_atan2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg1, const mpfr_float_backend<Digits10, AllocateType>& arg2)
1887 {
1888    mpfr_atan2(result.data(), arg1.data(), arg2.data(), GMP_RNDN);
1889 }
1890 
1891 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1892 inline void eval_sinh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1893 {
1894    mpfr_sinh(result.data(), arg.data(), GMP_RNDN);
1895 }
1896 
1897 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1898 inline void eval_cosh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1899 {
1900    mpfr_cosh(result.data(), arg.data(), GMP_RNDN);
1901 }
1902 
1903 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1904 inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1905 {
1906    mpfr_tanh(result.data(), arg.data(), GMP_RNDN);
1907 }
1908 
1909 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1910 inline void eval_log2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1911 {
1912    mpfr_log2(result.data(), arg.data(), GMP_RNDN);
1913 }
1914 
1915 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1916 inline void eval_modf(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg, mpfr_float_backend<Digits10, AllocateType>* pipart)
1917 {
1918    if (pipart == nullptr)
1919    {
1920       mpfr_float_backend<Digits10, AllocateType> ipart;
1921       mpfr_modf(ipart.data(), result.data(), arg.data(), GMP_RNDN);
1922    }
1923    else
1924    {
1925       mpfr_modf(pipart->data(), result.data(), arg.data(), GMP_RNDN);
1926    }
1927 }
1928 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1929 inline void eval_remainder(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1930 {
1931    mpfr_remainder(result.data(), a.data(), b.data(), GMP_RNDN);
1932 }
1933 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1934 inline void eval_remquo(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, int* pi)
1935 {
1936    long l;
1937    mpfr_remquo(result.data(), &l, a.data(), b.data(), GMP_RNDN);
1938    if (pi)
1939       *pi = static_cast<int>(l);
1940 }
1941 
1942 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1943 inline void eval_fmod(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1944 {
1945    mpfr_fmod(result.data(), a.data(), b.data(), GMP_RNDN);
1946 }
1947 
1948 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1949 inline void eval_multiply_add(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1950 {
1951    mpfr_fma(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1952 }
1953 
1954 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1955 inline void eval_multiply_add(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& c)
1956 {
1957    mpfr_fma(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1958 }
1959 
1960 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1961 inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1962 {
1963    mpfr_fms(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1964    result.negate();
1965 }
1966 
1967 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1968 inline void eval_multiply_subtract(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& c)
1969 {
1970    mpfr_fms(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1971 }
1972 
1973 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1974 inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10, AllocateType>& arg)
1975 {
1976    return (arg.data()[0]._mpfr_sign < 0) ? 1 : 0;
1977 }
1978 
1979 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1980 inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
1981 {
1982    std::size_t result = 0;
1983    std::size_t len    = val.data()[0]._mpfr_prec / mp_bits_per_limb;
1984    if (val.data()[0]._mpfr_prec % mp_bits_per_limb)
1985       ++len;
1986    for (std::size_t i = 0; i < len; ++i)
1987       boost::multiprecision::detail::hash_combine(result, val.data()[0]._mpfr_d[i]);
1988    boost::multiprecision::detail::hash_combine(result, val.data()[0]._mpfr_exp, val.data()[0]._mpfr_sign);
1989    return result;
1990 }
1991 
1992 } // namespace backends
1993 
1994 namespace detail {
1995 template <>
1996 struct is_variable_precision<backends::mpfr_float_backend<0> > : public std::integral_constant<bool, true>
1997 {};
1998 } // namespace detail
1999 
2000 template <>
2001 struct number_category<detail::canonical<mpfr_t, backends::mpfr_float_backend<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
2002 {};
2003 
2004 template <unsigned D, boost::multiprecision::mpfr_allocation_type A1, boost::multiprecision::mpfr_allocation_type A2>
2005 struct is_equivalent_number_type<backends::mpfr_float_backend<D, A1>, backends::mpfr_float_backend<D, A2> > : public std::integral_constant<bool, true> {};
2006 
2007 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2008 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& b)
2009 {
2010    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
2011 }
2012 
2013 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2014 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& b)
2015 {
2016    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>(-a) : a;
2017 }
2018 
2019 } // namespace multiprecision
2020 
2021 namespace math {
2022 
2023 using boost::multiprecision::copysign;
2024 using boost::multiprecision::signbit;
2025 
2026 namespace tools {
2027 
2028 #ifndef BOOST_MP_MATH_AVAILABLE
2029 
2030 template <typename T>
2031 inline int digits();
2032 
2033 template <typename T>
2034 inline T max_value();
2035 
2036 template <typename T>
2037 inline T min_value();
2038 
2039 #endif
2040 
2041 inline void set_output_precision(const boost::multiprecision::mpfr_float& val, std::ostream& os)
2042 {
2043    os << std::setprecision(static_cast<int>(val.precision()));
2044 }
2045 
2046 template <>
2047 inline int digits<boost::multiprecision::mpfr_float>()
2048 #ifdef BOOST_MATH_NOEXCEPT
2049     noexcept
2050 #endif
2051 {
2052    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::thread_default_precision()));
2053 }
2054 template <>
2055 inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2056 #ifdef BOOST_MATH_NOEXCEPT
2057     noexcept
2058 #endif
2059 {
2060    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::thread_default_precision()));
2061 }
2062 
2063 template <>
2064 inline boost::multiprecision::mpfr_float
2065 max_value<boost::multiprecision::mpfr_float>()
2066 {
2067    boost::multiprecision::mpfr_float result(0.5);
2068    mpfr_mul_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(mpfr_get_emax()), GMP_RNDN);
2069    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2070    return result;
2071 }
2072 
2073 template <>
2074 inline boost::multiprecision::mpfr_float
2075 min_value<boost::multiprecision::mpfr_float>()
2076 {
2077    boost::multiprecision::mpfr_float result(0.5);
2078    mpfr_div_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(-mpfr_get_emin()), GMP_RNDN);
2079    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2080    return result;
2081 }
2082 
2083 template <>
2084 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
2085 max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2086 {
2087    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
2088    mpfr_mul_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(mpfr_get_emax()), GMP_RNDN);
2089    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2090    return result;
2091 }
2092 
2093 template <>
2094 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
2095 min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2096 {
2097    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
2098    mpfr_div_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(-mpfr_get_emin()), GMP_RNDN);
2099    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2100    return result;
2101 }
2102 //
2103 // Over again with debug_adaptor:
2104 //
2105 template <>
2106 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2107 #ifdef BOOST_MATH_NOEXCEPT
2108     noexcept
2109 #endif
2110 {
2111    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::thread_default_precision()));
2112 }
2113 template <>
2114 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2115 #ifdef BOOST_MATH_NOEXCEPT
2116     noexcept
2117 #endif
2118 {
2119    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::thread_default_precision()));
2120 }
2121 
2122 template <>
2123 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2124 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2125 {
2126    return max_value<boost::multiprecision::mpfr_float>().backend();
2127 }
2128 
2129 template <>
2130 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2131 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2132 {
2133    return min_value<boost::multiprecision::mpfr_float>().backend();
2134 }
2135 
2136 template <>
2137 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2138 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2139 {
2140    return max_value<boost::multiprecision::mpfr_float>().backend();
2141 }
2142 
2143 template <>
2144 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2145 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2146 {
2147    return min_value<boost::multiprecision::mpfr_float>().backend();
2148 }
2149 
2150 //
2151 // Over again with logged_adaptor:
2152 //
2153 template <>
2154 inline int digits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2155 #ifdef BOOST_MATH_NOEXCEPT
2156     noexcept
2157 #endif
2158 {
2159    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision()));
2160 }
2161 template <>
2162 inline int digits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2163 #ifdef BOOST_MATH_NOEXCEPT
2164     noexcept
2165 #endif
2166 {
2167    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision()));
2168 }
2169 
2170 template <>
2171 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2172 max_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2173 {
2174    return max_value<boost::multiprecision::mpfr_float>().backend();
2175 }
2176 
2177 template <>
2178 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2179 min_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2180 {
2181    return min_value<boost::multiprecision::mpfr_float>().backend();
2182 }
2183 
2184 template <>
2185 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2186 max_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2187 {
2188    return max_value<boost::multiprecision::mpfr_float>().backend();
2189 }
2190 
2191 template <>
2192 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2193 min_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2194 {
2195    return min_value<boost::multiprecision::mpfr_float>().backend();
2196 }
2197 
2198 } // namespace tools
2199 
2200 namespace constants { namespace detail {
2201 
2202 template <class T>
2203 struct constant_pi;
2204 template <class T>
2205 struct constant_ln_two;
2206 template <class T>
2207 struct constant_euler;
2208 template <class T>
2209 struct constant_catalan;
2210 
2211 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2212 struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2213 {
2214    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2215    template <int N>
2216    static inline const result_type& get(const std::integral_constant<int, N>&)
2217    {
2218       // Rely on C++11 thread safe initialization:
2219       static result_type result{get(std::integral_constant<int, 0>())};
2220       return result;
2221    }
2222    static inline const result_type get(const std::integral_constant<int, 0>&)
2223    {
2224       result_type result;
2225       mpfr_const_pi(result.backend().data(), GMP_RNDN);
2226       return result;
2227    }
2228 };
2229 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2230 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2231 {
2232    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2233    template <int N>
2234    static inline const result_type& get(const std::integral_constant<int, N>&)
2235    {
2236       // Rely on C++11 thread safe initialization:
2237       static result_type result{get(std::integral_constant<int, 0>())};
2238       return result;
2239    }
2240    static inline const result_type get(const std::integral_constant<int, 0>&)
2241    {
2242       result_type result;
2243       mpfr_const_log2(result.backend().data(), GMP_RNDN);
2244       return result;
2245    }
2246 };
2247 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2248 struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2249 {
2250    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2251    template <int N>
2252    static inline const result_type& get(const std::integral_constant<int, N>&)
2253    {
2254       // Rely on C++11 thread safe initialization:
2255       static result_type result{get(std::integral_constant<int, 0>())};
2256       return result;
2257    }
2258    static inline const result_type get(const std::integral_constant<int, 0>&)
2259    {
2260       result_type result;
2261       mpfr_const_euler(result.backend().data(), GMP_RNDN);
2262       return result;
2263    }
2264 };
2265 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2266 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2267 {
2268    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2269    template <int N>
2270    static inline const result_type& get(const std::integral_constant<int, N>&)
2271    {
2272       // Rely on C++11 thread safe initialization:
2273       static result_type result{get(std::integral_constant<int, 0>())};
2274       return result;
2275    }
2276    static inline const result_type get(const std::integral_constant<int, 0>&)
2277    {
2278       result_type result;
2279       mpfr_const_catalan(result.backend().data(), GMP_RNDN);
2280       return result;
2281    }
2282 };
2283 //
2284 // Over again with debug_adaptor:
2285 //
2286 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2287 struct constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2288 {
2289    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2290    template <int N>
2291    static inline const result_type& get(const std::integral_constant<int, N>&)
2292    {
2293       // Rely on C++11 thread safe initialization:
2294       static result_type result{get(std::integral_constant<int, 0>())};
2295       return result;
2296    }
2297    static inline const result_type get(const std::integral_constant<int, 0>&)
2298    {
2299       result_type result;
2300       mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
2301       result.backend().update_view();
2302       return result;
2303    }
2304 };
2305 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2306 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2307 {
2308    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2309    template <int N>
2310    static inline const result_type& get(const std::integral_constant<int, N>&)
2311    {
2312       // Rely on C++11 thread safe initialization:
2313       static result_type result{get(std::integral_constant<int, 0>())};
2314       return result;
2315    }
2316    static inline const result_type get(const std::integral_constant<int, 0>&)
2317    {
2318       result_type result;
2319       mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
2320       result.backend().update_view();
2321       return result;
2322    }
2323 };
2324 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2325 struct constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2326 {
2327    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2328    template <int N>
2329    static inline const result_type& get(const std::integral_constant<int, N>&)
2330    {
2331       // Rely on C++11 thread safe initialization:
2332       static result_type result{get(std::integral_constant<int, 0>())};
2333       return result;
2334    }
2335    static inline const result_type get(const std::integral_constant<int, 0>&)
2336    {
2337       result_type result;
2338       mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
2339       result.backend().update_view();
2340       return result;
2341    }
2342 };
2343 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2344 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2345 {
2346    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2347    template <int N>
2348    static inline const result_type& get(const std::integral_constant<int, N>&)
2349    {
2350       // Rely on C++11 thread safe initialization:
2351       static result_type result{get(std::integral_constant<int, 0>())};
2352       return result;
2353    }
2354    static inline const result_type get(const std::integral_constant<int, 0>&)
2355    {
2356       result_type result;
2357       mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
2358       result.backend().update_view();
2359       return result;
2360    }
2361 };
2362 
2363 //
2364 // Over again with logged_adaptor:
2365 //
2366 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2367 struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2368 {
2369    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2370    template <int N>
2371    static inline const result_type& get(const std::integral_constant<int, N>&)
2372    {
2373       // C++11 thread safe static initialization:
2374       static result_type result{get(std::integral_constant<int, 0>())};
2375       return result;
2376    }
2377    static inline const result_type get(const std::integral_constant<int, 0>&)
2378    {
2379       result_type result;
2380       mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
2381       return result;
2382    }
2383 };
2384 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2385 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2386 {
2387    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2388    template <int N>
2389    static inline const result_type& get(const std::integral_constant<int, N>&)
2390    {
2391       // C++11 thread safe static initialization:
2392       static result_type result{get(std::integral_constant<int, 0>())};
2393       return result;
2394    }
2395    static inline const result_type get(const std::integral_constant<int, 0>&)
2396    {
2397       result_type result;
2398       mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
2399       return result;
2400    }
2401 };
2402 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2403 struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2404 {
2405    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2406    template <int N>
2407    static inline const result_type& get(const std::integral_constant<int, N>&)
2408    {
2409       // C++11 thread safe static initialization:
2410       static result_type result{get(std::integral_constant<int, 0>())};
2411       return result;
2412    }
2413    static inline const result_type get(const std::integral_constant<int, 0>&)
2414    {
2415       result_type result;
2416       mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
2417       return result;
2418    }
2419 };
2420 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2421 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2422 {
2423    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2424    template <int N>
2425    static inline const result_type& get(const std::integral_constant<int, N>&)
2426    {
2427       // C++11 thread safe static initialization:
2428       static result_type result{get(std::integral_constant<int, 0>())};
2429       return result;
2430    }
2431    static inline const result_type get(const std::integral_constant<int, 0>&)
2432    {
2433       result_type result;
2434       mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
2435       return result;
2436    }
2437 };
2438 
2439 }} // namespace constants::detail
2440 
2441 } // namespace math
2442 
2443 namespace multiprecision {
2444 //
2445 // Overloaded special functions which call native mpfr routines:
2446 //
2447 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2448 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2449 {
2450    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2451 
2452    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2453    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2454    return result;
2455 }
2456 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2457 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2458 {
2459    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2460 
2461    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2462    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2463    return result;
2464 }
2465 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2466 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2467 {
2468    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2469 
2470    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2471    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2472    return result;
2473 }
2474 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2475 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2476 {
2477    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2478 
2479    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2480    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2481    return result;
2482 }
2483 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2484 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2485 {
2486    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2487 
2488    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2489    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2490    return result;
2491 }
2492 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2493 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2494 {
2495    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2496 
2497    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2498    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2499    return result;
2500 }
2501 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2502 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2503 {
2504    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2505 
2506    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2507    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2508    return result;
2509 }
2510 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2511 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2512 {
2513    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2514 
2515    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2516    mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2517    return result;
2518 }
2519 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2520 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2521 {
2522    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2523 
2524    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2525    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2526    return result;
2527 }
2528 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2529 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2530 {
2531    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2532 
2533    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2534    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2535    return result;
2536 }
2537 
2538 //
2539 // Over again with debug_adaptor:
2540 //
2541 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2542 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2543 {
2544    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2545 
2546    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2547    mpfr_asinh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2548    result.backend().update_view();
2549    return result;
2550 }
2551 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2552 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2553 {
2554    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2555 
2556    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2557    mpfr_acosh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2558    result.backend().update_view();
2559    return result;
2560 }
2561 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2562 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2563 {
2564    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2565 
2566    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2567    mpfr_atanh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2568    result.backend().update_view();
2569    return result;
2570 }
2571 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2572 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2573 {
2574    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2575 
2576    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2577    mpfr_cbrt(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2578    result.backend().update_view();
2579    return result;
2580 }
2581 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2582 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2583 {
2584    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2585 
2586    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2587    mpfr_erf(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2588    result.backend().update_view();
2589    return result;
2590 }
2591 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2592 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2593 {
2594    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2595 
2596    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2597    mpfr_erfc(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2598    result.backend().update_view();
2599    return result;
2600 }
2601 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2602 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2603 {
2604    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2605 
2606    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2607    mpfr_expm1(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2608    result.backend().update_view();
2609    return result;
2610 }
2611 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2612 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2613 {
2614    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2615 
2616    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2617    mpfr_lngamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2618    result.backend().update_view();
2619    return result;
2620 }
2621 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2622 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2623 {
2624    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2625 
2626    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2627    mpfr_gamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2628    result.backend().update_view();
2629    return result;
2630 }
2631 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2632 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2633 {
2634    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2635 
2636    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2637    mpfr_log1p(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2638    result.backend().update_view();
2639    return result;
2640 }
2641 
2642 //
2643 // Over again with logged_adaptor:
2644 //
2645 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2646 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2647 {
2648    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2649 
2650    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2651    mpfr_asinh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2652    return result;
2653 }
2654 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2655 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2656 {
2657    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2658 
2659    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2660    mpfr_acosh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2661    return result;
2662 }
2663 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2664 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2665 {
2666    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2667 
2668    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2669    mpfr_atanh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2670    return result;
2671 }
2672 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2673 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2674 {
2675    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2676 
2677    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2678    mpfr_cbrt(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2679    return result;
2680 }
2681 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2682 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2683 {
2684    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2685 
2686    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2687    mpfr_erf(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2688    return result;
2689 }
2690 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2691 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2692 {
2693    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2694 
2695    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2696    mpfr_erfc(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2697    return result;
2698 }
2699 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2700 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2701 {
2702    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2703 
2704    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2705    mpfr_expm1(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2706    return result;
2707 }
2708 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2709 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2710 {
2711    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2712 
2713    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2714    mpfr_lngamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2715    return result;
2716 }
2717 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2718 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2719 {
2720    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2721 
2722    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2723    mpfr_gamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2724    return result;
2725 }
2726 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2727 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
2728 {
2729    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2730 
2731    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2732    mpfr_log1p(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2733    return result;
2734 }
2735 
2736 } // namespace multiprecision
2737 
2738 namespace math {
2739 //
2740 // Overloaded special functions which call native mpfr routines:
2741 //
2742 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2743 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy&)
2744 {
2745    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2746 
2747    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2748    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2749    if (mpfr_inf_p(result.backend().data()))
2750       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("asinh<%1%>(%1%)", nullptr, Policy());
2751    if (mpfr_nan_p(result.backend().data()))
2752       return policies::raise_evaluation_error("asinh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2753    return result;
2754 }
2755 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2756 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2757 {
2758    return asinh(arg, policies::policy<>());
2759 }
2760 
2761 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2762 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy&)
2763 {
2764    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2765 
2766    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2767    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2768    if (mpfr_inf_p(result.backend().data()))
2769       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("acosh<%1%>(%1%)", nullptr, Policy());
2770    if (mpfr_nan_p(result.backend().data()))
2771       return policies::raise_evaluation_error("acosh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2772    return result;
2773 }
2774 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2775 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2776 {
2777    return acosh(arg, policies::policy<>());
2778 }
2779 
2780 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2781 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& )
2782 {
2783    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2784 
2785    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2786    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2787    if (mpfr_inf_p(result.backend().data()))
2788       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("atanh<%1%>(%1%)", nullptr, Policy());
2789    if (mpfr_nan_p(result.backend().data()))
2790       return policies::raise_evaluation_error("atanh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2791    return result;
2792 }
2793 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2794 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2795 {
2796    return atanh(arg, policies::policy<>());
2797 }
2798 
2799 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2800 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy&)
2801 {
2802    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2803 
2804    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2805    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2806    if (mpfr_inf_p(result.backend().data()))
2807       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("cbrt<%1%>(%1%)", nullptr, Policy());
2808    if (mpfr_nan_p(result.backend().data()))
2809       return policies::raise_evaluation_error("cbrt<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2810    return result;
2811 }
2812 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2813 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2814 {
2815    return cbrt(arg, policies::policy<>());
2816 }
2817 
2818 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2819 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2820 {
2821    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2822 
2823    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2824    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2825    if (mpfr_inf_p(result.backend().data()))
2826       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erf<%1%>(%1%)", nullptr, pol);
2827    if (mpfr_nan_p(result.backend().data()))
2828       return policies::raise_evaluation_error("erf<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2829    return result;
2830 }
2831 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2832 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2833 {
2834    return erf(arg, policies::policy<>());
2835 }
2836 
2837 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2838 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2839 {
2840    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2841 
2842    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2843    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2844    if (mpfr_inf_p(result.backend().data()))
2845       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erfc<%1%>(%1%)", nullptr, pol);
2846    if (mpfr_nan_p(result.backend().data()))
2847       return policies::raise_evaluation_error("erfc<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2848    return result;
2849 }
2850 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2851 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2852 {
2853    return erfc(arg, policies::policy<>());
2854 }
2855 
2856 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2857 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2858 {
2859    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2860 
2861    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2862    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2863    if (mpfr_inf_p(result.backend().data()))
2864       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("expm1<%1%>(%1%)", nullptr, pol);
2865    if (mpfr_nan_p(result.backend().data()))
2866       return policies::raise_evaluation_error("expm1<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2867    return result;
2868 }
2869 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2870 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> exm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2871 {
2872    return expm1(arg, policies::policy<>());
2873 }
2874 
2875 #ifdef BOOST_MP_MATH_AVAILABLE
2876 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2877 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> arg, int* sign, const Policy& pol)
2878 {
2879    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2880    (void)precision_guard;  // warning suppression
2881 
2882    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2883    if (arg > 0)
2884    {
2885       mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2886       if (sign)
2887          *sign = 1;
2888    }
2889    else
2890    {
2891       if (floor(arg) == arg)
2892          return policies::raise_pole_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >(
2893              "lgamma<%1%>", "Evaluation of lgamma at a negative integer %1%.", arg, pol);
2894 
2895       boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> t = detail::sinpx(arg);
2896       arg                                                                                                                     = -arg;
2897       if (t < 0)
2898       {
2899          t = -t;
2900       }
2901       result = boost::multiprecision::log(boost::math::constants::pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >()) - lgamma(arg, 0, pol) - boost::multiprecision::log(t);
2902       if (sign)
2903       {
2904          boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> phase = 1 - arg;
2905          phase                                                                                                                       = floor(phase) / 2;
2906          if (floor(phase) == phase)
2907             *sign = -1;
2908          else
2909             *sign = 1;
2910       }
2911    }
2912    if (mpfr_inf_p(result.backend().data()))
2913       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("lgamma<%1%>(%1%)", nullptr, pol);
2914    if (mpfr_nan_p(result.backend().data()))
2915       return policies::raise_evaluation_error("lgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2916    return result;
2917 }
2918 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2919 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, int* sign)
2920 {
2921    return lgamma(arg, sign, policies::policy<>());
2922 }
2923 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2924 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2925 {
2926    return lgamma(arg, 0, pol);
2927 }
2928 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2929 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2930 {
2931    return lgamma(arg, 0, policies::policy<>());
2932 }
2933 #endif // BOOST_MP_MATH_AVAILABLE
2934 
2935 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2936 inline typename std::enable_if<boost::math::policies::is_policy<Policy>::value, boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2937 {
2938    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2939 
2940    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2941    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2942    if (mpfr_inf_p(result.backend().data()))
2943       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("tgamma<%1%>(%1%)", nullptr, pol);
2944    if (mpfr_nan_p(result.backend().data()))
2945       return policies::raise_evaluation_error("tgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2946    return result;
2947 }
2948 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2949 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2950 {
2951    return tgamma(arg, policies::policy<>());
2952 }
2953 
2954 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2955 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2956 {
2957    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2958 
2959    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2960    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2961    if (mpfr_inf_p(result.backend().data()))
2962       return (arg == -1 ? -1 : 1) * policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("log1p<%1%>(%1%)", nullptr, pol);
2963    if (mpfr_nan_p(result.backend().data()))
2964       return policies::raise_evaluation_error("log1p<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2965    return result;
2966 }
2967 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2968 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2969 {
2970    return log1p(arg, policies::policy<>());
2971 }
2972 
2973 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2974 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg, const Policy& pol)
2975 {
2976    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2977 
2978    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2979    mpfr_rec_sqrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2980    if (mpfr_inf_p(result.backend().data()))
2981       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("rsqrt<%1%>(%1%)", nullptr, pol);
2982    if (mpfr_nan_p(result.backend().data()))
2983       return policies::raise_evaluation_error("rsqrt<%1%>(%1%)", "Negative argument, result is a NaN", result, pol);
2984    return result;
2985 }
2986 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2987 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2988 {
2989    return rsqrt(arg, policies::policy<>());
2990 }
2991 
2992 //
2993 // Over again with debug_adaptor:
2994 //
2995 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2996 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
2997 {
2998    return asinh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
2999 }
3000 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3001 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3002 {
3003    return asinh(arg, policies::policy<>());
3004 }
3005 
3006 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3007 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3008 {
3009    return acosh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3010 }
3011 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3012 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3013 {
3014    return acosh(arg, policies::policy<>());
3015 }
3016 
3017 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3018 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3019 {
3020    return atanh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3021 }
3022 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3023 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3024 {
3025    return atanh(arg, policies::policy<>());
3026 }
3027 
3028 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3029 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3030 {
3031    return cbrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3032 }
3033 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3034 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3035 {
3036    return cbrt(arg, policies::policy<>());
3037 }
3038 
3039 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3040 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3041 {
3042    return erf(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3043 }
3044 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3045 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3046 {
3047    return erf(arg, policies::policy<>());
3048 }
3049 
3050 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3051 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3052 {
3053    return erfc(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3054 }
3055 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3056 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3057 {
3058    return erfc(arg, policies::policy<>());
3059 }
3060 
3061 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3062 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3063 {
3064    return expm1(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3065 }
3066 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3067 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> exm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3068 {
3069    return expm1(arg, policies::policy<>());
3070 }
3071 
3072 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3073 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> arg, int* sign, const Policy& pol)
3074 {
3075    return lgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), sign, pol).backend();
3076 }
3077 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3078 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, int* sign)
3079 {
3080    return lgamma(arg, sign, policies::policy<>());
3081 }
3082 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3083 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3084 {
3085    return lgamma(arg, 0, pol);
3086 }
3087 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3088 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3089 {
3090    return lgamma(arg, 0, policies::policy<>());
3091 }
3092 
3093 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3094 inline typename std::enable_if<boost::math::policies::is_policy<Policy>::value, boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >::type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3095 {
3096    return tgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3097 }
3098 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3099 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3100 {
3101    return tgamma(arg, policies::policy<>());
3102 }
3103 
3104 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3105 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3106 {
3107    return log1p(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3108 }
3109 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3110 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3111 {
3112    return log1p(arg, policies::policy<>());
3113 }
3114 
3115 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3116 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3117 {
3118    return rsqrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3119 }
3120 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3121 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3122 {
3123    return rsqrt(arg, policies::policy<>());
3124 }
3125 
3126 //
3127 // Over again with logged_adaptor:
3128 //
3129 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3130 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3131 {
3132    return asinh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3133 }
3134 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3135 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3136 {
3137    return asinh(arg, policies::policy<>());
3138 }
3139 
3140 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3141 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3142 {
3143    return acosh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3144 }
3145 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3146 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3147 {
3148    return acosh(arg, policies::policy<>());
3149 }
3150 
3151 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3152 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3153 {
3154    return atanh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3155 }
3156 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3157 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3158 {
3159    return atanh(arg, policies::policy<>());
3160 }
3161 
3162 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3163 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3164 {
3165    return cbrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3166 }
3167 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3168 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3169 {
3170    return cbrt(arg, policies::policy<>());
3171 }
3172 
3173 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3174 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3175 {
3176    return erf(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3177 }
3178 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3179 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3180 {
3181    return erf(arg, policies::policy<>());
3182 }
3183 
3184 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3185 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3186 {
3187    return erfc(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3188 }
3189 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3190 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3191 {
3192    return erfc(arg, policies::policy<>());
3193 }
3194 
3195 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3196 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3197 {
3198    return expm1(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3199 }
3200 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3201 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> exm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3202 {
3203    return expm1(arg, policies::policy<>());
3204 }
3205 
3206 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3207 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> arg, int* sign, const Policy& pol)
3208 {
3209    return lgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), sign, pol).backend();
3210 }
3211 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3212 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, int* sign)
3213 {
3214    return lgamma(arg, sign, policies::policy<>());
3215 }
3216 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3217 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3218 {
3219    return lgamma(arg, 0, pol);
3220 }
3221 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3222 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3223 {
3224    return lgamma(arg, 0, policies::policy<>());
3225 }
3226 
3227 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3228 inline typename std::enable_if<boost::math::policies::is_policy<Policy>::value, boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >::type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3229 {
3230    return tgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3231 }
3232 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3233 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3234 {
3235    return tgamma(arg, policies::policy<>());
3236 }
3237 
3238 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3239 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3240 {
3241    return log1p(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3242 }
3243 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3244 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3245 {
3246    return log1p(arg, policies::policy<>());
3247 }
3248 
3249 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3250 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg, const Policy& pol)
3251 {
3252    return rsqrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3253 }
3254 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3255 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>& arg)
3256 {
3257    return rsqrt(arg, policies::policy<>());
3258 }
3259 
3260 } // namespace math
3261 
3262 } // namespace boost
3263 
3264 namespace Eigen
3265 {
3266 
3267    template <class B1, class B2>
3268    struct NumTraitsImp;
3269 
3270    template <boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3271    struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>
3272    {
3273       using self_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>;
3274       using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
3275       using NonInteger = self_type; // Not correct but we can't do much better??
3276       using Literal = double;
3277       using Nested = self_type;
3278       enum
3279       {
3280          IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
3281          IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
3282          ReadCost = 1,
3283          AddCost = 4,
3284          MulCost = 8,
3285          IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
3286          RequireInitialization = 1,
3287       };
3288       static Real epsilon()
3289       {
3290          #ifdef BOOST_MP_MATH_AVAILABLE
3291          return boost::math::tools::epsilon< boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3292          #else
3293          self_type result{1};
3294          mpfr_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<self_type>::digits - 1, GMP_RNDN);
3295          return result;
3296          #endif
3297       }
3298       static Real dummy_precision()
3299       {
3300          return 1000 * epsilon();
3301       }
3302       static Real highest()
3303       {
3304          #ifdef BOOST_MP_MATH_AVAILABLE
3305          return boost::math::tools::max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3306          #else
3307          self_type value(0.5);
3308          mpfr_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax(), GMP_RNDN);
3309          return value;
3310          #endif
3311       }
3312       static Real lowest()
3313       {
3314          #ifdef BOOST_MP_MATH_AVAILABLE
3315          return boost::math::tools::min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3316          #else
3317          return -(highest)();
3318          #endif
3319       }
3320       static int digits10()
3321       {
3322          return Real::thread_default_precision();
3323       }
3324       static int digits()
3325       {
3326          return boost::math::tools::digits<Real>();
3327       }
3328       static int min_exponent()
3329       {
3330          return static_cast<int>(mpfr_get_emin());
3331       }
3332       static int max_exponent()
3333       {
3334          return static_cast<int>(mpfr_get_emax());
3335       }
3336       static Real infinity()
3337       {
3338          return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::infinity();
3339       }
3340       static Real quiet_NaN()
3341       {
3342          return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::quiet_NaN();
3343       }
3344    };
3345 
3346 }
3347 
3348 namespace std {
3349 
3350 //
3351 // numeric_limits [partial] specializations for the types declared in this header:
3352 //
3353 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3354 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
3355 {
3356    using number_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
3357 
3358    static number_type get_min()
3359    {
3360       number_type result{0.5};
3361       mpfr_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin(), GMP_RNDN);
3362       return result;
3363    }
3364    static number_type get_max()
3365    {
3366       number_type result{0.5};
3367       mpfr_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax(), GMP_RNDN);
3368       return result;
3369    }
3370    static number_type get_eps()
3371    {
3372       number_type result{1};
3373       mpfr_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<number_type>::digits - 1, GMP_RNDN);
3374       return result;
3375    }
3376 
3377  public:
3378    static constexpr bool is_specialized = true;
3379    static number_type(min)()
3380    {
3381       static number_type value{get_min()};
3382       return value;
3383    }
3384    static number_type(max)()
3385    {
3386       static number_type value{get_max()};
3387       return value;
3388    }
3389    static constexpr number_type lowest()
3390    {
3391       return -(max)();
3392    }
3393    static constexpr int digits   = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
3394    static constexpr int digits10 = Digits10;
3395    // Is this really correct???
3396    static constexpr int  max_digits10 = static_cast<int>(boost::multiprecision::detail::calc_max_digits10<static_cast<unsigned>(digits)>::value);
3397    static constexpr bool is_signed    = true;
3398    static constexpr bool is_integer   = false;
3399    static constexpr bool is_exact     = false;
3400    static constexpr int  radix        = 2;
3401    static number_type          epsilon()
3402    {
3403       static number_type value{get_eps()};
3404       return value;
3405    }
3406    // What value should this be????
3407    static number_type round_error()
3408    {
3409       // returns epsilon/2
3410       return 0.5;
3411    }
3412    static constexpr long min_exponent                  = MPFR_EMIN_DEFAULT;
3413    static constexpr long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
3414    static constexpr long max_exponent                  = MPFR_EMAX_DEFAULT;
3415    static constexpr long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
3416    static constexpr bool has_infinity                  = true;
3417    static constexpr bool has_quiet_NaN                 = true;
3418    static constexpr bool has_signaling_NaN             = false;
3419    static constexpr float_denorm_style has_denorm      = denorm_absent;
3420    static constexpr bool               has_denorm_loss = false;
3421    static number_type                        infinity()
3422    {
3423       number_type value;
3424       mpfr_set_inf(value.backend().data(), 1);
3425       return value;
3426    }
3427    static number_type quiet_NaN()
3428    {
3429       number_type value;
3430       mpfr_set_nan(value.backend().data());
3431       return value;
3432    }
3433    static constexpr number_type signaling_NaN()
3434    {
3435       return number_type(0);
3436    }
3437    static constexpr number_type denorm_min() { return (min)(); }
3438    static constexpr bool        is_iec559         = false;
3439    static constexpr bool        is_bounded        = true;
3440    static constexpr bool        is_modulo         = false;
3441    static constexpr bool        traps             = true;
3442    static constexpr bool        tinyness_before   = false;
3443    static constexpr float_round_style round_style = round_to_nearest;
3444 };
3445 
3446 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3447 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits;
3448 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3449 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits10;
3450 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3451 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_digits10;
3452 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3453 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_signed;
3454 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3455 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_integer;
3456 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3457 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_exact;
3458 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3459 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::radix;
3460 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3461 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent;
3462 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3463 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent10;
3464 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3465 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent;
3466 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3467 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent10;
3468 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3469 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_infinity;
3470 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3471 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_quiet_NaN;
3472 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3473 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_signaling_NaN;
3474 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3475 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm;
3476 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3477 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm_loss;
3478 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3479 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_iec559;
3480 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3481 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_bounded;
3482 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3483 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_modulo;
3484 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3485 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::traps;
3486 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3487 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::tinyness_before;
3488 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3489 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::round_style;
3490 
3491 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3492 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >
3493 {
3494    using number_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates>;
3495 
3496  public:
3497    static constexpr bool is_specialized = false;
3498    static number_type(min)()
3499    {
3500       number_type value(0.5);
3501       mpfr_div_2exp(value.backend().data(), value.backend().data(), -mpfr_get_emin(), GMP_RNDN);
3502       return value;
3503    }
3504    static number_type(max)()
3505    {
3506       number_type value(0.5);
3507       mpfr_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax(), GMP_RNDN);
3508       return value;
3509    }
3510    static number_type lowest()
3511    {
3512       return -(max)();
3513    }
3514    static constexpr int  digits       = INT_MAX;
3515    static constexpr int  digits10     = INT_MAX;
3516    static constexpr int  max_digits10 = INT_MAX;
3517    static constexpr bool is_signed    = true;
3518    static constexpr bool is_integer   = false;
3519    static constexpr bool is_exact     = false;
3520    static constexpr int  radix        = 2;
3521    static number_type          epsilon()
3522    {
3523       number_type value(1);
3524       mpfr_div_2exp(value.backend().data(), value.backend().data(), boost::multiprecision::detail::digits10_2_2(number_type::thread_default_precision()) - 1, GMP_RNDN);
3525       return value;
3526    }
3527    static number_type round_error()
3528    {
3529       return 0.5;
3530    }
3531    static constexpr long min_exponent                  = MPFR_EMIN_DEFAULT;
3532    static constexpr long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
3533    static constexpr long max_exponent                  = MPFR_EMAX_DEFAULT;
3534    static constexpr long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
3535    static constexpr bool has_infinity                  = true;
3536    static constexpr bool has_quiet_NaN                 = true;
3537    static constexpr bool has_signaling_NaN             = false;
3538    static constexpr float_denorm_style has_denorm      = denorm_absent;
3539    static constexpr bool               has_denorm_loss = false;
3540    static number_type                        infinity()
3541    {
3542       number_type value;
3543       mpfr_set_inf(value.backend().data(), 1);
3544       return value;
3545    }
3546    static number_type quiet_NaN()
3547    {
3548       number_type value;
3549       mpfr_set_nan(value.backend().data());
3550       return value;
3551    }
3552    static number_type          signaling_NaN() { return number_type(0); }
3553    static number_type          denorm_min() { return (min)(); }
3554    static constexpr bool is_iec559                = false;
3555    static constexpr bool is_bounded               = true;
3556    static constexpr bool is_modulo                = false;
3557    static constexpr bool traps                    = false;
3558    static constexpr bool tinyness_before          = false;
3559    static constexpr float_round_style round_style = round_toward_zero;
3560 };
3561 
3562 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3563 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits;
3564 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3565 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits10;
3566 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3567 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_digits10;
3568 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3569 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_signed;
3570 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3571 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_integer;
3572 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3573 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_exact;
3574 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3575 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::radix;
3576 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3577 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent;
3578 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3579 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent10;
3580 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3581 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent;
3582 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3583 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent10;
3584 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3585 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_infinity;
3586 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3587 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
3588 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3589 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
3590 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3591 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm;
3592 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3593 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
3594 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3595 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_iec559;
3596 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3597 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_bounded;
3598 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3599 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_modulo;
3600 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3601 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::traps;
3602 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3603 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::tinyness_before;
3604 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3605 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::round_style;
3606 
3607 } // namespace std
3608 #endif