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

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