• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
interval_errorboost::multiprecision::interval_error42    interval_error(const std::string& s) : std::runtime_error(s) {}
43 };
44 
45 namespace backends {
46 
47 namespace detail {
48 
mpfi_sgn(mpfi_srcptr p)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 
mpfi_float_impboost::multiprecision::backends::detail::mpfi_float_imp76    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    }
mpfi_float_impboost::multiprecision::backends::detail::mpfi_float_imp81    mpfi_float_imp(unsigned prec)
82    {
83       mpfi_init2(m_data, prec);
84       mpfi_set_ui(m_data, 0u);
85    }
86 
mpfi_float_impboost::multiprecision::backends::detail::mpfi_float_imp87    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
mpfi_float_impboost::multiprecision::backends::detail::mpfi_float_imp94    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
operator =boost::multiprecision::backends::detail::mpfi_float_imp100    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
operator =boost::multiprecision::backends::detail::mpfi_float_imp118    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
operator =boost::multiprecision::backends::detail::mpfi_float_imp126    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp134    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
operator =boost::multiprecision::backends::detail::mpfi_float_imp143    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp164    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
operator =boost::multiprecision::backends::detail::mpfi_float_imp176    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp183    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp190    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp197    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    }
operator =boost::multiprecision::backends::detail::mpfi_float_imp205    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    }
swapboost::multiprecision::backends::detail::mpfi_float_imp256    void swap(mpfi_float_imp& o) BOOST_NOEXCEPT
257    {
258       mpfi_swap(m_data, o.m_data);
259    }
strboost::multiprecision::backends::detail::mpfi_float_imp260    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    }
~mpfi_float_impboost::multiprecision::backends::detail::mpfi_float_imp274    ~mpfi_float_imp() BOOST_NOEXCEPT
275    {
276       if (m_data[0].left._mpfr_d)
277          mpfi_clear(m_data);
278    }
negateboost::multiprecision::backends::detail::mpfi_float_imp279    void negate() BOOST_NOEXCEPT
280    {
281       BOOST_ASSERT(m_data[0].left._mpfr_d);
282       mpfi_neg(m_data, m_data);
283    }
compareboost::multiprecision::backends::detail::mpfi_float_imp284    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>
compareboost::multiprecision::backends::detail::mpfi_float_imp297    int compare(V v) const BOOST_NOEXCEPT
298    {
299       mpfi_float_imp d;
300       d = v;
301       return compare(d);
302    }
databoost::multiprecision::backends::detail::mpfi_float_imp303    mpfi_t& data() BOOST_NOEXCEPT
304    {
305       BOOST_ASSERT(m_data[0].left._mpfr_d);
306       return m_data;
307    }
databoost::multiprecision::backends::detail::mpfi_float_imp308    const mpfi_t& data() const BOOST_NOEXCEPT
309    {
310       BOOST_ASSERT(m_data[0].left._mpfr_d);
311       return m_data;
312    }
left_databoost::multiprecision::backends::detail::mpfi_float_imp313    mpfr_ptr left_data() BOOST_NOEXCEPT
314    {
315       BOOST_ASSERT(m_data[0].left._mpfr_d);
316       return &(m_data[0].left);
317    }
left_databoost::multiprecision::backends::detail::mpfi_float_imp318    mpfr_srcptr left_data() const BOOST_NOEXCEPT
319    {
320       BOOST_ASSERT(m_data[0].left._mpfr_d);
321       return &(m_data[0].left);
322    }
right_databoost::multiprecision::backends::detail::mpfi_float_imp323    mpfr_ptr right_data() BOOST_NOEXCEPT
324    {
325       BOOST_ASSERT(m_data[0].left._mpfr_d);
326       return &(m_data[0].right);
327    }
right_databoost::multiprecision::backends::detail::mpfi_float_imp328    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;
get_default_precisionboost::multiprecision::backends::detail::mpfi_float_imp336    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 {
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend348    mpfi_float_backend() : detail::mpfi_float_imp<digits10>() {}
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend349    mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<digits10>(o) {}
350 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend351    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend355    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend361    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    }
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend366    mpfi_float_backend(const mpfi_t val)
367        : detail::mpfi_float_imp<digits10>()
368    {
369       mpfi_set(this->m_data, val);
370    }
operator =boost::multiprecision::backends::mpfi_float_backend371    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend377    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>
operator =boost::multiprecision::backends::mpfi_float_backend383    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend389    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
operator =boost::multiprecision::backends::mpfi_float_backend395    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>
operator =boost::multiprecision::backends::mpfi_float_backend402    mpfi_float_backend& operator=(const V& v)
403    {
404       *static_cast<detail::mpfi_float_imp<digits10>*>(this) = v;
405       return *this;
406    }
operator =boost::multiprecision::backends::mpfi_float_backend407    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>
operator =boost::multiprecision::backends::mpfi_float_backend414    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 {
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend431    mpfi_float_backend() : detail::mpfi_float_imp<0>() {}
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend432    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    }
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend437    mpfi_float_backend(const mpfi_float_backend& o) : detail::mpfi_float_imp<0>(o) {}
438 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend439    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
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend442    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend448    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>
mpfi_float_backendboost::multiprecision::backends::mpfi_float_backend455    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    }
operator =boost::multiprecision::backends::mpfi_float_backend460    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
operator =boost::multiprecision::backends::mpfi_float_backend467    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>
operator =boost::multiprecision::backends::mpfi_float_backend474    mpfi_float_backend& operator=(const V& v)
475    {
476       *static_cast<detail::mpfi_float_imp<0>*>(this) = v;
477       return *this;
478    }
operator =boost::multiprecision::backends::mpfi_float_backend479    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>
operator =boost::multiprecision::backends::mpfi_float_backend486    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    }
default_precisionboost::multiprecision::backends::mpfi_float_backend492    static unsigned default_precision() BOOST_NOEXCEPT
493    {
494       return get_default_precision();
495    }
default_precisionboost::multiprecision::backends::mpfi_float_backend496    static void default_precision(unsigned v) BOOST_NOEXCEPT
497    {
498       get_default_precision() = v;
499    }
precisionboost::multiprecision::backends::mpfi_float_backend500    unsigned precision() const BOOST_NOEXCEPT
501    {
502       return multiprecision::detail::digits2_2_10(mpfi_get_prec(this->m_data));
503    }
precisionboost::multiprecision::backends::mpfi_float_backend504    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>
eval_eq(const mpfi_float_backend<digits10> & a,const T & b)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>
eval_lt(const mpfi_float_backend<digits10> & a,const T & b)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>
eval_gt(const mpfi_float_backend<digits10> & a,const T & b)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>
eval_add(mpfi_float_backend<D1> & result,const mpfi_float_backend<D2> & o)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>
eval_subtract(mpfi_float_backend<D1> & result,const mpfi_float_backend<D2> & o)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>
eval_multiply(mpfi_float_backend<D1> & result,const mpfi_float_backend<D2> & o)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>
eval_divide(mpfi_float_backend<D1> & result,const mpfi_float_backend<D2> & o)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>
eval_add(mpfi_float_backend<digits10> & result,unsigned long i)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>
eval_subtract(mpfi_float_backend<digits10> & result,unsigned long i)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>
eval_multiply(mpfi_float_backend<digits10> & result,unsigned long i)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>
eval_divide(mpfi_float_backend<digits10> & result,unsigned long i)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>
eval_add(mpfi_float_backend<digits10> & result,long i)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>
eval_subtract(mpfi_float_backend<digits10> & result,long i)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>
eval_multiply(mpfi_float_backend<digits10> & result,long i)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>
eval_divide(mpfi_float_backend<digits10> & result,long i)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>
eval_add(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,const mpfi_float_backend<D3> & y)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>
eval_add(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,unsigned long y)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>
eval_add(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,long y)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>
eval_add(mpfi_float_backend<D1> & a,unsigned long x,const mpfi_float_backend<D2> & y)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>
eval_add(mpfi_float_backend<D1> & a,long x,const mpfi_float_backend<D2> & y)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>
eval_subtract(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,const mpfi_float_backend<D3> & y)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>
eval_subtract(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,unsigned long y)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>
eval_subtract(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,long y)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>
eval_subtract(mpfi_float_backend<D1> & a,unsigned long x,const mpfi_float_backend<D2> & y)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>
eval_subtract(mpfi_float_backend<D1> & a,long x,const mpfi_float_backend<D2> & y)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>
eval_multiply(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,const mpfi_float_backend<D3> & y)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>
eval_multiply(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,unsigned long y)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>
eval_multiply(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,long y)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>
eval_multiply(mpfi_float_backend<D1> & a,unsigned long x,const mpfi_float_backend<D2> & y)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>
eval_multiply(mpfi_float_backend<D1> & a,long x,const mpfi_float_backend<D2> & y)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>
eval_divide(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,const mpfi_float_backend<D3> & y)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>
eval_divide(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,unsigned long y)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>
eval_divide(mpfi_float_backend<D1> & a,const mpfi_float_backend<D2> & x,long y)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>
eval_divide(mpfi_float_backend<D1> & a,unsigned long x,const mpfi_float_backend<D2> & y)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>
eval_divide(mpfi_float_backend<D1> & a,long x,const mpfi_float_backend<D2> & y)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>
eval_is_zero(const mpfi_float_backend<digits10> & val)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>
eval_get_sign(const mpfi_float_backend<digits10> & val)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>
eval_convert_to(unsigned long * result,const mpfi_float_backend<digits10> & val)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>
eval_convert_to(long * result,const mpfi_float_backend<digits10> & val)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>
eval_convert_to(boost::ulong_long_type * result,const mpfi_float_backend<digits10> & val)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>
eval_convert_to(boost::long_long_type * result,const mpfi_float_backend<digits10> & val)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>
eval_convert_to(double * result,const mpfi_float_backend<digits10> & val)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>
eval_convert_to(long double * result,const mpfi_float_backend<digits10> & val)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>
assign_components(mpfi_float_backend<D1> & result,const mpfr_float_backend<D2,AllocationType> & a,const mpfr_float_backend<D2,AllocationType> & b)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
assign_components(mpfi_float_backend<Digits10> & result,const V & a,const V & b)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>
eval_sqrt(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val)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>
eval_abs(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val)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>
eval_fabs(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val)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>
eval_ceil(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val)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>
eval_floor(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val)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>
eval_ldexp(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val,long e)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>
eval_frexp(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val,int * e)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>
eval_frexp(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & val,long * e)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>
eval_fpclassify(const mpfi_float_backend<Digits10> & val)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>
eval_pow(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & b,const mpfi_float_backend<Digits10> & e)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>
eval_exp(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_exp2(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_log(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_log10(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_sin(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_cos(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_tan(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_asin(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_acos(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_atan(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_atan2(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg1,const mpfi_float_backend<Digits10> & arg2)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>
eval_sinh(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_cosh(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_tanh(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
eval_log2(mpfi_float_backend<Digits10> & result,const mpfi_float_backend<Digits10> & arg)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>
hash_value(const mpfi_float_backend<Digits10> & val)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>
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)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>
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)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>
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)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>
lower(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & val)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>
upper(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & val)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>
median(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & val)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>
width(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & val)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>
intersect(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & b)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>
hull(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & b)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>
overlap(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & b)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>
in(const number<mpfr_float_backend<Digits10>,ExpressionTemplates1> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates2> & b)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>
zero_in(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a)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>
subset(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & b)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>
proper_subset(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a,const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & b)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>
empty(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a)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>
singleton(const number<mpfi_float_backend<Digits10>,ExpressionTemplates> & a)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::mpfi_float_backend<Digits10>,ExpressionTemplates> & arg)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 <>
digits()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 <>
digits()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
max_value()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
min_value()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>
max_value()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>
min_value()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 <>
digits()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 <>
digits()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
max_value()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
min_value()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
max_value()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
min_value()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    {
initboost::math::constants::detail::mpfi_initializer::init1458       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       }
force_instantiateboost::math::constants::detail::mpfi_initializer::init1465       void force_instantiate() const {}
1466    };
1467    static const init initializer;
force_instantiateboost::math::constants::detail::mpfi_initializer1468    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>
getboost::math::constants::detail::constant_pi1482    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    }
getboost::math::constants::detail::constant_pi1494    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>
getboost::math::constants::detail::constant_ln_two1506    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    }
getboost::math::constants::detail::constant_ln_two1518    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>
getboost::math::constants::detail::constant_euler1530    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    }
getboost::math::constants::detail::constant_euler1542    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>
getboost::math::constants::detail::constant_catalan1554    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    }
getboost::math::constants::detail::constant_catalan1566    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;
number_type(min)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    }
number_type(max)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    }
lowest()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;
epsilon()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????
round_error()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;
infinity()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    }
quiet_NaN()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    }
signaling_NaN()1688    BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
1689    {
1690       return number_type(0);
1691    }
denorm_min()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    {
data_initializerstd::numeric_limits::data_initializer1703       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       }
do_nothingstd::numeric_limits::data_initializer1712       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;
number_type(min)1776    static number_type(min)() { return number_type(0); }
number_type(max)1777    static number_type(max)() { return number_type(0); }
lowest()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;
epsilon()1786    static number_type          epsilon() { return number_type(0); }
round_error()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;
infinity()1797    static number_type                        infinity() { return number_type(0); }
quiet_NaN()1798    static number_type                        quiet_NaN() { return number_type(0); }
signaling_NaN()1799    static number_type                        signaling_NaN() { return number_type(0); }
denorm_min()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
1859