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