• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright 2011 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP
7 #define BOOST_MATH_ER_GMP_BACKEND_HPP
8 
9 #include <boost/multiprecision/number.hpp>
10 #include <boost/multiprecision/debug_adaptor.hpp>
11 #include <boost/multiprecision/detail/integer_ops.hpp>
12 #include <boost/multiprecision/detail/big_lanczos.hpp>
13 #include <boost/multiprecision/detail/digits.hpp>
14 #include <boost/multiprecision/detail/atomic.hpp>
15 #include <boost/math/special_functions/fpclassify.hpp>
16 #include <boost/cstdint.hpp>
17 #include <boost/functional/hash_fwd.hpp>
18 //
19 // Some includes we need from Boost.Math, since we rely on that library to provide these functions:
20 //
21 #include <boost/math/special_functions/asinh.hpp>
22 #include <boost/math/special_functions/acosh.hpp>
23 #include <boost/math/special_functions/atanh.hpp>
24 #include <boost/math/special_functions/cbrt.hpp>
25 #include <boost/math/special_functions/expm1.hpp>
26 #include <boost/math/special_functions/gamma.hpp>
27 
28 #ifdef BOOST_MSVC
29 #pragma warning(push)
30 #pragma warning(disable : 4127)
31 #endif
32 #include <gmp.h>
33 #ifdef BOOST_MSVC
34 #pragma warning(pop)
35 #endif
36 
37 #if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL)
38 #define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL)
39 #else
40 #define BOOST_MP_MPIR_VERSION 0
41 #endif
42 
43 #include <cctype>
44 #include <cmath>
45 #include <limits>
46 #include <climits>
47 
48 namespace boost {
49 namespace multiprecision {
50 namespace backends {
51 
52 #ifdef BOOST_MSVC
53 // warning C4127: conditional expression is constant
54 #pragma warning(push)
55 #pragma warning(disable : 4127)
56 #endif
57 
58 template <unsigned digits10>
59 struct gmp_float;
60 struct gmp_int;
61 struct gmp_rational;
62 
63 } // namespace backends
64 
65 template <>
66 struct number_category<backends::gmp_int> : public mpl::int_<number_kind_integer>
67 {};
68 template <>
69 struct number_category<backends::gmp_rational> : public mpl::int_<number_kind_rational>
70 {};
71 template <unsigned digits10>
72 struct number_category<backends::gmp_float<digits10> > : public mpl::int_<number_kind_floating_point>
73 {};
74 
75 namespace backends {
76 //
77 // Within this file, the only functions we mark as noexcept are those that manipulate
78 // (but don't create) an mpf_t.  All other types may allocate at pretty much any time
79 // via a user-supplied allocator, and therefore throw.
80 //
81 namespace detail {
82 
83 template <unsigned digits10>
84 struct gmp_float_imp
85 {
86 #ifdef BOOST_HAS_LONG_LONG
87    typedef mpl::list<long, boost::long_long_type>           signed_types;
88    typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
89 #else
90    typedef mpl::list<long>          signed_types;
91    typedef mpl::list<unsigned long> unsigned_types;
92 #endif
93    typedef mpl::list<double, long double> float_types;
94    typedef long                           exponent_type;
95 
gmp_float_impboost::multiprecision::backends::detail::gmp_float_imp96    gmp_float_imp() BOOST_NOEXCEPT
97    {
98       m_data[0]._mp_d = 0; // uninitialized m_data
99    }
100 
gmp_float_impboost::multiprecision::backends::detail::gmp_float_imp101    gmp_float_imp(const gmp_float_imp& o)
102    {
103       //
104       // We have to do an init followed by a set here, otherwise *this may be at
105       // a lower precision than o: seems like mpf_init_set copies just enough bits
106       // to get the right value, but if it's then used in further calculations
107       // things go badly wrong!!
108       //
109       mpf_init2(m_data, mpf_get_prec(o.data()));
110       if (o.m_data[0]._mp_d)
111          mpf_set(m_data, o.m_data);
112    }
113 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
gmp_float_impboost::multiprecision::backends::detail::gmp_float_imp114    gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT
115    {
116       m_data[0]         = o.m_data[0];
117       o.m_data[0]._mp_d = 0;
118    }
119 #endif
operator =boost::multiprecision::backends::detail::gmp_float_imp120    gmp_float_imp& operator=(const gmp_float_imp& o)
121    {
122       if (m_data[0]._mp_d == 0)
123          mpf_init2(m_data, mpf_get_prec(o.data()));
124       if (mpf_get_prec(data()) != mpf_get_prec(o.data()))
125       {
126          mpf_t t;
127          mpf_init2(t, mpf_get_prec(o.data()));
128          mpf_set(t, o.data());
129          mpf_swap(data(), t);
130          mpf_clear(t);
131       }
132       else
133       {
134          if (o.m_data[0]._mp_d)
135             mpf_set(m_data, o.m_data);
136       }
137       return *this;
138    }
139 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::detail::gmp_float_imp140    gmp_float_imp& operator=(gmp_float_imp&& o) BOOST_NOEXCEPT
141    {
142       mpf_swap(m_data, o.m_data);
143       return *this;
144    }
145 #endif
146 
147 #ifdef BOOST_HAS_LONG_LONG
148 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
operator =boost::multiprecision::backends::detail::gmp_float_imp149    gmp_float_imp& operator=(boost::ulong_long_type i)
150    {
151       *this = static_cast<unsigned long>(i);
152       return *this;
153    }
154 #else
operator =boost::multiprecision::backends::detail::gmp_float_imp155    gmp_float_imp& operator=(boost::ulong_long_type i)
156    {
157       if (m_data[0]._mp_d == 0)
158          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
159       boost::ulong_long_type mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
160       unsigned               shift = 0;
161       mpf_t                  t;
162       mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
163       mpf_set_ui(m_data, 0);
164       while (i)
165       {
166          mpf_set_ui(t, static_cast<unsigned long>(i & mask));
167          if (shift)
168             mpf_mul_2exp(t, t, shift);
169          mpf_add(m_data, m_data, t);
170          shift += std::numeric_limits<unsigned long>::digits;
171          i >>= std::numeric_limits<unsigned long>::digits;
172       }
173       mpf_clear(t);
174       return *this;
175    }
176 #endif
operator =boost::multiprecision::backends::detail::gmp_float_imp177    gmp_float_imp& operator=(boost::long_long_type i)
178    {
179       if (m_data[0]._mp_d == 0)
180          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
181       bool neg = i < 0;
182       *this    = static_cast<boost::ulong_long_type>(boost::multiprecision::detail::unsigned_abs(i));
183       if (neg)
184          mpf_neg(m_data, m_data);
185       return *this;
186    }
187 #endif
operator =boost::multiprecision::backends::detail::gmp_float_imp188    gmp_float_imp& operator=(unsigned long i)
189    {
190       if (m_data[0]._mp_d == 0)
191          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
192       mpf_set_ui(m_data, i);
193       return *this;
194    }
operator =boost::multiprecision::backends::detail::gmp_float_imp195    gmp_float_imp& operator=(long i)
196    {
197       if (m_data[0]._mp_d == 0)
198          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
199       mpf_set_si(m_data, i);
200       return *this;
201    }
operator =boost::multiprecision::backends::detail::gmp_float_imp202    gmp_float_imp& operator=(double d)
203    {
204       if (m_data[0]._mp_d == 0)
205          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
206       mpf_set_d(m_data, d);
207       return *this;
208    }
operator =boost::multiprecision::backends::detail::gmp_float_imp209    gmp_float_imp& operator=(long double a)
210    {
211       using std::floor;
212       using std::frexp;
213       using std::ldexp;
214 
215       if (m_data[0]._mp_d == 0)
216          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
217 
218       if (a == 0)
219       {
220          mpf_set_si(m_data, 0);
221          return *this;
222       }
223 
224       if (a == 1)
225       {
226          mpf_set_si(m_data, 1);
227          return *this;
228       }
229 
230       BOOST_ASSERT(!(boost::math::isinf)(a));
231       BOOST_ASSERT(!(boost::math::isnan)(a));
232 
233       int         e;
234       long double f, term;
235       mpf_set_ui(m_data, 0u);
236 
237       f = frexp(a, &e);
238 
239       static const int shift = std::numeric_limits<int>::digits - 1;
240 
241       while (f)
242       {
243          // extract int sized bits from f:
244          f    = ldexp(f, shift);
245          term = floor(f);
246          e -= shift;
247          mpf_mul_2exp(m_data, m_data, shift);
248          if (term > 0)
249             mpf_add_ui(m_data, m_data, static_cast<unsigned>(term));
250          else
251             mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
252          f -= term;
253       }
254       if (e > 0)
255          mpf_mul_2exp(m_data, m_data, e);
256       else if (e < 0)
257          mpf_div_2exp(m_data, m_data, -e);
258       return *this;
259    }
operator =boost::multiprecision::backends::detail::gmp_float_imp260    gmp_float_imp& operator=(const char* s)
261    {
262       if (m_data[0]._mp_d == 0)
263          mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
264       if (s && (*s == '+'))
265          ++s;  // Leading "+" sign not supported by mpf_set_str:
266       if (0 != mpf_set_str(m_data, s, 10))
267          BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number.")));
268       return *this;
269    }
swapboost::multiprecision::backends::detail::gmp_float_imp270    void swap(gmp_float_imp& o) BOOST_NOEXCEPT
271    {
272       mpf_swap(m_data, o.m_data);
273    }
strboost::multiprecision::backends::detail::gmp_float_imp274    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
275    {
276       BOOST_ASSERT(m_data[0]._mp_d);
277 
278       bool            scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
279       bool            fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
280       std::streamsize org_digits(digits);
281 
282       if (scientific && digits)
283          ++digits;
284 
285       std::string result;
286       mp_exp_t    e;
287       void* (*alloc_func_ptr)(size_t);
288       void* (*realloc_func_ptr)(void*, size_t, size_t);
289       void (*free_func_ptr)(void*, size_t);
290       mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
291 
292       if (mpf_sgn(m_data) == 0)
293       {
294          e      = 0;
295          result = "0";
296          if (fixed && digits)
297             ++digits;
298       }
299       else
300       {
301          char* ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
302          --e; // To match with what our formatter expects.
303          if (fixed && e != -1)
304          {
305             // Oops we actually need a different number of digits to what we asked for:
306             (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
307             digits += e + 1;
308             if (digits == 0)
309             {
310                // We need to get *all* the digits and then possibly round up,
311                // we end up with either "0" or "1" as the result.
312                ps = mpf_get_str(0, &e, 10, 0, m_data);
313                --e;
314                unsigned offset = *ps == '-' ? 1 : 0;
315                if (ps[offset] > '5')
316                {
317                   ++e;
318                   ps[offset]     = '1';
319                   ps[offset + 1] = 0;
320                }
321                else if (ps[offset] == '5')
322                {
323                   unsigned i        = offset + 1;
324                   bool     round_up = false;
325                   while (ps[i] != 0)
326                   {
327                      if (ps[i] != '0')
328                      {
329                         round_up = true;
330                         break;
331                      }
332                      ++i;
333                   }
334                   if (round_up)
335                   {
336                      ++e;
337                      ps[offset]     = '1';
338                      ps[offset + 1] = 0;
339                   }
340                   else
341                   {
342                      ps[offset]     = '0';
343                      ps[offset + 1] = 0;
344                   }
345                }
346                else
347                {
348                   ps[offset]     = '0';
349                   ps[offset + 1] = 0;
350                }
351             }
352             else if (digits > 0)
353             {
354                mp_exp_t old_e = e;
355                ps             = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
356                --e; // To match with what our formatter expects.
357                if (old_e > e)
358                {
359                   // in some cases, when we ask for more digits of precision, it will
360                   // change the number of digits to the left of the decimal, if that
361                   // happens, account for it here.
362                   // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
363                   digits -= old_e - e;
364                   ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
365                   --e; // To match with what our formatter expects.
366                }
367             }
368             else
369             {
370                ps = mpf_get_str(0, &e, 10, 1, m_data);
371                --e;
372                unsigned offset = *ps == '-' ? 1 : 0;
373                ps[offset]      = '0';
374                ps[offset + 1]  = 0;
375             }
376          }
377          result = ps;
378          (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
379       }
380       boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0);
381       return result;
382    }
~gmp_float_impboost::multiprecision::backends::detail::gmp_float_imp383    ~gmp_float_imp() BOOST_NOEXCEPT
384    {
385       if (m_data[0]._mp_d)
386          mpf_clear(m_data);
387    }
negateboost::multiprecision::backends::detail::gmp_float_imp388    void negate() BOOST_NOEXCEPT
389    {
390       BOOST_ASSERT(m_data[0]._mp_d);
391       mpf_neg(m_data, m_data);
392    }
compareboost::multiprecision::backends::detail::gmp_float_imp393    int compare(const gmp_float<digits10>& o) const BOOST_NOEXCEPT
394    {
395       BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
396       return mpf_cmp(m_data, o.m_data);
397    }
compareboost::multiprecision::backends::detail::gmp_float_imp398    int compare(long i) const BOOST_NOEXCEPT
399    {
400       BOOST_ASSERT(m_data[0]._mp_d);
401       return mpf_cmp_si(m_data, i);
402    }
compareboost::multiprecision::backends::detail::gmp_float_imp403    int compare(unsigned long i) const BOOST_NOEXCEPT
404    {
405       BOOST_ASSERT(m_data[0]._mp_d);
406       return mpf_cmp_ui(m_data, i);
407    }
408    template <class V>
compareboost::multiprecision::backends::detail::gmp_float_imp409    typename enable_if<is_arithmetic<V>, int>::type compare(V v) const
410    {
411       gmp_float<digits10> d;
412       d = v;
413       return compare(d);
414    }
databoost::multiprecision::backends::detail::gmp_float_imp415    mpf_t& data() BOOST_NOEXCEPT
416    {
417       BOOST_ASSERT(m_data[0]._mp_d);
418       return m_data;
419    }
databoost::multiprecision::backends::detail::gmp_float_imp420    const mpf_t& data() const BOOST_NOEXCEPT
421    {
422       BOOST_ASSERT(m_data[0]._mp_d);
423       return m_data;
424    }
425 
426  protected:
427    mpf_t            m_data;
get_default_precisionboost::multiprecision::backends::detail::gmp_float_imp428    static boost::multiprecision::detail::precision_type& get_default_precision() BOOST_NOEXCEPT
429    {
430       static boost::multiprecision::detail::precision_type val(50);
431       return val;
432    }
433 };
434 
435 } // namespace detail
436 
437 struct gmp_int;
438 struct gmp_rational;
439 
440 template <unsigned digits10>
441 struct gmp_float : public detail::gmp_float_imp<digits10>
442 {
gmp_floatboost::multiprecision::backends::gmp_float443    gmp_float()
444    {
445       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
446    }
gmp_floatboost::multiprecision::backends::gmp_float447    gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {}
448    template <unsigned D>
449    gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= digits10>::type* = 0);
450    template <unsigned D>
451    explicit gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= digits10>::type* = 0);
452    gmp_float(const gmp_int& o);
453    gmp_float(const gmp_rational& o);
gmp_floatboost::multiprecision::backends::gmp_float454    gmp_float(const mpf_t val)
455    {
456       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
457       mpf_set(this->m_data, val);
458    }
gmp_floatboost::multiprecision::backends::gmp_float459    gmp_float(const mpz_t val)
460    {
461       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
462       mpf_set_z(this->m_data, val);
463    }
gmp_floatboost::multiprecision::backends::gmp_float464    gmp_float(const mpq_t val)
465    {
466       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
467       mpf_set_q(this->m_data, val);
468    }
469 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
gmp_floatboost::multiprecision::backends::gmp_float470    gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<digits10>(static_cast<detail::gmp_float_imp<digits10>&&>(o))
471    {}
472 #endif
operator =boost::multiprecision::backends::gmp_float473    gmp_float& operator=(const gmp_float& o)
474    {
475       *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10> const&>(o);
476       return *this;
477    }
478 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::gmp_float479    gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT
480    {
481       *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10>&&>(o);
482       return *this;
483    }
484 #endif
485    template <unsigned D>
486    gmp_float& operator=(const gmp_float<D>& o);
487    gmp_float& operator=(const gmp_int& o);
488    gmp_float& operator=(const gmp_rational& o);
operator =boost::multiprecision::backends::gmp_float489    gmp_float& operator=(const mpf_t val)
490    {
491       if (this->m_data[0]._mp_d == 0)
492          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
493       mpf_set(this->m_data, val);
494       return *this;
495    }
operator =boost::multiprecision::backends::gmp_float496    gmp_float& operator=(const mpz_t val)
497    {
498       if (this->m_data[0]._mp_d == 0)
499          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
500       mpf_set_z(this->m_data, val);
501       return *this;
502    }
operator =boost::multiprecision::backends::gmp_float503    gmp_float& operator=(const mpq_t val)
504    {
505       if (this->m_data[0]._mp_d == 0)
506          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
507       mpf_set_q(this->m_data, val);
508       return *this;
509    }
510    template <class V>
operator =boost::multiprecision::backends::gmp_float511    gmp_float& operator=(const V& v)
512    {
513       *static_cast<detail::gmp_float_imp<digits10>*>(this) = v;
514       return *this;
515    }
516 };
517 
518 template <>
519 struct gmp_float<0> : public detail::gmp_float_imp<0>
520 {
521    //
522    // We have a problem with mpf_t in that the precision we request isn't what we get.
523    // As a result the front end can end up chasing it's tail trying to create a variable
524    // with the the correct precision to hold the result of an expression.
525    // See: https://github.com/boostorg/multiprecision/issues/164
526    // The problem is made worse by the fact that our conversions from base10 to 2 and
527    // vice-versa do not exactly round trip (and probably never will).
528    // The workaround is to keep track of the precision requested, and always return
529    // that as the current actual precision.
530    //
531  private:
532    unsigned requested_precision;
533 
534  public:
gmp_floatboost::multiprecision::backends::gmp_float535    gmp_float() : requested_precision(get_default_precision())
536    {
537       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
538    }
gmp_floatboost::multiprecision::backends::gmp_float539    gmp_float(const mpf_t val) : requested_precision(get_default_precision())
540    {
541       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
542       mpf_set(this->m_data, val);
543    }
gmp_floatboost::multiprecision::backends::gmp_float544    gmp_float(const mpz_t val) : requested_precision(get_default_precision())
545    {
546       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
547       mpf_set_z(this->m_data, val);
548    }
gmp_floatboost::multiprecision::backends::gmp_float549    gmp_float(const mpq_t val) : requested_precision(get_default_precision())
550    {
551       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
552       mpf_set_q(this->m_data, val);
553    }
gmp_floatboost::multiprecision::backends::gmp_float554    gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o), requested_precision(o.requested_precision) {}
555    template <unsigned D>
gmp_floatboost::multiprecision::backends::gmp_float556    gmp_float(const gmp_float<D>& o)
557    {
558       mpf_init2(this->m_data, mpf_get_prec(o.data()));
559       mpf_set(this->m_data, o.data());
560       requested_precision = D;
561    }
562 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
gmp_floatboost::multiprecision::backends::gmp_float563    gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast<detail::gmp_float_imp<0>&&>(o)), requested_precision(o.requested_precision)
564    {}
565 #endif
566    gmp_float(const gmp_int& o);
567    gmp_float(const gmp_rational& o);
gmp_floatboost::multiprecision::backends::gmp_float568    gmp_float(const gmp_float& o, unsigned digits10) : requested_precision(digits10)
569    {
570       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
571       mpf_set(this->m_data, o.data());
572    }
573    template <class V>
gmp_floatboost::multiprecision::backends::gmp_float574    gmp_float(const V& o, unsigned digits10) : requested_precision(digits10)
575    {
576       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
577       *this = o;
578    }
579 
580 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
581    //
582    // Support for new types in C++17
583    //
584    template <class Traits>
gmp_floatboost::multiprecision::backends::gmp_float585    gmp_float(const std::basic_string_view<char, Traits>& o, unsigned digits10) : requested_precision(digits10)
586    {
587       using default_ops::assign_from_string_view;
588       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
589       assign_from_string_view(*this, o);
590    }
591 #endif
operator =boost::multiprecision::backends::gmp_float592    gmp_float& operator=(const gmp_float& o)
593    {
594       *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> const&>(o);
595       requested_precision                           = o.requested_precision;
596       return *this;
597    }
598 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::gmp_float599    gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT
600    {
601       *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0>&&>(o);
602       requested_precision                           = o.requested_precision;
603       return *this;
604    }
605 #endif
606    template <unsigned D>
operator =boost::multiprecision::backends::gmp_float607    gmp_float& operator=(const gmp_float<D>& o)
608    {
609       if (this->m_data[0]._mp_d == 0)
610       {
611          mpf_init2(this->m_data, mpf_get_prec(o.data()));
612       }
613       else
614       {
615          mpf_set_prec(this->m_data, mpf_get_prec(o.data()));
616       }
617       mpf_set(this->m_data, o.data());
618       requested_precision = D;
619       return *this;
620    }
621    gmp_float& operator=(const gmp_int& o);
622    gmp_float& operator=(const gmp_rational& o);
operator =boost::multiprecision::backends::gmp_float623    gmp_float& operator=(const mpf_t val)
624    {
625       if (this->m_data[0]._mp_d == 0)
626       {
627          requested_precision = get_default_precision();
628          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
629       }
630       mpf_set(this->m_data, val);
631       return *this;
632    }
operator =boost::multiprecision::backends::gmp_float633    gmp_float& operator=(const mpz_t val)
634    {
635       if (this->m_data[0]._mp_d == 0)
636       {
637          requested_precision = get_default_precision();
638          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
639       }
640       mpf_set_z(this->m_data, val);
641       return *this;
642    }
operator =boost::multiprecision::backends::gmp_float643    gmp_float& operator=(const mpq_t val)
644    {
645       if (this->m_data[0]._mp_d == 0)
646       {
647          requested_precision = get_default_precision();
648          mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
649       }
650       mpf_set_q(this->m_data, val);
651       return *this;
652    }
653    template <class V>
operator =boost::multiprecision::backends::gmp_float654    gmp_float& operator=(const V& v)
655    {
656       *static_cast<detail::gmp_float_imp<0>*>(this) = v;
657       return *this;
658    }
default_precisionboost::multiprecision::backends::gmp_float659    static unsigned default_precision() BOOST_NOEXCEPT
660    {
661       return get_default_precision();
662    }
default_precisionboost::multiprecision::backends::gmp_float663    static void default_precision(unsigned v) BOOST_NOEXCEPT
664    {
665       get_default_precision() = v;
666    }
precisionboost::multiprecision::backends::gmp_float667    unsigned precision() const BOOST_NOEXCEPT
668    {
669       return requested_precision;
670    }
precisionboost::multiprecision::backends::gmp_float671    void precision(unsigned digits10) BOOST_NOEXCEPT
672    {
673       requested_precision = digits10;
674       mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
675    }
swapboost::multiprecision::backends::gmp_float676    void swap(gmp_float& o)
677    {
678       std::swap(requested_precision, o.requested_precision);
679       gmp_float_imp<0>::swap(o);
680    }
681 };
682 
683 template <unsigned digits10, class T>
eval_eq(const gmp_float<digits10> & a,const T & b)684 inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
685 {
686    return a.compare(b) == 0;
687 }
688 template <unsigned digits10, class T>
eval_lt(const gmp_float<digits10> & a,const T & b)689 inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
690 {
691    return a.compare(b) < 0;
692 }
693 template <unsigned digits10, class T>
eval_gt(const gmp_float<digits10> & a,const T & b)694 inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT
695 {
696    return a.compare(b) > 0;
697 }
698 
699 template <unsigned D1, unsigned D2>
eval_add(gmp_float<D1> & result,const gmp_float<D2> & o)700 inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o)
701 {
702    mpf_add(result.data(), result.data(), o.data());
703 }
704 template <unsigned D1, unsigned D2>
eval_subtract(gmp_float<D1> & result,const gmp_float<D2> & o)705 inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o)
706 {
707    mpf_sub(result.data(), result.data(), o.data());
708 }
709 template <unsigned D1, unsigned D2>
eval_multiply(gmp_float<D1> & result,const gmp_float<D2> & o)710 inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o)
711 {
712    mpf_mul(result.data(), result.data(), o.data());
713 }
714 template <unsigned digits10>
eval_is_zero(const gmp_float<digits10> & val)715 inline bool eval_is_zero(const gmp_float<digits10>& val) BOOST_NOEXCEPT
716 {
717    return mpf_sgn(val.data()) == 0;
718 }
719 template <unsigned D1, unsigned D2>
eval_divide(gmp_float<D1> & result,const gmp_float<D2> & o)720 inline void eval_divide(gmp_float<D1>& result, const gmp_float<D2>& o)
721 {
722    if (eval_is_zero(o))
723       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
724    mpf_div(result.data(), result.data(), o.data());
725 }
726 template <unsigned digits10>
eval_add(gmp_float<digits10> & result,unsigned long i)727 inline void eval_add(gmp_float<digits10>& result, unsigned long i)
728 {
729    mpf_add_ui(result.data(), result.data(), i);
730 }
731 template <unsigned digits10>
eval_subtract(gmp_float<digits10> & result,unsigned long i)732 inline void eval_subtract(gmp_float<digits10>& result, unsigned long i)
733 {
734    mpf_sub_ui(result.data(), result.data(), i);
735 }
736 template <unsigned digits10>
eval_multiply(gmp_float<digits10> & result,unsigned long i)737 inline void eval_multiply(gmp_float<digits10>& result, unsigned long i)
738 {
739    mpf_mul_ui(result.data(), result.data(), i);
740 }
741 template <unsigned digits10>
eval_divide(gmp_float<digits10> & result,unsigned long i)742 inline void eval_divide(gmp_float<digits10>& result, unsigned long i)
743 {
744    if (i == 0)
745       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
746    mpf_div_ui(result.data(), result.data(), i);
747 }
748 template <unsigned digits10>
eval_add(gmp_float<digits10> & result,long i)749 inline void eval_add(gmp_float<digits10>& result, long i)
750 {
751    if (i > 0)
752       mpf_add_ui(result.data(), result.data(), i);
753    else
754       mpf_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
755 }
756 template <unsigned digits10>
eval_subtract(gmp_float<digits10> & result,long i)757 inline void eval_subtract(gmp_float<digits10>& result, long i)
758 {
759    if (i > 0)
760       mpf_sub_ui(result.data(), result.data(), i);
761    else
762       mpf_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
763 }
764 template <unsigned digits10>
eval_multiply(gmp_float<digits10> & result,long i)765 inline void eval_multiply(gmp_float<digits10>& result, long i)
766 {
767    mpf_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
768    if (i < 0)
769       mpf_neg(result.data(), result.data());
770 }
771 template <unsigned digits10>
eval_divide(gmp_float<digits10> & result,long i)772 inline void eval_divide(gmp_float<digits10>& result, long i)
773 {
774    if (i == 0)
775       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
776    mpf_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
777    if (i < 0)
778       mpf_neg(result.data(), result.data());
779 }
780 //
781 // Specialised 3 arg versions of the basic operators:
782 //
783 template <unsigned D1, unsigned D2, unsigned D3>
eval_add(gmp_float<D1> & a,const gmp_float<D2> & x,const gmp_float<D3> & y)784 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
785 {
786    mpf_add(a.data(), x.data(), y.data());
787 }
788 template <unsigned D1, unsigned D2>
eval_add(gmp_float<D1> & a,const gmp_float<D2> & x,unsigned long y)789 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
790 {
791    mpf_add_ui(a.data(), x.data(), y);
792 }
793 template <unsigned D1, unsigned D2>
eval_add(gmp_float<D1> & a,const gmp_float<D2> & x,long y)794 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
795 {
796    if (y < 0)
797       mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
798    else
799       mpf_add_ui(a.data(), x.data(), y);
800 }
801 template <unsigned D1, unsigned D2>
eval_add(gmp_float<D1> & a,unsigned long x,const gmp_float<D2> & y)802 inline void eval_add(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
803 {
804    mpf_add_ui(a.data(), y.data(), x);
805 }
806 template <unsigned D1, unsigned D2>
eval_add(gmp_float<D1> & a,long x,const gmp_float<D2> & y)807 inline void eval_add(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
808 {
809    if (x < 0)
810    {
811       mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
812       mpf_neg(a.data(), a.data());
813    }
814    else
815       mpf_add_ui(a.data(), y.data(), x);
816 }
817 template <unsigned D1, unsigned D2, unsigned D3>
eval_subtract(gmp_float<D1> & a,const gmp_float<D2> & x,const gmp_float<D3> & y)818 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
819 {
820    mpf_sub(a.data(), x.data(), y.data());
821 }
822 template <unsigned D1, unsigned D2>
eval_subtract(gmp_float<D1> & a,const gmp_float<D2> & x,unsigned long y)823 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
824 {
825    mpf_sub_ui(a.data(), x.data(), y);
826 }
827 template <unsigned D1, unsigned D2>
eval_subtract(gmp_float<D1> & a,const gmp_float<D2> & x,long y)828 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
829 {
830    if (y < 0)
831       mpf_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
832    else
833       mpf_sub_ui(a.data(), x.data(), y);
834 }
835 template <unsigned D1, unsigned D2>
eval_subtract(gmp_float<D1> & a,unsigned long x,const gmp_float<D2> & y)836 inline void eval_subtract(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
837 {
838    mpf_ui_sub(a.data(), x, y.data());
839 }
840 template <unsigned D1, unsigned D2>
eval_subtract(gmp_float<D1> & a,long x,const gmp_float<D2> & y)841 inline void eval_subtract(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
842 {
843    if (x < 0)
844    {
845       mpf_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
846       mpf_neg(a.data(), a.data());
847    }
848    else
849       mpf_ui_sub(a.data(), x, y.data());
850 }
851 
852 template <unsigned D1, unsigned D2, unsigned D3>
eval_multiply(gmp_float<D1> & a,const gmp_float<D2> & x,const gmp_float<D3> & y)853 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
854 {
855    mpf_mul(a.data(), x.data(), y.data());
856 }
857 template <unsigned D1, unsigned D2>
eval_multiply(gmp_float<D1> & a,const gmp_float<D2> & x,unsigned long y)858 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
859 {
860    mpf_mul_ui(a.data(), x.data(), y);
861 }
862 template <unsigned D1, unsigned D2>
eval_multiply(gmp_float<D1> & a,const gmp_float<D2> & x,long y)863 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
864 {
865    if (y < 0)
866    {
867       mpf_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
868       a.negate();
869    }
870    else
871       mpf_mul_ui(a.data(), x.data(), y);
872 }
873 template <unsigned D1, unsigned D2>
eval_multiply(gmp_float<D1> & a,unsigned long x,const gmp_float<D2> & y)874 inline void eval_multiply(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
875 {
876    mpf_mul_ui(a.data(), y.data(), x);
877 }
878 template <unsigned D1, unsigned D2>
eval_multiply(gmp_float<D1> & a,long x,const gmp_float<D2> & y)879 inline void eval_multiply(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
880 {
881    if (x < 0)
882    {
883       mpf_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
884       mpf_neg(a.data(), a.data());
885    }
886    else
887       mpf_mul_ui(a.data(), y.data(), x);
888 }
889 
890 template <unsigned D1, unsigned D2, unsigned D3>
eval_divide(gmp_float<D1> & a,const gmp_float<D2> & x,const gmp_float<D3> & y)891 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
892 {
893    if (eval_is_zero(y))
894       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
895    mpf_div(a.data(), x.data(), y.data());
896 }
897 template <unsigned D1, unsigned D2>
eval_divide(gmp_float<D1> & a,const gmp_float<D2> & x,unsigned long y)898 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
899 {
900    if (y == 0)
901       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
902    mpf_div_ui(a.data(), x.data(), y);
903 }
904 template <unsigned D1, unsigned D2>
eval_divide(gmp_float<D1> & a,const gmp_float<D2> & x,long y)905 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
906 {
907    if (y == 0)
908       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
909    if (y < 0)
910    {
911       mpf_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
912       a.negate();
913    }
914    else
915       mpf_div_ui(a.data(), x.data(), y);
916 }
917 template <unsigned D1, unsigned D2>
eval_divide(gmp_float<D1> & a,unsigned long x,const gmp_float<D2> & y)918 inline void eval_divide(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
919 {
920    if (eval_is_zero(y))
921       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
922    mpf_ui_div(a.data(), x, y.data());
923 }
924 template <unsigned D1, unsigned D2>
eval_divide(gmp_float<D1> & a,long x,const gmp_float<D2> & y)925 inline void eval_divide(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
926 {
927    if (eval_is_zero(y))
928       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
929    if (x < 0)
930    {
931       mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
932       mpf_neg(a.data(), a.data());
933    }
934    else
935       mpf_ui_div(a.data(), x, y.data());
936 }
937 
938 template <unsigned digits10>
eval_get_sign(const gmp_float<digits10> & val)939 inline int eval_get_sign(const gmp_float<digits10>& val) BOOST_NOEXCEPT
940 {
941    return mpf_sgn(val.data());
942 }
943 
944 template <unsigned digits10>
eval_convert_to(unsigned long * result,const gmp_float<digits10> & val)945 inline void eval_convert_to(unsigned long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
946 {
947    if (0 == mpf_fits_ulong_p(val.data()))
948       *result = (std::numeric_limits<unsigned long>::max)();
949    else
950       *result = (unsigned long)mpf_get_ui(val.data());
951 }
952 template <unsigned digits10>
eval_convert_to(long * result,const gmp_float<digits10> & val)953 inline void eval_convert_to(long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
954 {
955    if (0 == mpf_fits_slong_p(val.data()))
956    {
957       *result = (std::numeric_limits<long>::max)();
958       *result *= mpf_sgn(val.data());
959    }
960    else
961       *result = (long)mpf_get_si(val.data());
962 }
963 template <unsigned digits10>
eval_convert_to(double * result,const gmp_float<digits10> & val)964 inline void eval_convert_to(double* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT
965 {
966    *result = mpf_get_d(val.data());
967 }
968 #ifdef BOOST_HAS_LONG_LONG
969 template <unsigned digits10>
eval_convert_to(boost::long_long_type * result,const gmp_float<digits10> & val)970 inline void eval_convert_to(boost::long_long_type* result, const gmp_float<digits10>& val)
971 {
972    gmp_float<digits10> t(val);
973    if (eval_get_sign(t) < 0)
974       t.negate();
975 
976    long digits = std::numeric_limits<boost::long_long_type>::digits - std::numeric_limits<long>::digits;
977 
978    if (digits > 0)
979       mpf_div_2exp(t.data(), t.data(), digits);
980 
981    if (!mpf_fits_slong_p(t.data()))
982    {
983       if (eval_get_sign(val) < 0)
984          *result = (std::numeric_limits<boost::long_long_type>::min)();
985       else
986          *result = (std::numeric_limits<boost::long_long_type>::max)();
987       return;
988    };
989 
990    *result = mpf_get_si(t.data());
991    while (digits > 0)
992    {
993       *result <<= digits;
994       digits -= std::numeric_limits<unsigned long>::digits;
995       mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
996       unsigned long l = (unsigned long)mpf_get_ui(t.data());
997       if (digits < 0)
998          l >>= -digits;
999       *result |= l;
1000    }
1001    if (eval_get_sign(val) < 0)
1002       *result = -*result;
1003 }
1004 template <unsigned digits10>
eval_convert_to(boost::ulong_long_type * result,const gmp_float<digits10> & val)1005 inline void eval_convert_to(boost::ulong_long_type* result, const gmp_float<digits10>& val)
1006 {
1007    gmp_float<digits10> t(val);
1008 
1009    long digits = std::numeric_limits<boost::long_long_type>::digits - std::numeric_limits<long>::digits;
1010 
1011    if (digits > 0)
1012       mpf_div_2exp(t.data(), t.data(), digits);
1013 
1014    if (!mpf_fits_ulong_p(t.data()))
1015    {
1016       *result = (std::numeric_limits<boost::long_long_type>::max)();
1017       return;
1018    }
1019 
1020    *result = mpf_get_ui(t.data());
1021    while (digits > 0)
1022    {
1023       *result <<= digits;
1024       digits -= std::numeric_limits<unsigned long>::digits;
1025       mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
1026       unsigned long l = (unsigned long)mpf_get_ui(t.data());
1027       if (digits < 0)
1028          l >>= -digits;
1029       *result |= l;
1030    }
1031 }
1032 #endif
1033 
1034 //
1035 // Native non-member operations:
1036 //
1037 template <unsigned Digits10>
eval_sqrt(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1038 inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1039 {
1040    mpf_sqrt(result.data(), val.data());
1041 }
1042 
1043 template <unsigned Digits10>
eval_abs(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1044 inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1045 {
1046    mpf_abs(result.data(), val.data());
1047 }
1048 
1049 template <unsigned Digits10>
eval_fabs(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1050 inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1051 {
1052    mpf_abs(result.data(), val.data());
1053 }
1054 template <unsigned Digits10>
eval_ceil(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1055 inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1056 {
1057    mpf_ceil(result.data(), val.data());
1058 }
1059 template <unsigned Digits10>
eval_floor(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1060 inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1061 {
1062    mpf_floor(result.data(), val.data());
1063 }
1064 template <unsigned Digits10>
eval_trunc(gmp_float<Digits10> & result,const gmp_float<Digits10> & val)1065 inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1066 {
1067    mpf_trunc(result.data(), val.data());
1068 }
1069 template <unsigned Digits10>
eval_ldexp(gmp_float<Digits10> & result,const gmp_float<Digits10> & val,long e)1070 inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long e)
1071 {
1072    if (e > 0)
1073       mpf_mul_2exp(result.data(), val.data(), e);
1074    else if (e < 0)
1075       mpf_div_2exp(result.data(), val.data(), -e);
1076    else
1077       result = val;
1078 }
1079 template <unsigned Digits10>
eval_frexp(gmp_float<Digits10> & result,const gmp_float<Digits10> & val,int * e)1080 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
1081 {
1082 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1083    mpir_si v;
1084    mpf_get_d_2exp(&v, val.data());
1085 #else
1086    long                             v;
1087    mpf_get_d_2exp(&v, val.data());
1088 #endif
1089    *e = v;
1090    eval_ldexp(result, val, -v);
1091 }
1092 template <unsigned Digits10>
eval_frexp(gmp_float<Digits10> & result,const gmp_float<Digits10> & val,long * e)1093 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
1094 {
1095 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1096    mpir_si v;
1097    mpf_get_d_2exp(&v, val.data());
1098    *e = v;
1099    eval_ldexp(result, val, -v);
1100 #else
1101    mpf_get_d_2exp(e, val.data());
1102    eval_ldexp(result, val, -*e);
1103 #endif
1104 }
1105 
1106 template <unsigned Digits10>
hash_value(const gmp_float<Digits10> & val)1107 inline std::size_t hash_value(const gmp_float<Digits10>& val)
1108 {
1109    std::size_t result = 0;
1110    for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
1111       boost::hash_combine(result, val.data()[0]._mp_d[i]);
1112    boost::hash_combine(result, val.data()[0]._mp_exp);
1113    boost::hash_combine(result, val.data()[0]._mp_size);
1114    return result;
1115 }
1116 
1117 struct gmp_int
1118 {
1119 #ifdef BOOST_HAS_LONG_LONG
1120    typedef mpl::list<long, boost::long_long_type>           signed_types;
1121    typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
1122 #else
1123    typedef mpl::list<long>          signed_types;
1124    typedef mpl::list<unsigned long> unsigned_types;
1125 #endif
1126    typedef mpl::list<double, long double> float_types;
1127 
gmp_intboost::multiprecision::backends::gmp_int1128    gmp_int()
1129    {
1130       mpz_init(this->m_data);
1131    }
gmp_intboost::multiprecision::backends::gmp_int1132    gmp_int(const gmp_int& o)
1133    {
1134       if (o.m_data[0]._mp_d)
1135          mpz_init_set(m_data, o.m_data);
1136       else
1137          mpz_init(this->m_data);
1138    }
1139 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
gmp_intboost::multiprecision::backends::gmp_int1140    gmp_int(gmp_int&& o) BOOST_NOEXCEPT
1141    {
1142       m_data[0]         = o.m_data[0];
1143       o.m_data[0]._mp_d = 0;
1144    }
1145 #endif
gmp_intboost::multiprecision::backends::gmp_int1146    explicit gmp_int(const mpf_t val)
1147    {
1148       mpz_init(this->m_data);
1149       mpz_set_f(this->m_data, val);
1150    }
gmp_intboost::multiprecision::backends::gmp_int1151    gmp_int(const mpz_t val)
1152    {
1153       mpz_init_set(this->m_data, val);
1154    }
gmp_intboost::multiprecision::backends::gmp_int1155    explicit gmp_int(const mpq_t val)
1156    {
1157       mpz_init(this->m_data);
1158       mpz_set_q(this->m_data, val);
1159    }
1160    template <unsigned Digits10>
gmp_intboost::multiprecision::backends::gmp_int1161    explicit gmp_int(const gmp_float<Digits10>& o)
1162    {
1163       mpz_init(this->m_data);
1164       mpz_set_f(this->m_data, o.data());
1165    }
1166    explicit gmp_int(const gmp_rational& o);
operator =boost::multiprecision::backends::gmp_int1167    gmp_int& operator=(const gmp_int& o)
1168    {
1169       if (m_data[0]._mp_d == 0)
1170          mpz_init(this->m_data);
1171       mpz_set(m_data, o.m_data);
1172       return *this;
1173    }
1174 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::gmp_int1175    gmp_int& operator=(gmp_int&& o) BOOST_NOEXCEPT
1176    {
1177       mpz_swap(m_data, o.m_data);
1178       return *this;
1179    }
1180 #endif
1181 #ifdef BOOST_HAS_LONG_LONG
1182 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
operator =boost::multiprecision::backends::gmp_int1183    gmp_int& operator=(boost::ulong_long_type i)
1184    {
1185       *this = static_cast<unsigned long>(i);
1186       return *this;
1187    }
1188 #else
operator =boost::multiprecision::backends::gmp_int1189    gmp_int& operator=(boost::ulong_long_type i)
1190    {
1191       if (m_data[0]._mp_d == 0)
1192          mpz_init(this->m_data);
1193       boost::ulong_long_type mask  = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
1194       unsigned               shift = 0;
1195       mpz_t                  t;
1196       mpz_set_ui(m_data, 0);
1197       mpz_init_set_ui(t, 0);
1198       while (i)
1199       {
1200          mpz_set_ui(t, static_cast<unsigned long>(i & mask));
1201          if (shift)
1202             mpz_mul_2exp(t, t, shift);
1203          mpz_add(m_data, m_data, t);
1204          shift += std::numeric_limits<unsigned long>::digits;
1205          i >>= std::numeric_limits<unsigned long>::digits;
1206       }
1207       mpz_clear(t);
1208       return *this;
1209    }
1210 #endif
operator =boost::multiprecision::backends::gmp_int1211    gmp_int& operator=(boost::long_long_type i)
1212    {
1213       if (m_data[0]._mp_d == 0)
1214          mpz_init(this->m_data);
1215       bool neg = i < 0;
1216       *this    = boost::multiprecision::detail::unsigned_abs(i);
1217       if (neg)
1218          mpz_neg(m_data, m_data);
1219       return *this;
1220    }
1221 #endif
operator =boost::multiprecision::backends::gmp_int1222    gmp_int& operator=(unsigned long i)
1223    {
1224       if (m_data[0]._mp_d == 0)
1225          mpz_init(this->m_data);
1226       mpz_set_ui(m_data, i);
1227       return *this;
1228    }
operator =boost::multiprecision::backends::gmp_int1229    gmp_int& operator=(long i)
1230    {
1231       if (m_data[0]._mp_d == 0)
1232          mpz_init(this->m_data);
1233       mpz_set_si(m_data, i);
1234       return *this;
1235    }
operator =boost::multiprecision::backends::gmp_int1236    gmp_int& operator=(double d)
1237    {
1238       if (m_data[0]._mp_d == 0)
1239          mpz_init(this->m_data);
1240       mpz_set_d(m_data, d);
1241       return *this;
1242    }
operator =boost::multiprecision::backends::gmp_int1243    gmp_int& operator=(long double a)
1244    {
1245       using std::floor;
1246       using std::frexp;
1247       using std::ldexp;
1248 
1249       if (m_data[0]._mp_d == 0)
1250          mpz_init(this->m_data);
1251 
1252       if (a == 0)
1253       {
1254          mpz_set_si(m_data, 0);
1255          return *this;
1256       }
1257 
1258       if (a == 1)
1259       {
1260          mpz_set_si(m_data, 1);
1261          return *this;
1262       }
1263 
1264       BOOST_ASSERT(!(boost::math::isinf)(a));
1265       BOOST_ASSERT(!(boost::math::isnan)(a));
1266 
1267       int         e;
1268       long double f, term;
1269       mpz_set_ui(m_data, 0u);
1270 
1271       f = frexp(a, &e);
1272 
1273       static const int shift = std::numeric_limits<int>::digits - 1;
1274 
1275       while (f)
1276       {
1277          // extract int sized bits from f:
1278          f    = ldexp(f, shift);
1279          term = floor(f);
1280          e -= shift;
1281          mpz_mul_2exp(m_data, m_data, shift);
1282          if (term > 0)
1283             mpz_add_ui(m_data, m_data, static_cast<unsigned>(term));
1284          else
1285             mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
1286          f -= term;
1287       }
1288       if (e > 0)
1289          mpz_mul_2exp(m_data, m_data, e);
1290       else if (e < 0)
1291          mpz_div_2exp(m_data, m_data, -e);
1292       return *this;
1293    }
operator =boost::multiprecision::backends::gmp_int1294    gmp_int& operator=(const char* s)
1295    {
1296       if (m_data[0]._mp_d == 0)
1297          mpz_init(this->m_data);
1298       std::size_t n     = s ? std::strlen(s) : 0;
1299       int         radix = 10;
1300       if (n && (*s == '0'))
1301       {
1302          if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1303          {
1304             radix = 16;
1305             s += 2;
1306             n -= 2;
1307          }
1308          else
1309          {
1310             radix = 8;
1311             n -= 1;
1312          }
1313       }
1314       if (n)
1315       {
1316          if (0 != mpz_set_str(m_data, s, radix))
1317             BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer.")));
1318       }
1319       else
1320          mpz_set_ui(m_data, 0);
1321       return *this;
1322    }
operator =boost::multiprecision::backends::gmp_int1323    gmp_int& operator=(const mpf_t val)
1324    {
1325       if (m_data[0]._mp_d == 0)
1326          mpz_init(this->m_data);
1327       mpz_set_f(this->m_data, val);
1328       return *this;
1329    }
operator =boost::multiprecision::backends::gmp_int1330    gmp_int& operator=(const mpz_t val)
1331    {
1332       if (m_data[0]._mp_d == 0)
1333          mpz_init(this->m_data);
1334       mpz_set(this->m_data, val);
1335       return *this;
1336    }
operator =boost::multiprecision::backends::gmp_int1337    gmp_int& operator=(const mpq_t val)
1338    {
1339       if (m_data[0]._mp_d == 0)
1340          mpz_init(this->m_data);
1341       mpz_set_q(this->m_data, val);
1342       return *this;
1343    }
1344    template <unsigned Digits10>
operator =boost::multiprecision::backends::gmp_int1345    gmp_int& operator=(const gmp_float<Digits10>& o)
1346    {
1347       if (m_data[0]._mp_d == 0)
1348          mpz_init(this->m_data);
1349       mpz_set_f(this->m_data, o.data());
1350       return *this;
1351    }
1352    gmp_int& operator=(const gmp_rational& o);
swapboost::multiprecision::backends::gmp_int1353    void     swap(gmp_int& o)
1354    {
1355       mpz_swap(m_data, o.m_data);
1356    }
strboost::multiprecision::backends::gmp_int1357    std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const
1358    {
1359       BOOST_ASSERT(m_data[0]._mp_d);
1360 
1361       int base = 10;
1362       if ((f & std::ios_base::oct) == std::ios_base::oct)
1363          base = 8;
1364       else if ((f & std::ios_base::hex) == std::ios_base::hex)
1365          base = 16;
1366       //
1367       // sanity check, bases 8 and 16 are only available for positive numbers:
1368       //
1369       if ((base != 10) && (mpz_sgn(m_data) < 0))
1370          BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
1371       void* (*alloc_func_ptr)(size_t);
1372       void* (*realloc_func_ptr)(void*, size_t, size_t);
1373       void (*free_func_ptr)(void*, size_t);
1374       const char* ps = mpz_get_str(0, base, m_data);
1375       std::string s  = ps;
1376       mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
1377       (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
1378       if (f & std::ios_base::uppercase)
1379          for (size_t i = 0; i < s.length(); ++i)
1380             s[i] = std::toupper(s[i]);
1381       if ((base != 10) && (f & std::ios_base::showbase))
1382       {
1383          int         pos = s[0] == '-' ? 1 : 0;
1384          const char* pp  = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
1385          s.insert(static_cast<std::string::size_type>(pos), pp);
1386       }
1387       if ((f & std::ios_base::showpos) && (s[0] != '-'))
1388          s.insert(static_cast<std::string::size_type>(0), 1, '+');
1389 
1390       return s;
1391    }
~gmp_intboost::multiprecision::backends::gmp_int1392    ~gmp_int() BOOST_NOEXCEPT
1393    {
1394       if (m_data[0]._mp_d)
1395          mpz_clear(m_data);
1396    }
negateboost::multiprecision::backends::gmp_int1397    void negate() BOOST_NOEXCEPT
1398    {
1399       BOOST_ASSERT(m_data[0]._mp_d);
1400       mpz_neg(m_data, m_data);
1401    }
compareboost::multiprecision::backends::gmp_int1402    int compare(const gmp_int& o) const BOOST_NOEXCEPT
1403    {
1404       BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
1405       return mpz_cmp(m_data, o.m_data);
1406    }
compareboost::multiprecision::backends::gmp_int1407    int compare(long i) const BOOST_NOEXCEPT
1408    {
1409       BOOST_ASSERT(m_data[0]._mp_d);
1410       return mpz_cmp_si(m_data, i);
1411    }
compareboost::multiprecision::backends::gmp_int1412    int compare(unsigned long i) const BOOST_NOEXCEPT
1413    {
1414       BOOST_ASSERT(m_data[0]._mp_d);
1415       return mpz_cmp_ui(m_data, i);
1416    }
1417    template <class V>
compareboost::multiprecision::backends::gmp_int1418    int compare(V v) const
1419    {
1420       gmp_int d;
1421       d = v;
1422       return compare(d);
1423    }
databoost::multiprecision::backends::gmp_int1424    mpz_t& data() BOOST_NOEXCEPT
1425    {
1426       BOOST_ASSERT(m_data[0]._mp_d);
1427       return m_data;
1428    }
databoost::multiprecision::backends::gmp_int1429    const mpz_t& data() const BOOST_NOEXCEPT
1430    {
1431       BOOST_ASSERT(m_data[0]._mp_d);
1432       return m_data;
1433    }
1434 
1435  protected:
1436    mpz_t m_data;
1437 };
1438 
1439 template <class T>
eval_eq(const gmp_int & a,const T & b)1440 inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const gmp_int& a, const T& b)
1441 {
1442    return a.compare(b) == 0;
1443 }
1444 template <class T>
eval_lt(const gmp_int & a,const T & b)1445 inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const gmp_int& a, const T& b)
1446 {
1447    return a.compare(b) < 0;
1448 }
1449 template <class T>
eval_gt(const gmp_int & a,const T & b)1450 inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const gmp_int& a, const T& b)
1451 {
1452    return a.compare(b) > 0;
1453 }
1454 
eval_is_zero(const gmp_int & val)1455 inline bool eval_is_zero(const gmp_int& val)
1456 {
1457    return mpz_sgn(val.data()) == 0;
1458 }
eval_add(gmp_int & t,const gmp_int & o)1459 inline void eval_add(gmp_int& t, const gmp_int& o)
1460 {
1461    mpz_add(t.data(), t.data(), o.data());
1462 }
eval_multiply_add(gmp_int & t,const gmp_int & a,const gmp_int & b)1463 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b)
1464 {
1465    mpz_addmul(t.data(), a.data(), b.data());
1466 }
eval_multiply_subtract(gmp_int & t,const gmp_int & a,const gmp_int & b)1467 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b)
1468 {
1469    mpz_submul(t.data(), a.data(), b.data());
1470 }
eval_subtract(gmp_int & t,const gmp_int & o)1471 inline void eval_subtract(gmp_int& t, const gmp_int& o)
1472 {
1473    mpz_sub(t.data(), t.data(), o.data());
1474 }
eval_multiply(gmp_int & t,const gmp_int & o)1475 inline void eval_multiply(gmp_int& t, const gmp_int& o)
1476 {
1477    mpz_mul(t.data(), t.data(), o.data());
1478 }
eval_divide(gmp_int & t,const gmp_int & o)1479 inline void eval_divide(gmp_int& t, const gmp_int& o)
1480 {
1481    if (eval_is_zero(o))
1482       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1483    mpz_tdiv_q(t.data(), t.data(), o.data());
1484 }
eval_modulus(gmp_int & t,const gmp_int & o)1485 inline void eval_modulus(gmp_int& t, const gmp_int& o)
1486 {
1487    mpz_tdiv_r(t.data(), t.data(), o.data());
1488 }
eval_add(gmp_int & t,unsigned long i)1489 inline void eval_add(gmp_int& t, unsigned long i)
1490 {
1491    mpz_add_ui(t.data(), t.data(), i);
1492 }
eval_multiply_add(gmp_int & t,const gmp_int & a,unsigned long i)1493 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i)
1494 {
1495    mpz_addmul_ui(t.data(), a.data(), i);
1496 }
eval_multiply_subtract(gmp_int & t,const gmp_int & a,unsigned long i)1497 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i)
1498 {
1499    mpz_submul_ui(t.data(), a.data(), i);
1500 }
eval_subtract(gmp_int & t,unsigned long i)1501 inline void eval_subtract(gmp_int& t, unsigned long i)
1502 {
1503    mpz_sub_ui(t.data(), t.data(), i);
1504 }
eval_multiply(gmp_int & t,unsigned long i)1505 inline void eval_multiply(gmp_int& t, unsigned long i)
1506 {
1507    mpz_mul_ui(t.data(), t.data(), i);
1508 }
eval_modulus(gmp_int & t,unsigned long i)1509 inline void eval_modulus(gmp_int& t, unsigned long i)
1510 {
1511    mpz_tdiv_r_ui(t.data(), t.data(), i);
1512 }
eval_divide(gmp_int & t,unsigned long i)1513 inline void eval_divide(gmp_int& t, unsigned long i)
1514 {
1515    if (i == 0)
1516       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1517    mpz_tdiv_q_ui(t.data(), t.data(), i);
1518 }
eval_add(gmp_int & t,long i)1519 inline void eval_add(gmp_int& t, long i)
1520 {
1521    if (i > 0)
1522       mpz_add_ui(t.data(), t.data(), i);
1523    else
1524       mpz_sub_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1525 }
eval_multiply_add(gmp_int & t,const gmp_int & a,long i)1526 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i)
1527 {
1528    if (i > 0)
1529       mpz_addmul_ui(t.data(), a.data(), i);
1530    else
1531       mpz_submul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i));
1532 }
eval_multiply_subtract(gmp_int & t,const gmp_int & a,long i)1533 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i)
1534 {
1535    if (i > 0)
1536       mpz_submul_ui(t.data(), a.data(), i);
1537    else
1538       mpz_addmul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i));
1539 }
eval_subtract(gmp_int & t,long i)1540 inline void eval_subtract(gmp_int& t, long i)
1541 {
1542    if (i > 0)
1543       mpz_sub_ui(t.data(), t.data(), i);
1544    else
1545       mpz_add_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1546 }
eval_multiply(gmp_int & t,long i)1547 inline void eval_multiply(gmp_int& t, long i)
1548 {
1549    mpz_mul_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1550    if (i < 0)
1551       mpz_neg(t.data(), t.data());
1552 }
eval_modulus(gmp_int & t,long i)1553 inline void eval_modulus(gmp_int& t, long i)
1554 {
1555    mpz_tdiv_r_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1556 }
eval_divide(gmp_int & t,long i)1557 inline void eval_divide(gmp_int& t, long i)
1558 {
1559    if (i == 0)
1560       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1561    mpz_tdiv_q_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1562    if (i < 0)
1563       mpz_neg(t.data(), t.data());
1564 }
1565 template <class UI>
eval_left_shift(gmp_int & t,UI i)1566 inline void eval_left_shift(gmp_int& t, UI i)
1567 {
1568    mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1569 }
1570 template <class UI>
eval_right_shift(gmp_int & t,UI i)1571 inline void eval_right_shift(gmp_int& t, UI i)
1572 {
1573    mpz_fdiv_q_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1574 }
1575 template <class UI>
eval_left_shift(gmp_int & t,const gmp_int & v,UI i)1576 inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i)
1577 {
1578    mpz_mul_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1579 }
1580 template <class UI>
eval_right_shift(gmp_int & t,const gmp_int & v,UI i)1581 inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i)
1582 {
1583    mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1584 }
1585 
eval_bitwise_and(gmp_int & result,const gmp_int & v)1586 inline void eval_bitwise_and(gmp_int& result, const gmp_int& v)
1587 {
1588    mpz_and(result.data(), result.data(), v.data());
1589 }
1590 
eval_bitwise_or(gmp_int & result,const gmp_int & v)1591 inline void eval_bitwise_or(gmp_int& result, const gmp_int& v)
1592 {
1593    mpz_ior(result.data(), result.data(), v.data());
1594 }
1595 
eval_bitwise_xor(gmp_int & result,const gmp_int & v)1596 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v)
1597 {
1598    mpz_xor(result.data(), result.data(), v.data());
1599 }
1600 
eval_add(gmp_int & t,const gmp_int & p,const gmp_int & o)1601 inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o)
1602 {
1603    mpz_add(t.data(), p.data(), o.data());
1604 }
eval_subtract(gmp_int & t,const gmp_int & p,const gmp_int & o)1605 inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
1606 {
1607    mpz_sub(t.data(), p.data(), o.data());
1608 }
eval_multiply(gmp_int & t,const gmp_int & p,const gmp_int & o)1609 inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
1610 {
1611    mpz_mul(t.data(), p.data(), o.data());
1612 }
eval_divide(gmp_int & t,const gmp_int & p,const gmp_int & o)1613 inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
1614 {
1615    if (eval_is_zero(o))
1616       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1617    mpz_tdiv_q(t.data(), p.data(), o.data());
1618 }
eval_modulus(gmp_int & t,const gmp_int & p,const gmp_int & o)1619 inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
1620 {
1621    mpz_tdiv_r(t.data(), p.data(), o.data());
1622 }
eval_add(gmp_int & t,const gmp_int & p,unsigned long i)1623 inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i)
1624 {
1625    mpz_add_ui(t.data(), p.data(), i);
1626 }
eval_subtract(gmp_int & t,const gmp_int & p,unsigned long i)1627 inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i)
1628 {
1629    mpz_sub_ui(t.data(), p.data(), i);
1630 }
eval_multiply(gmp_int & t,const gmp_int & p,unsigned long i)1631 inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i)
1632 {
1633    mpz_mul_ui(t.data(), p.data(), i);
1634 }
eval_modulus(gmp_int & t,const gmp_int & p,unsigned long i)1635 inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i)
1636 {
1637    mpz_tdiv_r_ui(t.data(), p.data(), i);
1638 }
eval_divide(gmp_int & t,const gmp_int & p,unsigned long i)1639 inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i)
1640 {
1641    if (i == 0)
1642       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1643    mpz_tdiv_q_ui(t.data(), p.data(), i);
1644 }
eval_add(gmp_int & t,const gmp_int & p,long i)1645 inline void eval_add(gmp_int& t, const gmp_int& p, long i)
1646 {
1647    if (i > 0)
1648       mpz_add_ui(t.data(), p.data(), i);
1649    else
1650       mpz_sub_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1651 }
eval_subtract(gmp_int & t,const gmp_int & p,long i)1652 inline void eval_subtract(gmp_int& t, const gmp_int& p, long i)
1653 {
1654    if (i > 0)
1655       mpz_sub_ui(t.data(), p.data(), i);
1656    else
1657       mpz_add_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1658 }
eval_multiply(gmp_int & t,const gmp_int & p,long i)1659 inline void eval_multiply(gmp_int& t, const gmp_int& p, long i)
1660 {
1661    mpz_mul_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1662    if (i < 0)
1663       mpz_neg(t.data(), t.data());
1664 }
eval_modulus(gmp_int & t,const gmp_int & p,long i)1665 inline void eval_modulus(gmp_int& t, const gmp_int& p, long i)
1666 {
1667    mpz_tdiv_r_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1668 }
eval_divide(gmp_int & t,const gmp_int & p,long i)1669 inline void eval_divide(gmp_int& t, const gmp_int& p, long i)
1670 {
1671    if (i == 0)
1672       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1673    mpz_tdiv_q_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1674    if (i < 0)
1675       mpz_neg(t.data(), t.data());
1676 }
1677 
eval_bitwise_and(gmp_int & result,const gmp_int & u,const gmp_int & v)1678 inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v)
1679 {
1680    mpz_and(result.data(), u.data(), v.data());
1681 }
1682 
eval_bitwise_or(gmp_int & result,const gmp_int & u,const gmp_int & v)1683 inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v)
1684 {
1685    mpz_ior(result.data(), u.data(), v.data());
1686 }
1687 
eval_bitwise_xor(gmp_int & result,const gmp_int & u,const gmp_int & v)1688 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v)
1689 {
1690    mpz_xor(result.data(), u.data(), v.data());
1691 }
1692 
eval_complement(gmp_int & result,const gmp_int & u)1693 inline void eval_complement(gmp_int& result, const gmp_int& u)
1694 {
1695    mpz_com(result.data(), u.data());
1696 }
1697 
eval_get_sign(const gmp_int & val)1698 inline int eval_get_sign(const gmp_int& val)
1699 {
1700    return mpz_sgn(val.data());
1701 }
eval_convert_to(unsigned long * result,const gmp_int & val)1702 inline void eval_convert_to(unsigned long* result, const gmp_int& val)
1703 {
1704    if (mpz_sgn(val.data()) < 0)
1705    {
1706       BOOST_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
1707    }
1708    else
1709       *result = (unsigned long)mpz_get_ui(val.data());
1710 }
eval_convert_to(long * result,const gmp_int & val)1711 inline void eval_convert_to(long* result, const gmp_int& val)
1712 {
1713    if (0 == mpz_fits_slong_p(val.data()))
1714    {
1715       *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits<long>::min)() : (std::numeric_limits<long>::max)();
1716    }
1717    else
1718       *result = (signed long)mpz_get_si(val.data());
1719 }
eval_convert_to(double * result,const gmp_int & val)1720 inline void eval_convert_to(double* result, const gmp_int& val)
1721 {
1722    *result = mpz_get_d(val.data());
1723 }
1724 
eval_abs(gmp_int & result,const gmp_int & val)1725 inline void eval_abs(gmp_int& result, const gmp_int& val)
1726 {
1727    mpz_abs(result.data(), val.data());
1728 }
1729 
eval_gcd(gmp_int & result,const gmp_int & a,const gmp_int & b)1730 inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b)
1731 {
1732    mpz_gcd(result.data(), a.data(), b.data());
1733 }
eval_lcm(gmp_int & result,const gmp_int & a,const gmp_int & b)1734 inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b)
1735 {
1736    mpz_lcm(result.data(), a.data(), b.data());
1737 }
1738 template <class I>
eval_gcd(gmp_int & result,const gmp_int & a,const I b)1739 inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
1740 {
1741    mpz_gcd_ui(result.data(), a.data(), b);
1742 }
1743 template <class I>
eval_lcm(gmp_int & result,const gmp_int & a,const I b)1744 inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
1745 {
1746    mpz_lcm_ui(result.data(), a.data(), b);
1747 }
1748 template <class I>
eval_gcd(gmp_int & result,const gmp_int & a,const I b)1749 inline typename enable_if_c<(is_signed<I>::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
1750 {
1751    mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
1752 }
1753 template <class I>
eval_lcm(gmp_int & result,const gmp_int & a,const I b)1754 inline typename enable_if_c<is_signed<I>::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
1755 {
1756    mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
1757 }
1758 
eval_integer_sqrt(gmp_int & s,gmp_int & r,const gmp_int & x)1759 inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x)
1760 {
1761    mpz_sqrtrem(s.data(), r.data(), x.data());
1762 }
1763 
eval_lsb(const gmp_int & val)1764 inline unsigned eval_lsb(const gmp_int& val)
1765 {
1766    int c = eval_get_sign(val);
1767    if (c == 0)
1768    {
1769       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1770    }
1771    if (c < 0)
1772    {
1773       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1774    }
1775    return static_cast<unsigned>(mpz_scan1(val.data(), 0));
1776 }
1777 
eval_msb(const gmp_int & val)1778 inline unsigned eval_msb(const gmp_int& val)
1779 {
1780    int c = eval_get_sign(val);
1781    if (c == 0)
1782    {
1783       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1784    }
1785    if (c < 0)
1786    {
1787       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1788    }
1789    return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1);
1790 }
1791 
eval_bit_test(const gmp_int & val,unsigned index)1792 inline bool eval_bit_test(const gmp_int& val, unsigned index)
1793 {
1794    return mpz_tstbit(val.data(), index) ? true : false;
1795 }
1796 
eval_bit_set(gmp_int & val,unsigned index)1797 inline void eval_bit_set(gmp_int& val, unsigned index)
1798 {
1799    mpz_setbit(val.data(), index);
1800 }
1801 
eval_bit_unset(gmp_int & val,unsigned index)1802 inline void eval_bit_unset(gmp_int& val, unsigned index)
1803 {
1804    mpz_clrbit(val.data(), index);
1805 }
1806 
eval_bit_flip(gmp_int & val,unsigned index)1807 inline void eval_bit_flip(gmp_int& val, unsigned index)
1808 {
1809    mpz_combit(val.data(), index);
1810 }
1811 
eval_qr(const gmp_int & x,const gmp_int & y,gmp_int & q,gmp_int & r)1812 inline void eval_qr(const gmp_int& x, const gmp_int& y,
1813                     gmp_int& q, gmp_int& r)
1814 {
1815    mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data());
1816 }
1817 
1818 template <class Integer>
eval_integer_modulus(const gmp_int & x,Integer val)1819 inline typename enable_if<is_unsigned<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
1820 {
1821 #if defined(__MPIR_VERSION) && (__MPIR_VERSION >= 3)
1822    if ((sizeof(Integer) <= sizeof(mpir_ui)) || (val <= (std::numeric_limits<mpir_ui>::max)()))
1823 #else
1824    if ((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits<unsigned long>::max)()))
1825 #endif
1826    {
1827       return static_cast<Integer>(mpz_tdiv_ui(x.data(), val));
1828    }
1829    else
1830    {
1831       return default_ops::eval_integer_modulus(x, val);
1832    }
1833 }
1834 template <class Integer>
eval_integer_modulus(const gmp_int & x,Integer val)1835 inline typename enable_if<is_signed<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
1836 {
1837    return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
1838 }
eval_powm(gmp_int & result,const gmp_int & base,const gmp_int & p,const gmp_int & m)1839 inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m)
1840 {
1841    if (eval_get_sign(p) < 0)
1842    {
1843       BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
1844    }
1845    mpz_powm(result.data(), base.data(), p.data(), m.data());
1846 }
1847 
1848 template <class Integer>
1849 inline typename enable_if<
1850     mpl::and_<
1851         is_unsigned<Integer>,
1852         mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)> > >::type
eval_powm(gmp_int & result,const gmp_int & base,Integer p,const gmp_int & m)1853 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
1854 {
1855    mpz_powm_ui(result.data(), base.data(), p, m.data());
1856 }
1857 template <class Integer>
1858 inline typename enable_if<
1859     mpl::and_<
1860         is_signed<Integer>,
1861         mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)> > >::type
eval_powm(gmp_int & result,const gmp_int & base,Integer p,const gmp_int & m)1862 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
1863 {
1864    if (p < 0)
1865    {
1866       BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
1867    }
1868    mpz_powm_ui(result.data(), base.data(), p, m.data());
1869 }
1870 
hash_value(const gmp_int & val)1871 inline std::size_t hash_value(const gmp_int& val)
1872 {
1873    // We should really use mpz_limbs_read here, but that's unsupported on older versions:
1874    std::size_t result = 0;
1875    for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
1876       boost::hash_combine(result, val.data()[0]._mp_d[i]);
1877    boost::hash_combine(result, val.data()[0]._mp_size);
1878    return result;
1879 }
1880 
1881 struct gmp_rational;
1882 void eval_add(gmp_rational& t, const gmp_rational& o);
1883 
1884 struct gmp_rational
1885 {
1886 #ifdef BOOST_HAS_LONG_LONG
1887    typedef mpl::list<long, boost::long_long_type>           signed_types;
1888    typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types;
1889 #else
1890    typedef mpl::list<long>          signed_types;
1891    typedef mpl::list<unsigned long> unsigned_types;
1892 #endif
1893    typedef mpl::list<double, long double> float_types;
1894 
gmp_rationalboost::multiprecision::backends::gmp_rational1895    gmp_rational()
1896    {
1897       mpq_init(this->m_data);
1898    }
gmp_rationalboost::multiprecision::backends::gmp_rational1899    gmp_rational(const gmp_rational& o)
1900    {
1901       mpq_init(m_data);
1902       if (o.m_data[0]._mp_num._mp_d)
1903          mpq_set(m_data, o.m_data);
1904    }
gmp_rationalboost::multiprecision::backends::gmp_rational1905    gmp_rational(const gmp_int& o)
1906    {
1907       mpq_init(m_data);
1908       mpq_set_z(m_data, o.data());
1909    }
1910 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
gmp_rationalboost::multiprecision::backends::gmp_rational1911    gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT
1912    {
1913       m_data[0]                 = o.m_data[0];
1914       o.m_data[0]._mp_num._mp_d = 0;
1915       o.m_data[0]._mp_den._mp_d = 0;
1916    }
1917 #endif
gmp_rationalboost::multiprecision::backends::gmp_rational1918    gmp_rational(const mpq_t o)
1919    {
1920       mpq_init(m_data);
1921       mpq_set(m_data, o);
1922    }
gmp_rationalboost::multiprecision::backends::gmp_rational1923    gmp_rational(const mpz_t o)
1924    {
1925       mpq_init(m_data);
1926       mpq_set_z(m_data, o);
1927    }
operator =boost::multiprecision::backends::gmp_rational1928    gmp_rational& operator=(const gmp_rational& o)
1929    {
1930       if (m_data[0]._mp_den._mp_d == 0)
1931          mpq_init(m_data);
1932       mpq_set(m_data, o.m_data);
1933       return *this;
1934    }
1935 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =boost::multiprecision::backends::gmp_rational1936    gmp_rational& operator=(gmp_rational&& o) BOOST_NOEXCEPT
1937    {
1938       mpq_swap(m_data, o.m_data);
1939       return *this;
1940    }
1941 #endif
1942 #ifdef BOOST_HAS_LONG_LONG
1943 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
operator =boost::multiprecision::backends::gmp_rational1944    gmp_rational& operator=(boost::ulong_long_type i)
1945    {
1946       *this = static_cast<unsigned long>(i);
1947       return *this;
1948    }
1949 #else
operator =boost::multiprecision::backends::gmp_rational1950    gmp_rational& operator=(boost::ulong_long_type i)
1951    {
1952       if (m_data[0]._mp_den._mp_d == 0)
1953          mpq_init(m_data);
1954       gmp_int zi;
1955       zi = i;
1956       mpq_set_z(m_data, zi.data());
1957       return *this;
1958    }
operator =boost::multiprecision::backends::gmp_rational1959    gmp_rational& operator=(boost::long_long_type i)
1960    {
1961       if (m_data[0]._mp_den._mp_d == 0)
1962          mpq_init(m_data);
1963       bool neg = i < 0;
1964       *this    = boost::multiprecision::detail::unsigned_abs(i);
1965       if (neg)
1966          mpq_neg(m_data, m_data);
1967       return *this;
1968    }
1969 #endif
1970 #endif
operator =boost::multiprecision::backends::gmp_rational1971    gmp_rational& operator=(unsigned long i)
1972    {
1973       if (m_data[0]._mp_den._mp_d == 0)
1974          mpq_init(m_data);
1975       mpq_set_ui(m_data, i, 1);
1976       return *this;
1977    }
operator =boost::multiprecision::backends::gmp_rational1978    gmp_rational& operator=(long i)
1979    {
1980       if (m_data[0]._mp_den._mp_d == 0)
1981          mpq_init(m_data);
1982       mpq_set_si(m_data, i, 1);
1983       return *this;
1984    }
operator =boost::multiprecision::backends::gmp_rational1985    gmp_rational& operator=(double d)
1986    {
1987       if (m_data[0]._mp_den._mp_d == 0)
1988          mpq_init(m_data);
1989       mpq_set_d(m_data, d);
1990       return *this;
1991    }
operator =boost::multiprecision::backends::gmp_rational1992    gmp_rational& operator=(long double a)
1993    {
1994       using default_ops::eval_add;
1995       using default_ops::eval_subtract;
1996       using std::floor;
1997       using std::frexp;
1998       using std::ldexp;
1999 
2000       if (m_data[0]._mp_den._mp_d == 0)
2001          mpq_init(m_data);
2002 
2003       if (a == 0)
2004       {
2005          mpq_set_si(m_data, 0, 1);
2006          return *this;
2007       }
2008 
2009       if (a == 1)
2010       {
2011          mpq_set_si(m_data, 1, 1);
2012          return *this;
2013       }
2014 
2015       BOOST_ASSERT(!(boost::math::isinf)(a));
2016       BOOST_ASSERT(!(boost::math::isnan)(a));
2017 
2018       int         e;
2019       long double f, term;
2020       mpq_set_ui(m_data, 0, 1);
2021       mpq_set_ui(m_data, 0u, 1);
2022       gmp_rational t;
2023 
2024       f = frexp(a, &e);
2025 
2026       static const int shift = std::numeric_limits<int>::digits - 1;
2027 
2028       while (f)
2029       {
2030          // extract int sized bits from f:
2031          f    = ldexp(f, shift);
2032          term = floor(f);
2033          e -= shift;
2034          mpq_mul_2exp(m_data, m_data, shift);
2035          t = static_cast<long>(term);
2036          eval_add(*this, t);
2037          f -= term;
2038       }
2039       if (e > 0)
2040          mpq_mul_2exp(m_data, m_data, e);
2041       else if (e < 0)
2042          mpq_div_2exp(m_data, m_data, -e);
2043       return *this;
2044    }
operator =boost::multiprecision::backends::gmp_rational2045    gmp_rational& operator=(const char* s)
2046    {
2047       if (m_data[0]._mp_den._mp_d == 0)
2048          mpq_init(m_data);
2049       if (0 != mpq_set_str(m_data, s, 10))
2050          BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number.")));
2051       return *this;
2052    }
operator =boost::multiprecision::backends::gmp_rational2053    gmp_rational& operator=(const gmp_int& o)
2054    {
2055       if (m_data[0]._mp_den._mp_d == 0)
2056          mpq_init(m_data);
2057       mpq_set_z(m_data, o.data());
2058       return *this;
2059    }
operator =boost::multiprecision::backends::gmp_rational2060    gmp_rational& operator=(const mpq_t o)
2061    {
2062       if (m_data[0]._mp_den._mp_d == 0)
2063          mpq_init(m_data);
2064       mpq_set(m_data, o);
2065       return *this;
2066    }
operator =boost::multiprecision::backends::gmp_rational2067    gmp_rational& operator=(const mpz_t o)
2068    {
2069       if (m_data[0]._mp_den._mp_d == 0)
2070          mpq_init(m_data);
2071       mpq_set_z(m_data, o);
2072       return *this;
2073    }
swapboost::multiprecision::backends::gmp_rational2074    void swap(gmp_rational& o)
2075    {
2076       mpq_swap(m_data, o.m_data);
2077    }
strboost::multiprecision::backends::gmp_rational2078    std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/) const
2079    {
2080       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2081       // TODO make a better job of this including handling of f!!
2082       void* (*alloc_func_ptr)(size_t);
2083       void* (*realloc_func_ptr)(void*, size_t, size_t);
2084       void (*free_func_ptr)(void*, size_t);
2085       const char* ps = mpq_get_str(0, 10, m_data);
2086       std::string s  = ps;
2087       mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
2088       (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
2089       return s;
2090    }
~gmp_rationalboost::multiprecision::backends::gmp_rational2091    ~gmp_rational()
2092    {
2093       if (m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d)
2094          mpq_clear(m_data);
2095    }
negateboost::multiprecision::backends::gmp_rational2096    void negate()
2097    {
2098       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2099       mpq_neg(m_data, m_data);
2100    }
compareboost::multiprecision::backends::gmp_rational2101    int compare(const gmp_rational& o) const
2102    {
2103       BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d);
2104       return mpq_cmp(m_data, o.m_data);
2105    }
2106    template <class V>
compareboost::multiprecision::backends::gmp_rational2107    int compare(V v) const
2108    {
2109       gmp_rational d;
2110       d = v;
2111       return compare(d);
2112    }
compareboost::multiprecision::backends::gmp_rational2113    int compare(unsigned long v) const
2114    {
2115       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2116       return mpq_cmp_ui(m_data, v, 1);
2117    }
compareboost::multiprecision::backends::gmp_rational2118    int compare(long v) const
2119    {
2120       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2121       return mpq_cmp_si(m_data, v, 1);
2122    }
databoost::multiprecision::backends::gmp_rational2123    mpq_t& data()
2124    {
2125       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2126       return m_data;
2127    }
databoost::multiprecision::backends::gmp_rational2128    const mpq_t& data() const
2129    {
2130       BOOST_ASSERT(m_data[0]._mp_num._mp_d);
2131       return m_data;
2132    }
2133 
2134  protected:
2135    mpq_t m_data;
2136 };
2137 
eval_is_zero(const gmp_rational & val)2138 inline bool eval_is_zero(const gmp_rational& val)
2139 {
2140    return mpq_sgn(val.data()) == 0;
2141 }
2142 template <class T>
eval_eq(gmp_rational & a,const T & b)2143 inline bool eval_eq(gmp_rational& a, const T& b)
2144 {
2145    return a.compare(b) == 0;
2146 }
2147 template <class T>
eval_lt(gmp_rational & a,const T & b)2148 inline bool eval_lt(gmp_rational& a, const T& b)
2149 {
2150    return a.compare(b) < 0;
2151 }
2152 template <class T>
eval_gt(gmp_rational & a,const T & b)2153 inline bool eval_gt(gmp_rational& a, const T& b)
2154 {
2155    return a.compare(b) > 0;
2156 }
2157 
eval_add(gmp_rational & t,const gmp_rational & o)2158 inline void eval_add(gmp_rational& t, const gmp_rational& o)
2159 {
2160    mpq_add(t.data(), t.data(), o.data());
2161 }
eval_subtract(gmp_rational & t,const gmp_rational & o)2162 inline void eval_subtract(gmp_rational& t, const gmp_rational& o)
2163 {
2164    mpq_sub(t.data(), t.data(), o.data());
2165 }
eval_multiply(gmp_rational & t,const gmp_rational & o)2166 inline void eval_multiply(gmp_rational& t, const gmp_rational& o)
2167 {
2168    mpq_mul(t.data(), t.data(), o.data());
2169 }
eval_divide(gmp_rational & t,const gmp_rational & o)2170 inline void eval_divide(gmp_rational& t, const gmp_rational& o)
2171 {
2172    if (eval_is_zero(o))
2173       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2174    mpq_div(t.data(), t.data(), o.data());
2175 }
eval_add(gmp_rational & t,const gmp_rational & p,const gmp_rational & o)2176 inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2177 {
2178    mpq_add(t.data(), p.data(), o.data());
2179 }
eval_subtract(gmp_rational & t,const gmp_rational & p,const gmp_rational & o)2180 inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2181 {
2182    mpq_sub(t.data(), p.data(), o.data());
2183 }
eval_multiply(gmp_rational & t,const gmp_rational & p,const gmp_rational & o)2184 inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2185 {
2186    mpq_mul(t.data(), p.data(), o.data());
2187 }
eval_divide(gmp_rational & t,const gmp_rational & p,const gmp_rational & o)2188 inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2189 {
2190    if (eval_is_zero(o))
2191       BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2192    mpq_div(t.data(), p.data(), o.data());
2193 }
2194 
eval_get_sign(const gmp_rational & val)2195 inline int eval_get_sign(const gmp_rational& val)
2196 {
2197    return mpq_sgn(val.data());
2198 }
2199 template <class R>
eval_convert_to(R * result,const gmp_rational & backend)2200 inline typename enable_if_c<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const gmp_rational& backend)
2201 {
2202    //
2203    // The generic conversion is as good as anything we can write here:
2204    //
2205    // This does not round correctly:
2206    //
2207    //*result = mpq_get_d(val.data());
2208    //
2209    // This does:
2210    //
2211    ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend);
2212 }
2213 #ifdef BOOST_HAS_FLOAT128
eval_convert_to(__float128 * result,const gmp_rational & val)2214 inline void eval_convert_to(__float128* result, const gmp_rational& val)
2215 {
2216    using default_ops::eval_convert_to;
2217 
2218    gmp_int n, d;
2219    __float128 fn, fd;
2220    mpz_set(n.data(), mpq_numref(val.data()));
2221    mpz_set(d.data(), mpq_denref(val.data()));
2222 
2223    eval_convert_to(&fn, n);
2224    eval_convert_to(&fd, d);
2225 
2226    *result = fn / fd;
2227 }
2228 #endif
2229 
eval_convert_to(long * result,const gmp_rational & val)2230 inline void eval_convert_to(long* result, const gmp_rational& val)
2231 {
2232    double r;
2233    eval_convert_to(&r, val);
2234    *result = static_cast<long>(r);
2235 }
2236 
eval_convert_to(unsigned long * result,const gmp_rational & val)2237 inline void eval_convert_to(unsigned long* result, const gmp_rational& val)
2238 {
2239    double r;
2240    eval_convert_to(&r, val);
2241    *result = static_cast<long>(r);
2242 }
2243 
eval_abs(gmp_rational & result,const gmp_rational & val)2244 inline void eval_abs(gmp_rational& result, const gmp_rational& val)
2245 {
2246    mpq_abs(result.data(), val.data());
2247 }
2248 
assign_components(gmp_rational & result,unsigned long v1,unsigned long v2)2249 inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2)
2250 {
2251    mpq_set_ui(result.data(), v1, v2);
2252    mpq_canonicalize(result.data());
2253 }
assign_components(gmp_rational & result,long v1,long v2)2254 inline void assign_components(gmp_rational& result, long v1, long v2)
2255 {
2256    mpq_set_si(result.data(), v1, v2);
2257    mpq_canonicalize(result.data());
2258 }
assign_components(gmp_rational & result,gmp_int const & v1,gmp_int const & v2)2259 inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2)
2260 {
2261    mpz_set(mpq_numref(result.data()), v1.data());
2262    mpz_set(mpq_denref(result.data()), v2.data());
2263    mpq_canonicalize(result.data());
2264 }
2265 
hash_value(const gmp_rational & val)2266 inline std::size_t hash_value(const gmp_rational& val)
2267 {
2268    std::size_t result = 0;
2269    for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i)
2270       boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]);
2271    for (int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i)
2272       boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]);
2273    boost::hash_combine(result, val.data()[0]._mp_num._mp_size);
2274    return result;
2275 }
2276 
2277 //
2278 // Some member functions that are dependent upon previous code go here:
2279 //
2280 template <unsigned Digits10>
2281 template <unsigned D>
gmp_float(const gmp_float<D> & o,typename enable_if_c<D<=Digits10>::type *)2282 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= Digits10>::type*)
2283 {
2284    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2285    mpf_set(this->m_data, o.data());
2286 }
2287 template <unsigned Digits10>
2288 template <unsigned D>
gmp_float(const gmp_float<D> & o,typename disable_if_c<D<=Digits10>::type *)2289 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= Digits10>::type*)
2290 {
2291    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2292    mpf_set(this->m_data, o.data());
2293 }
2294 template <unsigned Digits10>
gmp_float(const gmp_int & o)2295 inline gmp_float<Digits10>::gmp_float(const gmp_int& o)
2296 {
2297    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2298    mpf_set_z(this->data(), o.data());
2299 }
2300 template <unsigned Digits10>
gmp_float(const gmp_rational & o)2301 inline gmp_float<Digits10>::gmp_float(const gmp_rational& o)
2302 {
2303    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2304    mpf_set_q(this->data(), o.data());
2305 }
2306 template <unsigned Digits10>
2307 template <unsigned D>
operator =(const gmp_float<D> & o)2308 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_float<D>& o)
2309 {
2310    if (this->m_data[0]._mp_d == 0)
2311       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2312    mpf_set(this->m_data, o.data());
2313    return *this;
2314 }
2315 template <unsigned Digits10>
operator =(const gmp_int & o)2316 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_int& o)
2317 {
2318    if (this->m_data[0]._mp_d == 0)
2319       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2320    mpf_set_z(this->data(), o.data());
2321    return *this;
2322 }
2323 template <unsigned Digits10>
operator =(const gmp_rational & o)2324 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_rational& o)
2325 {
2326    if (this->m_data[0]._mp_d == 0)
2327       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
2328    mpf_set_q(this->data(), o.data());
2329    return *this;
2330 }
gmp_float(const gmp_int & o)2331 inline gmp_float<0>::gmp_float(const gmp_int& o) : requested_precision(get_default_precision())
2332 {
2333    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
2334    mpf_set_z(this->data(), o.data());
2335 }
gmp_float(const gmp_rational & o)2336 inline gmp_float<0>::gmp_float(const gmp_rational& o) : requested_precision(get_default_precision())
2337 {
2338    mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
2339    mpf_set_q(this->data(), o.data());
2340 }
operator =(const gmp_int & o)2341 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o)
2342 {
2343    if (this->m_data[0]._mp_d == 0)
2344    {
2345       requested_precision = this->get_default_precision();
2346       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
2347    }
2348    mpf_set_z(this->data(), o.data());
2349    return *this;
2350 }
operator =(const gmp_rational & o)2351 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o)
2352 {
2353    if (this->m_data[0]._mp_d == 0)
2354    {
2355       requested_precision = this->get_default_precision();
2356       mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
2357    }
2358    mpf_set_q(this->data(), o.data());
2359    return *this;
2360 }
gmp_int(const gmp_rational & o)2361 inline gmp_int::gmp_int(const gmp_rational& o)
2362 {
2363    mpz_init(this->m_data);
2364    mpz_set_q(this->m_data, o.data());
2365 }
operator =(const gmp_rational & o)2366 inline gmp_int& gmp_int::operator=(const gmp_rational& o)
2367 {
2368    if (this->m_data[0]._mp_d == 0)
2369       mpz_init(this->m_data);
2370    mpz_set_q(this->m_data, o.data());
2371    return *this;
2372 }
2373 
2374 } //namespace backends
2375 
2376 using boost::multiprecision::backends::gmp_float;
2377 using boost::multiprecision::backends::gmp_int;
2378 using boost::multiprecision::backends::gmp_rational;
2379 
2380 template <expression_template_option ExpressionTemplates>
2381 struct component_type<number<gmp_rational, ExpressionTemplates> >
2382 {
2383    typedef number<gmp_int, ExpressionTemplates> type;
2384 };
2385 
2386 template <expression_template_option ET>
numerator(const number<gmp_rational,ET> & val)2387 inline number<gmp_int, ET> numerator(const number<gmp_rational, ET>& val)
2388 {
2389    number<gmp_int, ET> result;
2390    mpz_set(result.backend().data(), (mpq_numref(val.backend().data())));
2391    return result;
2392 }
2393 template <expression_template_option ET>
denominator(const number<gmp_rational,ET> & val)2394 inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
2395 {
2396    number<gmp_int, ET> result;
2397    mpz_set(result.backend().data(), (mpq_denref(val.backend().data())));
2398    return result;
2399 }
2400 
2401 namespace detail {
2402 
2403 #ifdef BOOST_NO_SFINAE_EXPR
2404 
2405 template <>
2406 struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_
2407 {};
2408 template <>
2409 struct is_explicitly_convertible<canonical<mpq_t, gmp_int>::type, gmp_int> : public mpl::true_
2410 {};
2411 template <unsigned Digits10>
2412 struct is_explicitly_convertible<gmp_float<Digits10>, gmp_int> : public mpl::true_
2413 {};
2414 template <>
2415 struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_
2416 {};
2417 template <unsigned D1, unsigned D2>
2418 struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_
2419 {};
2420 
2421 #endif
2422 
2423 template <>
2424 struct digits2<number<gmp_float<0>, et_on> >
2425 {
valueboost::multiprecision::detail::digits22426    static long value()
2427    {
2428       return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
2429    }
2430 };
2431 
2432 template <>
2433 struct digits2<number<gmp_float<0>, et_off> >
2434 {
valueboost::multiprecision::detail::digits22435    static long value()
2436    {
2437       return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
2438    }
2439 };
2440 
2441 template <>
2442 struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> >
2443 {
valueboost::multiprecision::detail::digits22444    static long value()
2445    {
2446       return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
2447    }
2448 };
2449 
2450 template <>
2451 struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> >
2452 {
valueboost::multiprecision::detail::digits22453    static long value()
2454    {
2455       return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision());
2456    }
2457 };
2458 
2459 } // namespace detail
2460 
2461 template <>
2462 struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer>
2463 {};
2464 template <>
2465 struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public mpl::int_<number_kind_rational>
2466 {};
2467 template <>
2468 struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public mpl::int_<number_kind_floating_point>
2469 {};
2470 
2471 namespace detail {
2472 template <>
2473 struct is_variable_precision<backends::gmp_float<0> > : public true_type
2474 {};
2475 } // namespace detail
2476 
2477 typedef number<gmp_float<50> >   mpf_float_50;
2478 typedef number<gmp_float<100> >  mpf_float_100;
2479 typedef number<gmp_float<500> >  mpf_float_500;
2480 typedef number<gmp_float<1000> > mpf_float_1000;
2481 typedef number<gmp_float<0> >    mpf_float;
2482 typedef number<gmp_int>          mpz_int;
2483 typedef number<gmp_rational>     mpq_rational;
2484 
2485 } // namespace multiprecision
2486 
2487 namespace math { namespace tools {
2488 
2489 template <>
digits()2490 inline int digits<boost::multiprecision::mpf_float>()
2491 #ifdef BOOST_MATH_NOEXCEPT
2492     BOOST_NOEXCEPT
2493 #endif
2494 {
2495    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
2496 }
2497 template <>
digits()2498 inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
2499 #ifdef BOOST_MATH_NOEXCEPT
2500     BOOST_NOEXCEPT
2501 #endif
2502 {
2503    return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision());
2504 }
2505 
2506 template <>
2507 inline boost::multiprecision::mpf_float
max_value()2508 max_value<boost::multiprecision::mpf_float>()
2509 {
2510    boost::multiprecision::mpf_float result(0.5);
2511    mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
2512    return result;
2513 }
2514 
2515 template <>
2516 inline boost::multiprecision::mpf_float
min_value()2517 min_value<boost::multiprecision::mpf_float>()
2518 {
2519    boost::multiprecision::mpf_float result(0.5);
2520    mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::min)() / 64 + 1);
2521    return result;
2522 }
2523 
2524 template <>
2525 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
max_value()2526 max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
2527 {
2528    boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
2529    mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
2530    return result;
2531 }
2532 
2533 template <>
2534 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
min_value()2535 min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
2536 {
2537    boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
2538    mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
2539    return result;
2540 }
2541 
2542 template <>
digits()2543 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
2544 #ifdef BOOST_MATH_NOEXCEPT
2545     BOOST_NOEXCEPT
2546 #endif
2547 {
2548    return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
2549 }
2550 template <>
digits()2551 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
2552 #ifdef BOOST_MATH_NOEXCEPT
2553     BOOST_NOEXCEPT
2554 #endif
2555 {
2556    return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision());
2557 }
2558 
2559 template <>
2560 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
max_value()2561 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
2562 {
2563    return max_value<boost::multiprecision::mpf_float>().backend();
2564 }
2565 
2566 template <>
2567 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
min_value()2568 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
2569 {
2570    return min_value<boost::multiprecision::mpf_float>().backend();
2571 }
2572 
2573 template <>
2574 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
max_value()2575 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
2576 {
2577    return max_value<boost::multiprecision::mpf_float>().backend();
2578 }
2579 
2580 template <>
2581 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
min_value()2582 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
2583 {
2584    return min_value<boost::multiprecision::mpf_float>().backend();
2585 }
2586 
2587 }} // namespace math::tools
2588 
2589 } // namespace boost
2590 
2591 namespace std {
2592 
2593 //
2594 // numeric_limits [partial] specializations for the types declared in this header:
2595 //
2596 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2597 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >
2598 {
2599    typedef boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> number_type;
2600 
2601  public:
2602    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
2603    //
2604    // min and max values chosen so as to not cause segfaults when calling
2605    // mpf_get_str on 64-bit Linux builds.  Possibly we could use larger
2606    // exponent values elsewhere.
2607    //
number_type(min)2608    static number_type(min)()
2609    {
2610       initializer.do_nothing();
2611       static std::pair<bool, number_type> value;
2612       if (!value.first)
2613       {
2614          value.first  = true;
2615          value.second = 1;
2616          mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
2617       }
2618       return value.second;
2619    }
number_type(max)2620    static number_type(max)()
2621    {
2622       initializer.do_nothing();
2623       static std::pair<bool, number_type> value;
2624       if (!value.first)
2625       {
2626          value.first  = true;
2627          value.second = 1;
2628          mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
2629       }
2630       return value.second;
2631    }
lowest()2632    BOOST_STATIC_CONSTEXPR number_type lowest()
2633    {
2634       return -(max)();
2635    }
2636    BOOST_STATIC_CONSTEXPR int digits   = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1));
2637    BOOST_STATIC_CONSTEXPR int digits10 = Digits10;
2638    // Have to allow for a possible extra limb inside the gmp data structure:
2639    BOOST_STATIC_CONSTEXPR int  max_digits10 = Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L);
2640    BOOST_STATIC_CONSTEXPR bool is_signed    = true;
2641    BOOST_STATIC_CONSTEXPR bool is_integer   = false;
2642    BOOST_STATIC_CONSTEXPR bool is_exact     = false;
2643    BOOST_STATIC_CONSTEXPR int  radix        = 2;
epsilon()2644    static number_type          epsilon()
2645    {
2646       initializer.do_nothing();
2647       static std::pair<bool, number_type> value;
2648       if (!value.first)
2649       {
2650          value.first  = true;
2651          value.second = 1;
2652          mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1);
2653       }
2654       return value.second;
2655    }
2656    // What value should this be????
round_error()2657    static number_type round_error()
2658    {
2659       // returns epsilon/2
2660       initializer.do_nothing();
2661       static std::pair<bool, number_type> value;
2662       if (!value.first)
2663       {
2664          value.first  = true;
2665          value.second = 1;
2666       }
2667       return value.second;
2668    }
2669    BOOST_STATIC_CONSTEXPR long               min_exponent      = LONG_MIN;
2670    BOOST_STATIC_CONSTEXPR long               min_exponent10    = (LONG_MIN / 1000) * 301L;
2671    BOOST_STATIC_CONSTEXPR long               max_exponent      = LONG_MAX;
2672    BOOST_STATIC_CONSTEXPR long               max_exponent10    = (LONG_MAX / 1000) * 301L;
2673    BOOST_STATIC_CONSTEXPR bool               has_infinity      = false;
2674    BOOST_STATIC_CONSTEXPR bool               has_quiet_NaN     = false;
2675    BOOST_STATIC_CONSTEXPR bool               has_signaling_NaN = false;
2676    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm        = denorm_absent;
2677    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss   = false;
infinity()2678    BOOST_STATIC_CONSTEXPR number_type        infinity() { return number_type(); }
quiet_NaN()2679    BOOST_STATIC_CONSTEXPR number_type        quiet_NaN() { return number_type(); }
signaling_NaN()2680    BOOST_STATIC_CONSTEXPR number_type        signaling_NaN() { return number_type(); }
denorm_min()2681    BOOST_STATIC_CONSTEXPR number_type        denorm_min() { return number_type(); }
2682    BOOST_STATIC_CONSTEXPR bool               is_iec559       = false;
2683    BOOST_STATIC_CONSTEXPR bool               is_bounded      = true;
2684    BOOST_STATIC_CONSTEXPR bool               is_modulo       = false;
2685    BOOST_STATIC_CONSTEXPR bool               traps           = true;
2686    BOOST_STATIC_CONSTEXPR bool               tinyness_before = false;
2687    BOOST_STATIC_CONSTEXPR float_round_style  round_style     = round_indeterminate;
2688 
2689  private:
2690    struct data_initializer
2691    {
data_initializerstd::numeric_limits::data_initializer2692       data_initializer()
2693       {
2694          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::epsilon();
2695          std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::round_error();
2696          (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::min)();
2697          (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::max)();
2698       }
do_nothingstd::numeric_limits::data_initializer2699       void do_nothing() const {}
2700    };
2701    static const data_initializer initializer;
2702 };
2703 
2704 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2705 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::initializer;
2706 
2707 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2708 
2709 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2710 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits;
2711 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2712 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits10;
2713 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2714 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_digits10;
2715 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2716 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_signed;
2717 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2718 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_integer;
2719 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2720 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_exact;
2721 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2722 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::radix;
2723 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2724 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent;
2725 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2726 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent10;
2727 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2728 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent;
2729 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2730 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent10;
2731 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2732 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_infinity;
2733 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2734 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
2735 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2736 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
2737 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2738 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm;
2739 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2740 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm_loss;
2741 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2742 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_iec559;
2743 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2744 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_bounded;
2745 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2746 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_modulo;
2747 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2748 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::traps;
2749 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2750 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::tinyness_before;
2751 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2752 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::round_style;
2753 
2754 #endif
2755 
2756 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2757 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
2758 {
2759    typedef boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> number_type;
2760 
2761  public:
2762    BOOST_STATIC_CONSTEXPR bool is_specialized = false;
number_type(min)2763    static number_type(min)() { return number_type(); }
number_type(max)2764    static number_type(max)() { return number_type(); }
lowest()2765    static number_type                        lowest() { return number_type(); }
2766    BOOST_STATIC_CONSTEXPR int                digits       = 0;
2767    BOOST_STATIC_CONSTEXPR int                digits10     = 0;
2768    BOOST_STATIC_CONSTEXPR int                max_digits10 = 0;
2769    BOOST_STATIC_CONSTEXPR bool               is_signed    = false;
2770    BOOST_STATIC_CONSTEXPR bool               is_integer   = false;
2771    BOOST_STATIC_CONSTEXPR bool               is_exact     = false;
2772    BOOST_STATIC_CONSTEXPR int                radix        = 0;
epsilon()2773    static number_type                        epsilon() { return number_type(); }
round_error()2774    static number_type                        round_error() { return number_type(); }
2775    BOOST_STATIC_CONSTEXPR int                min_exponent      = 0;
2776    BOOST_STATIC_CONSTEXPR int                min_exponent10    = 0;
2777    BOOST_STATIC_CONSTEXPR int                max_exponent      = 0;
2778    BOOST_STATIC_CONSTEXPR int                max_exponent10    = 0;
2779    BOOST_STATIC_CONSTEXPR bool               has_infinity      = false;
2780    BOOST_STATIC_CONSTEXPR bool               has_quiet_NaN     = false;
2781    BOOST_STATIC_CONSTEXPR bool               has_signaling_NaN = false;
2782    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm        = denorm_absent;
2783    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss   = false;
infinity()2784    static number_type                        infinity() { return number_type(); }
quiet_NaN()2785    static number_type                        quiet_NaN() { return number_type(); }
signaling_NaN()2786    static number_type                        signaling_NaN() { return number_type(); }
denorm_min()2787    static number_type                        denorm_min() { return number_type(); }
2788    BOOST_STATIC_CONSTEXPR bool               is_iec559       = false;
2789    BOOST_STATIC_CONSTEXPR bool               is_bounded      = false;
2790    BOOST_STATIC_CONSTEXPR bool               is_modulo       = false;
2791    BOOST_STATIC_CONSTEXPR bool               traps           = false;
2792    BOOST_STATIC_CONSTEXPR bool               tinyness_before = false;
2793    BOOST_STATIC_CONSTEXPR float_round_style  round_style     = round_indeterminate;
2794 };
2795 
2796 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2797 
2798 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2799 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits;
2800 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2801 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10;
2802 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2803 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10;
2804 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2805 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed;
2806 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2807 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer;
2808 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2809 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact;
2810 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2811 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix;
2812 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2813 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent;
2814 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2815 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10;
2816 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2817 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent;
2818 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2819 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10;
2820 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2821 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity;
2822 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2823 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN;
2824 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2825 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN;
2826 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2827 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm;
2828 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2829 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss;
2830 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2831 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559;
2832 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2833 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded;
2834 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2835 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo;
2836 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2837 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps;
2838 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2839 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before;
2840 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2841 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style;
2842 
2843 #endif
2844 
2845 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2846 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >
2847 {
2848    typedef boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> number_type;
2849 
2850  public:
2851    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
2852    //
2853    // Largest and smallest numbers are bounded only by available memory, set
2854    // to zero:
2855    //
number_type(min)2856    static number_type(min)()
2857    {
2858       return number_type();
2859    }
number_type(max)2860    static number_type(max)()
2861    {
2862       return number_type();
2863    }
lowest()2864    static number_type                        lowest() { return (min)(); }
2865    BOOST_STATIC_CONSTEXPR int                digits       = INT_MAX;
2866    BOOST_STATIC_CONSTEXPR int                digits10     = (INT_MAX / 1000) * 301L;
2867    BOOST_STATIC_CONSTEXPR int                max_digits10 = digits10 + 3;
2868    BOOST_STATIC_CONSTEXPR bool               is_signed    = true;
2869    BOOST_STATIC_CONSTEXPR bool               is_integer   = true;
2870    BOOST_STATIC_CONSTEXPR bool               is_exact     = true;
2871    BOOST_STATIC_CONSTEXPR int                radix        = 2;
epsilon()2872    static number_type                        epsilon() { return number_type(); }
round_error()2873    static number_type                        round_error() { return number_type(); }
2874    BOOST_STATIC_CONSTEXPR int                min_exponent      = 0;
2875    BOOST_STATIC_CONSTEXPR int                min_exponent10    = 0;
2876    BOOST_STATIC_CONSTEXPR int                max_exponent      = 0;
2877    BOOST_STATIC_CONSTEXPR int                max_exponent10    = 0;
2878    BOOST_STATIC_CONSTEXPR bool               has_infinity      = false;
2879    BOOST_STATIC_CONSTEXPR bool               has_quiet_NaN     = false;
2880    BOOST_STATIC_CONSTEXPR bool               has_signaling_NaN = false;
2881    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm        = denorm_absent;
2882    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss   = false;
infinity()2883    static number_type                        infinity() { return number_type(); }
quiet_NaN()2884    static number_type                        quiet_NaN() { return number_type(); }
signaling_NaN()2885    static number_type                        signaling_NaN() { return number_type(); }
denorm_min()2886    static number_type                        denorm_min() { return number_type(); }
2887    BOOST_STATIC_CONSTEXPR bool               is_iec559       = false;
2888    BOOST_STATIC_CONSTEXPR bool               is_bounded      = false;
2889    BOOST_STATIC_CONSTEXPR bool               is_modulo       = false;
2890    BOOST_STATIC_CONSTEXPR bool               traps           = false;
2891    BOOST_STATIC_CONSTEXPR bool               tinyness_before = false;
2892    BOOST_STATIC_CONSTEXPR float_round_style  round_style     = round_toward_zero;
2893 };
2894 
2895 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2896 
2897 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2898 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits;
2899 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2900 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10;
2901 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2902 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10;
2903 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2904 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed;
2905 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2906 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer;
2907 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2908 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact;
2909 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2910 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix;
2911 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2912 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent;
2913 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2914 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10;
2915 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2916 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent;
2917 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2918 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10;
2919 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2920 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity;
2921 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2922 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN;
2923 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2924 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN;
2925 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2926 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm;
2927 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2928 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss;
2929 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2930 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559;
2931 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2932 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded;
2933 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2934 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo;
2935 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2936 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps;
2937 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2938 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before;
2939 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2940 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style;
2941 
2942 #endif
2943 
2944 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2945 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >
2946 {
2947    typedef boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> number_type;
2948 
2949  public:
2950    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
2951    //
2952    // Largest and smallest numbers are bounded only by available memory, set
2953    // to zero:
2954    //
number_type(min)2955    static number_type(min)()
2956    {
2957       return number_type();
2958    }
number_type(max)2959    static number_type(max)()
2960    {
2961       return number_type();
2962    }
lowest()2963    static number_type lowest() { return (min)(); }
2964    // Digits are unbounded, use zero for now:
2965    BOOST_STATIC_CONSTEXPR int                digits       = INT_MAX;
2966    BOOST_STATIC_CONSTEXPR int                digits10     = (INT_MAX / 1000) * 301L;
2967    BOOST_STATIC_CONSTEXPR int                max_digits10 = digits10 + 3;
2968    BOOST_STATIC_CONSTEXPR bool               is_signed    = true;
2969    BOOST_STATIC_CONSTEXPR bool               is_integer   = false;
2970    BOOST_STATIC_CONSTEXPR bool               is_exact     = true;
2971    BOOST_STATIC_CONSTEXPR int                radix        = 2;
epsilon()2972    static number_type                        epsilon() { return number_type(); }
round_error()2973    static number_type                        round_error() { return number_type(); }
2974    BOOST_STATIC_CONSTEXPR int                min_exponent      = 0;
2975    BOOST_STATIC_CONSTEXPR int                min_exponent10    = 0;
2976    BOOST_STATIC_CONSTEXPR int                max_exponent      = 0;
2977    BOOST_STATIC_CONSTEXPR int                max_exponent10    = 0;
2978    BOOST_STATIC_CONSTEXPR bool               has_infinity      = false;
2979    BOOST_STATIC_CONSTEXPR bool               has_quiet_NaN     = false;
2980    BOOST_STATIC_CONSTEXPR bool               has_signaling_NaN = false;
2981    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm        = denorm_absent;
2982    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss   = false;
infinity()2983    static number_type                        infinity() { return number_type(); }
quiet_NaN()2984    static number_type                        quiet_NaN() { return number_type(); }
signaling_NaN()2985    static number_type                        signaling_NaN() { return number_type(); }
denorm_min()2986    static number_type                        denorm_min() { return number_type(); }
2987    BOOST_STATIC_CONSTEXPR bool               is_iec559       = false;
2988    BOOST_STATIC_CONSTEXPR bool               is_bounded      = false;
2989    BOOST_STATIC_CONSTEXPR bool               is_modulo       = false;
2990    BOOST_STATIC_CONSTEXPR bool               traps           = false;
2991    BOOST_STATIC_CONSTEXPR bool               tinyness_before = false;
2992    BOOST_STATIC_CONSTEXPR float_round_style  round_style     = round_toward_zero;
2993 };
2994 
2995 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2996 
2997 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2998 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits;
2999 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3000 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10;
3001 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3002 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10;
3003 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3004 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed;
3005 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3006 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer;
3007 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3008 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact;
3009 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3010 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix;
3011 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3012 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent;
3013 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3014 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10;
3015 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3016 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent;
3017 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3018 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10;
3019 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3020 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity;
3021 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3022 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN;
3023 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3024 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN;
3025 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3026 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm;
3027 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3028 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss;
3029 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3030 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559;
3031 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3032 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded;
3033 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3034 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo;
3035 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3036 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps;
3037 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3038 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before;
3039 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3040 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::round_style;
3041 
3042 #endif
3043 
3044 #ifdef BOOST_MSVC
3045 #pragma warning(pop)
3046 #endif
3047 
3048 } // namespace std
3049 
3050 #endif
3051