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