comparison DEPENDENCIES/generic/include/boost/multiprecision/mpfr.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
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_BN_MPFR_HPP
7 #define BOOST_MATH_BN_MPFR_HPP
8
9 #include <boost/multiprecision/number.hpp>
10 #include <boost/multiprecision/gmp.hpp>
11 #include <boost/math/special_functions/fpclassify.hpp>
12 #include <boost/cstdint.hpp>
13 #include <boost/multiprecision/detail/big_lanczos.hpp>
14 #include <boost/multiprecision/detail/digits.hpp>
15 #include <mpfr.h>
16 #include <cmath>
17 #include <algorithm>
18
19 namespace boost{
20 namespace multiprecision{
21
22 enum mpfr_allocation_type
23 {
24 allocate_stack,
25 allocate_dynamic
26 };
27
28 namespace backends{
29
30 template <unsigned digits10, mpfr_allocation_type AllocationType = allocate_dynamic>
31 struct mpfr_float_backend;
32
33 } // namespace backends
34
35 template <unsigned digits10, mpfr_allocation_type AllocationType>
36 struct number_category<backends::mpfr_float_backend<digits10, AllocationType> > : public mpl::int_<number_kind_floating_point>{};
37
38 namespace backends{
39
40 namespace detail{
41
42 template <bool b>
43 struct mpfr_cleanup
44 {
45 struct initializer
46 {
47 initializer() {}
48 ~initializer(){ mpfr_free_cache(); }
49 void force_instantiate()const {}
50 };
51 static const initializer init;
52 static void force_instantiate() { init.force_instantiate(); }
53 };
54
55 template <bool b>
56 typename mpfr_cleanup<b>::initializer const mpfr_cleanup<b>::init;
57
58 inline long get_default_precision() { return 50; }
59
60 template <unsigned digits10, mpfr_allocation_type AllocationType>
61 struct mpfr_float_imp;
62
63 template <unsigned digits10>
64 struct mpfr_float_imp<digits10, allocate_dynamic>
65 {
66 typedef mpl::list<long, long long> signed_types;
67 typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
68 typedef mpl::list<double, long double> float_types;
69 typedef long exponent_type;
70
71 mpfr_float_imp()
72 {
73 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
74 }
75 mpfr_float_imp(unsigned prec)
76 {
77 mpfr_init2(m_data, prec);
78 }
79
80 mpfr_float_imp(const mpfr_float_imp& o)
81 {
82 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
83 if(o.m_data[0]._mpfr_d)
84 mpfr_set(m_data, o.m_data, GMP_RNDN);
85 }
86 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
87 mpfr_float_imp(mpfr_float_imp&& o) BOOST_NOEXCEPT
88 {
89 m_data[0] = o.m_data[0];
90 o.m_data[0]._mpfr_d = 0;
91 }
92 #endif
93 mpfr_float_imp& operator = (const mpfr_float_imp& o)
94 {
95 if(m_data[0]._mpfr_d == 0)
96 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
97 if(o.m_data[0]._mpfr_d)
98 mpfr_set(m_data, o.m_data, GMP_RNDN);
99 return *this;
100 }
101 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
102 mpfr_float_imp& operator = (mpfr_float_imp&& o) BOOST_NOEXCEPT
103 {
104 mpfr_swap(m_data, o.m_data);
105 return *this;
106 }
107 #endif
108 #ifdef _MPFR_H_HAVE_INTMAX_T
109 mpfr_float_imp& operator = (unsigned long long i)
110 {
111 if(m_data[0]._mpfr_d == 0)
112 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
113 mpfr_set_uj(m_data, i, GMP_RNDN);
114 return *this;
115 }
116 mpfr_float_imp& operator = (long long i)
117 {
118 if(m_data[0]._mpfr_d == 0)
119 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
120 mpfr_set_sj(m_data, i, GMP_RNDN);
121 return *this;
122 }
123 #else
124 mpfr_float_imp& operator = (unsigned long long i)
125 {
126 if(m_data[0]._mpfr_d == 0)
127 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
128 unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
129 unsigned shift = 0;
130 mpfr_t t;
131 mpfr_init2(t, (std::max)(static_cast<unsigned>(std::numeric_limits<unsigned long long>::digits), static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10))));
132 mpfr_set_ui(m_data, 0, GMP_RNDN);
133 while(i)
134 {
135 mpfr_set_ui(t, static_cast<unsigned>(i & mask), GMP_RNDN);
136 if(shift)
137 mpfr_mul_2exp(t, t, shift, GMP_RNDN);
138 mpfr_add(m_data, m_data, t, GMP_RNDN);
139 shift += std::numeric_limits<unsigned>::digits;
140 i >>= std::numeric_limits<unsigned>::digits;
141 }
142 mpfr_clear(t);
143 return *this;
144 }
145 mpfr_float_imp& operator = (long long i)
146 {
147 BOOST_MP_USING_ABS
148 if(m_data[0]._mpfr_d == 0)
149 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
150 bool neg = i < 0;
151 *this = static_cast<unsigned long long>(abs(i));
152 if(neg)
153 mpfr_neg(m_data, m_data, GMP_RNDN);
154 return *this;
155 }
156 #endif
157 mpfr_float_imp& operator = (unsigned long i)
158 {
159 if(m_data[0]._mpfr_d == 0)
160 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
161 mpfr_set_ui(m_data, i, GMP_RNDN);
162 return *this;
163 }
164 mpfr_float_imp& operator = (long i)
165 {
166 if(m_data[0]._mpfr_d == 0)
167 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
168 mpfr_set_si(m_data, i, GMP_RNDN);
169 return *this;
170 }
171 mpfr_float_imp& operator = (double d)
172 {
173 if(m_data[0]._mpfr_d == 0)
174 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
175 mpfr_set_d(m_data, d, GMP_RNDN);
176 return *this;
177 }
178 mpfr_float_imp& operator = (long double a)
179 {
180 if(m_data[0]._mpfr_d == 0)
181 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
182 mpfr_set_ld(m_data, a, GMP_RNDN);
183 return *this;
184 }
185 mpfr_float_imp& operator = (const char* s)
186 {
187 if(m_data[0]._mpfr_d == 0)
188 mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
189 if(mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
190 {
191 BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
192 }
193 return *this;
194 }
195 void swap(mpfr_float_imp& o) BOOST_NOEXCEPT
196 {
197 mpfr_swap(m_data, o.m_data);
198 }
199 std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
200 {
201 BOOST_ASSERT(m_data[0]._mpfr_d);
202
203 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
204 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
205
206 std::streamsize org_digits(digits);
207
208 if(scientific && digits)
209 ++digits;
210
211 std::string result;
212 mp_exp_t e;
213 if(mpfr_inf_p(m_data))
214 {
215 if(mpfr_sgn(m_data) < 0)
216 result = "-inf";
217 else if(f & std::ios_base::showpos)
218 result = "+inf";
219 else
220 result = "inf";
221 return result;
222 }
223 if(mpfr_nan_p(m_data))
224 {
225 result = "nan";
226 return result;
227 }
228 if(mpfr_zero_p(m_data))
229 {
230 e = 0;
231 result = "0";
232 }
233 else
234 {
235 char* ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
236 --e; // To match with what our formatter expects.
237 if(fixed && e != -1)
238 {
239 // Oops we actually need a different number of digits to what we asked for:
240 mpfr_free_str(ps);
241 digits += e + 1;
242 if(digits == 0)
243 {
244 // We need to get *all* the digits and then possibly round up,
245 // we end up with either "0" or "1" as the result.
246 ps = mpfr_get_str (0, &e, 10, 0, m_data, GMP_RNDN);
247 --e;
248 unsigned offset = *ps == '-' ? 1 : 0;
249 if(ps[offset] > '5')
250 {
251 ++e;
252 ps[offset] = '1';
253 ps[offset + 1] = 0;
254 }
255 else if(ps[offset] == '5')
256 {
257 unsigned i = offset + 1;
258 bool round_up = false;
259 while(ps[i] != 0)
260 {
261 if(ps[i] != '0')
262 {
263 round_up = true;
264 break;
265 }
266 }
267 if(round_up)
268 {
269 ++e;
270 ps[offset] = '1';
271 ps[offset + 1] = 0;
272 }
273 else
274 {
275 ps[offset] = '0';
276 ps[offset + 1] = 0;
277 }
278 }
279 else
280 {
281 ps[offset] = '0';
282 ps[offset + 1] = 0;
283 }
284 }
285 else if(digits > 0)
286 {
287 ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
288 --e; // To match with what our formatter expects.
289 }
290 else
291 {
292 ps = mpfr_get_str (0, &e, 10, 1, m_data, GMP_RNDN);
293 --e;
294 unsigned offset = *ps == '-' ? 1 : 0;
295 ps[offset] = '0';
296 ps[offset + 1] = 0;
297 }
298 }
299 result = ps ? ps : "0";
300 if(ps)
301 mpfr_free_str(ps);
302 }
303 boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
304 return result;
305 }
306 ~mpfr_float_imp() BOOST_NOEXCEPT
307 {
308 if(m_data[0]._mpfr_d)
309 mpfr_clear(m_data);
310 detail::mpfr_cleanup<true>::force_instantiate();
311 }
312 void negate() BOOST_NOEXCEPT
313 {
314 BOOST_ASSERT(m_data[0]._mpfr_d);
315 mpfr_neg(m_data, m_data, GMP_RNDN);
316 }
317 template <mpfr_allocation_type AllocationType>
318 int compare(const mpfr_float_backend<digits10, AllocationType>& o)const BOOST_NOEXCEPT
319 {
320 BOOST_ASSERT(m_data[0]._mpfr_d && o.m_data[0]._mpfr_d);
321 return mpfr_cmp(m_data, o.m_data);
322 }
323 int compare(long i)const BOOST_NOEXCEPT
324 {
325 BOOST_ASSERT(m_data[0]._mpfr_d);
326 return mpfr_cmp_si(m_data, i);
327 }
328 int compare(unsigned long i)const BOOST_NOEXCEPT
329 {
330 BOOST_ASSERT(m_data[0]._mpfr_d);
331 return mpfr_cmp_ui(m_data, i);
332 }
333 template <class V>
334 int compare(V v)const BOOST_NOEXCEPT
335 {
336 mpfr_float_backend<digits10, allocate_dynamic> d;
337 d = v;
338 return compare(d);
339 }
340 mpfr_t& data() BOOST_NOEXCEPT
341 {
342 BOOST_ASSERT(m_data[0]._mpfr_d);
343 return m_data;
344 }
345 const mpfr_t& data()const BOOST_NOEXCEPT
346 {
347 BOOST_ASSERT(m_data[0]._mpfr_d);
348 return m_data;
349 }
350 protected:
351 mpfr_t m_data;
352 static unsigned& get_default_precision() BOOST_NOEXCEPT
353 {
354 static unsigned val = 50;
355 return val;
356 }
357 };
358
359 #ifdef BOOST_MSVC
360 #pragma warning(push)
361 #pragma warning(disable:4127) // Conditional expression is constant
362 #endif
363
364 template <unsigned digits10>
365 struct mpfr_float_imp<digits10, allocate_stack>
366 {
367 typedef mpl::list<long, long long> signed_types;
368 typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
369 typedef mpl::list<double, long double> float_types;
370 typedef long exponent_type;
371
372 static const unsigned digits2 = (digits10 * 1000uL) / 301uL + ((digits10 * 1000uL) % 301 ? 2u : 1u);
373 static const unsigned limb_count = mpfr_custom_get_size(digits2) / sizeof(mp_limb_t);
374
375 ~mpfr_float_imp() BOOST_NOEXCEPT
376 {
377 detail::mpfr_cleanup<true>::force_instantiate();
378 }
379 mpfr_float_imp()
380 {
381 mpfr_custom_init(m_buffer, digits2);
382 mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
383 }
384
385 mpfr_float_imp(const mpfr_float_imp& o)
386 {
387 mpfr_custom_init(m_buffer, digits2);
388 mpfr_custom_init_set(m_data, MPFR_NAN_KIND, 0, digits2, m_buffer);
389 mpfr_set(m_data, o.m_data, GMP_RNDN);
390 }
391 mpfr_float_imp& operator = (const mpfr_float_imp& o)
392 {
393 mpfr_set(m_data, o.m_data, GMP_RNDN);
394 return *this;
395 }
396 #ifdef _MPFR_H_HAVE_INTMAX_T
397 mpfr_float_imp& operator = (unsigned long long i)
398 {
399 mpfr_set_uj(m_data, i, GMP_RNDN);
400 return *this;
401 }
402 mpfr_float_imp& operator = (long long i)
403 {
404 mpfr_set_sj(m_data, i, GMP_RNDN);
405 return *this;
406 }
407 #else
408 mpfr_float_imp& operator = (unsigned long long i)
409 {
410 unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
411 unsigned shift = 0;
412 mpfr_t t;
413 mp_limb_t t_limbs[limb_count];
414 mpfr_custom_init(t_limbs, digits2);
415 mpfr_custom_init_set(t, MPFR_NAN_KIND, 0, digits2, t_limbs);
416 mpfr_set_ui(m_data, 0, GMP_RNDN);
417 while(i)
418 {
419 mpfr_set_ui(t, static_cast<unsigned>(i & mask), GMP_RNDN);
420 if(shift)
421 mpfr_mul_2exp(t, t, shift, GMP_RNDN);
422 mpfr_add(m_data, m_data, t, GMP_RNDN);
423 shift += std::numeric_limits<unsigned>::digits;
424 i >>= std::numeric_limits<unsigned>::digits;
425 }
426 return *this;
427 }
428 mpfr_float_imp& operator = (long long i)
429 {
430 BOOST_MP_USING_ABS
431 bool neg = i < 0;
432 *this = static_cast<unsigned long long>(abs(i));
433 if(neg)
434 mpfr_neg(m_data, m_data, GMP_RNDN);
435 return *this;
436 }
437 #endif
438 mpfr_float_imp& operator = (unsigned long i)
439 {
440 mpfr_set_ui(m_data, i, GMP_RNDN);
441 return *this;
442 }
443 mpfr_float_imp& operator = (long i)
444 {
445 mpfr_set_si(m_data, i, GMP_RNDN);
446 return *this;
447 }
448 mpfr_float_imp& operator = (double d)
449 {
450 mpfr_set_d(m_data, d, GMP_RNDN);
451 return *this;
452 }
453 mpfr_float_imp& operator = (long double a)
454 {
455 mpfr_set_ld(m_data, a, GMP_RNDN);
456 return *this;
457 }
458 mpfr_float_imp& operator = (const char* s)
459 {
460 if(mpfr_set_str(m_data, s, 10, GMP_RNDN) != 0)
461 {
462 BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse string \"") + s + std::string("\"as a valid floating point number.")));
463 }
464 return *this;
465 }
466 void swap(mpfr_float_imp& o) BOOST_NOEXCEPT
467 {
468 // We have to swap by copying:
469 mpfr_float_imp t(*this);
470 *this = o;
471 o = t;
472 }
473 std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
474 {
475 BOOST_ASSERT(m_data[0]._mpfr_d);
476
477 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
478 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
479
480 std::streamsize org_digits(digits);
481
482 if(scientific && digits)
483 ++digits;
484
485 std::string result;
486 mp_exp_t e;
487 if(mpfr_inf_p(m_data))
488 {
489 if(mpfr_sgn(m_data) < 0)
490 result = "-inf";
491 else if(f & std::ios_base::showpos)
492 result = "+inf";
493 else
494 result = "inf";
495 return result;
496 }
497 if(mpfr_nan_p(m_data))
498 {
499 result = "nan";
500 return result;
501 }
502 if(mpfr_zero_p(m_data))
503 {
504 e = 0;
505 result = "0";
506 }
507 else
508 {
509 char* ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
510 --e; // To match with what our formatter expects.
511 if(fixed && e != -1)
512 {
513 // Oops we actually need a different number of digits to what we asked for:
514 mpfr_free_str(ps);
515 digits += e + 1;
516 if(digits == 0)
517 {
518 // We need to get *all* the digits and then possibly round up,
519 // we end up with either "0" or "1" as the result.
520 ps = mpfr_get_str (0, &e, 10, 0, m_data, GMP_RNDN);
521 --e;
522 unsigned offset = *ps == '-' ? 1 : 0;
523 if(ps[offset] > '5')
524 {
525 ++e;
526 ps[offset] = '1';
527 ps[offset + 1] = 0;
528 }
529 else if(ps[offset] == '5')
530 {
531 unsigned i = offset + 1;
532 bool round_up = false;
533 while(ps[i] != 0)
534 {
535 if(ps[i] != '0')
536 {
537 round_up = true;
538 break;
539 }
540 }
541 if(round_up)
542 {
543 ++e;
544 ps[offset] = '1';
545 ps[offset + 1] = 0;
546 }
547 else
548 {
549 ps[offset] = '0';
550 ps[offset + 1] = 0;
551 }
552 }
553 else
554 {
555 ps[offset] = '0';
556 ps[offset + 1] = 0;
557 }
558 }
559 else if(digits > 0)
560 {
561 ps = mpfr_get_str (0, &e, 10, static_cast<std::size_t>(digits), m_data, GMP_RNDN);
562 --e; // To match with what our formatter expects.
563 }
564 else
565 {
566 ps = mpfr_get_str (0, &e, 10, 1, m_data, GMP_RNDN);
567 --e;
568 unsigned offset = *ps == '-' ? 1 : 0;
569 ps[offset] = '0';
570 ps[offset + 1] = 0;
571 }
572 }
573 result = ps ? ps : "0";
574 if(ps)
575 mpfr_free_str(ps);
576 }
577 boost::multiprecision::detail::format_float_string(result, e, org_digits, f, 0 != mpfr_zero_p(m_data));
578 return result;
579 }
580 void negate() BOOST_NOEXCEPT
581 {
582 mpfr_neg(m_data, m_data, GMP_RNDN);
583 }
584 template <mpfr_allocation_type AllocationType>
585 int compare(const mpfr_float_backend<digits10, AllocationType>& o)const BOOST_NOEXCEPT
586 {
587 return mpfr_cmp(m_data, o.m_data);
588 }
589 int compare(long i)const BOOST_NOEXCEPT
590 {
591 return mpfr_cmp_si(m_data, i);
592 }
593 int compare(unsigned long i)const BOOST_NOEXCEPT
594 {
595 return mpfr_cmp_ui(m_data, i);
596 }
597 template <class V>
598 int compare(V v)const BOOST_NOEXCEPT
599 {
600 mpfr_float_backend<digits10, allocate_stack> d;
601 d = v;
602 return compare(d);
603 }
604 mpfr_t& data() BOOST_NOEXCEPT
605 {
606 return m_data;
607 }
608 const mpfr_t& data()const BOOST_NOEXCEPT
609 {
610 return m_data;
611 }
612 protected:
613 mpfr_t m_data;
614 mp_limb_t m_buffer[limb_count];
615 };
616
617 #ifdef BOOST_MSVC
618 #pragma warning(pop)
619 #endif
620
621 } // namespace detail
622
623 template <unsigned digits10, mpfr_allocation_type AllocationType>
624 struct mpfr_float_backend : public detail::mpfr_float_imp<digits10, AllocationType>
625 {
626 mpfr_float_backend() : detail::mpfr_float_imp<digits10, AllocationType>() {}
627 mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<digits10, AllocationType>(o) {}
628 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
629 mpfr_float_backend(mpfr_float_backend&& o) : detail::mpfr_float_imp<digits10, AllocationType>(static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o)) {}
630 #endif
631 template <unsigned D, mpfr_allocation_type AT>
632 mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename enable_if_c<D <= digits10>::type* = 0)
633 : detail::mpfr_float_imp<digits10, AllocationType>()
634 {
635 mpfr_set(this->m_data, val.data(), GMP_RNDN);
636 }
637 template <unsigned D, mpfr_allocation_type AT>
638 explicit mpfr_float_backend(const mpfr_float_backend<D, AT>& val, typename disable_if_c<D <= digits10>::type* = 0)
639 : detail::mpfr_float_imp<digits10, AllocationType>()
640 {
641 mpfr_set(this->m_data, val.data(), GMP_RNDN);
642 }
643 template <unsigned D>
644 mpfr_float_backend(const gmp_float<D>& val, typename enable_if_c<D <= digits10>::type* = 0)
645 : detail::mpfr_float_imp<digits10, AllocationType>()
646 {
647 mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
648 }
649 template <unsigned D>
650 mpfr_float_backend(const gmp_float<D>& val, typename disable_if_c<D <= digits10>::type* = 0)
651 : detail::mpfr_float_imp<digits10, AllocationType>()
652 {
653 mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
654 }
655 mpfr_float_backend(const gmp_int& val)
656 : detail::mpfr_float_imp<digits10, AllocationType>()
657 {
658 mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
659 }
660 mpfr_float_backend(const gmp_rational& val)
661 : detail::mpfr_float_imp<digits10, AllocationType>()
662 {
663 mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
664 }
665 mpfr_float_backend(const mpfr_t val)
666 : detail::mpfr_float_imp<digits10, AllocationType>()
667 {
668 mpfr_set(this->m_data, val, GMP_RNDN);
669 }
670 mpfr_float_backend(const mpf_t val)
671 : detail::mpfr_float_imp<digits10, AllocationType>()
672 {
673 mpfr_set_f(this->m_data, val, GMP_RNDN);
674 }
675 mpfr_float_backend(const mpz_t val)
676 : detail::mpfr_float_imp<digits10, AllocationType>()
677 {
678 mpfr_set_z(this->m_data, val, GMP_RNDN);
679 }
680 mpfr_float_backend(const mpq_t val)
681 : detail::mpfr_float_imp<digits10, AllocationType>()
682 {
683 mpfr_set_q(this->m_data, val, GMP_RNDN);
684 }
685 mpfr_float_backend& operator=(const mpfr_float_backend& o)
686 {
687 *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType> const&>(o);
688 return *this;
689 }
690 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
691 mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT
692 {
693 *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = static_cast<detail::mpfr_float_imp<digits10, AllocationType>&&>(o);
694 return *this;
695 }
696 #endif
697 template <class V>
698 mpfr_float_backend& operator=(const V& v)
699 {
700 *static_cast<detail::mpfr_float_imp<digits10, AllocationType>*>(this) = v;
701 return *this;
702 }
703 mpfr_float_backend& operator=(const mpfr_t val)
704 {
705 if(this->m_data[0]._mpfr_d == 0)
706 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
707 mpfr_set(this->m_data, val, GMP_RNDN);
708 return *this;
709 }
710 mpfr_float_backend& operator=(const mpf_t val)
711 {
712 if(this->m_data[0]._mpfr_d == 0)
713 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
714 mpfr_set_f(this->m_data, val, GMP_RNDN);
715 return *this;
716 }
717 mpfr_float_backend& operator=(const mpz_t val)
718 {
719 if(this->m_data[0]._mpfr_d == 0)
720 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
721 mpfr_set_z(this->m_data, val, GMP_RNDN);
722 return *this;
723 }
724 mpfr_float_backend& operator=(const mpq_t val)
725 {
726 if(this->m_data[0]._mpfr_d == 0)
727 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
728 mpfr_set_q(this->m_data, val, GMP_RNDN);
729 return *this;
730 }
731 // We don't change our precision here, this is a fixed precision type:
732 template <unsigned D, mpfr_allocation_type AT>
733 mpfr_float_backend& operator=(const mpfr_float_backend<D, AT>& val)
734 {
735 if(this->m_data[0]._mpfr_d == 0)
736 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
737 mpfr_set(this->m_data, val.data(), GMP_RNDN);
738 return *this;
739 }
740 template <unsigned D>
741 mpfr_float_backend& operator=(const gmp_float<D>& val)
742 {
743 if(this->m_data[0]._mpfr_d == 0)
744 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
745 mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
746 return *this;
747 }
748 mpfr_float_backend& operator=(const gmp_int& val)
749 {
750 if(this->m_data[0]._mpfr_d == 0)
751 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
752 mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
753 return *this;
754 }
755 mpfr_float_backend& operator=(const gmp_rational& val)
756 {
757 if(this->m_data[0]._mpfr_d == 0)
758 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
759 mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
760 return *this;
761 }
762 };
763
764 template <>
765 struct mpfr_float_backend<0, allocate_dynamic> : public detail::mpfr_float_imp<0, allocate_dynamic>
766 {
767 mpfr_float_backend() : detail::mpfr_float_imp<0, allocate_dynamic>() {}
768 mpfr_float_backend(const mpfr_t val)
769 : detail::mpfr_float_imp<0, allocate_dynamic>(mpfr_get_prec(val))
770 {
771 mpfr_set(this->m_data, val, GMP_RNDN);
772 }
773 mpfr_float_backend(const mpf_t val)
774 : detail::mpfr_float_imp<0, allocate_dynamic>(mpf_get_prec(val))
775 {
776 mpfr_set_f(this->m_data, val, GMP_RNDN);
777 }
778 mpfr_float_backend(const mpz_t val)
779 : detail::mpfr_float_imp<0, allocate_dynamic>()
780 {
781 mpfr_set_z(this->m_data, val, GMP_RNDN);
782 }
783 mpfr_float_backend(const mpq_t val)
784 : detail::mpfr_float_imp<0, allocate_dynamic>()
785 {
786 mpfr_set_q(this->m_data, val, GMP_RNDN);
787 }
788 mpfr_float_backend(const mpfr_float_backend& o) : detail::mpfr_float_imp<0, allocate_dynamic>(o) {}
789 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
790 mpfr_float_backend(mpfr_float_backend&& o) BOOST_NOEXCEPT : detail::mpfr_float_imp<0, allocate_dynamic>(static_cast<detail::mpfr_float_imp<0, allocate_dynamic>&&>(o)) {}
791 #endif
792 mpfr_float_backend(const mpfr_float_backend& o, unsigned digits10)
793 : detail::mpfr_float_imp<0, allocate_dynamic>(digits10)
794 {
795 *this = o;
796 }
797 template <unsigned D>
798 mpfr_float_backend(const mpfr_float_backend<D>& val)
799 : detail::mpfr_float_imp<0, allocate_dynamic>(mpfr_get_prec(val.data()))
800 {
801 mpfr_set(this->m_data, val.data(), GMP_RNDN);
802 }
803 template <unsigned D>
804 mpfr_float_backend(const gmp_float<D>& val)
805 : detail::mpfr_float_imp<0, allocate_dynamic>(mpf_get_prec(val.data()))
806 {
807 mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
808 }
809 mpfr_float_backend(const gmp_int& val)
810 : detail::mpfr_float_imp<0, allocate_dynamic>()
811 {
812 mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
813 }
814 mpfr_float_backend(const gmp_rational& val)
815 : detail::mpfr_float_imp<0, allocate_dynamic>()
816 {
817 mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
818 }
819
820 mpfr_float_backend& operator=(const mpfr_float_backend& o)
821 {
822 if(this->m_data[0]._mpfr_d == 0)
823 mpfr_init2(this->m_data, mpfr_get_prec(o.data()));
824 else
825 mpfr_set_prec(this->m_data, mpfr_get_prec(o.data()));
826 mpfr_set(this->m_data, o.data(), GMP_RNDN);
827 return *this;
828 }
829 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
830 mpfr_float_backend& operator=(mpfr_float_backend&& o) BOOST_NOEXCEPT
831 {
832 *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = static_cast<detail::mpfr_float_imp<0, allocate_dynamic> &&>(o);
833 return *this;
834 }
835 #endif
836 template <class V>
837 mpfr_float_backend& operator=(const V& v)
838 {
839 *static_cast<detail::mpfr_float_imp<0, allocate_dynamic>*>(this) = v;
840 return *this;
841 }
842 mpfr_float_backend& operator=(const mpfr_t val)
843 {
844 if(this->m_data[0]._mpfr_d == 0)
845 mpfr_init2(this->m_data, mpfr_get_prec(val));
846 else
847 mpfr_set_prec(this->m_data, mpfr_get_prec(val));
848 mpfr_set(this->m_data, val, GMP_RNDN);
849 return *this;
850 }
851 mpfr_float_backend& operator=(const mpf_t val)
852 {
853 if(this->m_data[0]._mpfr_d == 0)
854 mpfr_init2(this->m_data, mpf_get_prec(val));
855 else
856 mpfr_set_prec(this->m_data, mpf_get_prec(val));
857 mpfr_set_f(this->m_data, val, GMP_RNDN);
858 return *this;
859 }
860 mpfr_float_backend& operator=(const mpz_t val)
861 {
862 if(this->m_data[0]._mpfr_d == 0)
863 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
864 mpfr_set_z(this->m_data, val, GMP_RNDN);
865 return *this;
866 }
867 mpfr_float_backend& operator=(const mpq_t val)
868 {
869 if(this->m_data[0]._mpfr_d == 0)
870 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
871 mpfr_set_q(this->m_data, val, GMP_RNDN);
872 return *this;
873 }
874 template <unsigned D>
875 mpfr_float_backend& operator=(const mpfr_float_backend<D>& val)
876 {
877 if(this->m_data[0]._mpfr_d == 0)
878 mpfr_init2(this->m_data, mpfr_get_prec(val.data()));
879 else
880 mpfr_set_prec(this->m_data, mpfr_get_prec(val.data()));
881 mpfr_set(this->m_data, val.data(), GMP_RNDN);
882 return *this;
883 }
884 template <unsigned D>
885 mpfr_float_backend& operator=(const gmp_float<D>& val)
886 {
887 if(this->m_data[0]._mpfr_d == 0)
888 mpfr_init2(this->m_data, mpf_get_prec(val.data()));
889 else
890 mpfr_set_prec(this->m_data, mpf_get_prec(val.data()));
891 mpfr_set_f(this->m_data, val.data(), GMP_RNDN);
892 return *this;
893 }
894 mpfr_float_backend& operator=(const gmp_int& val)
895 {
896 if(this->m_data[0]._mpfr_d == 0)
897 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
898 mpfr_set_z(this->m_data, val.data(), GMP_RNDN);
899 return *this;
900 }
901 mpfr_float_backend& operator=(const gmp_rational& val)
902 {
903 if(this->m_data[0]._mpfr_d == 0)
904 mpfr_init2(this->m_data, multiprecision::detail::digits10_2_2(get_default_precision()));
905 mpfr_set_q(this->m_data, val.data(), GMP_RNDN);
906 return *this;
907 }
908 static unsigned default_precision() BOOST_NOEXCEPT
909 {
910 return get_default_precision();
911 }
912 static void default_precision(unsigned v) BOOST_NOEXCEPT
913 {
914 get_default_precision() = v;
915 }
916 unsigned precision()const BOOST_NOEXCEPT
917 {
918 return multiprecision::detail::digits2_2_10(mpfr_get_prec(this->m_data));
919 }
920 void precision(unsigned digits10) BOOST_NOEXCEPT
921 {
922 mpfr_prec_round(this->m_data, multiprecision::detail::digits10_2_2((digits10)), GMP_RNDN);
923 }
924 };
925
926 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
927 inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
928 {
929 return a.compare(b) == 0;
930 }
931 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
932 inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
933 {
934 return a.compare(b) < 0;
935 }
936 template <unsigned digits10, mpfr_allocation_type AllocationType, class T>
937 inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const mpfr_float_backend<digits10, AllocationType>& a, const T& b) BOOST_NOEXCEPT
938 {
939 return a.compare(b) > 0;
940 }
941
942 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
943 inline void eval_add(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
944 {
945 mpfr_add(result.data(), result.data(), o.data(), GMP_RNDN);
946 }
947 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
948 inline void eval_subtract(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
949 {
950 mpfr_sub(result.data(), result.data(), o.data(), GMP_RNDN);
951 }
952 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
953 inline void eval_multiply(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
954 {
955 if((void*)&o == (void*)&result)
956 mpfr_sqr(result.data(), o.data(), GMP_RNDN);
957 else
958 mpfr_mul(result.data(), result.data(), o.data(), GMP_RNDN);
959 }
960 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
961 inline void eval_divide(mpfr_float_backend<D1, A1>& result, const mpfr_float_backend<D2, A2>& o)
962 {
963 mpfr_div(result.data(), result.data(), o.data(), GMP_RNDN);
964 }
965 template <unsigned digits10, mpfr_allocation_type AllocationType>
966 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
967 {
968 mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
969 }
970 template <unsigned digits10, mpfr_allocation_type AllocationType>
971 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
972 {
973 mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
974 }
975 template <unsigned digits10, mpfr_allocation_type AllocationType>
976 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
977 {
978 mpfr_mul_ui(result.data(), result.data(), i, GMP_RNDN);
979 }
980 template <unsigned digits10, mpfr_allocation_type AllocationType>
981 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, unsigned long i)
982 {
983 mpfr_div_ui(result.data(), result.data(), i, GMP_RNDN);
984 }
985 template <unsigned digits10, mpfr_allocation_type AllocationType>
986 inline void eval_add(mpfr_float_backend<digits10, AllocationType>& result, long i)
987 {
988 if(i > 0)
989 mpfr_add_ui(result.data(), result.data(), i, GMP_RNDN);
990 else
991 mpfr_sub_ui(result.data(), result.data(), std::abs(i), GMP_RNDN);
992 }
993 template <unsigned digits10, mpfr_allocation_type AllocationType>
994 inline void eval_subtract(mpfr_float_backend<digits10, AllocationType>& result, long i)
995 {
996 if(i > 0)
997 mpfr_sub_ui(result.data(), result.data(), i, GMP_RNDN);
998 else
999 mpfr_add_ui(result.data(), result.data(), std::abs(i), GMP_RNDN);
1000 }
1001 template <unsigned digits10, mpfr_allocation_type AllocationType>
1002 inline void eval_multiply(mpfr_float_backend<digits10, AllocationType>& result, long i)
1003 {
1004 mpfr_mul_ui(result.data(), result.data(), std::abs(i), GMP_RNDN);
1005 if(i < 0)
1006 mpfr_neg(result.data(), result.data(), GMP_RNDN);
1007 }
1008 template <unsigned digits10, mpfr_allocation_type AllocationType>
1009 inline void eval_divide(mpfr_float_backend<digits10, AllocationType>& result, long i)
1010 {
1011 mpfr_div_ui(result.data(), result.data(), std::abs(i), GMP_RNDN);
1012 if(i < 0)
1013 mpfr_neg(result.data(), result.data(), GMP_RNDN);
1014 }
1015 //
1016 // Specialised 3 arg versions of the basic operators:
1017 //
1018 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
1019 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1020 {
1021 mpfr_add(a.data(), x.data(), y.data(), GMP_RNDN);
1022 }
1023 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1024 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1025 {
1026 mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1027 }
1028 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1029 inline void eval_add(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1030 {
1031 if(y < 0)
1032 mpfr_sub_ui(a.data(), x.data(), -y, GMP_RNDN);
1033 else
1034 mpfr_add_ui(a.data(), x.data(), y, GMP_RNDN);
1035 }
1036 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1037 inline void eval_add(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1038 {
1039 mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1040 }
1041 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1042 inline void eval_add(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1043 {
1044 if(x < 0)
1045 {
1046 mpfr_ui_sub(a.data(), -x, y.data(), GMP_RNDN);
1047 mpfr_neg(a.data(), a.data(), GMP_RNDN);
1048 }
1049 else
1050 mpfr_add_ui(a.data(), y.data(), x, GMP_RNDN);
1051 }
1052 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
1053 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1054 {
1055 mpfr_sub(a.data(), x.data(), y.data(), GMP_RNDN);
1056 }
1057 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1058 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1059 {
1060 mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1061 }
1062 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1063 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1064 {
1065 if(y < 0)
1066 mpfr_add_ui(a.data(), x.data(), -y, GMP_RNDN);
1067 else
1068 mpfr_sub_ui(a.data(), x.data(), y, GMP_RNDN);
1069 }
1070 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1071 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1072 {
1073 mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1074 }
1075 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1076 inline void eval_subtract(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1077 {
1078 if(x < 0)
1079 {
1080 mpfr_add_ui(a.data(), y.data(), -x, GMP_RNDN);
1081 mpfr_neg(a.data(), a.data(), GMP_RNDN);
1082 }
1083 else
1084 mpfr_ui_sub(a.data(), x, y.data(), GMP_RNDN);
1085 }
1086
1087 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
1088 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1089 {
1090 if((void*)&x == (void*)&y)
1091 mpfr_sqr(a.data(), x.data(), GMP_RNDN);
1092 else
1093 mpfr_mul(a.data(), x.data(), y.data(), GMP_RNDN);
1094 }
1095 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1096 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1097 {
1098 mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1099 }
1100 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1101 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1102 {
1103 if(y < 0)
1104 {
1105 mpfr_mul_ui(a.data(), x.data(), -y, GMP_RNDN);
1106 a.negate();
1107 }
1108 else
1109 mpfr_mul_ui(a.data(), x.data(), y, GMP_RNDN);
1110 }
1111 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1112 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1113 {
1114 mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1115 }
1116 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1117 inline void eval_multiply(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1118 {
1119 if(x < 0)
1120 {
1121 mpfr_mul_ui(a.data(), y.data(), -x, GMP_RNDN);
1122 mpfr_neg(a.data(), a.data(), GMP_RNDN);
1123 }
1124 else
1125 mpfr_mul_ui(a.data(), y.data(), x, GMP_RNDN);
1126 }
1127
1128 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2, unsigned D3>
1129 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, const mpfr_float_backend<D3>& y)
1130 {
1131 mpfr_div(a.data(), x.data(), y.data(), GMP_RNDN);
1132 }
1133 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1134 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, unsigned long y)
1135 {
1136 mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1137 }
1138 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1139 inline void eval_divide(mpfr_float_backend<D1, A1>& a, const mpfr_float_backend<D2, A2>& x, long y)
1140 {
1141 if(y < 0)
1142 {
1143 mpfr_div_ui(a.data(), x.data(), -y, GMP_RNDN);
1144 a.negate();
1145 }
1146 else
1147 mpfr_div_ui(a.data(), x.data(), y, GMP_RNDN);
1148 }
1149 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1150 inline void eval_divide(mpfr_float_backend<D1, A1>& a, unsigned long x, const mpfr_float_backend<D2, A2>& y)
1151 {
1152 mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1153 }
1154 template <unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1155 inline void eval_divide(mpfr_float_backend<D1, A1>& a, long x, const mpfr_float_backend<D2, A2>& y)
1156 {
1157 if(x < 0)
1158 {
1159 mpfr_ui_div(a.data(), -x, y.data(), GMP_RNDN);
1160 mpfr_neg(a.data(), a.data(), GMP_RNDN);
1161 }
1162 else
1163 mpfr_ui_div(a.data(), x, y.data(), GMP_RNDN);
1164 }
1165
1166 template <unsigned digits10, mpfr_allocation_type AllocationType>
1167 inline bool eval_is_zero(const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1168 {
1169 return 0 != mpfr_zero_p(val.data());
1170 }
1171 template <unsigned digits10, mpfr_allocation_type AllocationType>
1172 inline int eval_get_sign(const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1173 {
1174 return mpfr_sgn(val.data());
1175 }
1176
1177 template <unsigned digits10, mpfr_allocation_type AllocationType>
1178 inline void eval_convert_to(unsigned long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1179 {
1180 if(mpfr_nan_p(val.data()))
1181 {
1182 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1183 }
1184 *result = mpfr_get_ui(val.data(), GMP_RNDZ);
1185 }
1186 template <unsigned digits10, mpfr_allocation_type AllocationType>
1187 inline void eval_convert_to(long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1188 {
1189 if(mpfr_nan_p(val.data()))
1190 {
1191 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1192 }
1193 *result = mpfr_get_si(val.data(), GMP_RNDZ);
1194 }
1195 #ifdef _MPFR_H_HAVE_INTMAX_T
1196 template <unsigned digits10, mpfr_allocation_type AllocationType>
1197 inline void eval_convert_to(unsigned long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1198 {
1199 if(mpfr_nan_p(val.data()))
1200 {
1201 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1202 }
1203 *result = mpfr_get_uj(val.data(), GMP_RNDZ);
1204 }
1205 template <unsigned digits10, mpfr_allocation_type AllocationType>
1206 inline void eval_convert_to(long long* result, const mpfr_float_backend<digits10, AllocationType>& val)
1207 {
1208 if(mpfr_nan_p(val.data()))
1209 {
1210 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1211 }
1212 *result = mpfr_get_sj(val.data(), GMP_RNDZ);
1213 }
1214 #endif
1215 template <unsigned digits10, mpfr_allocation_type AllocationType>
1216 inline void eval_convert_to(double* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1217 {
1218 *result = mpfr_get_d(val.data(), GMP_RNDN);
1219 }
1220 template <unsigned digits10, mpfr_allocation_type AllocationType>
1221 inline void eval_convert_to(long double* result, const mpfr_float_backend<digits10, AllocationType>& val) BOOST_NOEXCEPT
1222 {
1223 *result = mpfr_get_ld(val.data(), GMP_RNDN);
1224 }
1225
1226 //
1227 // Native non-member operations:
1228 //
1229 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1230 inline void eval_sqrt(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1231 {
1232 mpfr_sqrt(result.data(), val.data(), GMP_RNDN);
1233 }
1234
1235 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1236 inline void eval_abs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1237 {
1238 mpfr_abs(result.data(), val.data(), GMP_RNDN);
1239 }
1240
1241 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1242 inline void eval_fabs(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1243 {
1244 mpfr_abs(result.data(), val.data(), GMP_RNDN);
1245 }
1246 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1247 inline void eval_ceil(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1248 {
1249 mpfr_ceil(result.data(), val.data());
1250 }
1251 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1252 inline void eval_floor(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1253 {
1254 mpfr_floor(result.data(), val.data());
1255 }
1256 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1257 inline void eval_trunc(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val)
1258 {
1259 if(0 == mpfr_number_p(val.data()))
1260 {
1261 result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<mpfr_float_backend<Digits10, AllocateType> >(val), number<mpfr_float_backend<Digits10, AllocateType> >(val), boost::math::policies::policy<>()).backend();
1262 return;
1263 }
1264 mpfr_trunc(result.data(), val.data());
1265 }
1266 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1267 inline void eval_ldexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long e)
1268 {
1269 if(e > 0)
1270 mpfr_mul_2exp(result.data(), val.data(), e, GMP_RNDN);
1271 else if(e < 0)
1272 mpfr_div_2exp(result.data(), val.data(), -e, GMP_RNDN);
1273 else
1274 result = val;
1275 }
1276 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1277 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, int* e)
1278 {
1279 long v;
1280 mpfr_get_d_2exp(&v, val.data(), GMP_RNDN);
1281 *e = v;
1282 eval_ldexp(result, val, -v);
1283 }
1284 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1285 inline void eval_frexp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& val, long* e)
1286 {
1287 mpfr_get_d_2exp(e, val.data(), GMP_RNDN);
1288 return eval_ldexp(result, val, -*e);
1289 }
1290
1291 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1292 inline int eval_fpclassify(const mpfr_float_backend<Digits10, AllocateType>& val) BOOST_NOEXCEPT
1293 {
1294 return mpfr_inf_p(val.data()) ? FP_INFINITE : mpfr_nan_p(val.data()) ? FP_NAN : mpfr_zero_p(val.data()) ? FP_ZERO : FP_NORMAL;
1295 }
1296
1297 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1298 inline void eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const mpfr_float_backend<Digits10, AllocateType>& e)
1299 {
1300 mpfr_pow(result.data(), b.data(), e.data(), GMP_RNDN);
1301 }
1302
1303 #ifdef BOOST_MSVC
1304 //
1305 // The enable_if usage below doesn't work with msvc - but only when
1306 // certain other enable_if usages are defined first. It's a capricious
1307 // and rather annoying compiler bug in other words....
1308 //
1309 # define BOOST_MP_ENABLE_IF_WORKAROUND (Digits10 || !Digits10) &&
1310 #else
1311 #define BOOST_MP_ENABLE_IF_WORKAROUND
1312 #endif
1313
1314 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1315 inline typename enable_if<mpl::and_<is_signed<Integer>, mpl::bool_<BOOST_MP_ENABLE_IF_WORKAROUND (sizeof(Integer) <= sizeof(long))> > >::type
1316 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1317 {
1318 mpfr_pow_si(result.data(), b.data(), e, GMP_RNDN);
1319 }
1320
1321 template <unsigned Digits10, mpfr_allocation_type AllocateType, class Integer>
1322 inline typename enable_if<mpl::and_<is_unsigned<Integer>, mpl::bool_<BOOST_MP_ENABLE_IF_WORKAROUND (sizeof(Integer) <= sizeof(long))> > >::type
1323 eval_pow(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& b, const Integer& e)
1324 {
1325 mpfr_pow_ui(result.data(), b.data(), e, GMP_RNDN);
1326 }
1327
1328 #undef BOOST_MP_ENABLE_IF_WORKAROUND
1329
1330 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1331 inline void eval_exp(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1332 {
1333 mpfr_exp(result.data(), arg.data(), GMP_RNDN);
1334 }
1335
1336 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1337 inline void eval_log(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1338 {
1339 mpfr_log(result.data(), arg.data(), GMP_RNDN);
1340 }
1341
1342 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1343 inline void eval_log10(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1344 {
1345 mpfr_log10(result.data(), arg.data(), GMP_RNDN);
1346 }
1347
1348 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1349 inline void eval_sin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1350 {
1351 mpfr_sin(result.data(), arg.data(), GMP_RNDN);
1352 }
1353
1354 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1355 inline void eval_cos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1356 {
1357 mpfr_cos(result.data(), arg.data(), GMP_RNDN);
1358 }
1359
1360 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1361 inline void eval_tan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1362 {
1363 mpfr_tan(result.data(), arg.data(), GMP_RNDN);
1364 }
1365
1366 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1367 inline void eval_asin(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1368 {
1369 mpfr_asin(result.data(), arg.data(), GMP_RNDN);
1370 }
1371
1372 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1373 inline void eval_acos(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1374 {
1375 mpfr_acos(result.data(), arg.data(), GMP_RNDN);
1376 }
1377
1378 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1379 inline void eval_atan(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1380 {
1381 mpfr_atan(result.data(), arg.data(), GMP_RNDN);
1382 }
1383
1384 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1385 inline void eval_atan2(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg1, const mpfr_float_backend<Digits10, AllocateType>& arg2)
1386 {
1387 mpfr_atan2(result.data(), arg1.data(), arg2.data(), GMP_RNDN);
1388 }
1389
1390 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1391 inline void eval_sinh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1392 {
1393 mpfr_sinh(result.data(), arg.data(), GMP_RNDN);
1394 }
1395
1396 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1397 inline void eval_cosh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1398 {
1399 mpfr_cosh(result.data(), arg.data(), GMP_RNDN);
1400 }
1401
1402 template <unsigned Digits10, mpfr_allocation_type AllocateType>
1403 inline void eval_tanh(mpfr_float_backend<Digits10, AllocateType>& result, const mpfr_float_backend<Digits10, AllocateType>& arg)
1404 {
1405 mpfr_tanh(result.data(), arg.data(), GMP_RNDN);
1406 }
1407
1408 } // namespace backends
1409
1410 #ifdef BOOST_NO_SFINAE_EXPR
1411
1412 namespace detail{
1413
1414 template<unsigned D1, unsigned D2, mpfr_allocation_type A1, mpfr_allocation_type A2>
1415 struct is_explicitly_convertible<backends::mpfr_float_backend<D1, A1>, backends::mpfr_float_backend<D2, A2> > : public mpl::true_ {};
1416
1417 }
1418
1419 #endif
1420
1421 template<>
1422 struct number_category<detail::canonical<mpfr_t, backends::mpfr_float_backend<0> >::type> : public mpl::int_<number_kind_floating_point>{};
1423
1424 using boost::multiprecision::backends::mpfr_float_backend;
1425
1426 typedef number<mpfr_float_backend<50> > mpfr_float_50;
1427 typedef number<mpfr_float_backend<100> > mpfr_float_100;
1428 typedef number<mpfr_float_backend<500> > mpfr_float_500;
1429 typedef number<mpfr_float_backend<1000> > mpfr_float_1000;
1430 typedef number<mpfr_float_backend<0> > mpfr_float;
1431
1432 typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50;
1433 typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
1434
1435 } // namespace multiprecision
1436
1437 namespace math{
1438
1439 namespace tools{
1440
1441 template <>
1442 inline int digits<boost::multiprecision::mpfr_float>()
1443 {
1444 return boost::multiprecision::backends::detail::get_default_precision();
1445 }
1446 template <>
1447 inline int digits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, boost::multiprecision::et_off> >()
1448 {
1449 return boost::multiprecision::backends::detail::get_default_precision();
1450 }
1451
1452 } // namespace tools
1453
1454 namespace constants{ namespace detail{
1455
1456 template <class T> struct constant_pi;
1457 template <class T> struct constant_ln_two;
1458 template <class T> struct constant_euler;
1459 template <class T> struct constant_catalan;
1460
1461 namespace detail{
1462
1463 template <class T, int N>
1464 struct mpfr_constant_initializer
1465 {
1466 static void force_instantiate()
1467 {
1468 init.force_instantiate();
1469 }
1470 private:
1471 struct initializer
1472 {
1473 initializer()
1474 {
1475 T::get(mpl::int_<N>());
1476 }
1477 void force_instantiate()const{}
1478 };
1479 static const initializer init;
1480 };
1481
1482 template <class T, int N>
1483 typename mpfr_constant_initializer<T, N>::initializer const mpfr_constant_initializer<T, N>::init;
1484
1485 }
1486
1487 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1488 struct constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1489 {
1490 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1491 template<int N>
1492 static inline const result_type& get(const mpl::int_<N>&)
1493 {
1494 detail::mpfr_constant_initializer<constant_pi<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1495 static result_type result;
1496 static bool has_init = false;
1497 if(!has_init)
1498 {
1499 mpfr_const_pi(result.backend().data(), GMP_RNDN);
1500 has_init = true;
1501 }
1502 return result;
1503 }
1504 };
1505 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1506 struct constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1507 {
1508 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1509 template<int N>
1510 static inline const result_type& get(const mpl::int_<N>&)
1511 {
1512 detail::mpfr_constant_initializer<constant_ln_two<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1513 static result_type result;
1514 static bool init = false;
1515 if(!init)
1516 {
1517 mpfr_const_log2(result.backend().data(), GMP_RNDN);
1518 init = true;
1519 }
1520 return result;
1521 }
1522 };
1523 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1524 struct constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1525 {
1526 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1527 template<int N>
1528 static inline const result_type& get(const mpl::int_<N>&)
1529 {
1530 detail::mpfr_constant_initializer<constant_euler<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1531 static result_type result;
1532 static bool init = false;
1533 if(!init)
1534 {
1535 mpfr_const_euler(result.backend().data(), GMP_RNDN);
1536 init = true;
1537 }
1538 return result;
1539 }
1540 };
1541 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1542 struct constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1543 {
1544 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> result_type;
1545 template<int N>
1546 static inline const result_type& get(const mpl::int_<N>&)
1547 {
1548 detail::mpfr_constant_initializer<constant_catalan<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >, N>::force_instantiate();
1549 static result_type result;
1550 static bool init = false;
1551 if(!init)
1552 {
1553 mpfr_const_catalan(result.backend().data(), GMP_RNDN);
1554 init = true;
1555 }
1556 return result;
1557 }
1558 };
1559
1560 }} // namespaces
1561
1562 }} // namespaces
1563
1564 namespace std{
1565
1566 //
1567 // numeric_limits [partial] specializations for the types declared in this header:
1568 //
1569 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1570 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >
1571 {
1572 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> number_type;
1573 public:
1574 BOOST_STATIC_CONSTEXPR bool is_specialized = true;
1575 static number_type (min)()
1576 {
1577 initializer.do_nothing();
1578 static std::pair<bool, number_type> value;
1579 if(!value.first)
1580 {
1581 value.first = true;
1582 value.second = 0.5;
1583 mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), -mpfr_get_emin(), GMP_RNDN);
1584 }
1585 return value.second;
1586 }
1587 static number_type (max)()
1588 {
1589 initializer.do_nothing();
1590 static std::pair<bool, number_type> value;
1591 if(!value.first)
1592 {
1593 value.first = true;
1594 value.second = 0.5;
1595 mpfr_mul_2exp(value.second.backend().data(), value.second.backend().data(), mpfr_get_emax(), GMP_RNDN);
1596 }
1597 return value.second;
1598 }
1599 BOOST_STATIC_CONSTEXPR number_type lowest()
1600 {
1601 return -(max)();
1602 }
1603 BOOST_STATIC_CONSTEXPR int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301 ? 2 : 1));
1604 BOOST_STATIC_CONSTEXPR int digits10 = Digits10;
1605 // Is this really correct???
1606 BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 2;
1607 BOOST_STATIC_CONSTEXPR bool is_signed = true;
1608 BOOST_STATIC_CONSTEXPR bool is_integer = false;
1609 BOOST_STATIC_CONSTEXPR bool is_exact = false;
1610 BOOST_STATIC_CONSTEXPR int radix = 2;
1611 static number_type epsilon()
1612 {
1613 initializer.do_nothing();
1614 static std::pair<bool, number_type> value;
1615 if(!value.first)
1616 {
1617 value.first = true;
1618 value.second = 1;
1619 mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1, GMP_RNDN);
1620 }
1621 return value.second;
1622 }
1623 // What value should this be????
1624 static number_type round_error()
1625 {
1626 // returns epsilon/2
1627 initializer.do_nothing();
1628 static std::pair<bool, number_type> value;
1629 if(!value.first)
1630 {
1631 value.first = true;
1632 value.second = 1;
1633 mpfr_div_2exp(value.second.backend().data(), value.second.backend().data(), 1, GMP_RNDN);
1634 }
1635 return value.second;
1636 }
1637 BOOST_STATIC_CONSTEXPR long min_exponent = MPFR_EMIN_DEFAULT;
1638 BOOST_STATIC_CONSTEXPR long min_exponent10 = (MPFR_EMIN_DEFAULT / 1000) * 301L;
1639 BOOST_STATIC_CONSTEXPR long max_exponent = MPFR_EMAX_DEFAULT;
1640 BOOST_STATIC_CONSTEXPR long max_exponent10 = (MPFR_EMAX_DEFAULT / 1000) * 301L;
1641 BOOST_STATIC_CONSTEXPR bool has_infinity = true;
1642 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
1643 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
1644 BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
1645 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
1646 static number_type infinity()
1647 {
1648 // returns epsilon/2
1649 initializer.do_nothing();
1650 static std::pair<bool, number_type> value;
1651 if(!value.first)
1652 {
1653 value.first = true;
1654 value.second = 1;
1655 mpfr_set_inf(value.second.backend().data(), 1);
1656 }
1657 return value.second;
1658 }
1659 static number_type quiet_NaN()
1660 {
1661 // returns epsilon/2
1662 initializer.do_nothing();
1663 static std::pair<bool, number_type> value;
1664 if(!value.first)
1665 {
1666 value.first = true;
1667 value.second = 1;
1668 mpfr_set_nan(value.second.backend().data());
1669 }
1670 return value.second;
1671 }
1672 BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
1673 {
1674 return number_type(0);
1675 }
1676 BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
1677 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
1678 BOOST_STATIC_CONSTEXPR bool is_bounded = true;
1679 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
1680 BOOST_STATIC_CONSTEXPR bool traps = true;
1681 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
1682 BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
1683
1684 private:
1685 struct data_initializer
1686 {
1687 data_initializer()
1688 {
1689 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::epsilon();
1690 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::round_error();
1691 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::min)();
1692 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::max)();
1693 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::infinity();
1694 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<digits10, AllocateType> > >::quiet_NaN();
1695 }
1696 void do_nothing()const{}
1697 };
1698 static const data_initializer initializer;
1699 };
1700
1701 template<unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1702 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::initializer;
1703
1704 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
1705
1706 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1707 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits;
1708 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1709 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::digits10;
1710 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1711 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_digits10;
1712 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1713 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_signed;
1714 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1715 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_integer;
1716 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1717 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_exact;
1718 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1719 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::radix;
1720 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1721 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent;
1722 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1723 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::min_exponent10;
1724 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1725 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent;
1726 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1727 BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::max_exponent10;
1728 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1729 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_infinity;
1730 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1731 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_quiet_NaN;
1732 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1733 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_signaling_NaN;
1734 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1735 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm;
1736 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1737 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::has_denorm_loss;
1738 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1739 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_iec559;
1740 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1741 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_bounded;
1742 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1743 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::is_modulo;
1744 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1745 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::traps;
1746 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1747 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::tinyness_before;
1748 template <unsigned Digits10, boost::multiprecision::mpfr_allocation_type AllocateType, boost::multiprecision::expression_template_option ExpressionTemplates>
1749 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<Digits10, AllocateType>, ExpressionTemplates> >::round_style;
1750
1751 #endif
1752
1753
1754 template<boost::multiprecision::expression_template_option ExpressionTemplates>
1755 class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >
1756 {
1757 typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> number_type;
1758 public:
1759 BOOST_STATIC_CONSTEXPR bool is_specialized = false;
1760 static number_type (min)() { return number_type(0); }
1761 static number_type (max)() { return number_type(0); }
1762 static number_type lowest() { return number_type(0); }
1763 BOOST_STATIC_CONSTEXPR int digits = 0;
1764 BOOST_STATIC_CONSTEXPR int digits10 = 0;
1765 BOOST_STATIC_CONSTEXPR int max_digits10 = 0;
1766 BOOST_STATIC_CONSTEXPR bool is_signed = false;
1767 BOOST_STATIC_CONSTEXPR bool is_integer = false;
1768 BOOST_STATIC_CONSTEXPR bool is_exact = false;
1769 BOOST_STATIC_CONSTEXPR int radix = 0;
1770 static number_type epsilon() { return number_type(0); }
1771 static number_type round_error() { return number_type(0); }
1772 BOOST_STATIC_CONSTEXPR int min_exponent = 0;
1773 BOOST_STATIC_CONSTEXPR int min_exponent10 = 0;
1774 BOOST_STATIC_CONSTEXPR int max_exponent = 0;
1775 BOOST_STATIC_CONSTEXPR int max_exponent10 = 0;
1776 BOOST_STATIC_CONSTEXPR bool has_infinity = false;
1777 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false;
1778 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
1779 BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
1780 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
1781 static number_type infinity() { return number_type(0); }
1782 static number_type quiet_NaN() { return number_type(0); }
1783 static number_type signaling_NaN() { return number_type(0); }
1784 static number_type denorm_min() { return number_type(0); }
1785 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
1786 BOOST_STATIC_CONSTEXPR bool is_bounded = false;
1787 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
1788 BOOST_STATIC_CONSTEXPR bool traps = false;
1789 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
1790 BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero;
1791 };
1792
1793 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
1794
1795 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1796 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits;
1797 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1798 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::digits10;
1799 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1800 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_digits10;
1801 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1802 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_signed;
1803 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1804 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_integer;
1805 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1806 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_exact;
1807 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1808 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::radix;
1809 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1810 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent;
1811 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1812 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::min_exponent10;
1813 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1814 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent;
1815 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1816 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::max_exponent10;
1817 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1818 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_infinity;
1819 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1820 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_quiet_NaN;
1821 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1822 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_signaling_NaN;
1823 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1824 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm;
1825 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1826 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::has_denorm_loss;
1827 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1828 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_iec559;
1829 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1830 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_bounded;
1831 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1832 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::is_modulo;
1833 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1834 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::traps;
1835 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1836 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::tinyness_before;
1837 template <boost::multiprecision::expression_template_option ExpressionTemplates>
1838 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<0>, ExpressionTemplates> >::round_style;
1839
1840 #endif
1841 } // namespace std
1842 #endif