• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright 2011 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_MATH_BN_MPFR_HPP
7 #define BOOST_MATH_BN_MPFR_HPP
8 
9 #include <boost/multiprecision/number.hpp>
10 #include <boost/multiprecision/debug_adaptor.hpp>
11 #include <boost/multiprecision/gmp.hpp>
12 #include <boost/math/special_functions/fpclassify.hpp>
13 #include <boost/cstdint.hpp>
14 #include <boost/multiprecision/detail/big_lanczos.hpp>
15 #include <boost/multiprecision/detail/digits.hpp>
16 #include <boost/multiprecision/detail/atomic.hpp>
17 #include <mpfr.h>
18 #include <cmath>
19 #include <algorithm>
20 
21 #ifndef BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION
22 #define BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION 20
23 #endif
24 
25 namespace boost {
26 namespace multiprecision {
27 
28 enum mpfr_allocation_type
29 {
30    allocate_stack,
31    allocate_dynamic
32 };
33 
34 namespace backends {
35 
36 template <unsigned digits10, mpfr_allocation_type AllocationType = allocate_dynamic>
37 struct mpfr_float_backend;
38 
39 template <>
40 struct mpfr_float_backend<0, allocate_stack>;
41 
42 } // namespace backends
43 
44 template <unsigned digits10, mpfr_allocation_type AllocationType>
45 struct number_category<backends::mpfr_float_backend<digits10, AllocationType> > : public mpl::int_<number_kind_floating_point>
46 {};
47 
48 namespace backends {
49 
50 namespace detail {
51 
52 template <bool b>
53 struct mpfr_cleanup
54 {
55    struct initializer
56    {
initializerboost::multiprecision::backends::detail::mpfr_cleanup::initializer57       initializer() {}
~initializerboost::multiprecision::backends::detail::mpfr_cleanup::initializer58       ~initializer() { mpfr_free_cache(); }
force_instantiateboost::multiprecision::backends::detail::mpfr_cleanup::initializer59       void force_instantiate() const {}
60    };
61    static const initializer init;
force_instantiateboost::multiprecision::backends::detail::mpfr_cleanup62    static void              force_instantiate() { init.force_instantiate(); }
63 };
64 
65 template <bool b>
66 typename mpfr_cleanup<b>::initializer const mpfr_cleanup<b>::init;
67 
mpfr_copy_precision(mpfr_t dest,const mpfr_t src)68 inline void mpfr_copy_precision(mpfr_t dest, const mpfr_t src)
69 {
70    mpfr_prec_t p_dest = mpfr_get_prec(dest);
71    mpfr_prec_t p_src  = mpfr_get_prec(src);
72    if (p_dest != p_src)
73       mpfr_set_prec(dest, p_src);
74 }
mpfr_copy_precision(mpfr_t dest,const mpfr_t src1,const mpfr_t src2)75 inline void mpfr_copy_precision(mpfr_t dest, const mpfr_t src1, const mpfr_t src2)
76 {
77    mpfr_prec_t p_dest = mpfr_get_prec(dest);
78    mpfr_prec_t p_src1 = mpfr_get_prec(src1);
79    mpfr_prec_t p_src2 = mpfr_get_prec(src2);
80    if (p_src2 > p_src1)
81       p_src1 = p_src2;
82    if (p_dest != p_src1)
83       mpfr_set_prec(dest, p_src1);
84 }
85 
86 template <unsigned digits10, mpfr_allocation_type AllocationType>
87 struct mpfr_float_imp;
88 
89 template <unsigned digits10>
90 struct mpfr_float_imp<digits10, allocate_dynamic>
91 {
92 #ifdef BOOST_HAS_LONG_LONG
93    typedef mpl::list<long, boost::long_long_type>           signed_types;
94    typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
95 #else
96    typedef mpl::list<long>          signed_types;
97    typedef mpl::list<unsigned long> unsigned_types;
98 #endif
99    typedef mpl::list<double, long double> float_types;
100    typedef long                           exponent_type;
101 
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp102    mpfr_float_imp()
103    {
104       mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
105       mpfr_set_ui(m_data, 0u, GMP_RNDN);
106    }
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp107    mpfr_float_imp(unsigned digits2)
108    {
109       mpfr_init2(m_data, digits2);
110       mpfr_set_ui(m_data, 0u, GMP_RNDN);
111    }
112 
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp113    mpfr_float_imp(const mpfr_float_imp& o)
114    {
115       mpfr_init2(m_data, mpfr_get_prec(o.m_data));
116       if (o.m_data[0]._mpfr_d)
117          mpfr_set(m_data, o.m_data, GMP_RNDN);
118    }
119 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp120    mpfr_float_imp(mpfr_float_imp&& o) BOOST_NOEXCEPT
121    {
122       m_data[0]           = o.m_data[0];
123       o.m_data[0]._mpfr_d = 0;
124    }
125 #endif
operator =boost::multiprecision::backends::detail::mpfr_float_imp126    mpfr_float_imp& operator=(const mpfr_float_imp& o)
127    {
128       if ((o.m_data[0]._mpfr_d) && (this != &o))
129       {
130          if (m_data[0]._mpfr_d == 0)
131             mpfr_init2(m_data, mpfr_get_prec(o.m_data));
132          mpfr_set(m_data, o.m_data, GMP_RNDN);
133       }
134       return *this;
135    }
136 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::detail::mpfr_float_imp137    mpfr_float_imp& operator=(mpfr_float_imp&& o) BOOST_NOEXCEPT
138    {
139       mpfr_swap(m_data, o.m_data);
140       return *this;
141    }
142 #endif
143 #ifdef BOOST_HAS_LONG_LONG
144 #ifdef _MPFR_H_HAVE_INTMAX_T
operator =boost::multiprecision::backends::detail::mpfr_float_imp145    mpfr_float_imp& operator=(boost::ulong_long_type i)
146    {
147       if (m_data[0]._mpfr_d == 0)
148          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
149       mpfr_set_uj(m_data, i, GMP_RNDN);
150       return *this;
151    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp152    mpfr_float_imp& operator=(boost::long_long_type i)
153    {
154       if (m_data[0]._mpfr_d == 0)
155          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
156       mpfr_set_sj(m_data, i, GMP_RNDN);
157       return *this;
158    }
159 #else
operator =boost::multiprecision::backends::detail::mpfr_float_imp160    mpfr_float_imp& operator=(boost::ulong_long_type i)
161    {
162       if (m_data[0]._mpfr_d == 0)
163          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
164       boost::ulong_long_type mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
165       unsigned               shift = 0;
166       mpfr_t                 t;
167       mpfr_init2(t, (std::max)(static_cast<unsigned long>(std::numeric_limits<boost::ulong_long_type>::digits), mpfr_get_prec(m_data)));
168       mpfr_set_ui(m_data, 0, GMP_RNDN);
169       while (i)
170       {
171          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
172          if (shift)
173             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
174          mpfr_add(m_data, m_data, t, GMP_RNDN);
175          shift += std::numeric_limits<unsigned long>::digits;
176          i >>= std::numeric_limits<unsigned long>::digits;
177       }
178       mpfr_clear(t);
179       return *this;
180    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp181    mpfr_float_imp& operator=(boost::long_long_type i)
182    {
183       if (m_data[0]._mpfr_d == 0)
184          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
185       bool neg = i < 0;
186       *this    = boost::multiprecision::detail::unsigned_abs(i);
187       if (neg)
188          mpfr_neg(m_data, m_data, GMP_RNDN);
189       return *this;
190    }
191 #endif
192 #endif
operator =boost::multiprecision::backends::detail::mpfr_float_imp193    mpfr_float_imp& operator=(unsigned long i)
194    {
195       if (m_data[0]._mpfr_d == 0)
196          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
197       mpfr_set_ui(m_data, i, GMP_RNDN);
198       return *this;
199    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp200    mpfr_float_imp& operator=(long i)
201    {
202       if (m_data[0]._mpfr_d == 0)
203          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
204       mpfr_set_si(m_data, i, GMP_RNDN);
205       return *this;
206    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp207    mpfr_float_imp& operator=(double d)
208    {
209       if (m_data[0]._mpfr_d == 0)
210          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
211       mpfr_set_d(m_data, d, GMP_RNDN);
212       return *this;
213    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp214    mpfr_float_imp& operator=(long double a)
215    {
216       if (m_data[0]._mpfr_d == 0)
217          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
218       mpfr_set_ld(m_data, a, GMP_RNDN);
219       return *this;
220    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp221    mpfr_float_imp& operator=(const char* s)
222    {
223       if (m_data[0]._mpfr_d == 0)
224          mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
225       if (mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
226       {
227          BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
228       }
229       return *this;
230    }
swapboost::multiprecision::backends::detail::mpfr_float_imp231    void swap(mpfr_float_imp& o) BOOST_NOEXCEPT
232    {
233       mpfr_swap(m_data, o.m_data);
234    }
strboost::multiprecision::backends::detail::mpfr_float_imp235    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
236    {
237       BOOST_ASSERT(m_data[0]._mpfr_d);
238 
239       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
240       bool fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
241 
242       std::streamsize org_digits(digits);
243 
244       if (scientific && digits)
245          ++digits;
246 
247       std::string result;
248       mp_exp_t    e;
249       if (mpfr_inf_p(m_data))
250       {
251          if (mpfr_sgn(m_data) < 0)
252             result = "-inf";
253          else if (f & std::ios_base::showpos)
254             result = "+inf";
255          else
256             result = "inf";
257          return result;
258       }
259       if (mpfr_nan_p(m_data))
260       {
261          result = "nan";
262          return result;
263       }
264       if (mpfr_zero_p(m_data))
265       {
266          e      = 0;
267          result = "0";
268       }
269       else
270       {
271          char* ps = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
272          --e; // To match with what our formatter expects.
273          if (fixed && e != -1)
274          {
275             // Oops we actually need a different number of digits to what we asked for:
276             mpfr_free_str(ps);
277             digits += e + 1;
278             if (digits == 0)
279             {
280                // We need to get *all* the digits and then possibly round up,
281                // we end up with either "0" or "1" as the result.
282                ps = mpfr_get_str(0, &e, 10, 0, m_data, GMP_RNDN);
283                --e;
284                unsigned offset = *ps == '-' ? 1 : 0;
285                if (ps[offset] > '5')
286                {
287                   ++e;
288                   ps[offset]     = '1';
289                   ps[offset + 1] = 0;
290                }
291                else if (ps[offset] == '5')
292                {
293                   unsigned i        = offset + 1;
294                   bool     round_up = false;
295                   while (ps[i] != 0)
296                   {
297                      if (ps[i] != '0')
298                      {
299                         round_up = true;
300                         break;
301                      }
302                      ++i;
303                   }
304                   if (round_up)
305                   {
306                      ++e;
307                      ps[offset]     = '1';
308                      ps[offset + 1] = 0;
309                   }
310                   else
311                   {
312                      ps[offset]     = '0';
313                      ps[offset + 1] = 0;
314                   }
315                }
316                else
317                {
318                   ps[offset]     = '0';
319                   ps[offset + 1] = 0;
320                }
321             }
322             else if (digits > 0)
323             {
324                mp_exp_t old_e = e;
325                ps             = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
326                --e; // To match with what our formatter expects.
327                if (old_e > e)
328                {
329                   // in some cases, when we ask for more digits of precision, it will
330                   // change the number of digits to the left of the decimal, if that
331                   // happens, account for it here.
332                   // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
333                   digits -= old_e - e;
334                   ps = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
335                   --e; // To match with what our formatter expects.
336                }
337             }
338             else
339             {
340                ps = mpfr_get_str(0, &e, 10, 1, m_data, GMP_RNDN);
341                --e;
342                unsigned offset = *ps == '-' ? 1 : 0;
343                ps[offset]      = '0';
344                ps[offset + 1]  = 0;
345             }
346          }
347          result = ps ? ps : "0";
348          if (ps)
349             mpfr_free_str(ps);
350       }
351       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
352       return result;
353    }
~mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp354    ~mpfr_float_imp() BOOST_NOEXCEPT
355    {
356       if (m_data[0]._mpfr_d)
357          mpfr_clear(m_data);
358       detail::mpfr_cleanup<true>::force_instantiate();
359    }
negateboost::multiprecision::backends::detail::mpfr_float_imp360    void negate() BOOST_NOEXCEPT
361    {
362       BOOST_ASSERT(m_data[0]._mpfr_d);
363       mpfr_neg(m_data, m_data, GMP_RNDN);
364    }
365    template <mpfr_allocation_type AllocationType>
compareboost::multiprecision::backends::detail::mpfr_float_imp366    int compare(const mpfr_float_backend<digits10, AllocationType>& o) const BOOST_NOEXCEPT
367    {
368       BOOST_ASSERT(m_data[0]._mpfr_d && o.m_data[0]._mpfr_d);
369       return mpfr_cmp(m_data, o.m_data);
370    }
compareboost::multiprecision::backends::detail::mpfr_float_imp371    int compare(long i) const BOOST_NOEXCEPT
372    {
373       BOOST_ASSERT(m_data[0]._mpfr_d);
374       return mpfr_cmp_si(m_data, i);
375    }
compareboost::multiprecision::backends::detail::mpfr_float_imp376    int compare(unsigned long i) const BOOST_NOEXCEPT
377    {
378       BOOST_ASSERT(m_data[0]._mpfr_d);
379       return mpfr_cmp_ui(m_data, i);
380    }
381    template <class V>
compareboost::multiprecision::backends::detail::mpfr_float_imp382    int compare(V v) const BOOST_NOEXCEPT
383    {
384       mpfr_float_backend<digits10, allocate_dynamic> d(0uL, mpfr_get_prec(m_data));
385       d = v;
386       return compare(d);
387    }
databoost::multiprecision::backends::detail::mpfr_float_imp388    mpfr_t& data() BOOST_NOEXCEPT
389    {
390       BOOST_ASSERT(m_data[0]._mpfr_d);
391       return m_data;
392    }
databoost::multiprecision::backends::detail::mpfr_float_imp393    const mpfr_t& data() const BOOST_NOEXCEPT
394    {
395       BOOST_ASSERT(m_data[0]._mpfr_d);
396       return m_data;
397    }
398 
399  protected:
400    mpfr_t           m_data;
get_default_precisionboost::multiprecision::backends::detail::mpfr_float_imp401    static boost::multiprecision::detail::precision_type& get_default_precision() BOOST_NOEXCEPT
402    {
403       static boost::multiprecision::detail::precision_type val(BOOST_MULTIPRECISION_MPFR_DEFAULT_PRECISION);
404       return val;
405    }
406 };
407 
408 #ifdef BOOST_MSVC
409 #pragma warning(push)
410 #pragma warning(disable : 4127) // Conditional expression is constant
411 #endif
412 
413 template <unsigned digits10>
414 struct mpfr_float_imp<digits10, allocate_stack>
415 {
416 #ifdef BOOST_HAS_LONG_LONG
417    typedef mpl::list<long, boost::long_long_type>           signed_types;
418    typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
419 #else
420    typedef mpl::list<long>          signed_types;
421    typedef mpl::list<unsigned long> unsigned_types;
422 #endif
423    typedef mpl::list<double, long double> float_types;
424    typedef long                           exponent_type;
425 
426    static const unsigned digits2    = (digits10 * 1000uL) / 301uL + ((digits10 * 1000uL) % 301 ? 2u : 1u);
427    static const unsigned limb_count = mpfr_custom_get_size(digits2) / sizeof(mp_limb_t);
428 
~mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp429    ~mpfr_float_imp() BOOST_NOEXCEPT
430    {
431       detail::mpfr_cleanup<true>::force_instantiate();
432    }
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp433    mpfr_float_imp()
434    {
435       mpfr_custom_init(m_buffer, digits2);
436       mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
437       mpfr_set_ui(m_data, 0u, GMP_RNDN);
438    }
439 
mpfr_float_impboost::multiprecision::backends::detail::mpfr_float_imp440    mpfr_float_imp(const mpfr_float_imp& o)
441    {
442       mpfr_custom_init(m_buffer, digits2);
443       mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
444       mpfr_set(m_data, o.m_data, GMP_RNDN);
445    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp446    mpfr_float_imp& operator=(const mpfr_float_imp& o)
447    {
448       mpfr_set(m_data, o.m_data, GMP_RNDN);
449       return *this;
450    }
451 #ifdef BOOST_HAS_LONG_LONG
452 #ifdef _MPFR_H_HAVE_INTMAX_T
operator =boost::multiprecision::backends::detail::mpfr_float_imp453    mpfr_float_imp& operator=(boost::ulong_long_type i)
454    {
455       mpfr_set_uj(m_data, i, GMP_RNDN);
456       return *this;
457    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp458    mpfr_float_imp& operator=(boost::long_long_type i)
459    {
460       mpfr_set_sj(m_data, i, GMP_RNDN);
461       return *this;
462    }
463 #else
operator =boost::multiprecision::backends::detail::mpfr_float_imp464    mpfr_float_imp& operator=(boost::ulong_long_type i)
465    {
466       boost::ulong_long_type mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uL);
467       unsigned               shift = 0;
468       mpfr_t                 t;
469       mp_limb_t              t_limbs[limb_count];
470       mpfr_custom_init(t_limbs, digits2);
471       mpfr_custom_init_set(t, MPFR_NAN_KIND, 0, digits2, t_limbs);
472       mpfr_set_ui(m_data, 0, GMP_RNDN);
473       while (i)
474       {
475          mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
476          if (shift)
477             mpfr_mul_2exp(t, t, shift, GMP_RNDN);
478          mpfr_add(m_data, m_data, t, GMP_RNDN);
479          shift += std::numeric_limits<unsigned long>::digits;
480          i >>= std::numeric_limits<unsigned long>::digits;
481       }
482       return *this;
483    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp484    mpfr_float_imp& operator=(boost::long_long_type i)
485    {
486       bool neg = i < 0;
487       *this    = boost::multiprecision::detail::unsigned_abs(i);
488       if (neg)
489          mpfr_neg(m_data, m_data, GMP_RNDN);
490       return *this;
491    }
492 #endif
493 #endif
operator =boost::multiprecision::backends::detail::mpfr_float_imp494    mpfr_float_imp& operator=(unsigned long i)
495    {
496       mpfr_set_ui(m_data, i, GMP_RNDN);
497       return *this;
498    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp499    mpfr_float_imp& operator=(long i)
500    {
501       mpfr_set_si(m_data, i, GMP_RNDN);
502       return *this;
503    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp504    mpfr_float_imp& operator=(double d)
505    {
506       mpfr_set_d(m_data, d, GMP_RNDN);
507       return *this;
508    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp509    mpfr_float_imp& operator=(long double a)
510    {
511       mpfr_set_ld(m_data, a, GMP_RNDN);
512       return *this;
513    }
operator =boost::multiprecision::backends::detail::mpfr_float_imp514    mpfr_float_imp& operator=(const char* s)
515    {
516       if (mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
517       {
518          BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
519       }
520       return *this;
521    }
swapboost::multiprecision::backends::detail::mpfr_float_imp522    void swap(mpfr_float_imp& o) BOOST_NOEXCEPT
523    {
524       // We have to swap by copying:
525       mpfr_float_imp t(*this);
526       *this = o;
527       o     = t;
528    }
strboost::multiprecision::backends::detail::mpfr_float_imp529    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
530    {
531       BOOST_ASSERT(m_data[0]._mpfr_d);
532 
533       bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
534       bool fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
535 
536       std::streamsize org_digits(digits);
537 
538       if (scientific && digits)
539          ++digits;
540 
541       std::string result;
542       mp_exp_t    e;
543       if (mpfr_inf_p(m_data))
544       {
545          if (mpfr_sgn(m_data) < 0)
546             result = "-inf";
547          else if (f & std::ios_base::showpos)
548             result = "+inf";
549          else
550             result = "inf";
551          return result;
552       }
553       if (mpfr_nan_p(m_data))
554       {
555          result = "nan";
556          return result;
557       }
558       if (mpfr_zero_p(m_data))
559       {
560          e      = 0;
561          result = "0";
562       }
563       else
564       {
565          char* ps = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
566          --e; // To match with what our formatter expects.
567          if (fixed && e != -1)
568          {
569             // Oops we actually need a different number of digits to what we asked for:
570             mpfr_free_str(ps);
571             digits += e + 1;
572             if (digits == 0)
573             {
574                // We need to get *all* the digits and then possibly round up,
575                // we end up with either "0" or "1" as the result.
576                ps = mpfr_get_str(0, &e, 10, 0, m_data, GMP_RNDN);
577                --e;
578                unsigned offset = *ps == '-' ? 1 : 0;
579                if (ps[offset] > '5')
580                {
581                   ++e;
582                   ps[offset]     = '1';
583                   ps[offset + 1] = 0;
584                }
585                else if (ps[offset] == '5')
586                {
587                   unsigned i        = offset + 1;
588                   bool     round_up = false;
589                   while (ps[i] != 0)
590                   {
591                      if (ps[i] != '0')
592                      {
593                         round_up = true;
594                         break;
595                      }
596                   }
597                   if (round_up)
598                   {
599                      ++e;
600                      ps[offset]     = '1';
601                      ps[offset + 1] = 0;
602                   }
603                   else
604                   {
605                      ps[offset]     = '0';
606                      ps[offset + 1] = 0;
607                   }
608                }
609                else
610                {
611                   ps[offset]     = '0';
612                   ps[offset + 1] = 0;
613                }
614             }
615             else if (digits > 0)
616             {
617                ps = mpfr_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
618                --e; // To match with what our formatter expects.
619             }
620             else
621             {
622                ps = mpfr_get_str(0, &e, 10, 1, m_data, GMP_RNDN);
623                --e;
624                unsigned offset = *ps == '-' ? 1 : 0;
625                ps[offset]      = '0';
626                ps[offset + 1]  = 0;
627             }
628          }
629          result = ps ? ps : "0";
630          if (ps)
631             mpfr_free_str(ps);
632       }
633       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
634       return result;
635    }
negateboost::multiprecision::backends::detail::mpfr_float_imp636    void negate() BOOST_NOEXCEPT
637    {
638       mpfr_neg(m_data, m_data, GMP_RNDN);
639    }
640    template <mpfr_allocation_type AllocationType>
compareboost::multiprecision::backends::detail::mpfr_float_imp641    int compare(const mpfr_float_backend<digits10, AllocationType>& o) const BOOST_NOEXCEPT
642    {
643       return mpfr_cmp(m_data, o.m_data);
644    }
compareboost::multiprecision::backends::detail::mpfr_float_imp645    int compare(long i) const BOOST_NOEXCEPT
646    {
647       return mpfr_cmp_si(m_data, i);
648    }
compareboost::multiprecision::backends::detail::mpfr_float_imp649    int compare(unsigned long i) const BOOST_NOEXCEPT
650    {
651       return mpfr_cmp_ui(m_data, i);
652    }
653    template <class V>
compareboost::multiprecision::backends::detail::mpfr_float_imp654    int compare(V v) const BOOST_NOEXCEPT
655    {
656       mpfr_float_backend<digits10, allocate_stack> d;
657       d = v;
658       return compare(d);
659    }
databoost::multiprecision::backends::detail::mpfr_float_imp660    mpfr_t& data() BOOST_NOEXCEPT
661    {
662       return m_data;
663    }
databoost::multiprecision::backends::detail::mpfr_float_imp664    const mpfr_t& data() const BOOST_NOEXCEPT
665    {
666       return m_data;
667    }
668 
669  protected:
670    mpfr_t    m_data;
671    mp_limb_t m_buffer[limb_count];
672 };
673 
674 #ifdef BOOST_MSVC
675 #pragma warning(pop)
676 #endif
677 
678 } // namespace detail
679 
680 template <unsigned digits10, mpfr_allocation_type AllocationType>
681 struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationType>
682 {
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend683    mpfr_float_backend() : detail::mpfr_float_imp<digits10, AllocationType>() {}
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend684    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<digits10, AllocationType>(o) {}
685 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend686    mpfr_float_backend(mpfr_float_backend&& o) BOOST_NOEXCEPT : detail::mpfr_float_imp<digits10, AllocationType>(static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o))
687    {}
688 #endif
689    template <unsigned D, mpfr_allocation_type AT>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend690    mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename enable_if_c<D <= digits10>::type* = 0)
691        : detail::mpfr_float_imp<digits10, AllocationType>()
692    {
693       mpfr_set(this->m_data, val.data(), GMP_RNDN);
694    }
695    template <unsigned D, mpfr_allocation_type AT>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend696    explicit mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename disable_if_c<D <= digits10>::type* = 0)
697        : detail::mpfr_float_imp<digits10, AllocationType>()
698    {
699       mpfr_set(this->m_data, val.data(), GMP_RNDN);
700    }
701    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend702    mpfr_float_backend(const gmp_float<D>& val, typename enable_if_c<D <= digits10>::type* = 0)
703        : detail::mpfr_float_imp<digits10, AllocationType>()
704    {
705       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
706    }
707    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend708    mpfr_float_backend(const gmp_float<D>& val, typename disable_if_c<D <= digits10>::type* = 0)
709        : detail::mpfr_float_imp<digits10, AllocationType>()
710    {
711       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
712    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend713    mpfr_float_backend(const gmp_int& val)
714        : detail::mpfr_float_imp<digits10, AllocationType>()
715    {
716       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
717    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend718    mpfr_float_backend(const gmp_rational& val)
719        : detail::mpfr_float_imp<digits10, AllocationType>()
720    {
721       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
722    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend723    mpfr_float_backend(const mpfr_t val)
724        : detail::mpfr_float_imp<digits10, AllocationType>()
725    {
726       mpfr_set(this->m_data, val, GMP_RNDN);
727    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend728    mpfr_float_backend(const mpf_t val)
729        : detail::mpfr_float_imp<digits10, AllocationType>()
730    {
731       mpfr_set_f(this->m_data, val, GMP_RNDN);
732    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend733    mpfr_float_backend(const mpz_t val)
734        : detail::mpfr_float_imp<digits10, AllocationType>()
735    {
736       mpfr_set_z(this->m_data, val, GMP_RNDN);
737    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend738    mpfr_float_backend(const mpq_t val)
739        : detail::mpfr_float_imp<digits10, AllocationType>()
740    {
741       mpfr_set_q(this->m_data, val, GMP_RNDN);
742    }
743    // Construction with precision: we ignore the precision here.
744    template <class V>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend745    mpfr_float_backend(const V& o, unsigned)
746    {
747       *this = o;
748    }
operator =boost::multiprecision::backends::mpfr_float_backend749    mpfr_float_backend& operator=(const mpfr_float_backend& o)
750    {
751       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType> const&>(o);
752       return *this;
753    }
754 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::mpfr_float_backend755    mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT
756    {
757       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o);
758       return *this;
759    }
760 #endif
761    template <class V>
operator =boost::multiprecision::backends::mpfr_float_backend762    mpfr_float_backend& operator=(const V& v)
763    {
764       *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = v;
765       return *this;
766    }
operator =boost::multiprecision::backends::mpfr_float_backend767    mpfr_float_backend& operator=(const mpfr_t val)
768    {
769       if (this->m_data[0]._mpfr_d == 0)
770          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
771       mpfr_set(this->m_data, val, GMP_RNDN);
772       return *this;
773    }
operator =boost::multiprecision::backends::mpfr_float_backend774    mpfr_float_backend& operator=(const mpf_t val)
775    {
776       if (this->m_data[0]._mpfr_d == 0)
777          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
778       mpfr_set_f(this->m_data, val, GMP_RNDN);
779       return *this;
780    }
operator =boost::multiprecision::backends::mpfr_float_backend781    mpfr_float_backend& operator=(const mpz_t val)
782    {
783       if (this->m_data[0]._mpfr_d == 0)
784          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
785       mpfr_set_z(this->m_data, val, GMP_RNDN);
786       return *this;
787    }
operator =boost::multiprecision::backends::mpfr_float_backend788    mpfr_float_backend& operator=(const mpq_t val)
789    {
790       if (this->m_data[0]._mpfr_d == 0)
791          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
792       mpfr_set_q(this->m_data, val, GMP_RNDN);
793       return *this;
794    }
795    // We don't change our precision here, this is a fixed precision type:
796    template <unsigned D, mpfr_allocation_type AT>
operator =boost::multiprecision::backends::mpfr_float_backend797    mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
798    {
799       if (this->m_data[0]._mpfr_d == 0)
800          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
801       mpfr_set(this->m_data, val.data(), GMP_RNDN);
802       return *this;
803    }
804    template <unsigned D>
operator =boost::multiprecision::backends::mpfr_float_backend805    mpfr_float_backend& operator=(const gmp_float<D>& val)
806    {
807       if (this->m_data[0]._mpfr_d == 0)
808          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
809       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
810       return *this;
811    }
operator =boost::multiprecision::backends::mpfr_float_backend812    mpfr_float_backend& operator=(const gmp_int& val)
813    {
814       if (this->m_data[0]._mpfr_d == 0)
815          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
816       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
817       return *this;
818    }
operator =boost::multiprecision::backends::mpfr_float_backend819    mpfr_float_backend& operator=(const gmp_rational& val)
820    {
821       if (this->m_data[0]._mpfr_d == 0)
822          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
823       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
824       return *this;
825    }
826 };
827 
828 template <>
829 struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0, allocate_dynamic>
830 {
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend831    mpfr_float_backend() : detail::mpfr_float_imp<0, allocate_dynamic>() {}
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend832    mpfr_float_backend(const mpfr_t val)
833        : detail::mpfr_float_imp<0, allocate_dynamic>((unsigned)mpfr_get_prec(val))
834    {
835       mpfr_set(this->m_data, val, GMP_RNDN);
836    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend837    mpfr_float_backend(const mpf_t val)
838        : detail::mpfr_float_imp<0, allocate_dynamic>((unsigned)mpf_get_prec(val))
839    {
840       mpfr_set_f(this->m_data, val, GMP_RNDN);
841    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend842    mpfr_float_backend(const mpz_t val)
843        : detail::mpfr_float_imp<0, allocate_dynamic>()
844    {
845       mpfr_set_z(this->m_data, val, GMP_RNDN);
846    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend847    mpfr_float_backend(const mpq_t val)
848        : detail::mpfr_float_imp<0, allocate_dynamic>()
849    {
850       mpfr_set_q(this->m_data, val, GMP_RNDN);
851    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend852    mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<0, allocate_dynamic>(o) {}
853 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend854    mpfr_float_backend(mpfr_float_backend&& o) BOOST_NOEXCEPT : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<detail::mpfr_float_imp<0, allocate_dynamic>&&>(o))
855    {}
856 #endif
857    template <class V>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend858    mpfr_float_backend(const V& o, unsigned digits10)
859        : detail::mpfr_float_imp<0, allocate_dynamic>(multiprecision::detail::digits10_2_2(digits10))
860    {
861       *this = o;
862    }
863 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend864    mpfr_float_backend(const std::string_view& o, unsigned digits10)
865        : detail::mpfr_float_imp<0, allocate_dynamic>(multiprecision::detail::digits10_2_2(digits10))
866    {
867       std::string s(o);
868       *this = s.c_str();
869    }
870 #endif
871    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend872    mpfr_float_backend(const gmp_float<D>& val, unsigned digits10)
873        : detail::mpfr_float_imp<0, allocate_dynamic>(multiprecision::detail::digits10_2_2(digits10))
874    {
875       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
876    }
877    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend878    mpfr_float_backend(const mpfr_float_backend<D>& val, unsigned digits10)
879        : detail::mpfr_float_imp<0, allocate_dynamic>(multiprecision::detail::digits10_2_2(digits10))
880    {
881       mpfr_set(this->m_data, val.data(), GMP_RNDN);
882    }
883    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend884    mpfr_float_backend(const mpfr_float_backend<D>& val)
885        : detail::mpfr_float_imp<0, allocate_dynamic>(mpfr_get_prec(val.data()))
886    {
887       mpfr_set(this->m_data, val.data(), GMP_RNDN);
888    }
889    template <unsigned D>
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend890    mpfr_float_backend(const gmp_float<D>& val)
891        : detail::mpfr_float_imp<0, allocate_dynamic>(mpf_get_prec(val.data()))
892    {
893       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
894    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend895    mpfr_float_backend(const gmp_int& val)
896        : detail::mpfr_float_imp<0, allocate_dynamic>()
897    {
898       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
899    }
mpfr_float_backendboost::multiprecision::backends::mpfr_float_backend900    mpfr_float_backend(const gmp_rational& val)
901        : detail::mpfr_float_imp<0, allocate_dynamic>()
902    {
903       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
904    }
905 
operator =boost::multiprecision::backends::mpfr_float_backend906    mpfr_float_backend& operator=(const mpfr_float_backend& o)
907    {
908       if (this != &o)
909       {
910          if (this->m_data[0]._mpfr_d == 0)
911             mpfr_init2(this->m_data, mpfr_get_prec(o.data()));
912          else
913             detail::mpfr_copy_precision(this->m_data, o.data());
914          mpfr_set(this->m_data, o.data(), GMP_RNDN);
915       }
916       return *this;
917    }
918 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::mpfr_float_backend919    mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT
920    {
921       *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = static_cast<detail::mpfr_float_imp<0, allocate_dynamic>&&>(o);
922       return *this;
923    }
924 #endif
925    template <class V>
operator =boost::multiprecision::backends::mpfr_float_backend926    mpfr_float_backend& operator=(const V& v)
927    {
928       *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = v;
929       return *this;
930    }
operator =boost::multiprecision::backends::mpfr_float_backend931    mpfr_float_backend& operator=(const mpfr_t val)
932    {
933       if (this->m_data[0]._mpfr_d == 0)
934          mpfr_init2(this->m_data, mpfr_get_prec(val));
935       else
936          mpfr_set_prec(this->m_data, mpfr_get_prec(val));
937       mpfr_set(this->m_data, val, GMP_RNDN);
938       return *this;
939    }
operator =boost::multiprecision::backends::mpfr_float_backend940    mpfr_float_backend& operator=(const mpf_t val)
941    {
942       if (this->m_data[0]._mpfr_d == 0)
943          mpfr_init2(this->m_data, (mpfr_prec_t)mpf_get_prec(val));
944       else
945          mpfr_set_prec(this->m_data, (unsigned)mpf_get_prec(val));
946       mpfr_set_f(this->m_data, val, GMP_RNDN);
947       return *this;
948    }
operator =boost::multiprecision::backends::mpfr_float_backend949    mpfr_float_backend& operator=(const mpz_t val)
950    {
951       if (this->m_data[0]._mpfr_d == 0)
952          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
953       mpfr_set_z(this->m_data, val, GMP_RNDN);
954       return *this;
955    }
operator =boost::multiprecision::backends::mpfr_float_backend956    mpfr_float_backend& operator=(const mpq_t val)
957    {
958       if (this->m_data[0]._mpfr_d == 0)
959          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
960       mpfr_set_q(this->m_data, val, GMP_RNDN);
961       return *this;
962    }
963    template <unsigned D>
operator =boost::multiprecision::backends::mpfr_float_backend964    mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
965    {
966       if (this->m_data[0]._mpfr_d == 0)
967          mpfr_init2(this->m_data, mpfr_get_prec(val.data()));
968       else
969          mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
970       mpfr_set(this->m_data, val.data(), GMP_RNDN);
971       return *this;
972    }
973    template <unsigned D>
operator =boost::multiprecision::backends::mpfr_float_backend974    mpfr_float_backend& operator=(const gmp_float<D>& val)
975    {
976       if (this->m_data[0]._mpfr_d == 0)
977          mpfr_init2(this->m_data, mpf_get_prec(val.data()));
978       else
979          mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
980       mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
981       return *this;
982    }
operator =boost::multiprecision::backends::mpfr_float_backend983    mpfr_float_backend& operator=(const gmp_int& val)
984    {
985       if (this->m_data[0]._mpfr_d == 0)
986          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
987       mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
988       return *this;
989    }
operator =boost::multiprecision::backends::mpfr_float_backend990    mpfr_float_backend& operator=(const gmp_rational& val)
991    {
992       if (this->m_data[0]._mpfr_d == 0)
993          mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
994       mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
995       return *this;
996    }
default_precisionboost::multiprecision::backends::mpfr_float_backend997    static unsigned default_precision() BOOST_NOEXCEPT
998    {
999       return get_default_precision();
1000    }
default_precisionboost::multiprecision::backends::mpfr_float_backend1001    static void default_precision(unsigned v) BOOST_NOEXCEPT
1002    {
1003       get_default_precision() = v;
1004    }
precisionboost::multiprecision::backends::mpfr_float_backend1005    unsigned precision() const BOOST_NOEXCEPT
1006    {
1007       return multiprecision::detail::digits2_2_10(mpfr_get_prec(this->m_data));
1008    }
precisionboost::multiprecision::backends::mpfr_float_backend1009    void precision(unsigned digits10) BOOST_NOEXCEPT
1010    {
1011       mpfr_prec_round(this->m_data, multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN);
1012    }
1013 };
1014 
1015 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
eval_eq(const mpfr_float_backend<digits10,AllocationType> & a,const T & b)1016 inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
1017 {
1018    return a.compare(b) == 0;
1019 }
1020 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
eval_lt(const mpfr_float_backend<digits10,AllocationType> & a,const T & b)1021 inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
1022 {
1023    return a.compare(b) < 0;
1024 }
1025 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
eval_gt(const mpfr_float_backend<digits10,AllocationType> & a,const T & b)1026 inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
1027 {
1028    return a.compare(b) > 0;
1029 }
1030 
1031 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_add(mpfr_float_backend<D1,A1> & result,const mpfr_float_backend<D2,A2> & o)1032 inline void eval_add(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1033 {
1034    mpfr_add(result.data(), result.data(), o.data(), GMP_RNDN);
1035 }
1036 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_subtract(mpfr_float_backend<D1,A1> & result,const mpfr_float_backend<D2,A2> & o)1037 inline void eval_subtract(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1038 {
1039    mpfr_sub(result.data(), result.data(), o.data(), GMP_RNDN);
1040 }
1041 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_multiply(mpfr_float_backend<D1,A1> & result,const mpfr_float_backend<D2,A2> & o)1042 inline void eval_multiply(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1043 {
1044    if ((void*)&o == (void*)&result)
1045       mpfr_sqr(result.data(), o.data(), GMP_RNDN);
1046    else
1047       mpfr_mul(result.data(), result.data(), o.data(), GMP_RNDN);
1048 }
1049 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_divide(mpfr_float_backend<D1,A1> & result,const mpfr_float_backend<D2,A2> & o)1050 inline void eval_divide(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
1051 {
1052    mpfr_div(result.data(), result.data(), o.data(), GMP_RNDN);
1053 }
1054 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_add(mpfr_float_backend<digits10,AllocationType> & result,unsigned long i)1055 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1056 {
1057    mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1058 }
1059 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_subtract(mpfr_float_backend<digits10,AllocationType> & result,unsigned long i)1060 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1061 {
1062    mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
1063 }
1064 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_multiply(mpfr_float_backend<digits10,AllocationType> & result,unsigned long i)1065 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1066 {
1067    mpfr_mul_ui(result.data(), result.data(), i, GMP_RNDN);
1068 }
1069 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_divide(mpfr_float_backend<digits10,AllocationType> & result,unsigned long i)1070 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
1071 {
1072    mpfr_div_ui(result.data(), result.data(), i, GMP_RNDN);
1073 }
1074 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_add(mpfr_float_backend<digits10,AllocationType> & result,long i)1075 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, long i)
1076 {
1077    if (i > 0)
1078       mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
1079    else
1080       mpfr_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1081 }
1082 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_subtract(mpfr_float_backend<digits10,AllocationType> & result,long i)1083 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, long i)
1084 {
1085    if (i > 0)
1086       mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
1087    else
1088       mpfr_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1089 }
1090 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_multiply(mpfr_float_backend<digits10,AllocationType> & result,long i)1091 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, long i)
1092 {
1093    mpfr_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1094    if (i < 0)
1095       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1096 }
1097 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_divide(mpfr_float_backend<digits10,AllocationType> & result,long i)1098 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, long i)
1099 {
1100    mpfr_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i), GMP_RNDN);
1101    if (i < 0)
1102       mpfr_neg(result.data(), result.data(), GMP_RNDN);
1103 }
1104 //
1105 // Specialised 3 arg versions of the basic operators:
1106 //
1107 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
eval_add(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,const mpfr_float_backend<D3> & y)1108 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1109 {
1110    mpfr_add(a.data(), x.data(), y.data(), GMP_RNDN);
1111 }
1112 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_add(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,unsigned long y)1113 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1114 {
1115    mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1116 }
1117 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_add(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,long y)1118 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1119 {
1120    if (y < 0)
1121       mpfr_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1122    else
1123       mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1124 }
1125 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_add(mpfr_float_backend<D1,A1> & a,unsigned long x,const mpfr_float_backend<D2,A2> & y)1126 inline void eval_add(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1127 {
1128    mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1129 }
1130 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_add(mpfr_float_backend<D1,A1> & a,long x,const mpfr_float_backend<D2,A2> & y)1131 inline void eval_add(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1132 {
1133    if (x < 0)
1134    {
1135       mpfr_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1136       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1137    }
1138    else
1139       mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1140 }
1141 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
eval_subtract(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,const mpfr_float_backend<D3> & y)1142 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1143 {
1144    mpfr_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1145 }
1146 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_subtract(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,unsigned long y)1147 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1148 {
1149    mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1150 }
1151 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_subtract(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,long y)1152 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1153 {
1154    if (y < 0)
1155       mpfr_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1156    else
1157       mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1158 }
1159 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_subtract(mpfr_float_backend<D1,A1> & a,unsigned long x,const mpfr_float_backend<D2,A2> & y)1160 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1161 {
1162    mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1163 }
1164 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_subtract(mpfr_float_backend<D1,A1> & a,long x,const mpfr_float_backend<D2,A2> & y)1165 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1166 {
1167    if (x < 0)
1168    {
1169       mpfr_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1170       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1171    }
1172    else
1173       mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1174 }
1175 
1176 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
eval_multiply(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,const mpfr_float_backend<D3> & y)1177 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1178 {
1179    if ((void*)&x == (void*)&y)
1180       mpfr_sqr(a.data(), x.data(), GMP_RNDN);
1181    else
1182       mpfr_mul(a.data(), x.data(), y.data(), GMP_RNDN);
1183 }
1184 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_multiply(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,unsigned long y)1185 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1186 {
1187    mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1188 }
1189 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_multiply(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,long y)1190 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1191 {
1192    if (y < 0)
1193    {
1194       mpfr_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1195       a.negate();
1196    }
1197    else
1198       mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1199 }
1200 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_multiply(mpfr_float_backend<D1,A1> & a,unsigned long x,const mpfr_float_backend<D2,A2> & y)1201 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1202 {
1203    mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1204 }
1205 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_multiply(mpfr_float_backend<D1,A1> & a,long x,const mpfr_float_backend<D2,A2> & y)1206 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1207 {
1208    if (x < 0)
1209    {
1210       mpfr_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x), GMP_RNDN);
1211       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1212    }
1213    else
1214       mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1215 }
1216 
1217 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
eval_divide(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,const mpfr_float_backend<D3> & y)1218 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1219 {
1220    mpfr_div(a.data(), x.data(), y.data(), GMP_RNDN);
1221 }
1222 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_divide(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,unsigned long y)1223 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1224 {
1225    mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1226 }
1227 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_divide(mpfr_float_backend<D1,A1> & a,const mpfr_float_backend<D2,A2> & x,long y)1228 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1229 {
1230    if (y < 0)
1231    {
1232       mpfr_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y), GMP_RNDN);
1233       a.negate();
1234    }
1235    else
1236       mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1237 }
1238 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_divide(mpfr_float_backend<D1,A1> & a,unsigned long x,const mpfr_float_backend<D2,A2> & y)1239 inline void eval_divide(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1240 {
1241    mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1242 }
1243 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
eval_divide(mpfr_float_backend<D1,A1> & a,long x,const mpfr_float_backend<D2,A2> & y)1244 inline void eval_divide(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1245 {
1246    if (x < 0)
1247    {
1248       mpfr_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data(), GMP_RNDN);
1249       mpfr_neg(a.data(), a.data(), GMP_RNDN);
1250    }
1251    else
1252       mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1253 }
1254 
1255 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_is_zero(const mpfr_float_backend<digits10,AllocationType> & val)1256 inline bool eval_is_zero(const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1257 {
1258    return 0 != mpfr_zero_p(val.data());
1259 }
1260 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_get_sign(const mpfr_float_backend<digits10,AllocationType> & val)1261 inline int eval_get_sign(const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1262 {
1263    return mpfr_sgn(val.data());
1264 }
1265 
1266 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(unsigned long * result,const mpfr_float_backend<digits10,AllocationType> & val)1267 inline void eval_convert_to(unsigned long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1268 {
1269    if (mpfr_nan_p(val.data()))
1270    {
1271       BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1272    }
1273    *result = mpfr_get_ui(val.data(), GMP_RNDZ);
1274 }
1275 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(long * result,const mpfr_float_backend<digits10,AllocationType> & val)1276 inline void eval_convert_to(long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1277 {
1278    if (mpfr_nan_p(val.data()))
1279    {
1280       BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1281    }
1282    *result = mpfr_get_si(val.data(), GMP_RNDZ);
1283 }
1284 #ifdef _MPFR_H_HAVE_INTMAX_T
1285 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(boost::ulong_long_type * result,const mpfr_float_backend<digits10,AllocationType> & val)1286 inline void eval_convert_to(boost::ulong_long_type* result, const mpfr_float_backend<digits10, AllocationType>& val)
1287 {
1288    if (mpfr_nan_p(val.data()))
1289    {
1290       BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1291    }
1292    *result = mpfr_get_uj(val.data(), GMP_RNDZ);
1293 }
1294 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(boost::long_long_type * result,const mpfr_float_backend<digits10,AllocationType> & val)1295 inline void eval_convert_to(boost::long_long_type* result, const mpfr_float_backend<digits10, AllocationType>& val)
1296 {
1297    if (mpfr_nan_p(val.data()))
1298    {
1299       BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1300    }
1301    *result = mpfr_get_sj(val.data(), GMP_RNDZ);
1302 }
1303 #endif
1304 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(float * result,const mpfr_float_backend<digits10,AllocationType> & val)1305 inline void eval_convert_to(float* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1306 {
1307    *result = mpfr_get_flt(val.data(), GMP_RNDN);
1308 }
1309 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(double * result,const mpfr_float_backend<digits10,AllocationType> & val)1310 inline void eval_convert_to(double* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1311 {
1312    *result = mpfr_get_d(val.data(), GMP_RNDN);
1313 }
1314 template <unsigned digits10, mpfr_allocation_type AllocationType>
eval_convert_to(long double * result,const mpfr_float_backend<digits10,AllocationType> & val)1315 inline void eval_convert_to(long double* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1316 {
1317    *result = mpfr_get_ld(val.data(), GMP_RNDN);
1318 }
1319 
1320 //
1321 // Native non-member operations:
1322 //
1323 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_sqrt(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1324 inline void eval_sqrt(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1325 {
1326    mpfr_sqrt(result.data(), val.data(), GMP_RNDN);
1327 }
1328 
1329 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_abs(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1330 inline void eval_abs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1331 {
1332    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1333 }
1334 
1335 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_fabs(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1336 inline void eval_fabs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1337 {
1338    mpfr_abs(result.data(), val.data(), GMP_RNDN);
1339 }
1340 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_ceil(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1341 inline void eval_ceil(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1342 {
1343    mpfr_ceil(result.data(), val.data());
1344 }
1345 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_floor(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1346 inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1347 {
1348    mpfr_floor(result.data(), val.data());
1349 }
1350 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_trunc(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val)1351 inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1352 {
1353    mpfr_trunc(result.data(), val.data());
1354 }
1355 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_ldexp(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val,long e)1356 inline void eval_ldexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long e)
1357 {
1358    if (e > 0)
1359       mpfr_mul_2exp(result.data(), val.data(), e, GMP_RNDN);
1360    else if (e < 0)
1361       mpfr_div_2exp(result.data(), val.data(), -e, GMP_RNDN);
1362    else
1363       result = val;
1364 }
1365 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_frexp(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val,int * e)1366 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, int* e)
1367 {
1368    long v;
1369    mpfr_get_d_2exp(&v, val.data(), GMP_RNDN);
1370    *e = v;
1371    eval_ldexp(result, val, -v);
1372 }
1373 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_frexp(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & val,long * e)1374 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long* e)
1375 {
1376    mpfr_get_d_2exp(e, val.data(), GMP_RNDN);
1377    return eval_ldexp(result, val, -*e);
1378 }
1379 
1380 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_fpclassify(const mpfr_float_backend<Digits10,AllocateType> & val)1381 inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val) BOOST_NOEXCEPT
1382 {
1383    return mpfr_inf_p(val.data()) ? FP_INFINITE : mpfr_nan_p(val.data()) ? FP_NAN : mpfr_zero_p(val.data()) ? FP_ZERO : FP_NORMAL;
1384 }
1385 
1386 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_pow(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & b,const mpfr_float_backend<Digits10,AllocateType> & e)1387 inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
1388 {
1389    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))
1390    {
1391       mpfr_set(result.data(), b.data(), GMP_RNDN);
1392    }
1393    else
1394       mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
1395 }
1396 
1397 #ifdef BOOST_MSVC
1398 //
1399 // The enable_if usage below doesn't work with msvc - but only when
1400 // certain other enable_if usages are defined first.  It's a capricious
1401 // and rather annoying compiler bug in other words....
1402 //
1403 #define BOOST_MP_ENABLE_IF_WORKAROUND (Digits10 || !Digits10)&&
1404 #else
1405 #define BOOST_MP_ENABLE_IF_WORKAROUND
1406 #endif
1407 
1408 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1409 inline typename enable_if<mpl::and_<is_signed<Integer>, mpl::bool_<BOOST_MP_ENABLE_IF_WORKAROUND(sizeof(Integer) <= sizeof(long))> > >::type
eval_pow(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & b,const Integer & e)1410 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1411 {
1412    mpfr_pow_si(result.data(), b.data(), e, GMP_RNDN);
1413 }
1414 
1415 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1416 inline typename enable_if<mpl::and_<is_unsigned<Integer>, mpl::bool_<BOOST_MP_ENABLE_IF_WORKAROUND(sizeof(Integer) <= sizeof(long))> > >::type
eval_pow(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & b,const Integer & e)1417 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1418 {
1419    mpfr_pow_ui(result.data(), b.data(), e, GMP_RNDN);
1420 }
1421 
1422 #undef BOOST_MP_ENABLE_IF_WORKAROUND
1423 
1424 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_exp(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1425 inline void eval_exp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1426 {
1427    mpfr_exp(result.data(), arg.data(), GMP_RNDN);
1428 }
1429 
1430 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_exp2(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1431 inline void eval_exp2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1432 {
1433    mpfr_exp2(result.data(), arg.data(), GMP_RNDN);
1434 }
1435 
1436 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_log(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1437 inline void eval_log(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1438 {
1439    mpfr_log(result.data(), arg.data(), GMP_RNDN);
1440 }
1441 
1442 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_log10(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1443 inline void eval_log10(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1444 {
1445    mpfr_log10(result.data(), arg.data(), GMP_RNDN);
1446 }
1447 
1448 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_sin(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1449 inline void eval_sin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1450 {
1451    mpfr_sin(result.data(), arg.data(), GMP_RNDN);
1452 }
1453 
1454 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_cos(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1455 inline void eval_cos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1456 {
1457    mpfr_cos(result.data(), arg.data(), GMP_RNDN);
1458 }
1459 
1460 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_tan(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1461 inline void eval_tan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1462 {
1463    mpfr_tan(result.data(), arg.data(), GMP_RNDN);
1464 }
1465 
1466 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_asin(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1467 inline void eval_asin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1468 {
1469    mpfr_asin(result.data(), arg.data(), GMP_RNDN);
1470 }
1471 
1472 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_acos(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1473 inline void eval_acos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1474 {
1475    mpfr_acos(result.data(), arg.data(), GMP_RNDN);
1476 }
1477 
1478 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_atan(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1479 inline void eval_atan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1480 {
1481    mpfr_atan(result.data(), arg.data(), GMP_RNDN);
1482 }
1483 
1484 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_atan2(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg1,const mpfr_float_backend<Digits10,AllocateType> & arg2)1485 inline void eval_atan2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg1, const mpfr_float_backend<Digits10, AllocateType>& arg2)
1486 {
1487    mpfr_atan2(result.data(), arg1.data(), arg2.data(), GMP_RNDN);
1488 }
1489 
1490 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_sinh(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1491 inline void eval_sinh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1492 {
1493    mpfr_sinh(result.data(), arg.data(), GMP_RNDN);
1494 }
1495 
1496 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_cosh(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1497 inline void eval_cosh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1498 {
1499    mpfr_cosh(result.data(), arg.data(), GMP_RNDN);
1500 }
1501 
1502 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_tanh(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1503 inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1504 {
1505    mpfr_tanh(result.data(), arg.data(), GMP_RNDN);
1506 }
1507 
1508 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_log2(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg)1509 inline void eval_log2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1510 {
1511    mpfr_log2(result.data(), arg.data(), GMP_RNDN);
1512 }
1513 
1514 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_modf(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & arg,mpfr_float_backend<Digits10,AllocateType> * pipart)1515 inline void eval_modf(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg, mpfr_float_backend<Digits10, AllocateType>* pipart)
1516 {
1517    if (0 == pipart)
1518    {
1519       mpfr_float_backend<Digits10, AllocateType> ipart;
1520       mpfr_modf(ipart.data(), result.data(), arg.data(), GMP_RNDN);
1521    }
1522    else
1523    {
1524       mpfr_modf(pipart->data(), result.data(), arg.data(), GMP_RNDN);
1525    }
1526 }
1527 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_remainder(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & a,const mpfr_float_backend<Digits10,AllocateType> & b)1528 inline void eval_remainder(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1529 {
1530    mpfr_remainder(result.data(), a.data(), b.data(), GMP_RNDN);
1531 }
1532 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_remquo(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & a,const mpfr_float_backend<Digits10,AllocateType> & b,int * pi)1533 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)
1534 {
1535    long l;
1536    mpfr_remquo(result.data(), &l, a.data(), b.data(), GMP_RNDN);
1537    if (pi)
1538       *pi = l;
1539 }
1540 
1541 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_fmod(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & a,const mpfr_float_backend<Digits10,AllocateType> & b)1542 inline void eval_fmod(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& a, const mpfr_float_backend<Digits10, AllocateType>& b)
1543 {
1544    mpfr_fmod(result.data(), a.data(), b.data(), GMP_RNDN);
1545 }
1546 
1547 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_multiply_add(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & a,const mpfr_float_backend<Digits10,AllocateType> & b)1548 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)
1549 {
1550    mpfr_fma(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1551 }
1552 
1553 template <unsigned Digits10, mpfr_allocation_type AllocateType>
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)1554 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)
1555 {
1556    mpfr_fma(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1557 }
1558 
1559 template <unsigned Digits10, mpfr_allocation_type AllocateType>
eval_multiply_subtract(mpfr_float_backend<Digits10,AllocateType> & result,const mpfr_float_backend<Digits10,AllocateType> & a,const mpfr_float_backend<Digits10,AllocateType> & b)1560 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)
1561 {
1562    mpfr_fms(result.data(), a.data(), b.data(), result.data(), GMP_RNDN);
1563    result.negate();
1564 }
1565 
1566 template <unsigned Digits10, mpfr_allocation_type AllocateType>
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)1567 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)
1568 {
1569    mpfr_fms(result.data(), a.data(), b.data(), c.data(), GMP_RNDN);
1570 }
1571 
1572 template <unsigned Digits10, mpfr_allocation_type AllocateType>
BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10,AllocateType> & arg)1573 inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backend<Digits10, AllocateType>& arg)
1574 {
1575    return (arg.data()[0]._mpfr_sign < 0) ? 1 : 0;
1576 }
1577 
1578 template <unsigned Digits10, mpfr_allocation_type AllocateType>
hash_value(const mpfr_float_backend<Digits10,AllocateType> & val)1579 inline std::size_t hash_value(const mpfr_float_backend<Digits10, AllocateType>& val)
1580 {
1581    std::size_t result = 0;
1582    std::size_t len    = val.data()[0]._mpfr_prec / mp_bits_per_limb;
1583    if (val.data()[0]._mpfr_prec % mp_bits_per_limb)
1584       ++len;
1585    for (std::size_t i = 0; i < len; ++i)
1586       boost::hash_combine(result, val.data()[0]._mpfr_d[i]);
1587    boost::hash_combine(result, val.data()[0]._mpfr_exp);
1588    boost::hash_combine(result, val.data()[0]._mpfr_sign);
1589    return result;
1590 }
1591 
1592 } // namespace backends
1593 
1594 #ifdef BOOST_NO_SFINAE_EXPR
1595 
1596 namespace detail {
1597 
1598 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1599 struct is_explicitly_convertible<backends::mpfr_float_backend<D1, A1>, backends::mpfr_float_backend<D2, A2> > : public mpl::true_
1600 {};
1601 
1602 } // namespace detail
1603 
1604 #endif
1605 
1606 namespace detail {
1607 template <>
1608 struct is_variable_precision<backends::mpfr_float_backend<0> > : public true_type
1609 {};
1610 } // namespace detail
1611 
1612 template <>
1613 struct number_category<detail::canonical<mpfr_t, backends::mpfr_float_backend<0> >::type> : public mpl::int_<number_kind_floating_point>
1614 {};
1615 
1616 using boost::multiprecision::backends::mpfr_float_backend;
1617 
1618 typedef number<mpfr_float_backend<50> >   mpfr_float_50;
1619 typedef number<mpfr_float_backend<100> >  mpfr_float_100;
1620 typedef number<mpfr_float_backend<500> >  mpfr_float_500;
1621 typedef number<mpfr_float_backend<1000> > mpfr_float_1000;
1622 typedef number<mpfr_float_backend<0> >    mpfr_float;
1623 
1624 typedef number<mpfr_float_backend<50, allocate_stack> >  static_mpfr_float_50;
1625 typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
1626 
1627 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
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)1628 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)
1629 {
1630    return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>(-a) : a;
1631 }
1632 
1633 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
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)1634 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)
1635 {
1636    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;
1637 }
1638 
1639 } // namespace multiprecision
1640 
1641 namespace math {
1642 
1643 using boost::multiprecision::copysign;
1644 using boost::multiprecision::signbit;
1645 
1646 namespace tools {
1647 
1648 template <>
digits()1649 inline int digits<boost::multiprecision::mpfr_float>()
1650 #ifdef BOOST_MATH_NOEXCEPT
1651     BOOST_NOEXCEPT
1652 #endif
1653 {
1654    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::default_precision());
1655 }
1656 template <>
digits()1657 inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
1658 #ifdef BOOST_MATH_NOEXCEPT
1659     BOOST_NOEXCEPT
1660 #endif
1661 {
1662    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpfr_float::default_precision());
1663 }
1664 
1665 template <>
1666 inline boost::multiprecision::mpfr_float
max_value()1667 max_value<boost::multiprecision::mpfr_float>()
1668 {
1669    boost::multiprecision::mpfr_float result(0.5);
1670    mpfr_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax(), GMP_RNDN);
1671    BOOST_ASSERT(mpfr_number_p(result.backend().data()));
1672    return result;
1673 }
1674 
1675 template <>
1676 inline boost::multiprecision::mpfr_float
min_value()1677 min_value<boost::multiprecision::mpfr_float>()
1678 {
1679    boost::multiprecision::mpfr_float result(0.5);
1680    mpfr_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin(), GMP_RNDN);
1681    BOOST_ASSERT(mpfr_number_p(result.backend().data()));
1682    return result;
1683 }
1684 
1685 template <>
1686 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
max_value()1687 max_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
1688 {
1689    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
1690    mpfr_mul_2exp(result.backend().data(), result.backend().data(), mpfr_get_emax(), GMP_RNDN);
1691    BOOST_ASSERT(mpfr_number_p(result.backend().data()));
1692    return result;
1693 }
1694 
1695 template <>
1696 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off>
min_value()1697 min_value<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
1698 {
1699    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> result(0.5);
1700    mpfr_div_2exp(result.backend().data(), result.backend().data(), -mpfr_get_emin(), GMP_RNDN);
1701    BOOST_ASSERT(mpfr_number_p(result.backend().data()));
1702    return result;
1703 }
1704 
1705 template <>
digits()1706 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
1707 #ifdef BOOST_MATH_NOEXCEPT
1708     BOOST_NOEXCEPT
1709 #endif
1710 {
1711    return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision());
1712 }
1713 template <>
digits()1714 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
1715 #ifdef BOOST_MATH_NOEXCEPT
1716     BOOST_NOEXCEPT
1717 #endif
1718 {
1719    return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >::default_precision());
1720 }
1721 
1722 template <>
1723 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
max_value()1724 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
1725 {
1726    return max_value<boost::multiprecision::mpfr_float>().backend();
1727 }
1728 
1729 template <>
1730 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> >
min_value()1731 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float::backend_type> > >()
1732 {
1733    return min_value<boost::multiprecision::mpfr_float>().backend();
1734 }
1735 
1736 template <>
1737 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
max_value()1738 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
1739 {
1740    return max_value<boost::multiprecision::mpfr_float>().backend();
1741 }
1742 
1743 template <>
1744 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off>
min_value()1745 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<0> >, boost::multiprecision::et_off> >()
1746 {
1747    return min_value<boost::multiprecision::mpfr_float>().backend();
1748 }
1749 
1750 } // namespace tools
1751 
1752 namespace constants { namespace detail {
1753 
1754 template <class T>
1755 struct constant_pi;
1756 template <class T>
1757 struct constant_ln_two;
1758 template <class T>
1759 struct constant_euler;
1760 template <class T>
1761 struct constant_catalan;
1762 
1763 namespace detail {
1764 
1765 template <class T, int N>
1766 struct mpfr_constant_initializer
1767 {
force_instantiateboost::math::constants::detail::detail::mpfr_constant_initializer1768    static void force_instantiate()
1769    {
1770       init.force_instantiate();
1771    }
1772 
1773  private:
1774    struct initializer
1775    {
initializerboost::math::constants::detail::detail::mpfr_constant_initializer::initializer1776       initializer()
1777       {
1778          T::get(boost::integral_constant<int, N>());
1779       }
force_instantiateboost::math::constants::detail::detail::mpfr_constant_initializer::initializer1780       void force_instantiate() const {}
1781    };
1782    static const initializer init;
1783 };
1784 
1785 template <class T, int N>
1786 typename mpfr_constant_initializer<T, N>::initializer const mpfr_constant_initializer<T, N>::init;
1787 
1788 } // namespace detail
1789 
1790 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1791 struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1792 {
1793    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1794    template <int N>
getboost::math::constants::detail::constant_pi1795    static inline const result_type& get(const boost::integral_constant<int, N>&)
1796    {
1797       detail::mpfr_constant_initializer<constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1798       static result_type result;
1799       static bool        has_init = false;
1800       if (!has_init)
1801       {
1802          mpfr_const_pi(result.backend().data(), GMP_RNDN);
1803          has_init = true;
1804       }
1805       return result;
1806    }
getboost::math::constants::detail::constant_pi1807    static inline const result_type get(const boost::integral_constant<int, 0>&)
1808    {
1809       result_type result;
1810       mpfr_const_pi(result.backend().data(), GMP_RNDN);
1811       return result;
1812    }
1813 };
1814 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1815 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1816 {
1817    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1818    template <int N>
getboost::math::constants::detail::constant_ln_two1819    static inline const result_type& get(const boost::integral_constant<int, N>&)
1820    {
1821       detail::mpfr_constant_initializer<constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1822       static result_type result;
1823       static bool        init = false;
1824       if (!init)
1825       {
1826          mpfr_const_log2(result.backend().data(), GMP_RNDN);
1827          init = true;
1828       }
1829       return result;
1830    }
getboost::math::constants::detail::constant_ln_two1831    static inline const result_type get(const boost::integral_constant<int, 0>&)
1832    {
1833       result_type result;
1834       mpfr_const_log2(result.backend().data(), GMP_RNDN);
1835       return result;
1836    }
1837 };
1838 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1839 struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1840 {
1841    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1842    template <int N>
getboost::math::constants::detail::constant_euler1843    static inline const result_type& get(const boost::integral_constant<int, N>&)
1844    {
1845       detail::mpfr_constant_initializer<constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1846       static result_type result;
1847       static bool        init = false;
1848       if (!init)
1849       {
1850          mpfr_const_euler(result.backend().data(), GMP_RNDN);
1851          init = true;
1852       }
1853       return result;
1854    }
getboost::math::constants::detail::constant_euler1855    static inline const result_type get(const boost::integral_constant<int, 0>&)
1856    {
1857       result_type result;
1858       mpfr_const_euler(result.backend().data(), GMP_RNDN);
1859       return result;
1860    }
1861 };
1862 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1863 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1864 {
1865    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1866    template <int N>
getboost::math::constants::detail::constant_catalan1867    static inline const result_type& get(const boost::integral_constant<int, N>&)
1868    {
1869       detail::mpfr_constant_initializer<constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1870       static result_type result;
1871       static bool        init = false;
1872       if (!init)
1873       {
1874          mpfr_const_catalan(result.backend().data(), GMP_RNDN);
1875          init = true;
1876       }
1877       return result;
1878    }
getboost::math::constants::detail::constant_catalan1879    static inline const result_type get(const boost::integral_constant<int, 0>&)
1880    {
1881       result_type result;
1882       mpfr_const_catalan(result.backend().data(), GMP_RNDN);
1883       return result;
1884    }
1885 };
1886 
1887 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1888 struct constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
1889 {
1890    typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
1891    template <int N>
getboost::math::constants::detail::constant_pi1892    static inline const result_type& get(const boost::integral_constant<int, N>&)
1893    {
1894       detail::mpfr_constant_initializer<constant_pi<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
1895       static result_type result;
1896       static bool        has_init = false;
1897       if (!has_init)
1898       {
1899          mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
1900          has_init = true;
1901       }
1902       return result;
1903    }
getboost::math::constants::detail::constant_pi1904    static inline const result_type get(const boost::integral_constant<int, 0>&)
1905    {
1906       result_type result;
1907       mpfr_const_pi(result.backend().value().data(), GMP_RNDN);
1908       return result;
1909    }
1910 };
1911 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1912 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
1913 {
1914    typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
1915    template <int N>
getboost::math::constants::detail::constant_ln_two1916    static inline const result_type& get(const boost::integral_constant<int, N>&)
1917    {
1918       detail::mpfr_constant_initializer<constant_ln_two<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
1919       static result_type result;
1920       static bool        init = false;
1921       if (!init)
1922       {
1923          mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
1924          init = true;
1925       }
1926       return result;
1927    }
getboost::math::constants::detail::constant_ln_two1928    static inline const result_type get(const boost::integral_constant<int, 0>&)
1929    {
1930       result_type result;
1931       mpfr_const_log2(result.backend().value().data(), GMP_RNDN);
1932       return result;
1933    }
1934 };
1935 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1936 struct constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
1937 {
1938    typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
1939    template <int N>
getboost::math::constants::detail::constant_euler1940    static inline const result_type& get(const boost::integral_constant<int, N>&)
1941    {
1942       detail::mpfr_constant_initializer<constant_euler<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
1943       static result_type result;
1944       static bool        init = false;
1945       if (!init)
1946       {
1947          mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
1948          init = true;
1949       }
1950       return result;
1951    }
getboost::math::constants::detail::constant_euler1952    static inline const result_type get(const boost::integral_constant<int, 0>&)
1953    {
1954       result_type result;
1955       mpfr_const_euler(result.backend().value().data(), GMP_RNDN);
1956       return result;
1957    }
1958 };
1959 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1960 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >
1961 {
1962    typedef boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> result_type;
1963    template <int N>
getboost::math::constants::detail::constant_catalan1964    static inline const result_type& get(const boost::integral_constant<int, N>&)
1965    {
1966       detail::mpfr_constant_initializer<constant_catalan<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType> >, ExpressionTemplates> >, N>::force_instantiate();
1967       static result_type result;
1968       static bool        init = false;
1969       if (!init)
1970       {
1971          mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
1972          init = true;
1973       }
1974       return result;
1975    }
getboost::math::constants::detail::constant_catalan1976    static inline const result_type get(const boost::integral_constant<int, 0>&)
1977    {
1978       result_type result;
1979       mpfr_const_catalan(result.backend().value().data(), GMP_RNDN);
1980       return result;
1981    }
1982 };
1983 
1984 }} // namespace constants::detail
1985 
1986 } // namespace math
1987 
1988 namespace multiprecision {
1989 //
1990 // Overloaded special functions which call native mpfr routines:
1991 //
1992 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)1993 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)
1994 {
1995    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
1996 
1997    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
1998    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
1999    return result;
2000 }
2001 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2002 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)
2003 {
2004    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2005 
2006    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2007    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2008    return result;
2009 }
2010 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2011 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)
2012 {
2013    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2014 
2015    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2016    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2017    return result;
2018 }
2019 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2020 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)
2021 {
2022    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2023 
2024    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2025    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2026    return result;
2027 }
2028 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2029 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)
2030 {
2031    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2032 
2033    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2034    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2035    return result;
2036 }
2037 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2038 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)
2039 {
2040    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2041 
2042    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2043    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2044    return result;
2045 }
2046 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2047 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)
2048 {
2049    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2050 
2051    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2052    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2053    return result;
2054 }
2055 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2056 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)
2057 {
2058    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2059 
2060    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2061    mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2062    return result;
2063 }
2064 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2065 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)
2066 {
2067    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2068 
2069    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2070    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2071    return result;
2072 }
2073 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2074 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)
2075 {
2076    boost::multiprecision::detail::scoped_default_precision<number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2077 
2078    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2079    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2080    return result;
2081 }
2082 
2083 } // namespace multiprecision
2084 
2085 namespace math {
2086 //
2087 // Overloaded special functions which call native mpfr routines:
2088 //
2089 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy &)2090 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&)
2091 {
2092    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2093 
2094    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2095    mpfr_asinh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2096    if (mpfr_inf_p(result.backend().data()))
2097       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("asinh<%1%>(%1%)", 0, Policy());
2098    if (mpfr_nan_p(result.backend().data()))
2099       return policies::raise_evaluation_error("asinh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2100    return result;
2101 }
2102 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2103 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)
2104 {
2105    return asinh(arg, policies::policy<>());
2106 }
2107 
2108 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy &)2109 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&)
2110 {
2111    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2112 
2113    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2114    mpfr_acosh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2115    if (mpfr_inf_p(result.backend().data()))
2116       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("acosh<%1%>(%1%)", 0, Policy());
2117    if (mpfr_nan_p(result.backend().data()))
2118       return policies::raise_evaluation_error("acosh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2119    return result;
2120 }
2121 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2122 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)
2123 {
2124    return acosh(arg, policies::policy<>());
2125 }
2126 
2127 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy &)2128 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& )
2129 {
2130    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2131 
2132    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2133    mpfr_atanh(result.backend().data(), arg.backend().data(), GMP_RNDN);
2134    if (mpfr_inf_p(result.backend().data()))
2135       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("atanh<%1%>(%1%)", 0, Policy());
2136    if (mpfr_nan_p(result.backend().data()))
2137       return policies::raise_evaluation_error("atanh<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2138    return result;
2139 }
2140 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2141 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)
2142 {
2143    return atanh(arg, policies::policy<>());
2144 }
2145 
2146 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy &)2147 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&)
2148 {
2149    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2150 
2151    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2152    mpfr_cbrt(result.backend().data(), arg.backend().data(), GMP_RNDN);
2153    if (mpfr_inf_p(result.backend().data()))
2154       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("cbrt<%1%>(%1%)", 0, Policy());
2155    if (mpfr_nan_p(result.backend().data()))
2156       return policies::raise_evaluation_error("cbrt<%1%>(%1%)", "Unknown error, result is a NaN", result, Policy());
2157    return result;
2158 }
2159 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2160 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)
2161 {
2162    return cbrt(arg, policies::policy<>());
2163 }
2164 
2165 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2166 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)
2167 {
2168    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2169 
2170    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2171    mpfr_erf(result.backend().data(), arg.backend().data(), GMP_RNDN);
2172    if (mpfr_inf_p(result.backend().data()))
2173       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erf<%1%>(%1%)", 0, pol);
2174    if (mpfr_nan_p(result.backend().data()))
2175       return policies::raise_evaluation_error("erf<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2176    return result;
2177 }
2178 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2179 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)
2180 {
2181    return erf(arg, policies::policy<>());
2182 }
2183 
2184 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2185 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)
2186 {
2187    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2188 
2189    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2190    mpfr_erfc(result.backend().data(), arg.backend().data(), GMP_RNDN);
2191    if (mpfr_inf_p(result.backend().data()))
2192       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("erfc<%1%>(%1%)", 0, pol);
2193    if (mpfr_nan_p(result.backend().data()))
2194       return policies::raise_evaluation_error("erfc<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2195    return result;
2196 }
2197 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2198 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)
2199 {
2200    return erfc(arg, policies::policy<>());
2201 }
2202 
2203 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2204 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)
2205 {
2206    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2207 
2208    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2209    mpfr_expm1(result.backend().data(), arg.backend().data(), GMP_RNDN);
2210    if (mpfr_inf_p(result.backend().data()))
2211       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("expm1<%1%>(%1%)", 0, pol);
2212    if (mpfr_nan_p(result.backend().data()))
2213       return policies::raise_evaluation_error("expm1<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2214    return result;
2215 }
2216 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2217 inline boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> exm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates>& arg)
2218 {
2219    return expm1(arg, policies::policy<>());
2220 }
2221 
2222 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> arg,int * sign,const Policy & pol)2223 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)
2224 {
2225    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2226    (void)precision_guard;  // warning suppression
2227 
2228    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2229    if (arg > 0)
2230    {
2231       mpfr_lngamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2232       if (sign)
2233          *sign = 1;
2234    }
2235    else
2236    {
2237       if (floor(arg) == arg)
2238          return policies::raise_pole_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >(
2239              "lgamma<%1%>", "Evaluation of lgamma at a negative integer %1%.", arg, pol);
2240 
2241       boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> t = detail::sinpx(arg);
2242       arg                                                                                                                     = -arg;
2243       if (t < 0)
2244       {
2245          t = -t;
2246       }
2247       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);
2248       if (sign)
2249       {
2250          boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> phase = 1 - arg;
2251          phase                                                                                                                       = floor(phase) / 2;
2252          if (floor(phase) == phase)
2253             *sign = -1;
2254          else
2255             *sign = 1;
2256       }
2257    }
2258    if (mpfr_inf_p(result.backend().data()))
2259       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("lgamma<%1%>(%1%)", 0, pol);
2260    if (mpfr_nan_p(result.backend().data()))
2261       return policies::raise_evaluation_error("lgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2262    return result;
2263 }
2264 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,int * sign)2265 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)
2266 {
2267    return lgamma(arg, sign, policies::policy<>());
2268 }
2269 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2270 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)
2271 {
2272    return lgamma(arg, 0, pol);
2273 }
2274 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2275 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)
2276 {
2277    return lgamma(arg, 0, policies::policy<>());
2278 }
2279 
2280 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2281 inline typename boost::enable_if_c<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)
2282 {
2283    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2284 
2285    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2286    mpfr_gamma(result.backend().data(), arg.backend().data(), GMP_RNDN);
2287    if (mpfr_inf_p(result.backend().data()))
2288       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("tgamma<%1%>(%1%)", 0, pol);
2289    if (mpfr_nan_p(result.backend().data()))
2290       return policies::raise_evaluation_error("tgamma<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2291    return result;
2292 }
2293 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2294 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)
2295 {
2296    return tgamma(arg, policies::policy<>());
2297 }
2298 
2299 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg,const Policy & pol)2300 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)
2301 {
2302    boost::multiprecision::detail::scoped_default_precision<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> > precision_guard(arg);
2303 
2304    boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result;
2305    mpfr_log1p(result.backend().data(), arg.backend().data(), GMP_RNDN);
2306    if (mpfr_inf_p(result.backend().data()))
2307       return policies::raise_overflow_error<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >("log1p<%1%>(%1%)", 0, pol);
2308    if (mpfr_nan_p(result.backend().data()))
2309       return policies::raise_evaluation_error("log1p<%1%>(%1%)", "Unknown error, result is a NaN", result, pol);
2310    return result;
2311 }
2312 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10,AllocateType>,ExpressionTemplates> & arg)2313 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)
2314 {
2315    return log1p(arg, policies::policy<>());
2316 }
2317 
2318 } // namespace math
2319 
2320 } // namespace boost
2321 
2322 namespace std {
2323 
2324 //
2325 // numeric_limits [partial] specializations for the types declared in this header:
2326 //
2327 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2328 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
2329 {
2330    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> number_type;
2331 
2332  public:
2333    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
number_type(min)2334    static number_type(min)()
2335    {
2336       initializer.do_nothing();
2337       static std::pair<bool, number_type> value;
2338       if (!value.first)
2339       {
2340          value.first  = true;
2341          value.second = 0.5;
2342          mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), -mpfr_get_emin(), GMP_RNDN);
2343       }
2344       return value.second;
2345    }
number_type(max)2346    static number_type(max)()
2347    {
2348       initializer.do_nothing();
2349       static std::pair<bool, number_type> value;
2350       if (!value.first)
2351       {
2352          value.first  = true;
2353          value.second = 0.5;
2354          mpfr_mul_2exp(value.second.backend().data(), value.second.backend().data(), mpfr_get_emax(), GMP_RNDN);
2355       }
2356       return value.second;
2357    }
lowest()2358    BOOST_STATIC_CONSTEXPR number_type lowest()
2359    {
2360       return -(max)();
2361    }
2362    BOOST_STATIC_CONSTEXPR int digits   = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
2363    BOOST_STATIC_CONSTEXPR int digits10 = Digits10;
2364    // Is this really correct???
2365    BOOST_STATIC_CONSTEXPR int  max_digits10 = Digits10 + 3;
2366    BOOST_STATIC_CONSTEXPR bool is_signed    = true;
2367    BOOST_STATIC_CONSTEXPR bool is_integer   = false;
2368    BOOST_STATIC_CONSTEXPR bool is_exact     = false;
2369    BOOST_STATIC_CONSTEXPR int  radix        = 2;
epsilon()2370    static number_type          epsilon()
2371    {
2372       initializer.do_nothing();
2373       static std::pair<bool, number_type> value;
2374       if (!value.first)
2375       {
2376          value.first  = true;
2377          value.second = 1;
2378          mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1, GMP_RNDN);
2379       }
2380       return value.second;
2381    }
2382    // What value should this be????
round_error()2383    static number_type round_error()
2384    {
2385       // returns epsilon/2
2386       initializer.do_nothing();
2387       static std::pair<bool, number_type> value;
2388       if (!value.first)
2389       {
2390          value.first  = true;
2391          value.second = 1;
2392          mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), 1, GMP_RNDN);
2393       }
2394       return value.second;
2395    }
2396    BOOST_STATIC_CONSTEXPR long min_exponent                  = MPFR_EMIN_DEFAULT;
2397    BOOST_STATIC_CONSTEXPR long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
2398    BOOST_STATIC_CONSTEXPR long max_exponent                  = MPFR_EMAX_DEFAULT;
2399    BOOST_STATIC_CONSTEXPR long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
2400    BOOST_STATIC_CONSTEXPR bool has_infinity                  = true;
2401    BOOST_STATIC_CONSTEXPR bool has_quiet_NaN                 = true;
2402    BOOST_STATIC_CONSTEXPR bool has_signaling_NaN             = false;
2403    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm      = denorm_absent;
2404    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss = false;
infinity()2405    static number_type                        infinity()
2406    {
2407       // returns epsilon/2
2408       initializer.do_nothing();
2409       static std::pair<bool, number_type> value;
2410       if (!value.first)
2411       {
2412          value.first  = true;
2413          value.second = 1;
2414          mpfr_set_inf(value.second.backend().data(), 1);
2415       }
2416       return value.second;
2417    }
quiet_NaN()2418    static number_type quiet_NaN()
2419    {
2420       // returns epsilon/2
2421       initializer.do_nothing();
2422       static std::pair<bool, number_type> value;
2423       if (!value.first)
2424       {
2425          value.first  = true;
2426          value.second = 1;
2427          mpfr_set_nan(value.second.backend().data());
2428       }
2429       return value.second;
2430    }
signaling_NaN()2431    BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
2432    {
2433       return number_type(0);
2434    }
denorm_min()2435    BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
2436    BOOST_STATIC_CONSTEXPR bool        is_iec559         = false;
2437    BOOST_STATIC_CONSTEXPR bool        is_bounded        = true;
2438    BOOST_STATIC_CONSTEXPR bool        is_modulo         = false;
2439    BOOST_STATIC_CONSTEXPR bool        traps             = true;
2440    BOOST_STATIC_CONSTEXPR bool        tinyness_before   = false;
2441    BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
2442 
2443  private:
2444    struct data_initializer
2445    {
data_initializerstd::numeric_limits::data_initializer2446       data_initializer()
2447       {
2448          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::epsilon();
2449          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::round_error();
2450          (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::min)();
2451          (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::max)();
2452          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::infinity();
2453          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::quiet_NaN();
2454       }
do_nothingstd::numeric_limits::data_initializer2455       void do_nothing() const {}
2456    };
2457    static const data_initializer initializer;
2458 };
2459 
2460 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2461 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::initializer;
2462 
2463 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2464 
2465 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2466 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits;
2467 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2468 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits10;
2469 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2470 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_digits10;
2471 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2472 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_signed;
2473 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2474 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_integer;
2475 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2476 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_exact;
2477 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2478 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::radix;
2479 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2480 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent;
2481 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2482 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent10;
2483 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2484 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent;
2485 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2486 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent10;
2487 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2488 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_infinity;
2489 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2490 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_quiet_NaN;
2491 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2492 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_signaling_NaN;
2493 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2494 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm;
2495 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2496 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm_loss;
2497 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2498 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_iec559;
2499 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2500 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_bounded;
2501 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2502 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_modulo;
2503 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2504 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::traps;
2505 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2506 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::tinyness_before;
2507 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
2508 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::round_style;
2509 
2510 #endif
2511 
2512 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2513 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >
2514 {
2515    typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> number_type;
2516 
2517  public:
2518    BOOST_STATIC_CONSTEXPR bool is_specialized = false;
number_type(min)2519    static number_type(min)()
2520    {
2521       number_type value(0.5);
2522       mpfr_div_2exp(value.backend().data(), value.backend().data(), -mpfr_get_emin(), GMP_RNDN);
2523       return value;
2524    }
number_type(max)2525    static number_type(max)()
2526    {
2527       number_type value(0.5);
2528       mpfr_mul_2exp(value.backend().data(), value.backend().data(), mpfr_get_emax(), GMP_RNDN);
2529       return value;
2530    }
lowest()2531    static number_type lowest()
2532    {
2533       return -(max)();
2534    }
2535    BOOST_STATIC_CONSTEXPR int  digits       = INT_MAX;
2536    BOOST_STATIC_CONSTEXPR int  digits10     = INT_MAX;
2537    BOOST_STATIC_CONSTEXPR int  max_digits10 = INT_MAX;
2538    BOOST_STATIC_CONSTEXPR bool is_signed    = true;
2539    BOOST_STATIC_CONSTEXPR bool is_integer   = false;
2540    BOOST_STATIC_CONSTEXPR bool is_exact     = false;
2541    BOOST_STATIC_CONSTEXPR int  radix        = 2;
epsilon()2542    static number_type          epsilon()
2543    {
2544       number_type value(1);
2545       mpfr_div_2exp(value.backend().data(), value.backend().data(), boost::multiprecision::detail::digits10_2_2(number_type::default_precision()) - 1, GMP_RNDN);
2546       return value;
2547    }
round_error()2548    static number_type round_error()
2549    {
2550       return epsilon() / 2;
2551    }
2552    BOOST_STATIC_CONSTEXPR long min_exponent                  = MPFR_EMIN_DEFAULT;
2553    BOOST_STATIC_CONSTEXPR long min_exponent10                = (MPFR_EMIN_DEFAULT / 1000) * 301L;
2554    BOOST_STATIC_CONSTEXPR long max_exponent                  = MPFR_EMAX_DEFAULT;
2555    BOOST_STATIC_CONSTEXPR long max_exponent10                = (MPFR_EMAX_DEFAULT / 1000) * 301L;
2556    BOOST_STATIC_CONSTEXPR bool has_infinity                  = true;
2557    BOOST_STATIC_CONSTEXPR bool has_quiet_NaN                 = true;
2558    BOOST_STATIC_CONSTEXPR bool has_signaling_NaN             = false;
2559    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm      = denorm_absent;
2560    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss = false;
infinity()2561    static number_type                        infinity()
2562    {
2563       number_type value;
2564       mpfr_set_inf(value.backend().data(), 1);
2565       return value;
2566    }
quiet_NaN()2567    static number_type quiet_NaN()
2568    {
2569       number_type value;
2570       mpfr_set_nan(value.backend().data());
2571       return value;
2572    }
signaling_NaN()2573    static number_type          signaling_NaN() { return number_type(0); }
denorm_min()2574    static number_type          denorm_min() { return number_type(0); }
2575    BOOST_STATIC_CONSTEXPR bool is_iec559                = false;
2576    BOOST_STATIC_CONSTEXPR bool is_bounded               = true;
2577    BOOST_STATIC_CONSTEXPR bool is_modulo                = false;
2578    BOOST_STATIC_CONSTEXPR bool traps                    = false;
2579    BOOST_STATIC_CONSTEXPR bool tinyness_before          = false;
2580    BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
2581 };
2582 
2583 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2584 
2585 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2586 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits;
2587 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2588 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits10;
2589 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2590 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_digits10;
2591 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2592 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_signed;
2593 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2594 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_integer;
2595 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2596 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_exact;
2597 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2598 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::radix;
2599 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2600 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent;
2601 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2602 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent10;
2603 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2604 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent;
2605 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2606 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent10;
2607 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2608 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_infinity;
2609 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2610 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
2611 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2612 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
2613 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2614 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm;
2615 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2616 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
2617 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2618 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_iec559;
2619 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2620 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_bounded;
2621 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2622 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_modulo;
2623 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2624 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::traps;
2625 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2626 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::tinyness_before;
2627 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2628 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::round_style;
2629 
2630 #endif
2631 } // namespace std
2632 #endif
2633