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