]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multiprecision/float128.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / multiprecision / float128.hpp
CommitLineData
7c673cae
FG
1///////////////////////////////////////////////////////////////
2// Copyright 2013 John Maddock. Distributed under the Boost
3// Software License, Version 1.0. (See accompanying file
92f5a8d4 4// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
7c673cae
FG
5
6#ifndef BOOST_MP_FLOAT128_HPP
7#define BOOST_MP_FLOAT128_HPP
8
1e59de90
TL
9// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
10#if !defined(__amd64__) && !defined(__amd64) && !defined(__x86_64__) && !defined(__x86_64) && !defined(_M_X64) && !defined(_M_AMD64) && \
11 !defined(i386) && !defined(__i386) && !defined(__i386__) && !defined(_M_IX86) && !defined(__X86__) && !defined(_X86_) && !defined(__I86__) && \
12 !defined(__ia64__) && !defined(_IA64) && !defined(__IA64__) && !defined(__ia64) && !defined(_M_IA64) && !defined(__itanium__) && \
13 !defined(__hppa__) && !defined(__HPPA__) && !defined(__hppa) && \
14 !defined(__powerpc) && !defined(_M_PPC) && !defined(_ARCH_PPC) && !defined(_ARCH_PPC64) && !defined(__PPCBROADWAY__)
15#error libquadmath only works on on i386, x86_64, IA-64, and hppa HP-UX, as well as on PowerPC GNU/Linux targets that enable the vector scalar (VSX) instruction set.
16#endif
17
18#include <tuple>
19#include <boost/multiprecision/detail/standalone_config.hpp>
7c673cae 20#include <boost/multiprecision/number.hpp>
1e59de90
TL
21#include <boost/multiprecision/detail/hash.hpp>
22#include <boost/multiprecision/detail/no_exceptions_support.hpp>
7c673cae
FG
23
24#if defined(BOOST_INTEL) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
92f5a8d4
TL
25#if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__)
26#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
27#define BOOST_MP_USE_FLOAT128
28#endif
29#endif
30
31#ifndef BOOST_MP_USE_FLOAT128
32#define BOOST_MP_USE_QUAD
33#endif
7c673cae
FG
34#endif
35
36#if defined(__GNUC__) && !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
92f5a8d4 37#define BOOST_MP_USE_FLOAT128
7c673cae
FG
38#endif
39
40#if !defined(BOOST_MP_USE_FLOAT128) && !defined(BOOST_MP_USE_QUAD)
92f5a8d4 41#error "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
7c673cae
FG
42#endif
43#if defined(BOOST_MP_USE_FLOAT128) && defined(BOOST_MP_USE_QUAD)
92f5a8d4 44#error "Oh dear, both BOOST_MP_USE_FLOAT128 and BOOST_MP_USE_QUAD are defined, which one should I be using?"
7c673cae
FG
45#endif
46
47#if defined(BOOST_MP_USE_FLOAT128)
48
49extern "C" {
50#include <quadmath.h>
51}
52
1e59de90 53using float128_type = __float128;
7c673cae
FG
54
55#elif defined(BOOST_MP_USE_QUAD)
56
57#include <boost/multiprecision/detail/float_string_cvt.hpp>
58
1e59de90 59using float128_type = _Quad;
7c673cae
FG
60
61extern "C" {
62_Quad __ldexpq(_Quad, int);
63_Quad __frexpq(_Quad, int*);
64_Quad __fabsq(_Quad);
65_Quad __floorq(_Quad);
66_Quad __ceilq(_Quad);
67_Quad __sqrtq(_Quad);
68_Quad __truncq(_Quad);
69_Quad __expq(_Quad);
70_Quad __powq(_Quad, _Quad);
71_Quad __logq(_Quad);
72_Quad __log10q(_Quad);
73_Quad __sinq(_Quad);
74_Quad __cosq(_Quad);
75_Quad __tanq(_Quad);
76_Quad __asinq(_Quad);
77_Quad __acosq(_Quad);
78_Quad __atanq(_Quad);
79_Quad __sinhq(_Quad);
80_Quad __coshq(_Quad);
81_Quad __tanhq(_Quad);
82_Quad __fmodq(_Quad, _Quad);
83_Quad __atan2q(_Quad, _Quad);
84
85#define ldexpq __ldexpq
86#define frexpq __frexpq
87#define fabsq __fabsq
88#define floorq __floorq
89#define ceilq __ceilq
90#define sqrtq __sqrtq
91#define truncq __truncq
92#define expq __expq
93#define powq __powq
94#define logq __logq
95#define log10q __log10q
96#define sinq __sinq
97#define cosq __cosq
98#define tanq __tanq
99#define asinq __asinq
100#define acosq __acosq
101#define atanq __atanq
102#define sinhq __sinhq
103#define coshq __coshq
104#define tanhq __tanhq
105#define fmodq __fmodq
106#define atan2q __atan2q
107}
108
109inline _Quad isnanq(_Quad v)
110{
111 return v != v;
112}
113inline _Quad isinfq(_Quad v)
114{
115 return __fabsq(v) > 1.18973149535723176508575932662800702e4932Q;
116}
117
118#endif
119
92f5a8d4
TL
120namespace boost {
121namespace multiprecision {
f67539c2
TL
122
123#ifndef BOOST_MP_BITS_OF_FLOAT128_DEFINED
124
125namespace detail {
126
127template <>
128struct bits_of<float128_type>
129{
1e59de90 130 static constexpr const unsigned value = 113;
f67539c2
TL
131};
132
133}
134
135#endif
136
92f5a8d4 137namespace backends {
7c673cae
FG
138
139struct float128_backend;
140
141}
142
143using backends::float128_backend;
144
92f5a8d4 145template <>
1e59de90 146struct number_category<backends::float128_backend> : public std::integral_constant<int, number_kind_floating_point>
92f5a8d4 147{};
b32b8144 148#if defined(BOOST_MP_USE_QUAD)
92f5a8d4 149template <>
1e59de90 150struct number_category<float128_type> : public std::integral_constant<int, number_kind_floating_point>
92f5a8d4 151{};
b32b8144 152#endif
7c673cae 153
1e59de90 154using float128 = number<float128_backend, et_off>;
92f5a8d4
TL
155
156namespace quad_constants {
1e59de90 157constexpr float128_type quad_min = static_cast<float128_type>(1) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) / 1073741824;
92f5a8d4 158
1e59de90 159constexpr float128_type quad_denorm_min = static_cast<float128_type>(1) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) * static_cast<float128_type>(DBL_MIN) / 5.5751862996326557854e+42;
92f5a8d4
TL
160
161constexpr double dbl_mult = 8.9884656743115795386e+307; // This has one bit set only.
1e59de90
TL
162constexpr float128_type quad_max = (static_cast<float128_type>(1) - 9.62964972193617926527988971292463659e-35) // This now has all bits sets to 1
163 * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * static_cast<float128_type>(dbl_mult) * 65536;
92f5a8d4
TL
164} // namespace quad_constants
165
166#define BOOST_MP_QUAD_MIN boost::multiprecision::quad_constants::quad_min
167#define BOOST_MP_QUAD_DENORM_MIN boost::multiprecision::quad_constants::quad_denorm_min
168#define BOOST_MP_QUAD_MAX boost::multiprecision::quad_constants::quad_max
169
92f5a8d4
TL
170
171namespace backends {
7c673cae
FG
172
173struct float128_backend
174{
1e59de90
TL
175 using signed_types = std::tuple<signed char, short, int, long, long long>;
176 using unsigned_types = std::tuple<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;
177 using float_types = std::tuple<float, double, long double>;
178 using exponent_type = int ;
7c673cae 179
92f5a8d4 180 private:
7c673cae 181 float128_type m_value;
92f5a8d4
TL
182
183 public:
1e59de90
TL
184 constexpr float128_backend() noexcept : m_value(0) {}
185 constexpr float128_backend(const float128_backend& o) noexcept : m_value(o.m_value) {}
186 BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(const float128_backend& o) noexcept
7c673cae
FG
187 {
188 m_value = o.m_value;
189 return *this;
190 }
191 template <class T>
1e59de90 192 constexpr float128_backend(const T& i, const typename std::enable_if<std::is_convertible<T, float128_type>::value>::type* = 0) noexcept(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
92f5a8d4 193 : m_value(i) {}
7c673cae 194 template <class T>
1e59de90 195 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_convertible<T, float128_type>::value, float128_backend&>::type operator=(const T& i) noexcept(noexcept(std::declval<float128_type&>() = std::declval<const T&>()))
7c673cae
FG
196 {
197 m_value = i;
198 return *this;
199 }
92f5a8d4 200 BOOST_MP_CXX14_CONSTEXPR float128_backend(long double const& f) : m_value(f)
7c673cae 201 {
92f5a8d4 202 if (::fabsl(f) > LDBL_MAX)
1e59de90 203 m_value = (f < 0) ? -static_cast<float128_type>(HUGE_VAL) : static_cast<float128_type>(HUGE_VAL);
7c673cae 204 }
92f5a8d4 205 BOOST_MP_CXX14_CONSTEXPR float128_backend& operator=(long double const& f)
7c673cae 206 {
92f5a8d4 207 if (f > LDBL_MAX)
1e59de90 208 m_value = static_cast<float128_type>(HUGE_VAL);
92f5a8d4 209 else if (-f > LDBL_MAX)
1e59de90 210 m_value = -static_cast<float128_type>(HUGE_VAL);
7c673cae
FG
211 else
212 m_value = f;
213 return *this;
214 }
92f5a8d4 215 float128_backend& operator=(const char* s)
7c673cae
FG
216 {
217#ifndef BOOST_MP_USE_QUAD
218 char* p_end;
219 m_value = strtoflt128(s, &p_end);
92f5a8d4 220 if (p_end - s != (std::ptrdiff_t)std::strlen(s))
7c673cae 221 {
1e59de90 222 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unable to interpret input string as a floating point value"));
7c673cae
FG
223 }
224#else
225 boost::multiprecision::detail::convert_from_string(*this, s);
226#endif
227 return *this;
228 }
1e59de90 229 BOOST_MP_CXX14_CONSTEXPR void swap(float128_backend& o) noexcept
7c673cae 230 {
92f5a8d4
TL
231 // We don't call std::swap here because it's no constexpr (yet):
232 float128_type t(o.value());
233 o.value() = m_value;
234 m_value = t;
7c673cae 235 }
92f5a8d4 236 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
7c673cae
FG
237 {
238#ifndef BOOST_MP_USE_QUAD
92f5a8d4 239 char buf[128];
7c673cae 240 std::string format = "%";
92f5a8d4 241 if (f & std::ios_base::showpos)
7c673cae 242 format += "+";
92f5a8d4 243 if (f & std::ios_base::showpoint)
7c673cae
FG
244 format += "#";
245 format += ".*";
1e59de90 246 if ((digits == 0) && !(f & std::ios_base::fixed))
7c673cae
FG
247 digits = 36;
248 format += "Q";
92f5a8d4
TL
249
250 if (f & std::ios_base::scientific)
7c673cae 251 format += "e";
92f5a8d4 252 else if (f & std::ios_base::fixed)
7c673cae
FG
253 format += "f";
254 else
255 format += "g";
256
92f5a8d4
TL
257 int v;
258 if ((f & std::ios_base::scientific) && (f & std::ios_base::fixed))
259 {
260 v = quadmath_snprintf(buf, sizeof buf, "%Qa", m_value);
261 }
262 else
263 {
264 v = quadmath_snprintf(buf, sizeof buf, format.c_str(), digits, m_value);
265 }
7c673cae 266
92f5a8d4 267 if ((v < 0) || (v >= 127))
7c673cae 268 {
92f5a8d4 269 int v_max = v;
1e59de90 270 std::unique_ptr<char[]> buf2;
92f5a8d4
TL
271 buf2.reset(new char[v + 3]);
272 v = quadmath_snprintf(&buf2[0], v_max + 3, format.c_str(), digits, m_value);
273 if (v >= v_max + 3)
7c673cae 274 {
1e59de90 275 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Formatting of float128_type failed."));
7c673cae
FG
276 }
277 return &buf2[0];
278 }
279 return buf;
280#else
1e59de90 281 return boost::multiprecision::detail::convert_to_string(*this, digits ? digits : 36, f);
7c673cae
FG
282#endif
283 }
1e59de90 284 BOOST_MP_CXX14_CONSTEXPR void negate() noexcept
7c673cae
FG
285 {
286 m_value = -m_value;
287 }
92f5a8d4 288 BOOST_MP_CXX14_CONSTEXPR int compare(const float128_backend& o) const
7c673cae
FG
289 {
290 return m_value == o.m_value ? 0 : m_value < o.m_value ? -1 : 1;
291 }
292 template <class T>
92f5a8d4 293 BOOST_MP_CXX14_CONSTEXPR int compare(const T& i) const
7c673cae
FG
294 {
295 return m_value == i ? 0 : m_value < i ? -1 : 1;
296 }
92f5a8d4 297 BOOST_MP_CXX14_CONSTEXPR float128_type& value()
7c673cae
FG
298 {
299 return m_value;
300 }
92f5a8d4 301 BOOST_MP_CXX14_CONSTEXPR const float128_type& value() const
7c673cae
FG
302 {
303 return m_value;
304 }
305};
306
92f5a8d4 307inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a)
7c673cae
FG
308{
309 result.value() += a.value();
310}
311template <class A>
92f5a8d4 312inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const A& a)
7c673cae
FG
313{
314 result.value() += a;
315}
92f5a8d4 316inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a)
7c673cae
FG
317{
318 result.value() -= a.value();
319}
320template <class A>
92f5a8d4 321inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a)
7c673cae
FG
322{
323 result.value() -= a;
324}
92f5a8d4 325inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a)
7c673cae
FG
326{
327 result.value() *= a.value();
328}
329template <class A>
92f5a8d4 330inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const A& a)
7c673cae
FG
331{
332 result.value() *= a;
333}
92f5a8d4 334inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a)
7c673cae
FG
335{
336 result.value() /= a.value();
337}
338template <class A>
92f5a8d4 339inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const A& a)
7c673cae
FG
340{
341 result.value() /= a;
342}
343
92f5a8d4 344inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const float128_backend& b)
7c673cae
FG
345{
346 result.value() = a.value() + b.value();
347}
348template <class A>
92f5a8d4 349inline BOOST_MP_CXX14_CONSTEXPR void eval_add(float128_backend& result, const float128_backend& a, const A& b)
7c673cae
FG
350{
351 result.value() = a.value() + b;
352}
92f5a8d4 353inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const float128_backend& b)
7c673cae
FG
354{
355 result.value() = a.value() - b.value();
356}
357template <class A>
92f5a8d4 358inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const float128_backend& a, const A& b)
7c673cae
FG
359{
360 result.value() = a.value() - b;
361}
362template <class A>
92f5a8d4 363inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(float128_backend& result, const A& a, const float128_backend& b)
7c673cae
FG
364{
365 result.value() = a - b.value();
366}
92f5a8d4 367inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const float128_backend& b)
7c673cae
FG
368{
369 result.value() = a.value() * b.value();
370}
371template <class A>
92f5a8d4 372inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(float128_backend& result, const float128_backend& a, const A& b)
7c673cae
FG
373{
374 result.value() = a.value() * b;
375}
92f5a8d4 376inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(float128_backend& result, const float128_backend& a, const float128_backend& b)
7c673cae
FG
377{
378 result.value() = a.value() / b.value();
379}
380
381template <class R>
92f5a8d4 382inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(R* result, const float128_backend& val)
7c673cae
FG
383{
384 *result = static_cast<R>(val.value());
385}
386
387inline void eval_frexp(float128_backend& result, const float128_backend& arg, int* exp)
388{
389 result.value() = frexpq(arg.value(), exp);
390}
391
392inline void eval_ldexp(float128_backend& result, const float128_backend& arg, int exp)
393{
394 result.value() = ldexpq(arg.value(), exp);
395}
396
397inline void eval_floor(float128_backend& result, const float128_backend& arg)
398{
399 result.value() = floorq(arg.value());
400}
401inline void eval_ceil(float128_backend& result, const float128_backend& arg)
402{
403 result.value() = ceilq(arg.value());
404}
405inline void eval_sqrt(float128_backend& result, const float128_backend& arg)
406{
407 result.value() = sqrtq(arg.value());
408}
1e59de90 409
20effc67
TL
410inline void eval_rsqrt(float128_backend& result, const float128_backend& arg)
411{
1e59de90
TL
412#if (LDBL_MANT_DIG > 100)
413 // GCC can't mix and match __float128 and quad precision long double
414 // error: __float128 and long double cannot be used in the same expression
415 result.value() = 1 / sqrtq(arg.value());
416#else
20effc67
TL
417 using std::sqrt;
418 if (arg.value() < std::numeric_limits<long double>::denorm_min() || arg.value() > (std::numeric_limits<long double>::max)()) {
419 result.value() = 1/sqrtq(arg.value());
420 return;
421 }
422 float128_backend xk = 1/sqrt(static_cast<long double>(arg.value()));
423
424 // Newton iteration for f(x) = arg.value() - 1/x^2.
425 BOOST_IF_CONSTEXPR (sizeof(long double) == sizeof(double)) {
426 // If the long double is the same as a double, then we need two Newton iterations:
427 xk.value() = xk.value() + xk.value()*(1-arg.value()*xk.value()*xk.value())/2;
428 result.value() = xk.value() + xk.value()*(1-arg.value()*xk.value()*xk.value())/2;
20effc67 429 }
1e59de90
TL
430 else
431 {
432 // 80 bit long double only needs a single iteration to produce ~2ULPs.
433 result.value() = xk.value() + xk.value() * (1 - arg.value() * xk.value() * xk.value()) / 2;
434 }
435#endif
20effc67 436}
92f5a8d4
TL
437#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
438inline BOOST_MP_CXX14_CONSTEXPR
439#else
440inline
441#endif
442int eval_fpclassify(const float128_backend& arg)
7c673cae 443{
92f5a8d4
TL
444 float128_type v = arg.value();
445#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
446 if (BOOST_MP_IS_CONST_EVALUATED(v))
447 {
448 if (v != v)
449 return FP_NAN;
450 if (v == 0)
451 return FP_ZERO;
452 float128_type t(v);
453 if (t < 0)
454 t = -t;
455 if (t > BOOST_MP_QUAD_MAX)
456 return FP_INFINITE;
457 if (t < BOOST_MP_QUAD_MIN)
458 return FP_SUBNORMAL;
459 return FP_NORMAL;
460 }
461 else
462#endif
463 {
464 if (isnanq(v))
465 return FP_NAN;
466 else if (isinfq(v))
467 return FP_INFINITE;
468 else if (v == 0)
469 return FP_ZERO;
470
471 float128_backend t(arg);
472 if (t.value() < 0)
473 t.negate();
474 if (t.value() < BOOST_MP_QUAD_MIN)
475 return FP_SUBNORMAL;
476 return FP_NORMAL;
477 }
7c673cae 478}
92f5a8d4
TL
479#if defined(BOOST_GCC) && (__GNUC__ == 9)
480// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91705
481inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
482{
483 arg.value() = 1 + arg.value();
484}
485inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
486{
487 arg.value() = arg.value() - 1;
488}
489#else
490inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(float128_backend& arg)
7c673cae
FG
491{
492 ++arg.value();
493}
92f5a8d4 494inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(float128_backend& arg)
7c673cae
FG
495{
496 --arg.value();
497}
92f5a8d4 498#endif
7c673cae
FG
499
500/*********************************************************************
501*
502* abs/fabs:
503*
504*********************************************************************/
505
92f5a8d4
TL
506#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
507inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(float128_backend& result, const float128_backend& arg)
508#else
7c673cae 509inline void eval_abs(float128_backend& result, const float128_backend& arg)
92f5a8d4 510#endif
7c673cae 511{
92f5a8d4 512#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1e59de90 513 float128_type v(arg.value());
92f5a8d4
TL
514 if (BOOST_MP_IS_CONST_EVALUATED(v))
515 {
516 result.value() = v < 0 ? -v : v;
517 }
518 else
519#endif
520 {
521 result.value() = fabsq(arg.value());
522 }
7c673cae 523}
92f5a8d4
TL
524#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
525inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(float128_backend& result, const float128_backend& arg)
526#else
7c673cae 527inline void eval_fabs(float128_backend& result, const float128_backend& arg)
92f5a8d4 528#endif
7c673cae 529{
92f5a8d4 530#ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1e59de90 531 float128_type v(arg.value());
92f5a8d4
TL
532 if (BOOST_MP_IS_CONST_EVALUATED(v))
533 {
534 result.value() = v < 0 ? -v : v;
535 }
536 else
537#endif
538 {
539 result.value() = fabsq(arg.value());
540 }
7c673cae
FG
541}
542
543/*********************************************************************
544*
545* Floating point functions:
546*
547*********************************************************************/
548
549inline void eval_trunc(float128_backend& result, const float128_backend& arg)
550{
7c673cae
FG
551 result.value() = truncq(arg.value());
552}
553/*
554//
555// This doesn't actually work... rely on our own default version instead.
556//
557inline void eval_round(float128_backend& result, const float128_backend& arg)
558{
559 if(isnanq(arg.value()) || isinf(arg.value()))
560 {
561 result = boost::math::policies::raise_rounding_error(
562 "boost::multiprecision::trunc<%1%>(%1%)", 0,
563 number<float128_backend, et_off>(arg),
564 number<float128_backend, et_off>(arg),
565 boost::math::policies::policy<>()).backend();
566 return;
567 }
568 result.value() = roundq(arg.value());
569}
570*/
571
572inline void eval_exp(float128_backend& result, const float128_backend& arg)
573{
574 result.value() = expq(arg.value());
575}
576inline void eval_log(float128_backend& result, const float128_backend& arg)
577{
578 result.value() = logq(arg.value());
579}
580inline void eval_log10(float128_backend& result, const float128_backend& arg)
581{
582 result.value() = log10q(arg.value());
583}
584inline void eval_sin(float128_backend& result, const float128_backend& arg)
585{
586 result.value() = sinq(arg.value());
587}
588inline void eval_cos(float128_backend& result, const float128_backend& arg)
589{
590 result.value() = cosq(arg.value());
591}
592inline void eval_tan(float128_backend& result, const float128_backend& arg)
593{
594 result.value() = tanq(arg.value());
595}
596inline void eval_asin(float128_backend& result, const float128_backend& arg)
597{
598 result.value() = asinq(arg.value());
599}
600inline void eval_acos(float128_backend& result, const float128_backend& arg)
601{
602 result.value() = acosq(arg.value());
603}
604inline void eval_atan(float128_backend& result, const float128_backend& arg)
605{
606 result.value() = atanq(arg.value());
607}
608inline void eval_sinh(float128_backend& result, const float128_backend& arg)
609{
610 result.value() = sinhq(arg.value());
611}
612inline void eval_cosh(float128_backend& result, const float128_backend& arg)
613{
614 result.value() = coshq(arg.value());
615}
616inline void eval_tanh(float128_backend& result, const float128_backend& arg)
617{
618 result.value() = tanhq(arg.value());
619}
620inline void eval_fmod(float128_backend& result, const float128_backend& a, const float128_backend& b)
621{
622 result.value() = fmodq(a.value(), b.value());
623}
624inline void eval_pow(float128_backend& result, const float128_backend& a, const float128_backend& b)
625{
626 result.value() = powq(a.value(), b.value());
627}
628inline void eval_atan2(float128_backend& result, const float128_backend& a, const float128_backend& b)
629{
630 result.value() = atan2q(a.value(), b.value());
631}
92f5a8d4 632#ifndef BOOST_MP_USE_QUAD
7c673cae
FG
633inline void eval_multiply_add(float128_backend& result, const float128_backend& a, const float128_backend& b, const float128_backend& c)
634{
635 result.value() = fmaq(a.value(), b.value(), c.value());
636}
b32b8144
FG
637inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& arg)
638{
639 return ::signbitq(arg.value());
640}
92f5a8d4 641#endif
b32b8144 642
7c673cae
FG
643inline std::size_t hash_value(const float128_backend& val)
644{
1e59de90 645 return boost::multiprecision::detail::hash_value(static_cast<double>(val.value()));
7c673cae
FG
646}
647
648} // namespace backends
649
92f5a8d4
TL
650template <boost::multiprecision::expression_template_option ExpressionTemplates>
651inline boost::multiprecision::number<float128_backend, ExpressionTemplates> asinh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
652{
653 return asinhq(arg.backend().value());
654}
655template <boost::multiprecision::expression_template_option ExpressionTemplates>
656inline boost::multiprecision::number<float128_backend, ExpressionTemplates> acosh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
657{
658 return acoshq(arg.backend().value());
659}
660template <boost::multiprecision::expression_template_option ExpressionTemplates>
661inline boost::multiprecision::number<float128_backend, ExpressionTemplates> atanh BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
662{
663 return atanhq(arg.backend().value());
664}
665template <boost::multiprecision::expression_template_option ExpressionTemplates>
666inline boost::multiprecision::number<float128_backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
667{
668 return cbrtq(arg.backend().value());
669}
670template <boost::multiprecision::expression_template_option ExpressionTemplates>
671inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
672{
673 return erfq(arg.backend().value());
674}
675template <boost::multiprecision::expression_template_option ExpressionTemplates>
676inline boost::multiprecision::number<float128_backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
677{
678 return erfcq(arg.backend().value());
679}
680template <boost::multiprecision::expression_template_option ExpressionTemplates>
681inline boost::multiprecision::number<float128_backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
682{
683 return expm1q(arg.backend().value());
684}
685template <boost::multiprecision::expression_template_option ExpressionTemplates>
686inline boost::multiprecision::number<float128_backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
687{
688 return lgammaq(arg.backend().value());
689}
690template <boost::multiprecision::expression_template_option ExpressionTemplates>
691inline boost::multiprecision::number<float128_backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
692{
f67539c2
TL
693 if(eval_signbit(arg.backend()) != 0)
694 {
695 const bool result_is_neg = ((static_cast<unsigned long long>(floorq(-arg.backend().value())) % 2U) == 0U);
696
697 const boost::multiprecision::number<float128_backend, ExpressionTemplates> result_of_tgammaq = fabsq(tgammaq(arg.backend().value()));
698
699 return ((result_is_neg == false) ? result_of_tgammaq : -result_of_tgammaq);
700 }
701 else
702 {
703 return tgammaq(arg.backend().value());
704 }
92f5a8d4
TL
705}
706template <boost::multiprecision::expression_template_option ExpressionTemplates>
707inline boost::multiprecision::number<float128_backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
708{
709 return log1pq(arg.backend().value());
710}
20effc67
TL
711template <boost::multiprecision::expression_template_option ExpressionTemplates>
712inline boost::multiprecision::number<float128_backend, ExpressionTemplates> rsqrt BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<float128_backend, ExpressionTemplates>& arg)
713{
714 boost::multiprecision::number<float128_backend, ExpressionTemplates> res;
715 eval_rsqrt(res.backend(), arg.backend());
716 return res;
717}
7c673cae 718
92f5a8d4
TL
719#ifndef BOOST_MP_USE_QUAD
720template <multiprecision::expression_template_option ExpressionTemplates>
721inline 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)
722{
723 return ::copysignq(a.backend().value(), b.backend().value());
724}
7c673cae 725
1e59de90
TL
726namespace backends {
727
92f5a8d4
TL
728inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
729{
730 result.value() = remainderq(a.value(), b.value());
731}
732inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b, int* pi)
733{
734 result.value() = remquoq(a.value(), b.value(), pi);
735}
1e59de90
TL
736} // namespace backends
737
92f5a8d4 738#endif
7c673cae
FG
739
740} // namespace multiprecision
741
742namespace math {
743
92f5a8d4
TL
744using boost::multiprecision::copysign;
745using boost::multiprecision::signbit;
7c673cae
FG
746
747} // namespace math
748
749} // namespace boost
750
1e59de90 751#ifndef BOOST_MP_STANDALONE
92f5a8d4
TL
752namespace boost {
753namespace archive {
7c673cae
FG
754
755class binary_oarchive;
756class binary_iarchive;
757
92f5a8d4
TL
758} // namespace archive
759
760namespace serialization {
761namespace float128_detail {
7c673cae
FG
762
763template <class Archive>
1e59de90 764void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, false>&)
7c673cae
FG
765{
766 // saving
767 // non-binary
768 std::string s(val.str(0, std::ios_base::scientific));
92f5a8d4 769 ar& boost::make_nvp("value", s);
7c673cae
FG
770}
771template <class Archive>
1e59de90 772void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, false>&)
7c673cae
FG
773{
774 // loading
775 // non-binary
776 std::string s;
92f5a8d4 777 ar& boost::make_nvp("value", s);
7c673cae
FG
778 val = s.c_str();
779}
780
781template <class Archive>
1e59de90 782void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, false>&, const std::integral_constant<bool, true>&)
7c673cae
FG
783{
784 // saving
785 // binary
786 ar.save_binary(&val, sizeof(val));
787}
788template <class Archive>
1e59de90 789void do_serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, const std::integral_constant<bool, true>&, const std::integral_constant<bool, true>&)
7c673cae
FG
790{
791 // loading
792 // binary
793 ar.load_binary(&val, sizeof(val));
794}
795
92f5a8d4 796} // namespace float128_detail
7c673cae
FG
797
798template <class Archive>
799void serialize(Archive& ar, boost::multiprecision::backends::float128_backend& val, unsigned int /*version*/)
800{
1e59de90
TL
801 using load_tag = typename Archive::is_loading ;
802 using loading = std::integral_constant<bool, load_tag::value> ;
803 using binary_tag = typename std::integral_constant<bool, std::is_same<Archive, boost::archive::binary_oarchive>::value || std::is_same<Archive, boost::archive::binary_iarchive>::value>;
7c673cae 804
1e59de90 805 float128_detail::do_serialize(ar, val, loading(), binary_tag());
7c673cae
FG
806}
807
92f5a8d4 808} // namespace serialization
7c673cae
FG
809
810} // namespace boost
1e59de90 811#endif // BOOST_MP_STANDALONE
7c673cae 812
92f5a8d4 813namespace std {
7c673cae
FG
814
815template <boost::multiprecision::expression_template_option ExpressionTemplates>
816class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >
817{
1e59de90 818 using number_type = boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates>;
92f5a8d4
TL
819
820 public:
1e59de90
TL
821 static constexpr bool is_specialized = true;
822 static BOOST_MP_CXX14_CONSTEXPR number_type(min)() noexcept { return BOOST_MP_QUAD_MIN; }
823 static BOOST_MP_CXX14_CONSTEXPR number_type(max)() noexcept { return BOOST_MP_QUAD_MAX; }
824 static BOOST_MP_CXX14_CONSTEXPR number_type lowest() noexcept { return -(max)(); }
825 static constexpr int digits = 113;
826 static constexpr int digits10 = 33;
827 static constexpr int max_digits10 = 36;
828 static constexpr bool is_signed = true;
829 static constexpr bool is_integer = false;
830 static constexpr bool is_exact = false;
831 static constexpr int radix = 2;
92f5a8d4
TL
832 static BOOST_MP_CXX14_CONSTEXPR number_type epsilon() { return 1.92592994438723585305597794258492732e-34; /* this double value has only one bit set and so is exact */ }
833 static BOOST_MP_CXX14_CONSTEXPR number_type round_error() { return 0.5; }
1e59de90
TL
834 static constexpr int min_exponent = -16381;
835 static constexpr int min_exponent10 = min_exponent * 301L / 1000L;
836 static constexpr int max_exponent = 16384;
837 static constexpr int max_exponent10 = max_exponent * 301L / 1000L;
838 static constexpr bool has_infinity = true;
839 static constexpr bool has_quiet_NaN = true;
840 static constexpr bool has_signaling_NaN = false;
841 static constexpr float_denorm_style has_denorm = denorm_present;
842 static constexpr bool has_denorm_loss = true;
92f5a8d4 843 static BOOST_MP_CXX14_CONSTEXPR number_type infinity() { return HUGE_VAL; /* conversion from double infinity OK */ }
1e59de90 844 static BOOST_MP_CXX14_CONSTEXPR number_type quiet_NaN() { return number_type(NAN); }
92f5a8d4
TL
845 static BOOST_MP_CXX14_CONSTEXPR number_type signaling_NaN() { return 0; }
846 static BOOST_MP_CXX14_CONSTEXPR number_type denorm_min() { return BOOST_MP_QUAD_DENORM_MIN; }
1e59de90
TL
847 static constexpr bool is_iec559 = true;
848 static constexpr bool is_bounded = true;
849 static constexpr bool is_modulo = false;
850 static constexpr bool traps = false;
851 static constexpr bool tinyness_before = false;
852 static constexpr float_round_style round_style = round_to_nearest;
7c673cae
FG
853};
854
855template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 856constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_specialized;
7c673cae 857template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 858constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits;
7c673cae 859template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 860constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::digits10;
7c673cae 861template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 862constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_digits10;
7c673cae
FG
863
864template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 865constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_signed;
7c673cae 866template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 867constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_integer;
7c673cae 868template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 869constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_exact;
7c673cae 870template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 871constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::radix;
7c673cae 872
7c673cae 873template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 874constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent;
7c673cae 875template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 876constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent;
7c673cae 877template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 878constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::min_exponent10;
7c673cae 879template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 880constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::max_exponent10;
7c673cae
FG
881
882template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 883constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_infinity;
7c673cae 884template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 885constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_quiet_NaN;
7c673cae 886template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 887constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_signaling_NaN;
7c673cae 888template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 889constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm_loss;
7c673cae
FG
890
891template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 892constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_iec559;
7c673cae 893template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 894constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_bounded;
7c673cae 895template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 896constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::is_modulo;
7c673cae 897template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 898constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::traps;
7c673cae 899template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 900constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::tinyness_before;
7c673cae
FG
901
902template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 903constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::round_style;
7c673cae 904template <boost::multiprecision::expression_template_option ExpressionTemplates>
1e59de90 905constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::float128_backend, ExpressionTemplates> >::has_denorm;
7c673cae
FG
906
907} // namespace std
908
7c673cae 909#endif