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