Ticket #8667: gmp.hpp

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