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