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