1 ///////////////////////////////////////////////////////////////
2 //  Copyright 2013 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_
5 
6 #ifndef BOOST_MP_FLOAT128_HPP
7 #define BOOST_MP_FLOAT128_HPP
8 
9 #include <boost/config.hpp>
10 #include <boost/scoped_array.hpp>
11 #include <boost/functional/hash.hpp>
12 #include <boost/multiprecision/number.hpp>
13 
14 #if defined(BOOST_INTEL) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
15 #  if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
16 #    if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
17 #      define BOOST_MP_USE_FLOAT128
18 #    endif
19 #  endif
20 
21 #  ifndef BOOST_MP_USE_FLOAT128
22 #    define BOOST_MP_USE_QUAD
23 #  endif
24 #endif
25 
26 #if defined(__GNUC__) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
27 #  define BOOST_MP_USE_FLOAT128
28 #endif
29 
30 #if !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
31 #  error "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
32 #endif
33 #if defined(BOOST_MP_USE_FLOAT128) && defined(BOOST_MP_USE_QUAD)
34 #  error "Oh dear, both BOOST_MP_USE_FLOAT128 and BOOST_MP_USE_QUAD are defined, which one should I be using?"
35 #endif
36 
37 #if defined(BOOST_MP_USE_FLOAT128)
38 
39 extern "C" {
40 #include <quadmath.h>
41 }
42 
43 typedef __float128 float128_type;
44 
45 #elif defined(BOOST_MP_USE_QUAD)
46 
47 #include <boost/multiprecision/detail/float_string_cvt.hpp>
48 
49 typedef _Quad float128_type;
50 
51 extern "C" {
52 _Quad __ldexpq(_Quad, int);
53 _Quad __frexpq(_Quad, int*);
54 _Quad __fabsq(_Quad);
55 _Quad __floorq(_Quad);
56 _Quad __ceilq(_Quad);
57 _Quad __sqrtq(_Quad);
58 _Quad __truncq(_Quad);
59 _Quad __expq(_Quad);
60 _Quad __powq(_Quad, _Quad);
61 _Quad __logq(_Quad);
62 _Quad __log10q(_Quad);
63 _Quad __sinq(_Quad);
64 _Quad __cosq(_Quad);
65 _Quad __tanq(_Quad);
66 _Quad __asinq(_Quad);
67 _Quad __acosq(_Quad);
68 _Quad __atanq(_Quad);
69 _Quad __sinhq(_Quad);
70 _Quad __coshq(_Quad);
71 _Quad __tanhq(_Quad);
72 _Quad __fmodq(_Quad, _Quad);
73 _Quad __atan2q(_Quad, _Quad);
74 
75 #define ldexpq __ldexpq
76 #define frexpq __frexpq
77 #define fabsq __fabsq
78 #define floorq __floorq
79 #define ceilq __ceilq
80 #define sqrtq __sqrtq
81 #define truncq __truncq
82 #define expq __expq
83 #define powq __powq
84 #define logq __logq
85 #define log10q __log10q
86 #define sinq __sinq
87 #define cosq __cosq
88 #define tanq __tanq
89 #define asinq __asinq
90 #define acosq __acosq
91 #define atanq __atanq
92 #define sinhq __sinhq
93 #define coshq __coshq
94 #define tanhq __tanhq
95 #define fmodq __fmodq
96 #define atan2q __atan2q
97 }
98 
isnanq(_Quad v)99 inline _Quad isnanq(_Quad v)
100 {
101    return v != v;
102 }
isinfq(_Quad v)103 inline _Quad isinfq(_Quad v)
104 {
105    return __fabsq(v) > 1.18973149535723176508575932662800702e4932Q;
106 }
107 
108 #endif
109 
110 namespace boost{
111 namespace multiprecision{
112 namespace backends{
113 
114 struct float128_backend;
115 
116 }
117 
118 using backends::float128_backend;
119 
120 template<>
121 struct number_category<backends::float128_backend> : public mpl::int_<number_kind_floating_point> {};
122 #if defined(BOOST_MP_USE_QUAD)
123 template<>
124 struct number_category<float128_type> : public mpl::int_<number_kind_floating_point> {};
125 #endif
126 
127 typedef number<float128_backend, et_off> float128;
128 
129 #ifndef BOOST_NO_CXX11_CONSTEXPR
130 
131 namespace quad_constants {
132    constexpr __float128 quad_min = static_cast<__float128>(1)
133       * static_cast<__float128>(DBL_MIN)
134       * static_cast<__float128>(DBL_MIN)
135       * static_cast<__float128>(DBL_MIN)
136       * static_cast<__float128>(DBL_MIN)
137       * static_cast<__float128>(DBL_MIN)
138       * static_cast<__float128>(DBL_MIN)
139       * static_cast<__float128>(DBL_MIN)
140       * static_cast<__float128>(DBL_MIN)
141       * static_cast<__float128>(DBL_MIN)
142       * static_cast<__float128>(DBL_MIN)
143       * static_cast<__float128>(DBL_MIN)
144       * static_cast<__float128>(DBL_MIN)
145       * static_cast<__float128>(DBL_MIN)
146       * static_cast<__float128>(DBL_MIN)
147       * static_cast<__float128>(DBL_MIN)
148       * static_cast<__float128>(DBL_MIN) / 1073741824;
149 
150    constexpr __float128 quad_denorm_min = static_cast<__float128>(1)
151       * static_cast<__float128>(DBL_MIN)
152       * static_cast<__float128>(DBL_MIN)
153       * static_cast<__float128>(DBL_MIN)
154       * static_cast<__float128>(DBL_MIN)
155       * static_cast<__float128>(DBL_MIN)
156       * static_cast<__float128>(DBL_MIN)
157       * static_cast<__float128>(DBL_MIN)
158       * static_cast<__float128>(DBL_MIN)
159       * static_cast<__float128>(DBL_MIN)
160       * static_cast<__float128>(DBL_MIN)
161       * static_cast<__float128>(DBL_MIN)
162       * static_cast<__float128>(DBL_MIN)
163       * static_cast<__float128>(DBL_MIN)
164       * static_cast<__float128>(DBL_MIN)
165       * static_cast<__float128>(DBL_MIN)
166       * static_cast<__float128>(DBL_MIN) / 5.5751862996326557854e+42;
167 
168    constexpr double dbl_mult = 8.9884656743115795386e+307;  // This has one bit set only.
169    constexpr __float128 quad_max = (static_cast<__float128>(1) - 9.62964972193617926527988971292463659e-35)  // This now has all bits sets to 1
170       * static_cast<__float128>(dbl_mult)
171       * static_cast<__float128>(dbl_mult)
172       * static_cast<__float128>(dbl_mult)
173       * static_cast<__float128>(dbl_mult)
174       * static_cast<__float128>(dbl_mult)
175       * static_cast<__float128>(dbl_mult)
176       * static_cast<__float128>(dbl_mult)
177       * static_cast<__float128>(dbl_mult)
178       * static_cast<__float128>(dbl_mult)
179       * static_cast<__float128>(dbl_mult)
180       * static_cast<__float128>(dbl_mult)
181       * static_cast<__float128>(dbl_mult)
182       * static_cast<__float128>(dbl_mult)
183       * static_cast<__float128>(dbl_mult)
184       * static_cast<__float128>(dbl_mult)
185       * static_cast<__float128>(dbl_mult) * 65536;
186 }
187 
188 #define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
189 #define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
190 #define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max
191 
192 #else
193 
194 #define BOOST_MP_QUAD_MIN 3.36210314311209350626267781732175260e-4932Q
195 #define BOOST_MP_QUAD_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
196 #define BOOST_MP_QUAD_MAX 1.18973149535723176508575932662800702e4932Q
197 
198 #endif
199 
200 namespace backends{
201 
202 struct float128_backend
203 {
204    typedef mpl::list<signed char, short, int, long, boost::long_long_type>   signed_types;
205    typedef mpl::list<unsigned char, unsigned short,
206       unsigned int, unsigned long, boost::ulong_long_type>           unsigned_types;
207    typedef mpl::list<float, double, long double>                 float_types;
208    typedef int                                                   exponent_type;
209 
210 private:
211    float128_type m_value;
212 public:
float128_backendboost::multiprecision::backends::float128_backend213    BOOST_CONSTEXPR float128_backend() BOOST_NOEXCEPT : m_value(0) {}
float128_backendboost::multiprecision::backends::float128_backend214    BOOST_CONSTEXPR float128_backend(const float128_backend& o) BOOST_NOEXCEPT : m_value(o.m_value) {}
operator =boost::multiprecision::backends::float128_backend215    float128_backend& operator = (const float128_backend& o) BOOST_NOEXCEPT
216    {
217       m_value = o.m_value;
218       return *this;
219    }
220    template <class T>
float128_backendboost::multiprecision::backends::float128_backend221    BOOST_CONSTEXPR float128_backend(const T& i, const typename enable_if_c<is_convertible<T, float128_type>::value>::type* = 0) BOOST_NOEXCEPT_IF(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
222       : m_value(i) {}
223    template <class T>
operator =boost::multiprecision::backends::float128_backend224    typename enable_if_c<is_arithmetic<T>::value || is_convertible<T, float128_type>::value, float128_backend&>::type operator = (const T& i) BOOST_NOEXCEPT_IF(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
225    {
226       m_value = i;
227       return *this;
228    }
float128_backendboost::multiprecision::backends::float128_backend229    float128_backend(long double const& f)
230    {
231       BOOST_STATIC_CONSTEXPR __float128 inf_val = static_cast<__float128>(HUGE_VAL);
232       if(boost::math::isinf(f))
233          m_value = (f < 0) ? -inf_val : inf_val;
234       else
235          m_value = f;
236    }
operator =boost::multiprecision::backends::float128_backend237    float128_backend& operator=(long double const& f)
238    {
239       BOOST_STATIC_CONSTEXPR __float128 inf_val = static_cast<__float128>(HUGE_VAL);
240       if(boost::math::isinf(f))
241          m_value = (f < 0) ? -inf_val : inf_val;
242       else
243          m_value = f;
244       return *this;
245    }
operator =boost::multiprecision::backends::float128_backend246    float128_backend& operator = (const char* s)
247    {
248 #ifndef BOOST_MP_USE_QUAD
249       char* p_end;
250       m_value = strtoflt128(s, &p_end);
251       if(p_end - s != (std::ptrdiff_t)std::strlen(s))
252       {
253          BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a floating point value"));
254       }
255 #else
256       boost::multiprecision::detail::convert_from_string(*this, s);
257 #endif
258       return *this;
259    }
swapboost::multiprecision::backends::float128_backend260    void swap(float128_backend& o) BOOST_NOEXCEPT
261    {
262       std::swap(m_value, o.value());
263    }
strboost::multiprecision::backends::float128_backend264    std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
265    {
266 #ifndef BOOST_MP_USE_QUAD
267       char buf[100];
268       boost::scoped_array<char> buf2;
269       std::string format = "%";
270       if(f & std::ios_base::showpos)
271          format += "+";
272       if(f & std::ios_base::showpoint)
273          format += "#";
274       format += ".*";
275       if(digits == 0)
276          digits = 36;
277       format += "Q";
278       if(f & std::ios_base::scientific)
279          format += "e";
280       else if(f & std::ios_base::fixed)
281          format += "f";
282       else
283          format += "g";
284 
285       int v = quadmath_snprintf (buf, 100, format.c_str(), digits, m_value);
286 
287       if((v < 0) || (v >= 99))
288       {
289          int v_max = v;
290          buf2.reset(new char[v+3]);
291          v = quadmath_snprintf (&buf2[0], v_max + 3, format.c_str(), digits, m_value);
292          if(v >= v_max + 3)
293          {
294             BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
295          }
296          return &buf2[0];
297       }
298       return buf;
299 #else
300       return boost::multiprecision::detail::convert_to_string(*this, digits ? digits : 37, f);
301 #endif
302    }
negateboost::multiprecision::backends::float128_backend303    void negate() BOOST_NOEXCEPT
304    {
305       m_value = -m_value;
306    }
compareboost::multiprecision::backends::float128_backend307    int compare(const float128_backend& o)const
308    {
309       return m_value == o.m_value ? 0 : m_value < o.m_value ? -1 : 1;
310    }
311    template <class T>
compareboost::multiprecision::backends::float128_backend312    int compare(const T& i)const
313    {
314       return m_value == i ? 0 : m_value < i ? -1 : 1;
315    }
valueboost::multiprecision::backends::float128_backend316    float128_type& value()
317    {
318       return m_value;
319    }
valueboost::multiprecision::backends::float128_backend320    const float128_type& value()const
321    {
322       return m_value;
323    }
324 };
325 
eval_add(float128_backend & result,const float128_backend & a)326 inline void eval_add(float128_backend& result, const float128_backend& a)
327 {
328    result.value() += a.value();
329 }
330 template <class A>
eval_add(float128_backend & result,const A & a)331 inline void eval_add(float128_backend& result, const A& a)
332 {
333    result.value() += a;
334 }
eval_subtract(float128_backend & result,const float128_backend & a)335 inline void eval_subtract(float128_backend& result, const float128_backend& a)
336 {
337    result.value() -= a.value();
338 }
339 template <class A>
eval_subtract(float128_backend & result,const A & a)340 inline void eval_subtract(float128_backend& result, const A& a)
341 {
342    result.value() -= a;
343 }
eval_multiply(float128_backend & result,const float128_backend & a)344 inline void eval_multiply(float128_backend& result, const float128_backend& a)
345 {
346    result.value() *= a.value();
347 }
348 template <class A>
eval_multiply(float128_backend & result,const A & a)349 inline void eval_multiply(float128_backend& result, const A& a)
350 {
351    result.value() *= a;
352 }
eval_divide(float128_backend & result,const float128_backend & a)353 inline void eval_divide(float128_backend& result, const float128_backend& a)
354 {
355    result.value() /= a.value();
356 }
357 template <class A>
eval_divide(float128_backend & result,const A & a)358 inline void eval_divide(float128_backend& result, const A& a)
359 {
360    result.value() /= a;
361 }
362 
eval_add(float128_backend & result,const float128_backend & a,const float128_backend & b)363 inline void eval_add(float128_backend& result, const float128_backend& a, const float128_backend& b)
364 {
365    result.value() = a.value() + b.value();
366 }
367 template <class A>
eval_add(float128_backend & result,const float128_backend & a,const A & b)368 inline void eval_add(float128_backend& result, const float128_backend& a, const A& b)
369 {
370    result.value() = a.value() + b;
371 }
eval_subtract(float128_backend & result,const float128_backend & a,const float128_backend & b)372 inline void eval_subtract(float128_backend& result, const float128_backend& a, const float128_backend& b)
373 {
374    result.value() = a.value() - b.value();
375 }
376 template <class A>
eval_subtract(float128_backend & result,const float128_backend & a,const A & b)377 inline void eval_subtract(float128_backend& result, const float128_backend& a, const A& b)
378 {
379    result.value() = a.value() - b;
380 }
381 template <class A>
eval_subtract(float128_backend & result,const A & a,const float128_backend & b)382 inline void eval_subtract(float128_backend& result, const A& a, const float128_backend& b)
383 {
384    result.value() = a - b.value();
385 }
eval_multiply(float128_backend & result,const float128_backend & a,const float128_backend & b)386 inline void eval_multiply(float128_backend& result, const float128_backend& a, const float128_backend& b)
387 {
388    result.value() = a.value() * b.value();
389 }
390 template <class A>
eval_multiply(float128_backend & result,const float128_backend & a,const A & b)391 inline void eval_multiply(float128_backend& result, const float128_backend& a, const A& b)
392 {
393    result.value() = a.value() * b;
394 }
eval_divide(float128_backend & result,const float128_backend & a,const float128_backend & b)395 inline void eval_divide(float128_backend& result, const float128_backend& a, const float128_backend& b)
396 {
397    result.value() = a.value() / b.value();
398 }
399 
400 template <class R>
eval_convert_to(R * result,const float128_backend & val)401 inline void eval_convert_to(R* result, const float128_backend& val)
402 {
403    *result = static_cast<R>(val.value());
404 }
405 
eval_frexp(float128_backend & result,const float128_backend & arg,int * exp)406 inline void eval_frexp(float128_backend& result, const float128_backend& arg, int* exp)
407 {
408    result.value() = frexpq(arg.value(), exp);
409 }
410 
eval_ldexp(float128_backend & result,const float128_backend & arg,int exp)411 inline void eval_ldexp(float128_backend& result, const float128_backend& arg, int exp)
412 {
413    result.value() = ldexpq(arg.value(), exp);
414 }
415 
eval_floor(float128_backend & result,const float128_backend & arg)416 inline void eval_floor(float128_backend& result, const float128_backend& arg)
417 {
418    result.value() = floorq(arg.value());
419 }
eval_ceil(float128_backend & result,const float128_backend & arg)420 inline void eval_ceil(float128_backend& result, const float128_backend& arg)
421 {
422    result.value() = ceilq(arg.value());
423 }
eval_sqrt(float128_backend & result,const float128_backend & arg)424 inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
425 {
426    result.value() = sqrtq(arg.value());
427 }
eval_fpclassify(const float128_backend & arg)428 inline int eval_fpclassify(const float128_backend& arg)
429 {
430    if(isnanq(arg.value()))
431       return FP_NAN;
432    else if(isinfq(arg.value()))
433       return FP_INFINITE;
434    else if(arg.value() == 0)
435       return FP_ZERO;
436 
437    float128_backend t(arg);
438    if(t.value() < 0)
439       t.negate();
440    if(t.value() < BOOST_MP_QUAD_MIN)
441       return FP_SUBNORMAL;
442    return FP_NORMAL;
443 }
444 
eval_increment(float128_backend & arg)445 inline void eval_increment(float128_backend& arg)
446 {
447    ++arg.value();
448 }
eval_decrement(float128_backend & arg)449 inline void eval_decrement(float128_backend& arg)
450 {
451    --arg.value();
452 }
453 
454 /*********************************************************************
455 *
456 * abs/fabs:
457 *
458 *********************************************************************/
459 
eval_abs(float128_backend & result,const float128_backend & arg)460 inline void eval_abs(float128_backend& result, const float128_backend& arg)
461 {
462    result.value() = fabsq(arg.value());
463 }
eval_fabs(float128_backend & result,const float128_backend & arg)464 inline void eval_fabs(float128_backend& result, const float128_backend& arg)
465 {
466    result.value() = fabsq(arg.value());
467 }
468 
469 /*********************************************************************
470 *
471 * Floating point functions:
472 *
473 *********************************************************************/
474 
eval_trunc(float128_backend & result,const float128_backend & arg)475 inline void eval_trunc(float128_backend& result, const float128_backend& arg)
476 {
477    result.value() = truncq(arg.value());
478 }
479 /*
480 //
481 // This doesn't actually work... rely on our own default version instead.
482 //
483 inline void eval_round(float128_backend& result, const float128_backend& arg)
484 {
485    if(isnanq(arg.value()) || isinf(arg.value()))
486    {
487       result = boost::math::policies::raise_rounding_error(
488             "boost::multiprecision::trunc<%1%>(%1%)", 0,
489             number<float128_backend, et_off>(arg),
490             number<float128_backend, et_off>(arg),
491             boost::math::policies::policy<>()).backend();
492       return;
493    }
494    result.value() = roundq(arg.value());
495 }
496 */
497 
eval_exp(float128_backend & result,const float128_backend & arg)498 inline void eval_exp(float128_backend& result, const float128_backend& arg)
499 {
500    result.value() = expq(arg.value());
501 }
eval_log(float128_backend & result,const float128_backend & arg)502 inline void eval_log(float128_backend& result, const float128_backend& arg)
503 {
504    result.value() = logq(arg.value());
505 }
eval_log10(float128_backend & result,const float128_backend & arg)506 inline void eval_log10(float128_backend& result, const float128_backend& arg)
507 {
508    result.value() = log10q(arg.value());
509 }
eval_sin(float128_backend & result,const float128_backend & arg)510 inline void eval_sin(float128_backend& result, const float128_backend& arg)
511 {
512    result.value() = sinq(arg.value());
513 }
eval_cos(float128_backend & result,const float128_backend & arg)514 inline void eval_cos(float128_backend& result, const float128_backend& arg)
515 {
516    result.value() = cosq(arg.value());
517 }
eval_tan(float128_backend & result,const float128_backend & arg)518 inline void eval_tan(float128_backend& result, const float128_backend& arg)
519 {
520    result.value() = tanq(arg.value());
521 }
eval_asin(float128_backend & result,const float128_backend & arg)522 inline void eval_asin(float128_backend& result, const float128_backend& arg)
523 {
524    result.value() = asinq(arg.value());
525 }
eval_acos(float128_backend & result,const float128_backend & arg)526 inline void eval_acos(float128_backend& result, const float128_backend& arg)
527 {
528    result.value() = acosq(arg.value());
529 }
eval_atan(float128_backend & result,const float128_backend & arg)530 inline void eval_atan(float128_backend& result, const float128_backend& arg)
531 {
532    result.value() = atanq(arg.value());
533 }
eval_sinh(float128_backend & result,const float128_backend & arg)534 inline void eval_sinh(float128_backend& result, const float128_backend& arg)
535 {
536    result.value() = sinhq(arg.value());
537 }
eval_cosh(float128_backend & result,const float128_backend & arg)538 inline void eval_cosh(float128_backend& result, const float128_backend& arg)
539 {
540    result.value() = coshq(arg.value());
541 }
eval_tanh(float128_backend & result,const float128_backend & arg)542 inline void eval_tanh(float128_backend& result, const float128_backend& arg)
543 {
544    result.value() = tanhq(arg.value());
545 }
eval_fmod(float128_backend & result,const float128_backend & a,const float128_backend & b)546 inline void eval_fmod(float128_backend& result, const float128_backend& a, const float128_backend& b)
547 {
548    result.value() = fmodq(a.value(), b.value());
549 }
eval_pow(float128_backend & result,const float128_backend & a,const float128_backend & b)550 inline void eval_pow(float128_backend& result, const float128_backend& a, const float128_backend& b)
551 {
552    result.value() = powq(a.value(), b.value());
553 }
eval_atan2(float128_backend & result,const float128_backend & a,const float128_backend & b)554 inline void eval_atan2(float128_backend& result, const float128_backend& a, const float128_backend& b)
555 {
556    result.value() = atan2q(a.value(), b.value());
557 }
558 #ifndef BOOST_MP_USE_QUAD
eval_multiply_add(float128_backend & result,const float128_backend & a,const float128_backend & b,const float128_backend & c)559 inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
560 {
561    result.value() = fmaq(a.value(), b.value(), c.value());
562 }
BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend & arg)563 inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
564 {
565    return ::signbitq(arg.value());
566 }
567 #endif
568 
hash_value(const float128_backend & val)569 inline std::size_t hash_value(const float128_backend& val)
570 {
571    return  boost::hash_value(static_cast<double>(val.value()));
572 }
573 
574 } // namespace backends
575 
576    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)577    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
578    {
579       return asinhq(arg.backend().value());
580    }
581    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)582    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
583    {
584       return acoshq(arg.backend().value());
585    }
586    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)587    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
588    {
589       return atanhq(arg.backend().value());
590    }
591    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)592    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
593    {
594       return cbrtq(arg.backend().value());
595    }
596    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)597    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
598    {
599       return erfq(arg.backend().value());
600    }
601    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)602    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
603    {
604       return erfcq(arg.backend().value());
605    }
606    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)607    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
608    {
609       return expm1q(arg.backend().value());
610    }
611    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)612    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
613    {
614       return lgammaq(arg.backend().value());
615    }
616    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)617    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
618    {
619       return tgammaq(arg.backend().value());
620    }
621    template<boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)622    inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
623    {
624       return log1pq(arg.backend().value());
625    }
626 
627 #ifndef BOOST_MP_USE_QUAD
628    template <multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend,ExpressionTemplates> & a,const boost::multiprecision::number<boost::multiprecision::backends::float128_backend,ExpressionTemplates> & b)629    inline boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& a, const boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>& b)
630    {
631       return ::copysignq(a.backend().value(), b.backend().value());
632    }
633 
eval_remainder(float128_backend & result,const float128_backend & a,const float128_backend & b)634    inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
635    {
636       result.value() = remainderq(a.value(), b.value());
637    }
eval_remainder(float128_backend & result,const float128_backend & a,const float128_backend & b,int * pi)638    inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
639    {
640       result.value() = remquoq(a.value(), b.value(), pi);
641    }
642 #endif
643 
644 } // namespace multiprecision
645 
646 namespace math {
647 
648    using boost::multiprecision::signbit;
649    using boost::multiprecision::copysign;
650 
651 } // namespace math
652 
653 } // namespace boost
654 
655 namespace boost{
656 namespace archive{
657 
658 class binary_oarchive;
659 class binary_iarchive;
660 
661 }
662 
663 namespace serialization{ namespace float128_detail{
664 
665 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::false_ &,const mpl::false_ &)666 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::false_&)
667 {
668    // saving
669    // non-binary
670    std::string s(val.str(0, std::ios_base::scientific));
671    ar & boost::serialization::make_nvp("value", s);
672 }
673 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::true_ &,const mpl::false_ &)674 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::false_&)
675 {
676    // loading
677    // non-binary
678    std::string s;
679    ar & boost::serialization::make_nvp("value", s);
680    val = s.c_str();
681 }
682 
683 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::false_ &,const mpl::true_ &)684 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::true_&)
685 {
686    // saving
687    // binary
688    ar.save_binary(&val, sizeof(val));
689 }
690 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::true_ &,const mpl::true_ &)691 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::true_&)
692 {
693    // loading
694    // binary
695    ar.load_binary(&val, sizeof(val));
696 }
697 
698 } // detail
699 
700 template <class Archive>
serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,unsigned int)701 void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/)
702 {
703    typedef typename Archive::is_loading load_tag;
704    typedef typename mpl::bool_<boost::is_same<Archive, boost::archive::binary_oarchive>::value || boost::is_same<Archive, boost::archive::binary_iarchive>::value> binary_tag;
705 
706    float128_detail::do_serialize(ar, val, load_tag(), binary_tag());
707 }
708 
709 } // namepsace archive
710 
711 } // namespace boost
712 
713 namespace std{
714 
715 template <boost::multiprecision::expression_template_option ExpressionTemplates>
716 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >
717 {
718    typedef boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> number_type;
719 public:
720    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
number_type(min)721    static number_type (min)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MIN; }
number_type(max)722    static number_type (max)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MAX; }
lowest()723    static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
724    BOOST_STATIC_CONSTEXPR int digits = 113;
725    BOOST_STATIC_CONSTEXPR int digits10 = 33;
726    BOOST_STATIC_CONSTEXPR int max_digits10 = 36;
727    BOOST_STATIC_CONSTEXPR bool is_signed = true;
728    BOOST_STATIC_CONSTEXPR bool is_integer = false;
729    BOOST_STATIC_CONSTEXPR bool is_exact = false;
730    BOOST_STATIC_CONSTEXPR int radix = 2;
epsilon()731    static number_type epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
round_error()732    static number_type round_error() { return 0.5; }
733    BOOST_STATIC_CONSTEXPR int min_exponent = -16381;
734    BOOST_STATIC_CONSTEXPR int min_exponent10 = min_exponent * 301L / 1000L;
735    BOOST_STATIC_CONSTEXPR int max_exponent = 16384;
736    BOOST_STATIC_CONSTEXPR int max_exponent10 = max_exponent * 301L / 1000L;
737    BOOST_STATIC_CONSTEXPR bool has_infinity = true;
738    BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
739    BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
740    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_present;
741    BOOST_STATIC_CONSTEXPR bool has_denorm_loss = true;
infinity()742    static number_type infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
quiet_NaN()743    static number_type quiet_NaN() { return number_type("nan"); }
signaling_NaN()744    static number_type signaling_NaN() { return 0; }
denorm_min()745    static number_type denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
746    BOOST_STATIC_CONSTEXPR bool is_iec559 = true;
747    BOOST_STATIC_CONSTEXPR bool is_bounded = false;
748    BOOST_STATIC_CONSTEXPR bool is_modulo = false;
749    BOOST_STATIC_CONSTEXPR bool traps = false;
750    BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
751    BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
752 };
753 
754 template <boost::multiprecision::expression_template_option ExpressionTemplates>
755 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_specialized;
756 template <boost::multiprecision::expression_template_option ExpressionTemplates>
757 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits;
758 template <boost::multiprecision::expression_template_option ExpressionTemplates>
759 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits10;
760 template <boost::multiprecision::expression_template_option ExpressionTemplates>
761 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_digits10;
762 
763 template <boost::multiprecision::expression_template_option ExpressionTemplates>
764 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_signed;
765 template <boost::multiprecision::expression_template_option ExpressionTemplates>
766 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_integer;
767 template <boost::multiprecision::expression_template_option ExpressionTemplates>
768 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_exact;
769 template <boost::multiprecision::expression_template_option ExpressionTemplates>
770 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::radix;
771 
772 
773 template <boost::multiprecision::expression_template_option ExpressionTemplates>
774 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent;
775 template <boost::multiprecision::expression_template_option ExpressionTemplates>
776 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent;
777 template <boost::multiprecision::expression_template_option ExpressionTemplates>
778 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent10;
779 template <boost::multiprecision::expression_template_option ExpressionTemplates>
780 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent10;
781 
782 template <boost::multiprecision::expression_template_option ExpressionTemplates>
783 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_infinity;
784 template <boost::multiprecision::expression_template_option ExpressionTemplates>
785 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_quiet_NaN;
786 template <boost::multiprecision::expression_template_option ExpressionTemplates>
787 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_signaling_NaN;
788 template <boost::multiprecision::expression_template_option ExpressionTemplates>
789 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm_loss;
790 
791 template <boost::multiprecision::expression_template_option ExpressionTemplates>
792 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_iec559;
793 template <boost::multiprecision::expression_template_option ExpressionTemplates>
794 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_bounded;
795 template <boost::multiprecision::expression_template_option ExpressionTemplates>
796 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_modulo;
797 template <boost::multiprecision::expression_template_option ExpressionTemplates>
798 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::traps;
799 template <boost::multiprecision::expression_template_option ExpressionTemplates>
800 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::tinyness_before;
801 
802 template <boost::multiprecision::expression_template_option ExpressionTemplates>
803 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::round_style;
804 template <boost::multiprecision::expression_template_option ExpressionTemplates>
805 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm;
806 
807 } // namespace std
808 
809 
810 #endif
811