Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:41:00

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                      ++i;
0857                   }
0858                   if (round_up)
0859                   {
0860                      ++e;
0861                      ps[offset]     = '1';
0862                      ps[offset + 1] = 0;
0863                   }
0864                   else
0865                   {
0866                      ps[offset]     = '0';
0867                      ps[offset + 1] = 0;
0868                   }
0869                }
0870                else
0871                {
0872                   ps[offset]     = '0';
0873                   ps[offset + 1] = 0;
0874                }
0875             }
0876             else if (digits > 0)
0877             {
0878                ps = mpfr_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
0879                --e; // To match with what our formatter expects.
0880             }
0881             else
0882             {
0883                ps = mpfr_get_str(nullptr, &e, 10, 1, m_data, GMP_RNDN);
0884                --e;
0885                unsigned offset = *ps == '-' ? 1 : 0;
0886                ps[offset]      = '0';
0887                ps[offset + 1]  = 0;
0888             }
0889          }
0890          result = ps ? ps : "0";
0891          if (ps)
0892             mpfr_free_str(ps);
0893       }
0894       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
0895       return result;
0896    }
0897    void negate() noexcept
0898    {
0899       mpfr_neg(m_data, m_data, GMP_RNDN);
0900    }
0901    template <mpfr_allocation_type AllocationType>
0902    int compare(const mpfr_float_backend<digits10, AllocationType>& o) const
0903    {
0904       return mpfr_cmp(m_data, o.m_data);
0905    }
0906    int compare(long i) const
0907    {
0908       return mpfr_cmp_si(m_data, i);
0909    }
0910    int compare(unsigned long i) const
0911    {
0912       return mpfr_cmp_ui(m_data, i);
0913    }
0914    int compare(double i) const
0915    {
0916       return mpfr_cmp_d(m_data, i);
0917    }
0918    int compare(long double i) const
0919    {
0920       return mpfr_cmp_ld(m_data, i);
0921    }
0922    template <class V>
0923    int compare(V v) const
0924    {
0925       mpfr_float_backend<digits10, allocate_stack> d;
0926       d = v;
0927       return compare(d);
0928    }
0929    mpfr_t& data() noexcept
0930    {
0931       return m_data;
0932    }
0933    const mpfr_t& data() const noexcept
0934    {
0935       return m_data;
0936    }
0937 
0938  protected:
0939    mpfr_t    m_data;
0940    mp_limb_t m_buffer[limb_count];
0941 };
0942 
0943 #ifdef BOOST_MSVC
0944 #pragma warning(pop)
0945 #endif
0946 
0947 } // namespace detail
0948 
0949 template <unsigned digits10, mpfr_allocation_type AllocationType>
0950 struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationType>
0951 {
0952    mpfr_float_backend() : detail::mpfr_float_imp<digits10, AllocationType>() {}
0953    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<digits10, AllocationType>(o) {}
0954    // rvalue copy
0955    mpfr_float_backend(mpfr_float_backend&& o) noexcept : detail::mpfr_float_imp<digits10, AllocationType>(static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o))
0956    {}
0957    template <unsigned D, mpfr_allocation_type AT>
0958    mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0959        : detail::mpfr_float_imp<digits10, AllocationType>()
0960    {
0961       mpfr_set(this->m_data, val.data(), GMP_RNDN);
0962    }
0963    template <unsigned D, mpfr_allocation_type AT>
0964    explicit mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0965        : detail::mpfr_float_imp<digits10, AllocationType>()
0966    {
0967       mpfr_set(this->m_data, val.data(), GMP_RNDN);
0968    }
0969    template <unsigned D>
0970    mpfr_float_backend(const gmp_float<D>& val, typename std::enable_if<D <= digits10>::type* = nullptr)
0971        : detail::mpfr_float_imp<digits10, AllocationType>()
0972    {
0973       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
0974    }
0975    template <unsigned D>
0976    mpfr_float_backend(const gmp_float<D>& val, typename std::enable_if<!(D <= digits10)>::type* = nullptr)
0977        : detail::mpfr_float_imp<digits10, AllocationType>()
0978    {
0979       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
0980    }
0981    mpfr_float_backend(const gmp_int& val)
0982        : detail::mpfr_float_imp<digits10, AllocationType>()
0983    {
0984       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
0985    }
0986    mpfr_float_backend(const gmp_rational& val)
0987        : detail::mpfr_float_imp<digits10, AllocationType>()
0988    {
0989       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
0990    }
0991    mpfr_float_backend(const mpfr_t val)
0992        : detail::mpfr_float_imp<digits10, AllocationType>()
0993    {
0994       mpfr_set(this->m_data, val, GMP_RNDN);
0995    }
0996    mpfr_float_backend(const mpf_t val)
0997        : detail::mpfr_float_imp<digits10, AllocationType>()
0998    {
0999       mpfr_set_f(this->m_data, val, GMP_RNDN);
1000    }
1001    mpfr_float_backend(const mpz_t val)
1002        : detail::mpfr_float_imp<digits10, AllocationType>()
1003    {
1004       mpfr_set_z(this->m_data, val, GMP_RNDN);
1005    }
1006    mpfr_float_backend(const mpq_t val)
1007        : detail::mpfr_float_imp<digits10, AllocationType>()
1008    {
1009       mpfr_set_q(this->m_data, val, GMP_RNDN);
1010    }
1011    // Construction with precision: we ignore the precision here.
1012    template <class V>
1013    mpfr_float_backend(const V& o, unsigned)
1014    {
1015       *this = o;
1016    }
1017    mpfr_float_backend& operator=(const mpfr_float_backend& o)
1018    {
1019       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType> const&>(o);
1020       return *this;
1021    }
1022    // rvalue assign
1023    mpfr_float_backend& operator=(mpfr_float_backend&& o) noexcept
1024    {
1025       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o);
1026       return *this;
1027    }
1028    template <class V>
1029    typename std::enable_if<std::is_assignable<detail::mpfr_float_imp<digits10, AllocationType>, V>::value, mpfr_float_backend&>::type operator=(const V& v)
1030    {
1031       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = v;
1032       return *this;
1033    }
1034    mpfr_float_backend& operator=(const mpfr_t val)
1035    {
1036       if (this->m_data[0]._mpfr_d == nullptr)
1037          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1038       mpfr_set(this->m_data, val, GMP_RNDN);
1039       return *this;
1040    }
1041    mpfr_float_backend& operator=(const mpf_t val)
1042    {
1043       if (this->m_data[0]._mpfr_d == nullptr)
1044          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1045       mpfr_set_f(this->m_data, val, GMP_RNDN);
1046       return *this;
1047    }
1048    mpfr_float_backend& operator=(const mpz_t val)
1049    {
1050       if (this->m_data[0]._mpfr_d == nullptr)
1051          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1052       mpfr_set_z(this->m_data, val, GMP_RNDN);
1053       return *this;
1054    }
1055    mpfr_float_backend& operator=(const mpq_t val)
1056    {
1057       if (this->m_data[0]._mpfr_d == nullptr)
1058          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1059       mpfr_set_q(this->m_data, val, GMP_RNDN);
1060       return *this;
1061    }
1062    // We don't change our precision here, this is a fixed precision type:
1063    template <unsigned D, mpfr_allocation_type AT>
1064    mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
1065    {
1066       if (this->m_data[0]._mpfr_d == nullptr)
1067          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1068       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1069       return *this;
1070    }
1071    template <unsigned D>
1072    mpfr_float_backend& operator=(const gmp_float<D>& val)
1073    {
1074       if (this->m_data[0]._mpfr_d == nullptr)
1075          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1076       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1077       return *this;
1078    }
1079    mpfr_float_backend& operator=(const gmp_int& val)
1080    {
1081       if (this->m_data[0]._mpfr_d == nullptr)
1082          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1083       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1084       return *this;
1085    }
1086    mpfr_float_backend& operator=(const gmp_rational& val)
1087    {
1088       if (this->m_data[0]._mpfr_d == nullptr)
1089          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
1090       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1091       return *this;
1092    }
1093 };
1094 
1095 template <>
1096 struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0, allocate_dynamic>
1097 {
1098    mpfr_float_backend() : detail::mpfr_float_imp<0, allocate_dynamic>() {}
1099    mpfr_float_backend(const mpfr_t val)
1100        : 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())))
1101    {
1102       mpfr_set(this->m_data, val, GMP_RNDN);
1103    }
1104    mpfr_float_backend(const mpf_t val)
1105        : 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())))
1106    {
1107       mpfr_set_f(this->m_data, val, GMP_RNDN);
1108    }
1109    mpfr_float_backend(const mpz_t val)
1110        : detail::mpfr_float_imp<0, allocate_dynamic>()
1111    {
1112       mpfr_set_z(this->m_data, val, GMP_RNDN);
1113    }
1114    mpfr_float_backend(const mpq_t val)
1115        : detail::mpfr_float_imp<0, allocate_dynamic>()
1116    {
1117       mpfr_set_q(this->m_data, val, GMP_RNDN);
1118    }
1119    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<0, allocate_dynamic>(o) {}
1120    // rvalue copy
1121    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))
1122    {}
1123    template <class V>
1124    mpfr_float_backend(const V& o, unsigned digits10)
1125        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1126    {
1127       *this = o;
1128    }
1129 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
1130    mpfr_float_backend(const std::string_view& o, unsigned digits10)
1131        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1132    {
1133       std::string s(o);
1134       *this = s.c_str();
1135    }
1136 #endif
1137    template <unsigned D>
1138    mpfr_float_backend(const gmp_float<D>& val, unsigned digits10)
1139        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1140    {
1141       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1142    }
1143    template <unsigned D>
1144    mpfr_float_backend(const mpfr_float_backend<D>& val, unsigned digits10)
1145        : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10)))
1146    {
1147       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1148    }
1149    template <unsigned D>
1150    mpfr_float_backend(const mpfr_float_backend<D>& val)
1151        : 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())))
1152    {
1153       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1154    }
1155    template <unsigned D>
1156    mpfr_float_backend(const gmp_float<D>& val)
1157        : 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())))
1158    {
1159       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1160    }
1161    mpfr_float_backend(const gmp_int& val)
1162        : 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())))
1163    {
1164       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1165    }
1166    mpfr_float_backend(const gmp_rational& val)
1167        : 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())))
1168    {
1169       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1170    }
1171 
1172    mpfr_float_backend& operator=(const mpfr_float_backend& o) = default;
1173    // rvalue assign
1174    mpfr_float_backend& operator=(mpfr_float_backend&& o) noexcept = default;
1175 
1176    template <class V>
1177    typename std::enable_if<std::is_assignable<detail::mpfr_float_imp<0, allocate_dynamic>, V>::value, mpfr_float_backend&>::type operator=(const V& v)
1178    {
1179       constexpr unsigned d10 = std::is_floating_point<V>::value ?
1180          std::numeric_limits<V>::digits10 :
1181          std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
1182          1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
1183 
1184       if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1185       {
1186          BOOST_IF_CONSTEXPR(std::is_floating_point<V>::value)
1187          {
1188             if (std::numeric_limits<V>::digits > mpfr_get_prec(this->data()))
1189                mpfr_set_prec(this->data(), std::numeric_limits<V>::digits);
1190          }
1191          else
1192          {
1193             if(precision() < d10)
1194                this->precision(d10);
1195          }
1196       }
1197 
1198       *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = v;
1199       return *this;
1200    }
1201    mpfr_float_backend& operator=(const mpfr_t val)
1202    {
1203       if (this->m_data[0]._mpfr_d == nullptr)
1204          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())));
1205       else if(preserve_all_precision())
1206          mpfr_set_prec(this->m_data, mpfr_get_prec(val));
1207       mpfr_set(this->m_data, val, GMP_RNDN);
1208       return *this;
1209    }
1210    mpfr_float_backend& operator=(const mpf_t val)
1211    {
1212       if (this->m_data[0]._mpfr_d == nullptr)
1213          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())));
1214       else if(preserve_all_precision())
1215          mpfr_set_prec(this->m_data, static_cast<mpfr_prec_t>(mpf_get_prec(val)));
1216       mpfr_set_f(this->m_data, val, GMP_RNDN);
1217       return *this;
1218    }
1219    mpfr_float_backend& operator=(const mpz_t val)
1220    {
1221       if (this->m_data[0]._mpfr_d == nullptr)
1222          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(get_default_precision())));
1223       mpfr_set_z(this->m_data, val, GMP_RNDN);
1224       return *this;
1225    }
1226    mpfr_float_backend& operator=(const mpq_t val)
1227    {
1228       if (this->m_data[0]._mpfr_d == nullptr)
1229          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(get_default_precision())));
1230       mpfr_set_q(this->m_data, val, GMP_RNDN);
1231       return *this;
1232    }
1233    template <unsigned D>
1234    mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
1235    {
1236       if (this->m_data[0]._mpfr_d == nullptr)
1237          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()));
1238       else if (preserve_related_precision())
1239          mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
1240       mpfr_set(this->m_data, val.data(), GMP_RNDN);
1241       return *this;
1242    }
1243    template <unsigned D>
1244    mpfr_float_backend& operator=(const gmp_float<D>& val)
1245    {
1246       if (this->m_data[0]._mpfr_d == nullptr)
1247          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()));
1248       else if (preserve_all_precision())
1249          mpfr_set_prec(this->m_data, static_cast<mpfr_prec_t>(mpf_get_prec(val.data())));
1250       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
1251       return *this;
1252    }
1253    mpfr_float_backend& operator=(const gmp_int& val)
1254    {
1255       if (this->m_data[0]._mpfr_d == nullptr)
1256       {
1257          unsigned requested_precision = this->thread_default_precision();
1258          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1259          {
1260             unsigned d2  = static_cast<unsigned>(used_gmp_int_bits(val));
1261             unsigned d10 = static_cast<unsigned>(1ULL + multiprecision::detail::digits2_2_10(d2));
1262             if (d10 > requested_precision)
1263                requested_precision = d10;
1264          }
1265          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(requested_precision)));
1266       }
1267       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1268       {
1269          unsigned requested_precision = this->thread_default_precision();
1270          unsigned d2  = static_cast<unsigned>(used_gmp_int_bits(val));
1271          unsigned d10 = static_cast<unsigned>(1ULL + multiprecision::detail::digits2_2_10(d2));
1272          if (d10 > requested_precision)
1273             this->precision(d10);
1274       }
1275       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
1276       return *this;
1277    }
1278    mpfr_float_backend& operator=(const gmp_rational& val)
1279    {
1280       if (this->m_data[0]._mpfr_d == nullptr)
1281       {
1282          unsigned requested_precision = this->get_default_precision();
1283          if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1284          {
1285             unsigned d10 = static_cast<unsigned>(1u + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val)));
1286             if (d10 > requested_precision)
1287                requested_precision = d10;
1288          }
1289          mpfr_init2(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2(requested_precision)));
1290       }
1291       else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
1292       {
1293          unsigned requested_precision = this->get_default_precision();
1294          unsigned d10 = static_cast<unsigned>(1u + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(val)));
1295          if (d10 > requested_precision)
1296             this->precision(d10);
1297       }
1298       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
1299       return *this;
1300    }
1301    static unsigned default_precision() noexcept
1302    {
1303       return get_global_default_precision();
1304    }
1305    static void default_precision(unsigned v) noexcept
1306    {
1307       get_global_default_precision() = v;
1308    }
1309    static unsigned thread_default_precision() noexcept
1310    {
1311       return get_default_precision();
1312    }
1313    static void thread_default_precision(unsigned v) noexcept
1314    {
1315       get_default_precision() = v;
1316    }
1317    unsigned precision() const noexcept
1318    {
1319       return static_cast<unsigned>(multiprecision::detail::digits2_2_10(static_cast<unsigned long>(mpfr_get_prec(this->m_data))));
1320    }
1321    void precision(unsigned digits10) noexcept
1322    {
1323       mpfr_prec_round(this->m_data, static_cast<mpfr_prec_t>(multiprecision::detail::digits10_2_2((digits10))), GMP_RNDN);
1324    }
1325    //
1326    // Variable precision options:
1327    //
1328    static variable_precision_options default_variable_precision_options()noexcept
1329    {
1330       return get_global_default_options();
1331    }
1332    static variable_precision_options thread_default_variable_precision_options()noexcept
1333    {
1334       return get_default_options();
1335    }
1336    static void default_variable_precision_options(variable_precision_options opts)
1337    {
1338       get_global_default_options() = opts;
1339    }
1340    static void thread_default_variable_precision_options(variable_precision_options opts)
1341    {
1342       get_default_options() = opts;
1343    }
1344    static bool preserve_source_precision()
1345    {
1346       return get_default_options() >= variable_precision_options::preserve_source_precision;
1347    }
1348    static bool preserve_related_precision()
1349    {
1350       return get_default_options() >= variable_precision_options::preserve_related_precision;
1351    }
1352    static bool preserve_all_precision()
1353    {
1354       return get_default_options() >= variable_precision_options::preserve_all_precision;
1355    }
1356 };
1357 
1358 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1359 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)
1360 {
1361    return a.compare(b) == 0;
1362 }
1363 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1364 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)
1365 {
1366    return a.compare(b) < 0;
1367 }
1368 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
1369 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)
1370 {
1371    return a.compare(b) > 0;
1372 }
1373 
1374 template <unsigned digits10, mpfr_allocation_type AllocationType>
1375 inline bool eval_eq(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b)noexcept
1376 {
1377    return mpfr_equal_p(a.data(), b.data());
1378 }
1379 template <unsigned digits10, mpfr_allocation_type AllocationType>
1380 inline bool eval_lt(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b) noexcept
1381 {
1382    return mpfr_less_p(a.data(), b.data());
1383 }
1384 template <unsigned digits10, mpfr_allocation_type AllocationType>
1385 inline bool eval_gt(const mpfr_float_backend<digits10, AllocationType>& a, const mpfr_float_backend<digits10, AllocationType>& b) noexcept
1386 {
1387    return mpfr_greater_p(a.data(), b.data());
1388 }
1389 
1390 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1391 inline void eval_add(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1392 {
1393    mpfr_add(result.data(), result.data(), o.data(), GMP_RNDN);
1394 }
1395 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1396 inline void eval_subtract(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1397 {
1398    mpfr_sub(result.data(), result.data(), o.data(), GMP_RNDN);
1399 }
1400 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1401 inline void eval_multiply(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1402 {
1403    if ((void*)&o == (void*)&result)
1404       mpfr_sqr(result.data(), o.data(), GMP_RNDN);
1405    else
1406       mpfr_mul(result.data(), result.data(), o.data(), GMP_RNDN);
1407 }
1408 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1409 inline void eval_divide(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1410 {
1411    mpfr_div(result.data(), result.data(), o.data(), GMP_RNDN);
1412 }
1413 template <unsigned digits10, mpfr_allocation_type AllocationType>
1414 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1415 {
1416    mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1417 }
1418 template <unsigned digits10, mpfr_allocation_type AllocationType>
1419 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1420 {
1421    mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
1422 }
1423 template <unsigned digits10, mpfr_allocation_type AllocationType>
1424 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1425 {
1426    mpfr_mul_ui(result.data(), result.data(), i, GMP_RNDN);
1427 }
1428 template <unsigned digits10, mpfr_allocation_type AllocationType>
1429 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1430 {
1431    mpfr_div_ui(result.data(), result.data(), i, GMP_RNDN);
1432 }
1433 template <unsigned digits10, mpfr_allocation_type AllocationType>
1434 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, long i)
1435 {
1436    if (i > 0)
1437       mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1438    else
1439       mpfr_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1440 }
1441 template <unsigned digits10, mpfr_allocation_type AllocationType>
1442 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, long i)
1443 {
1444    if (i > 0)
1445       mpfr_sub_ui(result.data(), result.data(), static_cast<typename std::make_unsigned<long>::type>(i), GMP_RNDN);
1446    else
1447       mpfr_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1448 }
1449 template <unsigned digits10, mpfr_allocation_type AllocationType>
1450 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, long i)
1451 {
1452    mpfr_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1453    if (i < 0)
1454       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1455 }
1456 template <unsigned digits10, mpfr_allocation_type AllocationType>
1457 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, long i)
1458 {
1459    mpfr_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1460    if (i < 0)
1461       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1462 }
1463 //
1464 // Specialised 3 arg versions of the basic operators:
1465 //
1466 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1467 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1468 {
1469    mpfr_add(a.data(), x.data(), y.data(), GMP_RNDN);
1470 }
1471 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1472 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1473 {
1474    mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1475 }
1476 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1477 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1478 {
1479    if (y < 0)
1480       mpfr_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1481    else
1482       mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1483 }
1484 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1485 inline void eval_add(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1486 {
1487    mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1488 }
1489 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1490 inline void eval_add(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1491 {
1492    if (x < 0)
1493    {
1494       mpfr_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1495       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1496    }
1497    else
1498       mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1499 }
1500 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1501 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1502 {
1503    mpfr_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1504 }
1505 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1506 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1507 {
1508    mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1509 }
1510 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1511 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1512 {
1513    if (y < 0)
1514       mpfr_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1515    else
1516       mpfr_sub_ui(a.data(), x.data(), static_cast<typename std::make_unsigned<long>::type>(y), GMP_RNDN);
1517 }
1518 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1519 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1520 {
1521    mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1522 }
1523 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1524 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1525 {
1526    if (x < 0)
1527    {
1528       mpfr_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1529       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1530    }
1531    else
1532       mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1533 }
1534 
1535 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1536 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1537 {
1538    if ((void*)&x == (void*)&y)
1539       mpfr_sqr(a.data(), x.data(), GMP_RNDN);
1540    else
1541       mpfr_mul(a.data(), x.data(), y.data(), GMP_RNDN);
1542 }
1543 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1544 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1545 {
1546    mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1547 }
1548 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1549 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1550 {
1551    if (y < 0)
1552    {
1553       mpfr_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1554       a.negate();
1555    }
1556    else
1557       mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1558 }
1559 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1560 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1561 {
1562    mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1563 }
1564 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1565 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1566 {
1567    if (x < 0)
1568    {
1569       mpfr_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1570       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1571    }
1572    else
1573       mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1574 }
1575 
1576 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3, mpfr_allocation_type A3>
1577 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3, A3>& y)
1578 {
1579    mpfr_div(a.data(), x.data(), y.data(), GMP_RNDN);
1580 }
1581 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1582 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1583 {
1584    mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1585 }
1586 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1587 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1588 {
1589    if (y < 0)
1590    {
1591       mpfr_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1592       a.negate();
1593    }
1594    else
1595       mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1596 }
1597 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1598 inline void eval_divide(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1599 {
1600    mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1601 }
1602 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1603 inline void eval_divide(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1604 {
1605    if (x < 0)
1606    {
1607       mpfr_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1608       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1609    }
1610    else
1611       mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1612 }
1613 
1614 template <unsigned digits10, mpfr_allocation_type AllocationType>
1615 inline bool eval_is_zero(const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1616 {
1617    return 0 != mpfr_zero_p(val.data());
1618 }
1619 template <unsigned digits10, mpfr_allocation_type AllocationType>
1620 inline int eval_get_sign(const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1621 {
1622    return mpfr_sgn(val.data());
1623 }
1624 
1625 template <unsigned digits10, mpfr_allocation_type AllocationType>
1626 inline void eval_convert_to(unsigned long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1627 {
1628    if (mpfr_nan_p(val.data()))
1629    {
1630       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1631    }
1632    *result = mpfr_get_ui(val.data(), GMP_RNDZ);
1633 }
1634 template <unsigned digits10, mpfr_allocation_type AllocationType>
1635 inline void eval_convert_to(long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1636 {
1637    if (mpfr_nan_p(val.data()))
1638    {
1639       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1640    }
1641    *result = mpfr_get_si(val.data(), GMP_RNDZ);
1642 }
1643 #ifdef _MPFR_H_HAVE_INTMAX_T
1644 template <unsigned digits10, mpfr_allocation_type AllocationType>
1645 inline void eval_convert_to(unsigned long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1646 {
1647    if (mpfr_nan_p(val.data()))
1648    {
1649       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1650    }
1651    *result = mpfr_get_uj(val.data(), GMP_RNDZ);
1652 }
1653 template <unsigned digits10, mpfr_allocation_type AllocationType>
1654 inline void eval_convert_to(long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1655 {
1656    if (mpfr_nan_p(val.data()))
1657    {
1658       BOOST_MP_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1659    }
1660    *result = mpfr_get_sj(val.data(), GMP_RNDZ);
1661 }
1662 #endif
1663 template <unsigned digits10, mpfr_allocation_type AllocationType>
1664 inline void eval_convert_to(float* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1665 {
1666    *result = mpfr_get_flt(val.data(), GMP_RNDN);
1667 }
1668 template <unsigned digits10, mpfr_allocation_type AllocationType>
1669 inline void eval_convert_to(double* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1670 {
1671    *result = mpfr_get_d(val.data(), GMP_RNDN);
1672 }
1673 template <unsigned digits10, mpfr_allocation_type AllocationType>
1674 inline void eval_convert_to(long double* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1675 {
1676    *result = mpfr_get_ld(val.data(), GMP_RNDN);
1677 }
1678 
1679 #ifdef BOOST_HAS_INT128
1680 template <unsigned digits10, mpfr_allocation_type AllocationType>
1681 inline void eval_convert_to(int128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1682 {
1683    gmp_int i;
1684    mpfr_get_z(i.data(), val.data(), GMP_RNDN);
1685    eval_convert_to(result, i);
1686 }
1687 template <unsigned digits10, mpfr_allocation_type AllocationType>
1688 inline void eval_convert_to(uint128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1689 {
1690    gmp_int i;
1691    mpfr_get_z(i.data(), val.data(), GMP_RNDN);
1692    eval_convert_to(result, i);
1693 }
1694 #endif
1695 #if defined(BOOST_HAS_FLOAT128)
1696 template <unsigned digits10, mpfr_allocation_type AllocationType>
1697 inline void eval_convert_to(float128_type* result, const mpfr_float_backend<digits10, AllocationType>& val) noexcept
1698 {
1699    *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr);
1700 }
1701 #endif
1702 
1703 //
1704 // Native non-member operations:
1705 //
1706 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1707 inline void eval_sqrt(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1708 {
1709    mpfr_sqrt(result.data(), val.data(), GMP_RNDN);
1710 }
1711 
1712 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1713 inline void eval_abs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1714 {
1715    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1716 }
1717 
1718 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1719 inline void eval_fabs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1720 {
1721    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1722 }
1723 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1724 inline void eval_ceil(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1725 {
1726    mpfr_ceil(result.data(), val.data());
1727 }
1728 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1729 inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1730 {
1731    mpfr_floor(result.data(), val.data());
1732 }
1733 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1734 inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1735 {
1736    mpfr_trunc(result.data(), val.data());
1737 }
1738 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1739 inline void eval_ldexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long e)
1740 {
1741    using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1742 
1743    if (e > 0)
1744       mpfr_mul_2exp(result.data(), val.data(), static_cast<local_uint_type>(e), GMP_RNDN);
1745    else if (e < 0)
1746       mpfr_div_2exp(result.data(), val.data(), static_cast<local_uint_type>(-e), GMP_RNDN);
1747    else
1748       result = val;
1749 }
1750 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1751 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, int* e)
1752 {
1753    if (mpfr_zero_p(val.data()))
1754    {
1755       *e = 0;
1756       result = val;
1757       return;
1758    }
1759    mp_exp_t v = mpfr_get_exp(val.data());
1760    *e = static_cast<int>(v);
1761    if (v)
1762       eval_ldexp(result, val, -v);
1763    else
1764       result = val;
1765 }
1766 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1767 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long* e)
1768 {
1769    if (mpfr_zero_p(val.data()))
1770    {
1771       *e = 0;
1772       result = val;
1773       return;
1774    }
1775    mp_exp_t v = mpfr_get_exp(val.data());
1776    *e = v;
1777    if(v)
1778       eval_ldexp(result, val, -v);
1779    else
1780       result = val;
1781 }
1782 
1783 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1784 inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val) noexcept
1785 {
1786    return mpfr_inf_p(val.data()) ? FP_INFINITE : mpfr_nan_p(val.data()) ? FP_NAN : mpfr_zero_p(val.data()) ? FP_ZERO : FP_NORMAL;
1787 }
1788 
1789 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1790 inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
1791 {
1792    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))
1793    {
1794       mpfr_set(result.data(), b.data(), GMP_RNDN);
1795    }
1796    else
1797       mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
1798 }
1799 
1800 #ifdef BOOST_MSVC
1801 //
1802 // The enable_if usage below doesn't work with msvc - but only when
1803 // certain other enable_if usages are defined first.  It's a capricious
1804 // and rather annoying compiler bug in other words....
1805 //
1806 #define BOOST_MP_ENABLE_IF_WORKAROUND (Digits10 || !Digits10)&&
1807 #else
1808 #define BOOST_MP_ENABLE_IF_WORKAROUND
1809 #endif
1810 
1811 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1812 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
1813 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1814 {
1815    mpfr_pow_si(result.data(), b.data(), e, GMP_RNDN);
1816 }
1817 
1818 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1819 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value && (BOOST_MP_ENABLE_IF_WORKAROUND(sizeof(Integer) <= sizeof(long)))>::type
1820 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1821 {
1822    mpfr_pow_ui(result.data(), b.data(), e, GMP_RNDN);
1823 }
1824 
1825 #undef BOOST_MP_ENABLE_IF_WORKAROUND
1826 
1827 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1828 inline void eval_exp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1829 {
1830    mpfr_exp(result.data(), arg.data(), GMP_RNDN);
1831 }
1832 
1833 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1834 inline void eval_exp2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1835 {
1836    mpfr_exp2(result.data(), arg.data(), GMP_RNDN);
1837 }
1838 
1839 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1840 inline void eval_log(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1841 {
1842    mpfr_log(result.data(), arg.data(), GMP_RNDN);
1843 }
1844 
1845 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1846 inline void eval_log10(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1847 {
1848    mpfr_log10(result.data(), arg.data(), GMP_RNDN);
1849 }
1850 
1851 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1852 inline void eval_sin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1853 {
1854    mpfr_sin(result.data(), arg.data(), GMP_RNDN);
1855 }
1856 
1857 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1858 inline void eval_cos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1859 {
1860    mpfr_cos(result.data(), arg.data(), GMP_RNDN);
1861 }
1862 
1863 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1864 inline void eval_tan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1865 {
1866    mpfr_tan(result.data(), arg.data(), GMP_RNDN);
1867 }
1868 
1869 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1870 inline void eval_asin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1871 {
1872    mpfr_asin(result.data(), arg.data(), GMP_RNDN);
1873 }
1874 
1875 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1876 inline void eval_acos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1877 {
1878    mpfr_acos(result.data(), arg.data(), GMP_RNDN);
1879 }
1880 
1881 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1882 inline void eval_atan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1883 {
1884    mpfr_atan(result.data(), arg.data(), GMP_RNDN);
1885 }
1886 
1887 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1888 inline void eval_atan2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg1, const mpfr_float_backend<Digits10, AllocateType>& arg2)
1889 {
1890    mpfr_atan2(result.data(), arg1.data(), arg2.data(), GMP_RNDN);
1891 }
1892 
1893 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1894 inline void eval_sinh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1895 {
1896    mpfr_sinh(result.data(), arg.data(), GMP_RNDN);
1897 }
1898 
1899 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1900 inline void eval_cosh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1901 {
1902    mpfr_cosh(result.data(), arg.data(), GMP_RNDN);
1903 }
1904 
1905 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1906 inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1907 {
1908    mpfr_tanh(result.data(), arg.data(), GMP_RNDN);
1909 }
1910 
1911 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1912 inline void eval_log2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1913 {
1914    mpfr_log2(result.data(), arg.data(), GMP_RNDN);
1915 }
1916 
1917 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1918 inline void eval_modf(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg, mpfr_float_backend<Digits10, AllocateType>* pipart)
1919 {
1920    if (pipart == nullptr)
1921    {
1922       mpfr_float_backend<Digits10, AllocateType> ipart;
1923       mpfr_modf(ipart.data(), result.data(), arg.data(), GMP_RNDN);
1924    }
1925    else
1926    {
1927       mpfr_modf(pipart->data(), result.data(), arg.data(), GMP_RNDN);
1928    }
1929 }
1930 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1931 inline void eval_remainder(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1932 {
1933    mpfr_remainder(result.data(), a.data(), b.data(), GMP_RNDN);
1934 }
1935 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1936 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)
1937 {
1938    long l;
1939    mpfr_remquo(result.data(), &l, a.data(), b.data(), GMP_RNDN);
1940    if (pi)
1941       *pi = static_cast<int>(l);
1942 }
1943 
1944 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1945 inline void eval_fmod(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1946 {
1947    mpfr_fmod(result.data(), a.data(), b.data(), GMP_RNDN);
1948 }
1949 
1950 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1951 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)
1952 {
1953    mpfr_fma(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1954 }
1955 
1956 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1957 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)
1958 {
1959    mpfr_fma(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1960 }
1961 
1962 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1963 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)
1964 {
1965    mpfr_fms(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1966    result.negate();
1967 }
1968 
1969 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1970 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)
1971 {
1972    mpfr_fms(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1973 }
1974 
1975 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1976 inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10, AllocateType>& arg)
1977 {
1978    return (arg.data()[0]._mpfr_sign < 0) ? 1 : 0;
1979 }
1980 
1981 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1982 inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
1983 {
1984    std::size_t result = 0;
1985    std::size_t len    = val.data()[0]._mpfr_prec / mp_bits_per_limb;
1986    if (val.data()[0]._mpfr_prec % mp_bits_per_limb)
1987       ++len;
1988    for (std::size_t i = 0; i < len; ++i)
1989       boost::multiprecision::detail::hash_combine(result, val.data()[0]._mpfr_d[i]);
1990    boost::multiprecision::detail::hash_combine(result, val.data()[0]._mpfr_exp, val.data()[0]._mpfr_sign);
1991    return result;
1992 }
1993 
1994 } // namespace backends
1995 
1996 namespace detail {
1997 template <>
1998 struct is_variable_precision<backends::mpfr_float_backend<0> > : public std::integral_constant<bool, true>
1999 {};
2000 } // namespace detail
2001 
2002 template <>
2003 struct number_category<detail::canonical<mpfr_t, backends::mpfr_float_backend<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
2004 {};
2005 
2006 template <unsigned D, boost::multiprecision::mpfr_allocation_type A1, boost::multiprecision::mpfr_allocation_type A2>
2007 struct is_equivalent_number_type<backends::mpfr_float_backend<D, A1>, backends::mpfr_float_backend<D, A2> > : public std::integral_constant<bool, true> {};
2008 
2009 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2010 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)
2011 {
2012    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
2013 }
2014 
2015 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2016 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)
2017 {
2018    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;
2019 }
2020 
2021 } // namespace multiprecision
2022 
2023 namespace math {
2024 
2025 using boost::multiprecision::copysign;
2026 using boost::multiprecision::signbit;
2027 
2028 namespace tools {
2029 
2030 #ifndef BOOST_MP_MATH_AVAILABLE
2031 
2032 template <typename T>
2033 inline int digits();
2034 
2035 template <typename T>
2036 inline T max_value();
2037 
2038 template <typename T>
2039 inline T min_value();
2040 
2041 #endif
2042 
2043 inline void set_output_precision(const boost::multiprecision::mpfr_float& val, std::ostream& os)
2044 {
2045    os << std::setprecision(static_cast<int>(val.precision()));
2046 }
2047 
2048 template <>
2049 inline int digits<boost::multiprecision::mpfr_float>()
2050 #ifdef BOOST_MATH_NOEXCEPT
2051     noexcept
2052 #endif
2053 {
2054    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::thread_default_precision()));
2055 }
2056 template <>
2057 inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2058 #ifdef BOOST_MATH_NOEXCEPT
2059     noexcept
2060 #endif
2061 {
2062    return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::thread_default_precision()));
2063 }
2064 
2065 template <>
2066 inline boost::multiprecision::mpfr_float
2067 max_value<boost::multiprecision::mpfr_float>()
2068 {
2069    boost::multiprecision::mpfr_float result(0.5);
2070    mpfr_mul_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(mpfr_get_emax()), GMP_RNDN);
2071    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2072    return result;
2073 }
2074 
2075 template <>
2076 inline boost::multiprecision::mpfr_float
2077 min_value<boost::multiprecision::mpfr_float>()
2078 {
2079    boost::multiprecision::mpfr_float result(0.5);
2080    mpfr_div_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(-mpfr_get_emin()), GMP_RNDN);
2081    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2082    return result;
2083 }
2084 
2085 template <>
2086 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
2087 max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2088 {
2089    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
2090    mpfr_mul_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(mpfr_get_emax()), GMP_RNDN);
2091    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2092    return result;
2093 }
2094 
2095 template <>
2096 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
2097 min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
2098 {
2099    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
2100    mpfr_div_2exp(result.backend().data(), result.backend().data(), static_cast<typename std::make_unsigned<mpfr_exp_t>::type>(-mpfr_get_emin()), GMP_RNDN);
2101    BOOST_MP_ASSERT(mpfr_number_p(result.backend().data()));
2102    return result;
2103 }
2104 //
2105 // Over again with debug_adaptor:
2106 //
2107 template <>
2108 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2109 #ifdef BOOST_MATH_NOEXCEPT
2110     noexcept
2111 #endif
2112 {
2113    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()));
2114 }
2115 template <>
2116 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2117 #ifdef BOOST_MATH_NOEXCEPT
2118     noexcept
2119 #endif
2120 {
2121    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()));
2122 }
2123 
2124 template <>
2125 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2126 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2127 {
2128    return max_value<boost::multiprecision::mpfr_float>().backend();
2129 }
2130 
2131 template <>
2132 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2133 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2134 {
2135    return min_value<boost::multiprecision::mpfr_float>().backend();
2136 }
2137 
2138 template <>
2139 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2140 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2141 {
2142    return max_value<boost::multiprecision::mpfr_float>().backend();
2143 }
2144 
2145 template <>
2146 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2147 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2148 {
2149    return min_value<boost::multiprecision::mpfr_float>().backend();
2150 }
2151 
2152 //
2153 // Over again with logged_adaptor:
2154 //
2155 template <>
2156 inline int digits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2157 #ifdef BOOST_MATH_NOEXCEPT
2158     noexcept
2159 #endif
2160 {
2161    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()));
2162 }
2163 template <>
2164 inline int digits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2165 #ifdef BOOST_MATH_NOEXCEPT
2166     noexcept
2167 #endif
2168 {
2169    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()));
2170 }
2171 
2172 template <>
2173 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2174 max_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2175 {
2176    return max_value<boost::multiprecision::mpfr_float>().backend();
2177 }
2178 
2179 template <>
2180 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> >
2181 min_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
2182 {
2183    return min_value<boost::multiprecision::mpfr_float>().backend();
2184 }
2185 
2186 template <>
2187 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2188 max_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2189 {
2190    return max_value<boost::multiprecision::mpfr_float>().backend();
2191 }
2192 
2193 template <>
2194 inline boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
2195 min_value<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
2196 {
2197    return min_value<boost::multiprecision::mpfr_float>().backend();
2198 }
2199 
2200 } // namespace tools
2201 
2202 namespace constants { namespace detail {
2203 
2204 template <class T>
2205 struct constant_pi;
2206 template <class T>
2207 struct constant_ln_two;
2208 template <class T>
2209 struct constant_euler;
2210 template <class T>
2211 struct constant_catalan;
2212 
2213 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2214 struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2215 {
2216    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2217    template <int N>
2218    static inline const result_type& get(const std::integral_constant<int, N>&)
2219    {
2220       // Rely on C++11 thread safe initialization:
2221       static result_type result{get(std::integral_constant<int, 0>())};
2222       return result;
2223    }
2224    static inline const result_type get(const std::integral_constant<int, 0>&)
2225    {
2226       result_type result;
2227       mpfr_const_pi(result.backend().data(), GMP_RNDN);
2228       return result;
2229    }
2230 };
2231 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2232 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2233 {
2234    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2235    template <int N>
2236    static inline const result_type& get(const std::integral_constant<int, N>&)
2237    {
2238       // Rely on C++11 thread safe initialization:
2239       static result_type result{get(std::integral_constant<int, 0>())};
2240       return result;
2241    }
2242    static inline const result_type get(const std::integral_constant<int, 0>&)
2243    {
2244       result_type result;
2245       mpfr_const_log2(result.backend().data(), GMP_RNDN);
2246       return result;
2247    }
2248 };
2249 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2250 struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2251 {
2252    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2253    template <int N>
2254    static inline const result_type& get(const std::integral_constant<int, N>&)
2255    {
2256       // Rely on C++11 thread safe initialization:
2257       static result_type result{get(std::integral_constant<int, 0>())};
2258       return result;
2259    }
2260    static inline const result_type get(const std::integral_constant<int, 0>&)
2261    {
2262       result_type result;
2263       mpfr_const_euler(result.backend().data(), GMP_RNDN);
2264       return result;
2265    }
2266 };
2267 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2268 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2269 {
2270    using result_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
2271    template <int N>
2272    static inline const result_type& get(const std::integral_constant<int, N>&)
2273    {
2274       // Rely on C++11 thread safe initialization:
2275       static result_type result{get(std::integral_constant<int, 0>())};
2276       return result;
2277    }
2278    static inline const result_type get(const std::integral_constant<int, 0>&)
2279    {
2280       result_type result;
2281       mpfr_const_catalan(result.backend().data(), GMP_RNDN);
2282       return result;
2283    }
2284 };
2285 //
2286 // Over again with debug_adaptor:
2287 //
2288 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2289 struct constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2290 {
2291    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2292    template <int N>
2293    static inline const result_type& get(const std::integral_constant<int, N>&)
2294    {
2295       // Rely on C++11 thread safe initialization:
2296       static result_type result{get(std::integral_constant<int, 0>())};
2297       return result;
2298    }
2299    static inline const result_type get(const std::integral_constant<int, 0>&)
2300    {
2301       result_type result;
2302       mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
2303       result.backend().update_view();
2304       return result;
2305    }
2306 };
2307 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2308 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2309 {
2310    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2311    template <int N>
2312    static inline const result_type& get(const std::integral_constant<int, N>&)
2313    {
2314       // Rely on C++11 thread safe initialization:
2315       static result_type result{get(std::integral_constant<int, 0>())};
2316       return result;
2317    }
2318    static inline const result_type get(const std::integral_constant<int, 0>&)
2319    {
2320       result_type result;
2321       mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
2322       result.backend().update_view();
2323       return result;
2324    }
2325 };
2326 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2327 struct constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2328 {
2329    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2330    template <int N>
2331    static inline const result_type& get(const std::integral_constant<int, N>&)
2332    {
2333       // Rely on C++11 thread safe initialization:
2334       static result_type result{get(std::integral_constant<int, 0>())};
2335       return result;
2336    }
2337    static inline const result_type get(const std::integral_constant<int, 0>&)
2338    {
2339       result_type result;
2340       mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
2341       result.backend().update_view();
2342       return result;
2343    }
2344 };
2345 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2346 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2347 {
2348    using result_type = boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2349    template <int N>
2350    static inline const result_type& get(const std::integral_constant<int, N>&)
2351    {
2352       // Rely on C++11 thread safe initialization:
2353       static result_type result{get(std::integral_constant<int, 0>())};
2354       return result;
2355    }
2356    static inline const result_type get(const std::integral_constant<int, 0>&)
2357    {
2358       result_type result;
2359       mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
2360       result.backend().update_view();
2361       return result;
2362    }
2363 };
2364 
2365 //
2366 // Over again with logged_adaptor:
2367 //
2368 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2369 struct constant_pi<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2370 {
2371    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2372    template <int N>
2373    static inline const result_type& get(const std::integral_constant<int, N>&)
2374    {
2375       // C++11 thread safe static initialization:
2376       static result_type result{get(std::integral_constant<int, 0>())};
2377       return result;
2378    }
2379    static inline const result_type get(const std::integral_constant<int, 0>&)
2380    {
2381       result_type result;
2382       mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
2383       return result;
2384    }
2385 };
2386 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2387 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2388 {
2389    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2390    template <int N>
2391    static inline const result_type& get(const std::integral_constant<int, N>&)
2392    {
2393       // C++11 thread safe static initialization:
2394       static result_type result{get(std::integral_constant<int, 0>())};
2395       return result;
2396    }
2397    static inline const result_type get(const std::integral_constant<int, 0>&)
2398    {
2399       result_type result;
2400       mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
2401       return result;
2402    }
2403 };
2404 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2405 struct constant_euler<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2406 {
2407    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2408    template <int N>
2409    static inline const result_type& get(const std::integral_constant<int, N>&)
2410    {
2411       // C++11 thread safe static initialization:
2412       static result_type result{get(std::integral_constant<int, 0>())};
2413       return result;
2414    }
2415    static inline const result_type get(const std::integral_constant<int, 0>&)
2416    {
2417       result_type result;
2418       mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
2419       return result;
2420    }
2421 };
2422 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2423 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
2424 {
2425    using result_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates>;
2426    template <int N>
2427    static inline const result_type& get(const std::integral_constant<int, N>&)
2428    {
2429       // C++11 thread safe static initialization:
2430       static result_type result{get(std::integral_constant<int, 0>())};
2431       return result;
2432    }
2433    static inline const result_type get(const std::integral_constant<int, 0>&)
2434    {
2435       result_type result;
2436       mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
2437       return result;
2438    }
2439 };
2440 
2441 }} // namespace constants::detail
2442 
2443 } // namespace math
2444 
2445 namespace multiprecision {
2446 //
2447 // Overloaded special functions which call native mpfr routines:
2448 //
2449 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2450 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)
2451 {
2452    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2453 
2454    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2455    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2456    return result;
2457 }
2458 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2459 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)
2460 {
2461    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2462 
2463    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2464    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2465    return result;
2466 }
2467 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2468 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)
2469 {
2470    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2471 
2472    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2473    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2474    return result;
2475 }
2476 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2477 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)
2478 {
2479    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2480 
2481    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2482    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2483    return result;
2484 }
2485 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2486 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)
2487 {
2488    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2489 
2490    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2491    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2492    return result;
2493 }
2494 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2495 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)
2496 {
2497    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2498 
2499    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2500    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2501    return result;
2502 }
2503 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2504 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)
2505 {
2506    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2507 
2508    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2509    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2510    return result;
2511 }
2512 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2513 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)
2514 {
2515    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2516 
2517    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2518    mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2519    return result;
2520 }
2521 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2522 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)
2523 {
2524    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2525 
2526    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2527    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2528    return result;
2529 }
2530 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2531 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)
2532 {
2533    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2534 
2535    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2536    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2537    return result;
2538 }
2539 
2540 //
2541 // Over again with debug_adaptor:
2542 //
2543 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2544 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)
2545 {
2546    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2547 
2548    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2549    mpfr_asinh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2550    result.backend().update_view();
2551    return result;
2552 }
2553 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2554 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)
2555 {
2556    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2557 
2558    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2559    mpfr_acosh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2560    result.backend().update_view();
2561    return result;
2562 }
2563 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2564 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)
2565 {
2566    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2567 
2568    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2569    mpfr_atanh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2570    result.backend().update_view();
2571    return result;
2572 }
2573 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2574 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)
2575 {
2576    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2577 
2578    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2579    mpfr_cbrt(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2580    result.backend().update_view();
2581    return result;
2582 }
2583 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2584 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)
2585 {
2586    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2587 
2588    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2589    mpfr_erf(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2590    result.backend().update_view();
2591    return result;
2592 }
2593 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2594 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)
2595 {
2596    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2597 
2598    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2599    mpfr_erfc(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2600    result.backend().update_view();
2601    return result;
2602 }
2603 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2604 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)
2605 {
2606    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2607 
2608    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2609    mpfr_expm1(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2610    result.backend().update_view();
2611    return result;
2612 }
2613 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2614 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)
2615 {
2616    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2617 
2618    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2619    mpfr_lngamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2620    result.backend().update_view();
2621    return result;
2622 }
2623 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2624 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)
2625 {
2626    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2627 
2628    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2629    mpfr_gamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2630    result.backend().update_view();
2631    return result;
2632 }
2633 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2634 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)
2635 {
2636    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2637 
2638    boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2639    mpfr_log1p(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2640    result.backend().update_view();
2641    return result;
2642 }
2643 
2644 //
2645 // Over again with logged_adaptor:
2646 //
2647 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2648 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)
2649 {
2650    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2651 
2652    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2653    mpfr_asinh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2654    return result;
2655 }
2656 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2657 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)
2658 {
2659    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2660 
2661    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2662    mpfr_acosh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2663    return result;
2664 }
2665 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2666 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)
2667 {
2668    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2669 
2670    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2671    mpfr_atanh(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2672    return result;
2673 }
2674 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2675 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)
2676 {
2677    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2678 
2679    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2680    mpfr_cbrt(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2681    return result;
2682 }
2683 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2684 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)
2685 {
2686    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2687 
2688    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2689    mpfr_erf(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2690    return result;
2691 }
2692 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2693 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)
2694 {
2695    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2696 
2697    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2698    mpfr_erfc(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2699    return result;
2700 }
2701 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2702 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)
2703 {
2704    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2705 
2706    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2707    mpfr_expm1(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2708    return result;
2709 }
2710 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2711 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)
2712 {
2713    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2714 
2715    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2716    mpfr_lngamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2717    return result;
2718 }
2719 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2720 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)
2721 {
2722    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2723 
2724    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2725    mpfr_gamma(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2726    return result;
2727 }
2728 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2729 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)
2730 {
2731    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> > precision_guard(arg);
2732 
2733    boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result;
2734    mpfr_log1p(result.backend().value().data(), arg.backend().value().data(), GMP_RNDN);
2735    return result;
2736 }
2737 
2738 } // namespace multiprecision
2739 
2740 namespace math {
2741 //
2742 // Overloaded special functions which call native mpfr routines:
2743 //
2744 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2745 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&)
2746 {
2747    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2748 
2749    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2750    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2751    if (mpfr_inf_p(result.backend().data()))
2752       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("asinh<%1%>(%1%)", nullptr, Policy());
2753    if (mpfr_nan_p(result.backend().data()))
2754       return policies::raise_evaluation_error("asinh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2755    return result;
2756 }
2757 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2758 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)
2759 {
2760    return asinh(arg, policies::policy<>());
2761 }
2762 
2763 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2764 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&)
2765 {
2766    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2767 
2768    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2769    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2770    if (mpfr_inf_p(result.backend().data()))
2771       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("acosh<%1%>(%1%)", nullptr, Policy());
2772    if (mpfr_nan_p(result.backend().data()))
2773       return policies::raise_evaluation_error("acosh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2774    return result;
2775 }
2776 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2777 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)
2778 {
2779    return acosh(arg, policies::policy<>());
2780 }
2781 
2782 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2783 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& )
2784 {
2785    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2786 
2787    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2788    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2789    if (mpfr_inf_p(result.backend().data()))
2790       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("atanh<%1%>(%1%)", nullptr, Policy());
2791    if (mpfr_nan_p(result.backend().data()))
2792       return policies::raise_evaluation_error("atanh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2793    return result;
2794 }
2795 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2796 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)
2797 {
2798    return atanh(arg, policies::policy<>());
2799 }
2800 
2801 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2802 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&)
2803 {
2804    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2805 
2806    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2807    if (mpfr_nan_p(arg.backend().data()))
2808       return policies::raise_domain_error("cbrt<%1%>(%1%)", "Input is a NaN", result, Policy());
2809    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2810    if (mpfr_inf_p(result.backend().data()))
2811       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("cbrt<%1%>(%1%)", nullptr, Policy());
2812    if (mpfr_nan_p(result.backend().data()))
2813       return policies::raise_evaluation_error("cbrt<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2814    return result;
2815 }
2816 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2817 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)
2818 {
2819    return cbrt(arg, policies::policy<>());
2820 }
2821 
2822 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2823 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)
2824 {
2825    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2826 
2827    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2828    if (mpfr_nan_p(arg.backend().data()))
2829       return policies::raise_domain_error("erf<%1%>(%1%)", "Input is a NaN", result, pol);
2830    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2831    if (mpfr_inf_p(result.backend().data()))
2832       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erf<%1%>(%1%)", nullptr, pol);
2833    if (mpfr_nan_p(result.backend().data()))
2834       return policies::raise_evaluation_error("erf<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2835    return result;
2836 }
2837 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2838 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)
2839 {
2840    return erf(arg, policies::policy<>());
2841 }
2842 
2843 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2844 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)
2845 {
2846    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2847 
2848    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2849    if (mpfr_nan_p(arg.backend().data()))
2850       return policies::raise_domain_error("erf<%1%>(%1%)", "Input is a NaN", result, pol);
2851    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2852    if (mpfr_inf_p(result.backend().data()))
2853       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erfc<%1%>(%1%)", nullptr, pol);
2854    if (mpfr_nan_p(result.backend().data()))
2855       return policies::raise_evaluation_error("erfc<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2856    return result;
2857 }
2858 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2859 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)
2860 {
2861    return erfc(arg, policies::policy<>());
2862 }
2863 
2864 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2865 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)
2866 {
2867    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2868 
2869    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2870    if (mpfr_nan_p(arg.backend().data()))
2871       return policies::raise_domain_error("erf<%1%>(%1%)", "Input is a NaN", result, pol);
2872    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2873    if (mpfr_inf_p(result.backend().data()))
2874       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("expm1<%1%>(%1%)", nullptr, pol);
2875    if (mpfr_nan_p(result.backend().data()))
2876       return policies::raise_evaluation_error("expm1<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2877    return result;
2878 }
2879 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2880 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)
2881 {
2882    return expm1(arg, policies::policy<>());
2883 }
2884 
2885 #ifdef BOOST_MP_MATH_AVAILABLE
2886 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2887 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)
2888 {
2889    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2890    (void)precision_guard;  // warning suppression
2891 
2892    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2893    if (arg > 0)
2894    {
2895       mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2896       if (sign)
2897          *sign = 1;
2898    }
2899    else
2900    {
2901       if (floor(arg) == arg)
2902          return policies::raise_pole_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >(
2903              "lgamma<%1%>", "Evaluation of lgamma at a negative integer %1%.", arg, pol);
2904 
2905       boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> t = detail::sinpx(arg);
2906       arg                                                                                                                     = -arg;
2907       if (t < 0)
2908       {
2909          t = -t;
2910       }
2911       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);
2912       if (sign)
2913       {
2914          boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> phase = 1 - arg;
2915          phase                                                                                                                       = floor(phase) / 2;
2916          if (floor(phase) == phase)
2917             *sign = -1;
2918          else
2919             *sign = 1;
2920       }
2921    }
2922    if (mpfr_inf_p(result.backend().data()))
2923       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("lgamma<%1%>(%1%)", nullptr, pol);
2924    if (mpfr_nan_p(result.backend().data()))
2925       return policies::raise_evaluation_error("lgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2926    return result;
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, int* sign)
2930 {
2931    return lgamma(arg, sign, policies::policy<>());
2932 }
2933 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2934 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)
2935 {
2936    return lgamma(arg, 0, pol);
2937 }
2938 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2939 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)
2940 {
2941    return lgamma(arg, 0, policies::policy<>());
2942 }
2943 #endif // BOOST_MP_MATH_AVAILABLE
2944 
2945 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2946 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)
2947 {
2948    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2949 
2950    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2951    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2952    if (mpfr_inf_p(result.backend().data()))
2953       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("tgamma<%1%>(%1%)", nullptr, pol);
2954    if (mpfr_nan_p(result.backend().data()))
2955       return policies::raise_evaluation_error("tgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2956    return result;
2957 }
2958 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2959 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)
2960 {
2961    return tgamma(arg, policies::policy<>());
2962 }
2963 
2964 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2965 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)
2966 {
2967    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2968 
2969    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2970    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2971    if (mpfr_inf_p(result.backend().data()))
2972       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);
2973    if (mpfr_nan_p(result.backend().data()))
2974       return policies::raise_evaluation_error("log1p<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2975    return result;
2976 }
2977 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2978 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)
2979 {
2980    return log1p(arg, policies::policy<>());
2981 }
2982 
2983 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
2984 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)
2985 {
2986    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2987 
2988    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2989    mpfr_rec_sqrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2990    if (mpfr_inf_p(result.backend().data()))
2991       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("rsqrt<%1%>(%1%)", nullptr, pol);
2992    if (mpfr_nan_p(result.backend().data()))
2993       return policies::raise_evaluation_error("rsqrt<%1%>(%1%)", "Negative argument, result is a NaN", result, pol);
2994    return result;
2995 }
2996 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2997 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)
2998 {
2999    return rsqrt(arg, policies::policy<>());
3000 }
3001 
3002 //
3003 // Over again with debug_adaptor:
3004 //
3005 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3006 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)
3007 {
3008    return asinh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3009 }
3010 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3011 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)
3012 {
3013    return asinh(arg, policies::policy<>());
3014 }
3015 
3016 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3017 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)
3018 {
3019    return acosh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3020 }
3021 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3022 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)
3023 {
3024    return acosh(arg, policies::policy<>());
3025 }
3026 
3027 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3028 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)
3029 {
3030    return atanh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3031 }
3032 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3033 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)
3034 {
3035    return atanh(arg, policies::policy<>());
3036 }
3037 
3038 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3039 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)
3040 {
3041    return cbrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3042 }
3043 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3044 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)
3045 {
3046    return cbrt(arg, policies::policy<>());
3047 }
3048 
3049 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3050 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)
3051 {
3052    return erf(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3053 }
3054 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3055 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)
3056 {
3057    return erf(arg, policies::policy<>());
3058 }
3059 
3060 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3061 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)
3062 {
3063    return erfc(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3064 }
3065 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3066 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)
3067 {
3068    return erfc(arg, policies::policy<>());
3069 }
3070 
3071 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3072 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)
3073 {
3074    return expm1(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3075 }
3076 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3077 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)
3078 {
3079    return expm1(arg, policies::policy<>());
3080 }
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(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> arg, int* sign, const Policy& pol)
3084 {
3085    return lgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), sign, pol).backend();
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, int* sign)
3089 {
3090    return lgamma(arg, sign, policies::policy<>());
3091 }
3092 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3093 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)
3094 {
3095    return lgamma(arg, 0, pol);
3096 }
3097 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3098 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)
3099 {
3100    return lgamma(arg, 0, policies::policy<>());
3101 }
3102 
3103 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3104 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)
3105 {
3106    return tgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3107 }
3108 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3109 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)
3110 {
3111    return tgamma(arg, policies::policy<>());
3112 }
3113 
3114 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3115 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)
3116 {
3117    return log1p(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3118 }
3119 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3120 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)
3121 {
3122    return log1p(arg, policies::policy<>());
3123 }
3124 
3125 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3126 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)
3127 {
3128    return rsqrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3129 }
3130 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3131 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)
3132 {
3133    return rsqrt(arg, policies::policy<>());
3134 }
3135 
3136 //
3137 // Over again with logged_adaptor:
3138 //
3139 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3140 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)
3141 {
3142    return asinh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3143 }
3144 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3145 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)
3146 {
3147    return asinh(arg, policies::policy<>());
3148 }
3149 
3150 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3151 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)
3152 {
3153    return acosh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3154 }
3155 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3156 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)
3157 {
3158    return acosh(arg, policies::policy<>());
3159 }
3160 
3161 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3162 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)
3163 {
3164    return atanh(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3165 }
3166 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3167 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)
3168 {
3169    return atanh(arg, policies::policy<>());
3170 }
3171 
3172 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3173 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)
3174 {
3175    return cbrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3176 }
3177 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3178 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)
3179 {
3180    return cbrt(arg, policies::policy<>());
3181 }
3182 
3183 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3184 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)
3185 {
3186    return erf(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3187 }
3188 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3189 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)
3190 {
3191    return erf(arg, policies::policy<>());
3192 }
3193 
3194 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3195 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)
3196 {
3197    return erfc(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3198 }
3199 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3200 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)
3201 {
3202    return erfc(arg, policies::policy<>());
3203 }
3204 
3205 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3206 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)
3207 {
3208    return expm1(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3209 }
3210 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3211 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)
3212 {
3213    return expm1(arg, policies::policy<>());
3214 }
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(boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> arg, int* sign, const Policy& pol)
3218 {
3219    return lgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), sign, pol).backend();
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, int* sign)
3223 {
3224    return lgamma(arg, sign, policies::policy<>());
3225 }
3226 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3227 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)
3228 {
3229    return lgamma(arg, 0, pol);
3230 }
3231 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3232 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)
3233 {
3234    return lgamma(arg, 0, policies::policy<>());
3235 }
3236 
3237 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3238 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)
3239 {
3240    return tgamma(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3241 }
3242 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3243 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)
3244 {
3245    return tgamma(arg, policies::policy<>());
3246 }
3247 
3248 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3249 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)
3250 {
3251    return log1p(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3252 }
3253 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3254 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)
3255 {
3256    return log1p(arg, policies::policy<>());
3257 }
3258 
3259 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
3260 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)
3261 {
3262    return rsqrt(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(arg.backend().value()), pol).backend();
3263 }
3264 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3265 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)
3266 {
3267    return rsqrt(arg, policies::policy<>());
3268 }
3269 
3270 } // namespace math
3271 
3272 } // namespace boost
3273 
3274 namespace Eigen
3275 {
3276 
3277    template <class B1, class B2>
3278    struct NumTraitsImp;
3279 
3280    template <boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3281    struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>
3282    {
3283       using self_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>;
3284       using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
3285       using NonInteger = self_type; // Not correct but we can't do much better??
3286       using Literal = double;
3287       using Nested = self_type;
3288       enum
3289       {
3290          IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
3291          IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
3292          ReadCost = 1,
3293          AddCost = 4,
3294          MulCost = 8,
3295          IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
3296          RequireInitialization = 1,
3297       };
3298       static Real epsilon()
3299       {
3300          #ifdef BOOST_MP_MATH_AVAILABLE
3301          return boost::math::tools::epsilon< boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3302          #else
3303          self_type result{1};
3304          mpfr_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<self_type>::digits - 1, GMP_RNDN);
3305          return result;
3306          #endif
3307       }
3308       static Real dummy_precision()
3309       {
3310          return 1000 * epsilon();
3311       }
3312       static Real highest()
3313       {
3314          #ifdef BOOST_MP_MATH_AVAILABLE
3315          return boost::math::tools::max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3316          #else
3317          self_type value(0.5);
3318          mpfr_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax(), GMP_RNDN);
3319          return value;
3320          #endif
3321       }
3322       static Real lowest()
3323       {
3324          #ifdef BOOST_MP_MATH_AVAILABLE
3325          return boost::math::tools::min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0, AllocateType>, ExpressionTemplates>>();
3326          #else
3327          return -(highest)();
3328          #endif
3329       }
3330       static int digits10()
3331       {
3332          return Real::thread_default_precision();
3333       }
3334       static int digits()
3335       {
3336          return boost::math::tools::digits<Real>();
3337       }
3338       static int min_exponent()
3339       {
3340          return static_cast<int>(mpfr_get_emin());
3341       }
3342       static int max_exponent()
3343       {
3344          return static_cast<int>(mpfr_get_emax());
3345       }
3346       static Real infinity()
3347       {
3348          return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::infinity();
3349       }
3350       static Real quiet_NaN()
3351       {
3352          return std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<50, AllocateType>, ExpressionTemplates>>::quiet_NaN();
3353       }
3354    };
3355 
3356 }
3357 
3358 namespace std {
3359 
3360 //
3361 // numeric_limits [partial] specializations for the types declared in this header:
3362 //
3363 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3364 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
3365 {
3366    using number_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>;
3367 
3368    static number_type get_min()
3369    {
3370       number_type result{0.5};
3371       mpfr_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin(), GMP_RNDN);
3372       return result;
3373    }
3374    static number_type get_max()
3375    {
3376       number_type result{0.5};
3377       mpfr_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax(), GMP_RNDN);
3378       return result;
3379    }
3380    static number_type get_eps()
3381    {
3382       number_type result{1};
3383       mpfr_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<number_type>::digits - 1, GMP_RNDN);
3384       return result;
3385    }
3386 
3387  public:
3388    static constexpr bool is_specialized = true;
3389    static number_type(min)()
3390    {
3391       static number_type value{get_min()};
3392       return value;
3393    }
3394    static number_type(max)()
3395    {
3396       static number_type value{get_max()};
3397       return value;
3398    }
3399    static constexpr number_type lowest()
3400    {
3401       return -(max)();
3402    }
3403    static constexpr int digits   = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
3404    static constexpr int digits10 = Digits10;
3405    // Is this really correct???
3406    static constexpr int  max_digits10 = static_cast<int>(boost::multiprecision::detail::calc_max_digits10<static_cast<unsigned>(digits)>::value);
3407    static constexpr bool is_signed    = true;
3408    static constexpr bool is_integer   = false;
3409    static constexpr bool is_exact     = false;
3410    static constexpr int  radix        = 2;
3411    static number_type          epsilon()
3412    {
3413       static number_type value{get_eps()};
3414       return value;
3415    }
3416    // What value should this be????
3417    static number_type round_error()
3418    {
3419       // returns epsilon/2
3420       return 0.5;
3421    }
3422    static constexpr long min_exponent                  = MPFR_EMIN_DEFAULT;
3423    static constexpr long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
3424    static constexpr long max_exponent                  = MPFR_EMAX_DEFAULT;
3425    static constexpr long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
3426    static constexpr bool has_infinity                  = true;
3427    static constexpr bool has_quiet_NaN                 = true;
3428    static constexpr bool has_signaling_NaN             = false;
3429 #ifdef _MSC_VER
3430 #pragma warning(push)
3431 #pragma warning(disable : 4996)
3432 #endif
3433    static constexpr float_denorm_style       has_denorm      = denorm_absent;
3434 #ifdef _MSC_VER
3435 #pragma warning(pop)
3436 #endif
3437    static constexpr bool has_denorm_loss = false;
3438    static number_type                        infinity()
3439    {
3440       number_type value;
3441       mpfr_set_inf(value.backend().data(), 1);
3442       return value;
3443    }
3444    static number_type quiet_NaN()
3445    {
3446       number_type value;
3447       mpfr_set_nan(value.backend().data());
3448       return value;
3449    }
3450    static constexpr number_type signaling_NaN()
3451    {
3452       return number_type(0);
3453    }
3454    static constexpr number_type denorm_min() { return (min)(); }
3455    static constexpr bool        is_iec559         = false;
3456    static constexpr bool        is_bounded        = true;
3457    static constexpr bool        is_modulo         = false;
3458    static constexpr bool        traps             = true;
3459    static constexpr bool        tinyness_before   = false;
3460    static constexpr float_round_style round_style = round_to_nearest;
3461 };
3462 
3463 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3464 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits;
3465 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3466 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits10;
3467 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3468 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_digits10;
3469 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3470 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_signed;
3471 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3472 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_integer;
3473 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3474 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_exact;
3475 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3476 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::radix;
3477 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3478 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent;
3479 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3480 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent10;
3481 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3482 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent;
3483 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3484 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent10;
3485 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3486 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_infinity;
3487 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3488 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_quiet_NaN;
3489 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3490 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_signaling_NaN;
3491 #ifdef _MSC_VER
3492 #pragma warning(push)
3493 #pragma warning(disable : 4996)
3494 #endif
3495 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3496 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm;
3497 #ifdef _MSC_VER
3498 #pragma warning(pop)
3499 #endif
3500 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3501 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm_loss;
3502 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3503 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_iec559;
3504 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3505 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_bounded;
3506 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3507 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_modulo;
3508 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3509 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::traps;
3510 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3511 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::tinyness_before;
3512 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
3513 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::round_style;
3514 
3515 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3516 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >
3517 {
3518    using number_type = boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates>;
3519 
3520  public:
3521    static constexpr bool is_specialized = false;
3522    static number_type(min)()
3523    {
3524       number_type value(0.5);
3525       mpfr_div_2exp(value.backend().data(), value.backend().data(), -mpfr_get_emin(), GMP_RNDN);
3526       return value;
3527    }
3528    static number_type(max)()
3529    {
3530       number_type value(0.5);
3531       mpfr_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax(), GMP_RNDN);
3532       return value;
3533    }
3534    static number_type lowest()
3535    {
3536       return -(max)();
3537    }
3538    static constexpr int  digits       = INT_MAX;
3539    static constexpr int  digits10     = INT_MAX;
3540    static constexpr int  max_digits10 = INT_MAX;
3541    static constexpr bool is_signed    = true;
3542    static constexpr bool is_integer   = false;
3543    static constexpr bool is_exact     = false;
3544    static constexpr int  radix        = 2;
3545    static number_type          epsilon()
3546    {
3547       number_type value(1);
3548       mpfr_div_2exp(value.backend().data(), value.backend().data(), boost::multiprecision::detail::digits10_2_2(number_type::thread_default_precision()) - 1, GMP_RNDN);
3549       return value;
3550    }
3551    static number_type round_error()
3552    {
3553       return 0.5;
3554    }
3555    static constexpr long min_exponent                  = MPFR_EMIN_DEFAULT;
3556    static constexpr long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
3557    static constexpr long max_exponent                  = MPFR_EMAX_DEFAULT;
3558    static constexpr long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
3559    static constexpr bool has_infinity                  = true;
3560    static constexpr bool has_quiet_NaN                 = true;
3561    static constexpr bool has_signaling_NaN             = false;
3562 #ifdef _MSC_VER
3563 #pragma warning(push)
3564 #pragma warning(disable : 4996)
3565 #endif
3566    static constexpr float_denorm_style       has_denorm      = denorm_absent;
3567 #ifdef _MSC_VER
3568 #pragma warning(pop)
3569 #endif
3570    static constexpr bool has_denorm_loss = false;
3571    static number_type                        infinity()
3572    {
3573       number_type value;
3574       mpfr_set_inf(value.backend().data(), 1);
3575       return value;
3576    }
3577    static number_type quiet_NaN()
3578    {
3579       number_type value;
3580       mpfr_set_nan(value.backend().data());
3581       return value;
3582    }
3583    static number_type          signaling_NaN() { return number_type(0); }
3584    static number_type          denorm_min() { return (min)(); }
3585    static constexpr bool is_iec559                = false;
3586    static constexpr bool is_bounded               = true;
3587    static constexpr bool is_modulo                = false;
3588    static constexpr bool traps                    = false;
3589    static constexpr bool tinyness_before          = false;
3590    static constexpr float_round_style round_style = round_toward_zero;
3591 };
3592 
3593 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3594 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits;
3595 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3596 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits10;
3597 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3598 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_digits10;
3599 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3600 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_signed;
3601 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3602 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_integer;
3603 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3604 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_exact;
3605 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3606 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::radix;
3607 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3608 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent;
3609 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3610 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent10;
3611 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3612 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent;
3613 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3614 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent10;
3615 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3616 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_infinity;
3617 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3618 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
3619 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3620 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
3621 #ifdef _MSC_VER
3622 #pragma warning(push)
3623 #pragma warning(disable : 4996)
3624 #endif
3625 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3626 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm;
3627 #ifdef _MSC_VER
3628 #pragma warning(pop)
3629 #endif
3630 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3631 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
3632 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3633 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_iec559;
3634 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3635 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_bounded;
3636 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3637 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_modulo;
3638 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3639 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::traps;
3640 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3641 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::tinyness_before;
3642 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3643 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::round_style;
3644 
3645 } // namespace std
3646 #endif