]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/include/boost/multiprecision/gmp.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / multiprecision / include / boost / multiprecision / gmp.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_MATH_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
46 namespace boost{
47 namespace multiprecision{
48 namespace 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
56 template <unsigned digits10>
57 struct gmp_float;
58 struct gmp_int;
59 struct gmp_rational;
60
61 } // namespace backends
62
63 template<>
64 struct number_category<backends::gmp_int> : public mpl::int_<number_kind_integer>{};
65 template<>
66 struct number_category<backends::gmp_rational> : public mpl::int_<number_kind_rational>{};
67 template <unsigned digits10>
68 struct number_category<backends::gmp_float<digits10> > : public mpl::int_<number_kind_floating_point>{};
69
70 namespace 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 //
76 namespace detail{
77
78 template <unsigned digits10>
79 struct 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 }
390 protected:
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
401 struct gmp_int;
402 struct gmp_rational;
403
404 template <unsigned digits10>
405 struct 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
481 template <>
482 struct 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
594 template <unsigned digits10, class T>
595 inline 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 }
599 template <unsigned digits10, class T>
600 inline 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 }
604 template <unsigned digits10, class T>
605 inline 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
610 template <unsigned D1, unsigned D2>
611 inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o)
612 {
613 mpf_add(result.data(), result.data(), o.data());
614 }
615 template <unsigned D1, unsigned D2>
616 inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o)
617 {
618 mpf_sub(result.data(), result.data(), o.data());
619 }
620 template <unsigned D1, unsigned D2>
621 inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o)
622 {
623 mpf_mul(result.data(), result.data(), o.data());
624 }
625 template <unsigned digits10>
626 inline bool eval_is_zero(const gmp_float<digits10>& val) BOOST_NOEXCEPT
627 {
628 return mpf_sgn(val.data()) == 0;
629 }
630 template <unsigned D1, unsigned D2>
631 inline 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 }
637 template <unsigned digits10>
638 inline void eval_add(gmp_float<digits10>& result, unsigned long i)
639 {
640 mpf_add_ui(result.data(), result.data(), i);
641 }
642 template <unsigned digits10>
643 inline void eval_subtract(gmp_float<digits10>& result, unsigned long i)
644 {
645 mpf_sub_ui(result.data(), result.data(), i);
646 }
647 template <unsigned digits10>
648 inline void eval_multiply(gmp_float<digits10>& result, unsigned long i)
649 {
650 mpf_mul_ui(result.data(), result.data(), i);
651 }
652 template <unsigned digits10>
653 inline 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 }
659 template <unsigned digits10>
660 inline 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 }
667 template <unsigned digits10>
668 inline 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 }
675 template <unsigned digits10>
676 inline 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 }
682 template <unsigned digits10>
683 inline 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 //
694 template <unsigned D1, unsigned D2, unsigned D3>
695 inline 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 }
699 template <unsigned D1, unsigned D2>
700 inline 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 }
704 template <unsigned D1, unsigned D2>
705 inline 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 }
712 template <unsigned D1, unsigned D2>
713 inline 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 }
717 template <unsigned D1, unsigned D2>
718 inline 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 }
728 template <unsigned D1, unsigned D2, unsigned D3>
729 inline 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 }
733 template <unsigned D1, unsigned D2>
734 inline 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 }
738 template <unsigned D1, unsigned D2>
739 inline 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 }
746 template <unsigned D1, unsigned D2>
747 inline 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 }
751 template <unsigned D1, unsigned D2>
752 inline 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
763 template <unsigned D1, unsigned D2, unsigned D3>
764 inline 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 }
768 template <unsigned D1, unsigned D2>
769 inline 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 }
773 template <unsigned D1, unsigned D2>
774 inline 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 }
784 template <unsigned D1, unsigned D2>
785 inline 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 }
789 template <unsigned D1, unsigned D2>
790 inline 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
801 template <unsigned D1, unsigned D2, unsigned D3>
802 inline 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 }
808 template <unsigned D1, unsigned D2>
809 inline 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 }
815 template <unsigned D1, unsigned D2>
816 inline 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 }
828 template <unsigned D1, unsigned D2>
829 inline 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 }
835 template <unsigned D1, unsigned D2>
836 inline 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
849 template <unsigned digits10>
850 inline int eval_get_sign(const gmp_float<digits10>& val) BOOST_NOEXCEPT
851 {
852 return mpf_sgn(val.data());
853 }
854
855 template <unsigned digits10>
856 inline 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 }
863 template <unsigned digits10>
864 inline 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 }
874 template <unsigned digits10>
875 inline 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
880 template <unsigned digits10>
881 inline 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 }
915 template <unsigned digits10>
916 inline 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 //
948 template <unsigned Digits10>
949 inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
950 {
951 mpf_sqrt(result.data(), val.data());
952 }
953
954 template <unsigned Digits10>
955 inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
956 {
957 mpf_abs(result.data(), val.data());
958 }
959
960 template <unsigned Digits10>
961 inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
962 {
963 mpf_abs(result.data(), val.data());
964 }
965 template <unsigned Digits10>
966 inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
967 {
968 mpf_ceil(result.data(), val.data());
969 }
970 template <unsigned Digits10>
971 inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
972 {
973 mpf_floor(result.data(), val.data());
974 }
975 template <unsigned Digits10>
976 inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
977 {
978 mpf_trunc(result.data(), val.data());
979 }
980 template <unsigned Digits10>
981 inline 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 }
990 template <unsigned Digits10>
991 inline 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 }
1003 template <unsigned Digits10>
1004 inline 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
1017 template <unsigned Digits10>
1018 inline 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
1028 struct 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 }
1341 protected:
1342 mpz_t m_data;
1343 };
1344
1345 template <class T>
1346 inline 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 }
1350 template <class T>
1351 inline 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 }
1355 template <class T>
1356 inline 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
1361 inline bool eval_is_zero(const gmp_int& val)
1362 {
1363 return mpz_sgn(val.data()) == 0;
1364 }
1365 inline void eval_add(gmp_int& t, const gmp_int& o)
1366 {
1367 mpz_add(t.data(), t.data(), o.data());
1368 }
1369 inline 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 }
1373 inline 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 }
1377 inline void eval_subtract(gmp_int& t, const gmp_int& o)
1378 {
1379 mpz_sub(t.data(), t.data(), o.data());
1380 }
1381 inline void eval_multiply(gmp_int& t, const gmp_int& o)
1382 {
1383 mpz_mul(t.data(), t.data(), o.data());
1384 }
1385 inline 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 }
1391 inline void eval_modulus(gmp_int& t, const gmp_int& o)
1392 {
1393 mpz_tdiv_r(t.data(), t.data(), o.data());
1394 }
1395 inline void eval_add(gmp_int& t, unsigned long i)
1396 {
1397 mpz_add_ui(t.data(), t.data(), i);
1398 }
1399 inline 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 }
1403 inline 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 }
1407 inline void eval_subtract(gmp_int& t, unsigned long i)
1408 {
1409 mpz_sub_ui(t.data(), t.data(), i);
1410 }
1411 inline void eval_multiply(gmp_int& t, unsigned long i)
1412 {
1413 mpz_mul_ui(t.data(), t.data(), i);
1414 }
1415 inline void eval_modulus(gmp_int& t, unsigned long i)
1416 {
1417 mpz_tdiv_r_ui(t.data(), t.data(), i);
1418 }
1419 inline 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 }
1425 inline 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 }
1432 inline 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 }
1439 inline 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 }
1446 inline 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 }
1453 inline 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 }
1459 inline 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 }
1463 inline 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 }
1471 template <class UI>
1472 inline void eval_left_shift(gmp_int& t, UI i)
1473 {
1474 mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1475 }
1476 template <class UI>
1477 inline 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 }
1481 template <class UI>
1482 inline 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 }
1486 template <class UI>
1487 inline 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
1492 inline void eval_bitwise_and(gmp_int& result, const gmp_int& v)
1493 {
1494 mpz_and(result.data(), result.data(), v.data());
1495 }
1496
1497 inline void eval_bitwise_or(gmp_int& result, const gmp_int& v)
1498 {
1499 mpz_ior(result.data(), result.data(), v.data());
1500 }
1501
1502 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v)
1503 {
1504 mpz_xor(result.data(), result.data(), v.data());
1505 }
1506
1507 inline 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 }
1511 inline 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 }
1515 inline 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 }
1519 inline 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 }
1525 inline 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 }
1529 inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i)
1530 {
1531 mpz_add_ui(t.data(), p.data(), i);
1532 }
1533 inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i)
1534 {
1535 mpz_sub_ui(t.data(), p.data(), i);
1536 }
1537 inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i)
1538 {
1539 mpz_mul_ui(t.data(), p.data(), i);
1540 }
1541 inline 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 }
1545 inline 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 }
1551 inline 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 }
1558 inline 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 }
1565 inline 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 }
1571 inline 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 }
1575 inline 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
1584 inline 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
1589 inline 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
1594 inline 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
1599 inline void eval_complement(gmp_int& result, const gmp_int& u)
1600 {
1601 mpz_com(result.data(), u.data());
1602 }
1603
1604 inline int eval_get_sign(const gmp_int& val)
1605 {
1606 return mpz_sgn(val.data());
1607 }
1608 inline 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 }
1617 inline 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 }
1627 inline void eval_convert_to(double* result, const gmp_int& val)
1628 {
1629 *result = mpz_get_d(val.data());
1630 }
1631
1632 inline void eval_abs(gmp_int& result, const gmp_int& val)
1633 {
1634 mpz_abs(result.data(), val.data());
1635 }
1636
1637 inline 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 }
1641 inline 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 }
1645 template <class I>
1646 inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
1647 {
1648 mpz_gcd_ui(result.data(), a.data(), b);
1649 }
1650 template <class I>
1651 inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
1652 {
1653 mpz_lcm_ui(result.data(), a.data(), b);
1654 }
1655 template <class I>
1656 inline typename enable_if_c<(is_signed<I>::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
1657 {
1658 mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
1659 }
1660 template <class I>
1661 inline typename enable_if_c<is_signed<I>::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
1662 {
1663 mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
1664 }
1665
1666 inline 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
1671 inline 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
1685 inline 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
1699 inline bool eval_bit_test(const gmp_int& val, unsigned index)
1700 {
1701 return mpz_tstbit(val.data(), index) ? true : false;
1702 }
1703
1704 inline void eval_bit_set(gmp_int& val, unsigned index)
1705 {
1706 mpz_setbit(val.data(), index);
1707 }
1708
1709 inline void eval_bit_unset(gmp_int& val, unsigned index)
1710 {
1711 mpz_clrbit(val.data(), index);
1712 }
1713
1714 inline void eval_bit_flip(gmp_int& val, unsigned index)
1715 {
1716 mpz_combit(val.data(), index);
1717 }
1718
1719 inline 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
1725 template <class Integer>
1726 inline 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 }
1737 template <class Integer>
1738 inline 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 }
1742 inline 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
1751 template <class Integer>
1752 inline 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 }
1761 template <class Integer>
1762 inline 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
1776 inline 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
1786 struct gmp_rational;
1787 void eval_add(gmp_rational& t, const gmp_rational& o);
1788
1789 struct 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 }
2036 protected:
2037 mpq_t m_data;
2038 };
2039
2040 inline bool eval_is_zero(const gmp_rational& val)
2041 {
2042 return mpq_sgn(val.data()) == 0;
2043 }
2044 template <class T>
2045 inline bool eval_eq(gmp_rational& a, const T& b)
2046 {
2047 return a.compare(b) == 0;
2048 }
2049 template <class T>
2050 inline bool eval_lt(gmp_rational& a, const T& b)
2051 {
2052 return a.compare(b) < 0;
2053 }
2054 template <class T>
2055 inline bool eval_gt(gmp_rational& a, const T& b)
2056 {
2057 return a.compare(b) > 0;
2058 }
2059
2060 inline void eval_add(gmp_rational& t, const gmp_rational& o)
2061 {
2062 mpq_add(t.data(), t.data(), o.data());
2063 }
2064 inline void eval_subtract(gmp_rational& t, const gmp_rational& o)
2065 {
2066 mpq_sub(t.data(), t.data(), o.data());
2067 }
2068 inline void eval_multiply(gmp_rational& t, const gmp_rational& o)
2069 {
2070 mpq_mul(t.data(), t.data(), o.data());
2071 }
2072 inline 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 }
2078 inline 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 }
2082 inline 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 }
2086 inline 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 }
2090 inline 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
2097 inline int eval_get_sign(const gmp_rational& val)
2098 {
2099 return mpq_sgn(val.data());
2100 }
2101 inline 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
2113 inline 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
2120 inline 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
2127 inline void eval_abs(gmp_rational& result, const gmp_rational& val)
2128 {
2129 mpq_abs(result.data(), val.data());
2130 }
2131
2132 inline 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 }
2137 inline 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 }
2142 inline 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
2149 inline 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 //
2163 template <unsigned Digits10>
2164 template <unsigned D>
2165 inline 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 }
2170 template <unsigned Digits10>
2171 template <unsigned D>
2172 inline 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 }
2177 template <unsigned Digits10>
2178 inline 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 }
2183 template <unsigned Digits10>
2184 inline 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 }
2189 template <unsigned Digits10>
2190 template <unsigned D>
2191 inline 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 }
2198 template <unsigned Digits10>
2199 inline 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 }
2206 template <unsigned Digits10>
2207 inline 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 }
2214 inline 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 }
2219 inline 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 }
2224 inline 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 }
2231 inline 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 }
2238 inline 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 }
2243 inline 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
2253 using boost::multiprecision::backends::gmp_int;
2254 using boost::multiprecision::backends::gmp_rational;
2255 using boost::multiprecision::backends::gmp_float;
2256
2257 template <>
2258 struct component_type<number<gmp_rational> >
2259 {
2260 typedef number<gmp_int> type;
2261 };
2262
2263 template <expression_template_option ET>
2264 inline 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 }
2270 template <expression_template_option ET>
2271 inline 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
2278 namespace detail{
2279
2280 #ifdef BOOST_NO_SFINAE_EXPR
2281
2282 template<>
2283 struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
2284 template<>
2285 struct is_explicitly_convertible<canonical<mpq_t, gmp_int>::type, gmp_int> : public mpl::true_ {};
2286 template<unsigned Digits10>
2287 struct is_explicitly_convertible<gmp_float<Digits10>, gmp_int> : public mpl::true_ {};
2288 template<>
2289 struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_ {};
2290 template<unsigned D1, unsigned D2>
2291 struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_ {};
2292
2293 #endif
2294
2295 template <>
2296 struct 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
2304 template <>
2305 struct 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
2313 template <>
2314 struct 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
2322 template <>
2323 struct 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
2333 template<>
2334 struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer>{};
2335 template<>
2336 struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public mpl::int_<number_kind_rational>{};
2337 template<>
2338 struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public mpl::int_<number_kind_floating_point>{};
2339
2340
2341 typedef number<gmp_float<50> > mpf_float_50;
2342 typedef number<gmp_float<100> > mpf_float_100;
2343 typedef number<gmp_float<500> > mpf_float_500;
2344 typedef number<gmp_float<1000> > mpf_float_1000;
2345 typedef number<gmp_float<0> > mpf_float;
2346 typedef number<gmp_int > mpz_int;
2347 typedef number<gmp_rational > mpq_rational;
2348
2349 } // namespace multiprecision
2350
2351 namespace 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
2457 namespace std{
2458
2459 //
2460 // numeric_limits [partial] specializations for the types declared in this header:
2461 //
2462 template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2463 class 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;
2466 public:
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
2554 private:
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
2569 template<unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2570 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::initializer;
2571
2572 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2573
2574 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2575 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits;
2576 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2577 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits10;
2578 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2579 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_digits10;
2580 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2581 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_signed;
2582 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2583 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_integer;
2584 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2585 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_exact;
2586 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2587 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::radix;
2588 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2589 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent;
2590 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2591 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent10;
2592 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2593 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent;
2594 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2595 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent10;
2596 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2597 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_infinity;
2598 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2599 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
2600 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2601 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
2602 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2603 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm;
2604 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2605 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm_loss;
2606 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2607 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_iec559;
2608 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2609 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_bounded;
2610 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2611 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_modulo;
2612 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2613 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::traps;
2614 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2615 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::tinyness_before;
2616 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
2617 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::round_style;
2618
2619 #endif
2620
2621 template<boost::multiprecision::expression_template_option ExpressionTemplates>
2622 class 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;
2625 public:
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
2662 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2663 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits;
2664 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2665 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10;
2666 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2667 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10;
2668 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2669 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed;
2670 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2671 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer;
2672 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2673 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact;
2674 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2675 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix;
2676 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2677 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent;
2678 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2679 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10;
2680 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2681 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent;
2682 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2683 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10;
2684 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2685 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity;
2686 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2687 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN;
2688 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2689 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN;
2690 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2691 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm;
2692 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2693 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss;
2694 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2695 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559;
2696 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2697 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded;
2698 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2699 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo;
2700 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2701 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps;
2702 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2703 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before;
2704 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2705 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style;
2706
2707 #endif
2708
2709 template<boost::multiprecision::expression_template_option ExpressionTemplates>
2710 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >
2711 {
2712 typedef boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> number_type;
2713 public:
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
2760 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2761 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits;
2762 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2763 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10;
2764 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2765 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10;
2766 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2767 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed;
2768 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2769 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer;
2770 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2771 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact;
2772 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2773 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix;
2774 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2775 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent;
2776 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2777 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10;
2778 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2779 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent;
2780 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2781 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10;
2782 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2783 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity;
2784 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2785 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN;
2786 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2787 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN;
2788 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2789 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm;
2790 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2791 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss;
2792 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2793 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559;
2794 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2795 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded;
2796 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2797 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo;
2798 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2799 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps;
2800 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2801 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before;
2802 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2803 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style;
2804
2805 #endif
2806
2807 template<boost::multiprecision::expression_template_option ExpressionTemplates>
2808 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >
2809 {
2810 typedef boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> number_type;
2811 public:
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
2859 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2860 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits;
2861 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2862 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10;
2863 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2864 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10;
2865 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2866 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed;
2867 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2868 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer;
2869 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2870 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact;
2871 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2872 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix;
2873 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2874 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent;
2875 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2876 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10;
2877 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2878 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent;
2879 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2880 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10;
2881 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2882 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity;
2883 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2884 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN;
2885 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2886 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN;
2887 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2888 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm;
2889 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2890 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss;
2891 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2892 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559;
2893 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2894 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded;
2895 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2896 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo;
2897 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2898 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps;
2899 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2900 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before;
2901 template <boost::multiprecision::expression_template_option ExpressionTemplates>
2902 BOOST_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