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