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