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