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 https://www.boost.org/LICENSE_1_0.txt
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 {};
123 #if defined(BOOST_MP_USE_QUAD)
124 template <>
125 struct number_category<float128_type> : public mpl::int_<number_kind_floating_point>
126 {};
127 #endif
128 
129 typedef number<float128_backend, et_off> float128;
130 
131 #ifndef BOOST_NO_CXX11_CONSTEXPR
132 
133 namespace quad_constants {
134 constexpr __float128 quad_min = static_cast<__float128>(1) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) / 1073741824;
135 
136 constexpr __float128 quad_denorm_min = static_cast<__float128>(1) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) * static_cast<__float128>(DBL_MIN) / 5.5751862996326557854e+42;
137 
138 constexpr double     dbl_mult = 8.9884656743115795386e+307;                                              // This has one bit set only.
139 constexpr __float128 quad_max = (static_cast<__float128>(1) - 9.62964972193617926527988971292463659e-35) // This now has all bits sets to 1
140                                 * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * static_cast<__float128>(dbl_mult) * 65536;
141 } // namespace quad_constants
142 
143 #define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
144 #define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
145 #define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max
146 
147 #else
148 
149 #define BOOST_MP_QUAD_MIN 3.36210314311209350626267781732175260e-4932Q
150 #define BOOST_MP_QUAD_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
151 #define BOOST_MP_QUAD_MAX 1.18973149535723176508575932662800702e4932Q
152 
153 #endif
154 
155 namespace backends {
156 
157 struct float128_backend
158 {
159    typedef mpl::list<signed char, short, int, long, boost::long_long_type> signed_types;
160    typedef mpl::list<unsigned char, unsigned short,
161                      unsigned int, unsigned long, boost::ulong_long_type>
162        unsigned_types;
163    typedef mpl::list<float, double, long double> float_types;
164    typedef int                                   exponent_type;
165 
166  private:
167    float128_type m_value;
168 
169  public:
float128_backendboost::multiprecision::backends::float128_backend170    BOOST_CONSTEXPR   float128_backend() BOOST_NOEXCEPT : m_value(0) {}
float128_backendboost::multiprecision::backends::float128_backend171    BOOST_CONSTEXPR   float128_backend(const float128_backend& o) BOOST_NOEXCEPT : m_value(o.m_value) {}
operator =boost::multiprecision::backends::float128_backend172    BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(const float128_backend& o) BOOST_NOEXCEPT
173    {
174       m_value = o.m_value;
175       return *this;
176    }
177    template <class T>
float128_backendboost::multiprecision::backends::float128_backend178    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&>()))
179        : m_value(i) {}
180    template <class T>
operator =boost::multiprecision::backends::float128_backend181    BOOST_MP_CXX14_CONSTEXPR 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&>()))
182    {
183       m_value = i;
184       return *this;
185    }
float128_backendboost::multiprecision::backends::float128_backend186    BOOST_MP_CXX14_CONSTEXPR float128_backend(long double const& f) : m_value(f)
187    {
188       if (::fabsl(f) > LDBL_MAX)
189          m_value = (f < 0) ? -static_cast<__float128>(HUGE_VAL) : static_cast<__float128>(HUGE_VAL);
190    }
operator =boost::multiprecision::backends::float128_backend191    BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(long double const& f)
192    {
193       if (f > LDBL_MAX)
194          m_value = static_cast<__float128>(HUGE_VAL);
195       else if (-f > LDBL_MAX)
196          m_value = -static_cast<__float128>(HUGE_VAL);
197       else
198          m_value = f;
199       return *this;
200    }
operator =boost::multiprecision::backends::float128_backend201    float128_backend& operator=(const char* s)
202    {
203 #ifndef BOOST_MP_USE_QUAD
204       char* p_end;
205       m_value = strtoflt128(s, &p_end);
206       if (p_end - s != (std::ptrdiff_t)std::strlen(s))
207       {
208          BOOST_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a floating point value"));
209       }
210 #else
211       boost::multiprecision::detail::convert_from_string(*this, s);
212 #endif
213       return *this;
214    }
swapboost::multiprecision::backends::float128_backend215    BOOST_MP_CXX14_CONSTEXPR void swap(float128_backend& o) BOOST_NOEXCEPT
216    {
217       // We don't call std::swap here because it's no constexpr (yet):
218       float128_type t(o.value());
219       o.value() = m_value;
220       m_value = t;
221    }
strboost::multiprecision::backends::float128_backend222    std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
223    {
224 #ifndef BOOST_MP_USE_QUAD
225       char        buf[128];
226       std::string format = "%";
227       if (f & std::ios_base::showpos)
228          format += "+";
229       if (f & std::ios_base::showpoint)
230          format += "#";
231       format += ".*";
232       if (digits == 0)
233          digits = 36;
234       format += "Q";
235 
236       if (f & std::ios_base::scientific)
237          format += "e";
238       else if (f & std::ios_base::fixed)
239          format += "f";
240       else
241          format += "g";
242 
243       int v;
244       if ((f & std::ios_base::scientific) && (f & std::ios_base::fixed))
245       {
246          v = quadmath_snprintf(buf, sizeof buf, "%Qa", m_value);
247       }
248       else
249       {
250          v = quadmath_snprintf(buf, sizeof buf, format.c_str(), digits, m_value);
251       }
252 
253       if ((v < 0) || (v >= 127))
254       {
255          int                       v_max = v;
256          boost::scoped_array<char> buf2;
257          buf2.reset(new char[v + 3]);
258          v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
259          if (v >= v_max + 3)
260          {
261             BOOST_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
262          }
263          return &buf2[0];
264       }
265       return buf;
266 #else
267       return boost::multiprecision::detail::convert_to_string(*this, digits ? digits : 37, f);
268 #endif
269    }
negateboost::multiprecision::backends::float128_backend270    BOOST_MP_CXX14_CONSTEXPR void negate() BOOST_NOEXCEPT
271    {
272       m_value = -m_value;
273    }
compareboost::multiprecision::backends::float128_backend274    BOOST_MP_CXX14_CONSTEXPR int compare(const float128_backend& o) const
275    {
276       return m_value == o.m_value ? 0 : m_value < o.m_value ? -1 : 1;
277    }
278    template <class T>
compareboost::multiprecision::backends::float128_backend279    BOOST_MP_CXX14_CONSTEXPR int compare(const T& i) const
280    {
281       return m_value == i ? 0 : m_value < i ? -1 : 1;
282    }
valueboost::multiprecision::backends::float128_backend283    BOOST_MP_CXX14_CONSTEXPR float128_type& value()
284    {
285       return m_value;
286    }
valueboost::multiprecision::backends::float128_backend287    BOOST_MP_CXX14_CONSTEXPR const float128_type& value() const
288    {
289       return m_value;
290    }
291 };
292 
eval_add(float128_backend & result,const float128_backend & a)293 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a)
294 {
295    result.value() += a.value();
296 }
297 template <class A>
eval_add(float128_backend & result,const A & a)298 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const A& a)
299 {
300    result.value() += a;
301 }
eval_subtract(float128_backend & result,const float128_backend & a)302 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a)
303 {
304    result.value() -= a.value();
305 }
306 template <class A>
eval_subtract(float128_backend & result,const A & a)307 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a)
308 {
309    result.value() -= a;
310 }
eval_multiply(float128_backend & result,const float128_backend & a)311 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a)
312 {
313    result.value() *= a.value();
314 }
315 template <class A>
eval_multiply(float128_backend & result,const A & a)316 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const A& a)
317 {
318    result.value() *= a;
319 }
eval_divide(float128_backend & result,const float128_backend & a)320 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a)
321 {
322    result.value() /= a.value();
323 }
324 template <class A>
eval_divide(float128_backend & result,const A & a)325 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const A& a)
326 {
327    result.value() /= a;
328 }
329 
eval_add(float128_backend & result,const float128_backend & a,const float128_backend & b)330 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const float128_backend& b)
331 {
332    result.value() = a.value() + b.value();
333 }
334 template <class A>
eval_add(float128_backend & result,const float128_backend & a,const A & b)335 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const A& b)
336 {
337    result.value() = a.value() + b;
338 }
eval_subtract(float128_backend & result,const float128_backend & a,const float128_backend & b)339 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const float128_backend& b)
340 {
341    result.value() = a.value() - b.value();
342 }
343 template <class A>
eval_subtract(float128_backend & result,const float128_backend & a,const A & b)344 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const A& b)
345 {
346    result.value() = a.value() - b;
347 }
348 template <class A>
eval_subtract(float128_backend & result,const A & a,const float128_backend & b)349 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a, const float128_backend& b)
350 {
351    result.value() = a - b.value();
352 }
eval_multiply(float128_backend & result,const float128_backend & a,const float128_backend & b)353 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const float128_backend& b)
354 {
355    result.value() = a.value() * b.value();
356 }
357 template <class A>
eval_multiply(float128_backend & result,const float128_backend & a,const A & b)358 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const A& b)
359 {
360    result.value() = a.value() * b;
361 }
eval_divide(float128_backend & result,const float128_backend & a,const float128_backend & b)362 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a, const float128_backend& b)
363 {
364    result.value() = a.value() / b.value();
365 }
366 
367 template <class R>
eval_convert_to(R * result,const float128_backend & val)368 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(R* result, const float128_backend& val)
369 {
370    *result = static_cast<R>(val.value());
371 }
372 
eval_frexp(float128_backend & result,const float128_backend & arg,int * exp)373 inline void eval_frexp(float128_backend& result, const float128_backend& arg, int* exp)
374 {
375    result.value() = frexpq(arg.value(), exp);
376 }
377 
eval_ldexp(float128_backend & result,const float128_backend & arg,int exp)378 inline void eval_ldexp(float128_backend& result, const float128_backend& arg, int exp)
379 {
380    result.value() = ldexpq(arg.value(), exp);
381 }
382 
eval_floor(float128_backend & result,const float128_backend & arg)383 inline void eval_floor(float128_backend& result, const float128_backend& arg)
384 {
385    result.value() = floorq(arg.value());
386 }
eval_ceil(float128_backend & result,const float128_backend & arg)387 inline void eval_ceil(float128_backend& result, const float128_backend& arg)
388 {
389    result.value() = ceilq(arg.value());
390 }
eval_sqrt(float128_backend & result,const float128_backend & arg)391 inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
392 {
393    result.value() = sqrtq(arg.value());
394 }
395 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
396 inline BOOST_MP_CXX14_CONSTEXPR
397 #else
398 inline
399 #endif
eval_fpclassify(const float128_backend & arg)400 int eval_fpclassify(const float128_backend& arg)
401 {
402    float128_type v = arg.value();
403 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
404    if (BOOST_MP_IS_CONST_EVALUATED(v))
405    {
406       if (v != v)
407          return FP_NAN;
408       if (v == 0)
409          return FP_ZERO;
410       float128_type t(v);
411       if (t < 0)
412          t = -t;
413       if (t > BOOST_MP_QUAD_MAX)
414          return FP_INFINITE;
415       if (t < BOOST_MP_QUAD_MIN)
416          return FP_SUBNORMAL;
417       return FP_NORMAL;
418    }
419    else
420 #endif
421    {
422       if (isnanq(v))
423          return FP_NAN;
424       else if (isinfq(v))
425          return FP_INFINITE;
426       else if (v == 0)
427          return FP_ZERO;
428 
429       float128_backend t(arg);
430       if (t.value() < 0)
431          t.negate();
432       if (t.value() < BOOST_MP_QUAD_MIN)
433          return FP_SUBNORMAL;
434       return FP_NORMAL;
435    }
436 }
437 #if defined(BOOST_GCC) && (__GNUC__ == 9)
438 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91705
eval_increment(float128_backend & arg)439 inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
440 {
441    arg.value() = 1 + arg.value();
442 }
eval_decrement(float128_backend & arg)443 inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
444 {
445    arg.value() = arg.value() - 1;
446 }
447 #else
eval_increment(float128_backend & arg)448 inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
449 {
450    ++arg.value();
451 }
eval_decrement(float128_backend & arg)452 inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
453 {
454    --arg.value();
455 }
456 #endif
457 
458 /*********************************************************************
459 *
460 * abs/fabs:
461 *
462 *********************************************************************/
463 
464 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
eval_abs(float128_backend & result,const float128_backend & arg)465 inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(float128_backend& result, const float128_backend& arg)
466 #else
467 inline void eval_abs(float128_backend& result, const float128_backend& arg)
468 #endif
469 {
470    float128_type v(arg.value());
471 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
472    if (BOOST_MP_IS_CONST_EVALUATED(v))
473    {
474       result.value() = v < 0 ? -v : v;
475    }
476    else
477 #endif
478    {
479       result.value() = fabsq(arg.value());
480    }
481 }
482 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
eval_fabs(float128_backend & result,const float128_backend & arg)483 inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(float128_backend& result, const float128_backend& arg)
484 #else
485 inline void eval_fabs(float128_backend& result, const float128_backend& arg)
486 #endif
487 {
488    float128_type v(arg.value());
489 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
490    if (BOOST_MP_IS_CONST_EVALUATED(v))
491    {
492       result.value() = v < 0 ? -v : v;
493    }
494    else
495 #endif
496    {
497       result.value() = fabsq(arg.value());
498    }
499 }
500 
501 /*********************************************************************
502 *
503 * Floating point functions:
504 *
505 *********************************************************************/
506 
eval_trunc(float128_backend & result,const float128_backend & arg)507 inline void eval_trunc(float128_backend& result, const float128_backend& arg)
508 {
509    result.value() = truncq(arg.value());
510 }
511 /*
512 //
513 // This doesn't actually work... rely on our own default version instead.
514 //
515 inline void eval_round(float128_backend& result, const float128_backend& arg)
516 {
517    if(isnanq(arg.value()) || isinf(arg.value()))
518    {
519       result = boost::math::policies::raise_rounding_error(
520             "boost::multiprecision::trunc<%1%>(%1%)", 0,
521             number<float128_backend, et_off>(arg),
522             number<float128_backend, et_off>(arg),
523             boost::math::policies::policy<>()).backend();
524       return;
525    }
526    result.value() = roundq(arg.value());
527 }
528 */
529 
eval_exp(float128_backend & result,const float128_backend & arg)530 inline void eval_exp(float128_backend& result, const float128_backend& arg)
531 {
532    result.value() = expq(arg.value());
533 }
eval_log(float128_backend & result,const float128_backend & arg)534 inline void eval_log(float128_backend& result, const float128_backend& arg)
535 {
536    result.value() = logq(arg.value());
537 }
eval_log10(float128_backend & result,const float128_backend & arg)538 inline void eval_log10(float128_backend& result, const float128_backend& arg)
539 {
540    result.value() = log10q(arg.value());
541 }
eval_sin(float128_backend & result,const float128_backend & arg)542 inline void eval_sin(float128_backend& result, const float128_backend& arg)
543 {
544    result.value() = sinq(arg.value());
545 }
eval_cos(float128_backend & result,const float128_backend & arg)546 inline void eval_cos(float128_backend& result, const float128_backend& arg)
547 {
548    result.value() = cosq(arg.value());
549 }
eval_tan(float128_backend & result,const float128_backend & arg)550 inline void eval_tan(float128_backend& result, const float128_backend& arg)
551 {
552    result.value() = tanq(arg.value());
553 }
eval_asin(float128_backend & result,const float128_backend & arg)554 inline void eval_asin(float128_backend& result, const float128_backend& arg)
555 {
556    result.value() = asinq(arg.value());
557 }
eval_acos(float128_backend & result,const float128_backend & arg)558 inline void eval_acos(float128_backend& result, const float128_backend& arg)
559 {
560    result.value() = acosq(arg.value());
561 }
eval_atan(float128_backend & result,const float128_backend & arg)562 inline void eval_atan(float128_backend& result, const float128_backend& arg)
563 {
564    result.value() = atanq(arg.value());
565 }
eval_sinh(float128_backend & result,const float128_backend & arg)566 inline void eval_sinh(float128_backend& result, const float128_backend& arg)
567 {
568    result.value() = sinhq(arg.value());
569 }
eval_cosh(float128_backend & result,const float128_backend & arg)570 inline void eval_cosh(float128_backend& result, const float128_backend& arg)
571 {
572    result.value() = coshq(arg.value());
573 }
eval_tanh(float128_backend & result,const float128_backend & arg)574 inline void eval_tanh(float128_backend& result, const float128_backend& arg)
575 {
576    result.value() = tanhq(arg.value());
577 }
eval_fmod(float128_backend & result,const float128_backend & a,const float128_backend & b)578 inline void eval_fmod(float128_backend& result, const float128_backend& a, const float128_backend& b)
579 {
580    result.value() = fmodq(a.value(), b.value());
581 }
eval_pow(float128_backend & result,const float128_backend & a,const float128_backend & b)582 inline void eval_pow(float128_backend& result, const float128_backend& a, const float128_backend& b)
583 {
584    result.value() = powq(a.value(), b.value());
585 }
eval_atan2(float128_backend & result,const float128_backend & a,const float128_backend & b)586 inline void eval_atan2(float128_backend& result, const float128_backend& a, const float128_backend& b)
587 {
588    result.value() = atan2q(a.value(), b.value());
589 }
590 #ifndef BOOST_MP_USE_QUAD
eval_multiply_add(float128_backend & result,const float128_backend & a,const float128_backend & b,const float128_backend & c)591 inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
592 {
593    result.value() = fmaq(a.value(), b.value(), c.value());
594 }
BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend & arg)595 inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
596 {
597    return ::signbitq(arg.value());
598 }
599 #endif
600 
hash_value(const float128_backend & val)601 inline std::size_t hash_value(const float128_backend& val)
602 {
603    return boost::hash_value(static_cast<double>(val.value()));
604 }
605 
606 } // namespace backends
607 
608 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)609 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
610 {
611    return asinhq(arg.backend().value());
612 }
613 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)614 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
615 {
616    return acoshq(arg.backend().value());
617 }
618 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)619 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
620 {
621    return atanhq(arg.backend().value());
622 }
623 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)624 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
625 {
626    return cbrtq(arg.backend().value());
627 }
628 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)629 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
630 {
631    return erfq(arg.backend().value());
632 }
633 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)634 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
635 {
636    return erfcq(arg.backend().value());
637 }
638 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)639 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
640 {
641    return expm1q(arg.backend().value());
642 }
643 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)644 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
645 {
646    return lgammaq(arg.backend().value());
647 }
648 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)649 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
650 {
651    return tgammaq(arg.backend().value());
652 }
653 template <boost::multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend,ExpressionTemplates> & arg)654 inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
655 {
656    return log1pq(arg.backend().value());
657 }
658 
659 #ifndef BOOST_MP_USE_QUAD
660 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)661 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)
662 {
663    return ::copysignq(a.backend().value(), b.backend().value());
664 }
665 
eval_remainder(float128_backend & result,const float128_backend & a,const float128_backend & b)666 inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
667 {
668    result.value() = remainderq(a.value(), b.value());
669 }
eval_remainder(float128_backend & result,const float128_backend & a,const float128_backend & b,int * pi)670 inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
671 {
672    result.value() = remquoq(a.value(), b.value(), pi);
673 }
674 #endif
675 
676 } // namespace multiprecision
677 
678 namespace math {
679 
680 using boost::multiprecision::copysign;
681 using boost::multiprecision::signbit;
682 
683 } // namespace math
684 
685 } // namespace boost
686 
687 namespace boost {
688 namespace archive {
689 
690 class binary_oarchive;
691 class binary_iarchive;
692 
693 } // namespace archive
694 
695 namespace serialization {
696 namespace float128_detail {
697 
698 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::false_ &,const mpl::false_ &)699 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::false_&)
700 {
701    // saving
702    // non-binary
703    std::string s(val.str(0, std::ios_base::scientific));
704    ar&         boost::make_nvp("value", s);
705 }
706 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::true_ &,const mpl::false_ &)707 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::false_&)
708 {
709    // loading
710    // non-binary
711    std::string s;
712    ar&         boost::make_nvp("value", s);
713    val = s.c_str();
714 }
715 
716 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::false_ &,const mpl::true_ &)717 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::false_&, const mpl::true_&)
718 {
719    // saving
720    // binary
721    ar.save_binary(&val, sizeof(val));
722 }
723 template <class Archive>
do_serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,const mpl::true_ &,const mpl::true_ &)724 void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const mpl::true_&, const mpl::true_&)
725 {
726    // loading
727    // binary
728    ar.load_binary(&val, sizeof(val));
729 }
730 
731 } // namespace float128_detail
732 
733 template <class Archive>
serialize(Archive & ar,boost::multiprecision::backends::float128_backend & val,unsigned int)734 void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/)
735 {
736    typedef typename Archive::is_loading                                                                                                                            load_tag;
737    typedef typename mpl::bool_<boost::is_same<Archive, boost::archive::binary_oarchive>::value || boost::is_same<Archive, boost::archive::binary_iarchive>::value> binary_tag;
738 
739    float128_detail::do_serialize(ar, val, load_tag(), binary_tag());
740 }
741 
742 } // namespace serialization
743 
744 } // namespace boost
745 
746 namespace std {
747 
748 template <boost::multiprecision::expression_template_option ExpressionTemplates>
749 class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >
750 {
751    typedef boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> number_type;
752 
753  public:
754    BOOST_STATIC_CONSTEXPR bool is_specialized = true;
number_type(min)755    static BOOST_MP_CXX14_CONSTEXPR number_type(min)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MIN; }
number_type(max)756    static BOOST_MP_CXX14_CONSTEXPR number_type(max)() BOOST_NOEXCEPT { return BOOST_MP_QUAD_MAX; }
lowest()757    static BOOST_MP_CXX14_CONSTEXPR number_type          lowest() BOOST_NOEXCEPT { return -(max)(); }
758    BOOST_STATIC_CONSTEXPR int  digits       = 113;
759    BOOST_STATIC_CONSTEXPR int  digits10     = 33;
760    BOOST_STATIC_CONSTEXPR int  max_digits10 = 36;
761    BOOST_STATIC_CONSTEXPR bool is_signed    = true;
762    BOOST_STATIC_CONSTEXPR bool is_integer   = false;
763    BOOST_STATIC_CONSTEXPR bool is_exact     = false;
764    BOOST_STATIC_CONSTEXPR int  radix        = 2;
epsilon()765    static BOOST_MP_CXX14_CONSTEXPR number_type          epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
round_error()766    static BOOST_MP_CXX14_CONSTEXPR number_type          round_error() { return 0.5; }
767    BOOST_STATIC_CONSTEXPR int  min_exponent                  = -16381;
768    BOOST_STATIC_CONSTEXPR int  min_exponent10                = min_exponent * 301L / 1000L;
769    BOOST_STATIC_CONSTEXPR int  max_exponent                  = 16384;
770    BOOST_STATIC_CONSTEXPR int  max_exponent10                = max_exponent * 301L / 1000L;
771    BOOST_STATIC_CONSTEXPR bool has_infinity                  = true;
772    BOOST_STATIC_CONSTEXPR bool has_quiet_NaN                 = true;
773    BOOST_STATIC_CONSTEXPR bool has_signaling_NaN             = false;
774    BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm      = denorm_present;
775    BOOST_STATIC_CONSTEXPR bool               has_denorm_loss = true;
infinity()776    static BOOST_MP_CXX14_CONSTEXPR number_type                        infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
quiet_NaN()777    static BOOST_MP_CXX14_CONSTEXPR number_type                        quiet_NaN() { return number_type("nan"); }
signaling_NaN()778    static BOOST_MP_CXX14_CONSTEXPR number_type                        signaling_NaN() { return 0; }
denorm_min()779    static BOOST_MP_CXX14_CONSTEXPR number_type                        denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
780    BOOST_STATIC_CONSTEXPR bool               is_iec559       = true;
781    BOOST_STATIC_CONSTEXPR bool               is_bounded      = true;
782    BOOST_STATIC_CONSTEXPR bool               is_modulo       = false;
783    BOOST_STATIC_CONSTEXPR bool               traps           = false;
784    BOOST_STATIC_CONSTEXPR bool               tinyness_before = false;
785    BOOST_STATIC_CONSTEXPR float_round_style round_style      = round_to_nearest;
786 };
787 
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> >::is_specialized;
790 template <boost::multiprecision::expression_template_option ExpressionTemplates>
791 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits;
792 template <boost::multiprecision::expression_template_option ExpressionTemplates>
793 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits10;
794 template <boost::multiprecision::expression_template_option ExpressionTemplates>
795 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_digits10;
796 
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> >::is_signed;
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> >::is_integer;
801 template <boost::multiprecision::expression_template_option ExpressionTemplates>
802 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_exact;
803 template <boost::multiprecision::expression_template_option ExpressionTemplates>
804 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::radix;
805 
806 template <boost::multiprecision::expression_template_option ExpressionTemplates>
807 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent;
808 template <boost::multiprecision::expression_template_option ExpressionTemplates>
809 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent;
810 template <boost::multiprecision::expression_template_option ExpressionTemplates>
811 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent10;
812 template <boost::multiprecision::expression_template_option ExpressionTemplates>
813 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent10;
814 
815 template <boost::multiprecision::expression_template_option ExpressionTemplates>
816 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_infinity;
817 template <boost::multiprecision::expression_template_option ExpressionTemplates>
818 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_quiet_NaN;
819 template <boost::multiprecision::expression_template_option ExpressionTemplates>
820 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_signaling_NaN;
821 template <boost::multiprecision::expression_template_option ExpressionTemplates>
822 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm_loss;
823 
824 template <boost::multiprecision::expression_template_option ExpressionTemplates>
825 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_iec559;
826 template <boost::multiprecision::expression_template_option ExpressionTemplates>
827 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_bounded;
828 template <boost::multiprecision::expression_template_option ExpressionTemplates>
829 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_modulo;
830 template <boost::multiprecision::expression_template_option ExpressionTemplates>
831 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::traps;
832 template <boost::multiprecision::expression_template_option ExpressionTemplates>
833 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::tinyness_before;
834 
835 template <boost::multiprecision::expression_template_option ExpressionTemplates>
836 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::round_style;
837 template <boost::multiprecision::expression_template_option ExpressionTemplates>
838 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm;
839 
840 } // namespace std
841 
842 #endif
843