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