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