3 #ifndef DUNE_QUADMATH_HH
4 #define DUNE_QUADMATH_HH
15 #include <type_traits>
36 using float128_t = __float128;
41 float128_t value_ = 0.0q;
44 constexpr Float128() =
default;
45 constexpr Float128(
const float128_t& value) noexcept
51 std::enable_if_t<std::is_arithmetic<T>::value,
int> = 0>
52 constexpr Float128(
const T& value) noexcept
57 explicit Float128(
const char* str) noexcept
58 : value_(strtoflt128(str, NULL))
62 constexpr
operator float128_t() const noexcept {
return value_; }
64 constexpr float128_t
const& value() const noexcept {
return value_; }
65 constexpr float128_t& value() noexcept {
return value_; }
68 template<
class CharT,
class Traits>
69 friend std::basic_istream<CharT, Traits>&
70 operator>>(std::basic_istream<CharT, Traits>& in, Float128& x)
75 x.value() = strtoflt128(buf.c_str(), NULL);
79 template<
class CharT,
class Traits>
80 friend std::basic_ostream<CharT, Traits>&
81 operator<<(std::basic_ostream<CharT, Traits>& out,
const Float128& x)
83 const std::size_t bufSize = 128;
86 std::string format =
"%." + std::to_string(out.precision()) +
"Q" +
87 ((out.flags() | std::ios_base::scientific) ?
"e" :
"f");
88 const int numChars = quadmath_snprintf(buf, bufSize, format.c_str(), x.value());
89 if (std::size_t(numChars) >= bufSize) {
97 constexpr Float128& operator++() noexcept { ++value_;
return *
this; }
98 constexpr Float128& operator--() noexcept { --value_;
return *
this; }
100 constexpr Float128 operator++(
int) noexcept { Float128 tmp{*
this}; ++value_;
return tmp; }
101 constexpr Float128 operator--(
int) noexcept { Float128 tmp{*
this}; --value_;
return tmp; }
104 constexpr Float128
operator+() const noexcept {
return Float128{+value_}; }
105 constexpr Float128
operator-() const noexcept {
return Float128{-value_}; }
108 #define DUNE_ASSIGN_OP(OP) \
109 constexpr Float128& operator OP(const Float128& u) noexcept \
111 value_ OP float128_t(u); \
114 static_assert(true, "Require semicolon to unconfuse editors")
122 #undef DUNE_ASSIGN_OP
129 #define DUNE_BINARY_OP(OP) \
130 constexpr Float128 operator OP(const Float128& t, \
131 const Float128& u) noexcept \
133 return Float128{float128_t(t) OP float128_t(u)}; \
136 std::enable_if_t<std::is_arithmetic<T>::value, int> = 0> \
137 constexpr Float128 operator OP(const T& t, \
138 const Float128& u) noexcept \
140 return Float128{float128_t(t) OP float128_t(u)}; \
143 std::enable_if_t<std::is_arithmetic<U>::value, int> = 0> \
144 constexpr Float128 operator OP(const Float128& t, \
145 const U& u) noexcept \
147 return Float128{float128_t(t) OP float128_t(u)}; \
149 static_assert(true, "Require semicolon to unconfuse editors")
156 #undef DUNE_BINARY_OP
161 #define DUNE_BINARY_BOOL_OP(OP) \
162 constexpr bool operator OP(const Float128& t, \
163 const Float128& u) noexcept \
165 return float128_t(t) OP float128_t(u); \
168 std::enable_if_t<std::is_arithmetic<T>::value, int> = 0> \
169 constexpr bool operator OP(const T& t, \
170 const Float128& u) noexcept \
172 return float128_t(t) OP float128_t(u); \
175 std::enable_if_t<std::is_arithmetic<U>::value, int> = 0> \
176 constexpr bool operator OP(const Float128& t, \
177 const U& u) noexcept \
179 return float128_t(t) OP float128_t(u); \
181 static_assert(true, "Require semicolon to unconfuse editors")
183 DUNE_BINARY_BOOL_OP(==);
184 DUNE_BINARY_BOOL_OP(!=);
185 DUNE_BINARY_BOOL_OP(<);
186 DUNE_BINARY_BOOL_OP(>);
187 DUNE_BINARY_BOOL_OP(<=);
188 DUNE_BINARY_BOOL_OP(>=);
190 #undef DUNE_BINARY_BOOL_OP
195 #define DUNE_UNARY_FUNC(name,func) \
196 inline Float128 name(const Float128& u) noexcept \
198 return Float128{func (float128_t(u))}; \
200 static_assert(true, "Require semicolon to unconfuse editors")
203 #define DUNE_CUSTOM_UNARY_FUNC(type,name,func) \
204 inline type name(const Float128& u) noexcept \
206 return (type)(func (float128_t(u))); \
208 static_assert(true, "Require semicolon to unconfuse editors")
211 #define DUNE_BINARY_FUNC(name,func) \
212 inline Float128 name(const Float128& t, \
213 const Float128& u) noexcept \
215 return Float128{func (float128_t(t), float128_t(u))}; \
217 static_assert(true, "Require semicolon to unconfuse editors")
236 DUNE_CUSTOM_UNARY_FUNC(
int, ilogb, ilogbq);
238 DUNE_CUSTOM_UNARY_FUNC(
long long int, llrint, llrintq);
239 DUNE_CUSTOM_UNARY_FUNC(
long long int, llround, llroundq);
245 DUNE_CUSTOM_UNARY_FUNC(
long int, lrint, lrintq);
246 DUNE_CUSTOM_UNARY_FUNC(
long int, lround, lroundq);
248 DUNE_BINARY_FUNC(nextafter, nextafterq);
249 DUNE_BINARY_FUNC(pow, powq);
260 DUNE_CUSTOM_UNARY_FUNC(
bool, isfinite, finiteq);
261 DUNE_CUSTOM_UNARY_FUNC(
bool, isinf, isinfq);
262 DUNE_CUSTOM_UNARY_FUNC(
bool, isnan, isnanq);
263 DUNE_CUSTOM_UNARY_FUNC(
bool, signbit, signbitq);
265 #undef DUNE_UNARY_FUNC
266 #undef DUNE_CUSTOM_UNARY_FUNC
267 #undef DUNE_BINARY_FUNC
271 #define DUNE_BINARY_ARITHMETIC_FUNC(name,func) \
272 inline Float128 name(const Float128& t, \
273 const Float128& u) noexcept \
275 return Float128{func (float128_t(t), float128_t(u))}; \
278 std::enable_if_t<std::is_arithmetic<T>::value, int> = 0> \
279 inline Float128 name(const T& t, \
280 const Float128& u) noexcept \
282 return Float128{func (float128_t(t), float128_t(u))}; \
285 std::enable_if_t<std::is_arithmetic<U>::value, int> = 0> \
286 inline Float128 name(const Float128& t, \
287 const U& u) noexcept \
289 return Float128{func (float128_t(t), float128_t(u))}; \
291 static_assert(true, "Require semicolon to unconfuse editors")
293 DUNE_BINARY_ARITHMETIC_FUNC(atan2,atan2q);
294 DUNE_BINARY_ARITHMETIC_FUNC(copysign,copysignq);
295 DUNE_BINARY_ARITHMETIC_FUNC(fdim,fdimq);
296 DUNE_BINARY_ARITHMETIC_FUNC(fmax,fmaxq);
297 DUNE_BINARY_ARITHMETIC_FUNC(fmin,fminq);
298 DUNE_BINARY_ARITHMETIC_FUNC(fmod,fmodq);
299 DUNE_BINARY_ARITHMETIC_FUNC(hypot,hypotq);
300 DUNE_BINARY_ARITHMETIC_FUNC(remainder,remainderq);
302 #undef DUNE_BINARY_ARITHMETIC_FUNC
306 inline Float128 fma(
const Float128& t,
const Float128& u,
const Float128& v)
308 return Float128{fmaq(float128_t(t),float128_t(u),float128_t(v))};
311 inline Float128 frexp(
const Float128& u,
int* p)
313 return Float128{frexpq(float128_t(u), p)};
316 inline Float128 ldexp(
const Float128& u,
int p)
318 return Float128{ldexpq(float128_t(u), p)};
321 inline Float128 remquo(
const Float128& t,
const Float128& u,
int* quo)
323 return Float128{remquoq(float128_t(t), float128_t(u), quo)};
326 inline Float128 scalbln(
const Float128& u,
long int e)
328 return Float128{scalblnq(float128_t(u), e)};
331 inline Float128 scalbn(
const Float128& u,
int e)
333 return Float128{scalbnq(float128_t(u), e)};
344 std::enable_if_t<std::is_integral<Int>::value,
int> = 0>
345 inline Float128 pow(
const Float128& x,
const Int p)
347 static const Float128
max_value = FLT128_MAX;
348 static const Float128
min_value = FLT128_MIN;
349 static const Float128 inf_value = float128_t{1} / float128_t{0};
351 const bool isneg = (x < 0);
352 const bool isnan = (x != x);
355 if (isnan) {
return x; }
356 if (isinf) {
return Float128{nanq(
"")}; }
358 const Float128 abs_x = (isneg ? -x : x);
361 return (isneg ? -inf_value : +inf_value);
363 return Float128(1) / pow(x, Int(-p));
366 if (p == Int(0)) {
return Float128(1); }
367 if (p == Int(1)) {
return x; }
369 return (isneg ? -inf_value : +inf_value);
371 if (p == Int(2)) {
return (x * x); }
372 if (p == Int(3)) {
return ((x * x) * x); }
373 if (p == Int(4)) {
const Float128 x2 = (x * x);
return (x2 * x2); }
375 Float128 result = ((p % Int(2)) != Int(0)) ? x : Float128(1);
379 while (Int(p2 /= 2) != Int(0)) {
382 const bool has_binary_power = (Int(p2 % Int(2)) != Int(0));
383 if (has_binary_power)
394 struct IsNumber<Impl::Float128>
395 :
public std::true_type {};
401 #ifndef NO_STD_NUMERIC_LIMITS_SPECIALIZATION
403 class numeric_limits<
Dune::Impl::Float128>
405 using Float128 = Dune::Impl::Float128;
406 using float128_t = Dune::Impl::float128_t;
409 static constexpr
bool is_specialized =
true;
410 static constexpr Float128
min() noexcept {
return FLT128_MIN; }
411 static constexpr Float128
max() noexcept {
return FLT128_MAX; }
412 static constexpr Float128 lowest() noexcept {
return -FLT128_MAX; }
413 static constexpr
int digits = FLT128_MANT_DIG;
414 static constexpr
int digits10 = 34;
415 static constexpr
int max_digits10 = 36;
416 static constexpr
bool is_signed =
true;
417 static constexpr
bool is_integer =
false;
418 static constexpr
bool is_exact =
false;
419 static constexpr
int radix = 2;
420 static constexpr Float128 epsilon() noexcept {
return FLT128_EPSILON; }
421 static constexpr Float128 round_error() noexcept {
return float128_t{0.5}; }
422 static constexpr
int min_exponent = FLT128_MIN_EXP;
423 static constexpr
int min_exponent10 = FLT128_MIN_10_EXP;
424 static constexpr
int max_exponent = FLT128_MAX_EXP;
425 static constexpr
int max_exponent10 = FLT128_MAX_10_EXP;
426 static constexpr
bool has_infinity =
true;
427 static constexpr
bool has_quiet_NaN =
true;
428 static constexpr
bool has_signaling_NaN =
false;
429 static constexpr float_denorm_style has_denorm = denorm_present;
430 static constexpr
bool has_denorm_loss =
false;
431 static constexpr Float128 infinity() noexcept {
return float128_t{1}/float128_t{0}; }
432 static Float128 quiet_NaN() noexcept {
return nanq(
""); }
433 static constexpr Float128 signaling_NaN() noexcept {
return float128_t{}; }
434 static constexpr Float128 denorm_min() noexcept {
return FLT128_DENORM_MIN; }
435 static constexpr
bool is_iec559 =
true;
436 static constexpr
bool is_bounded =
false;
437 static constexpr
bool is_modulo =
false;
438 static constexpr
bool traps =
false;
439 static constexpr
bool tinyness_before =
false;
440 static constexpr float_round_style round_style = round_to_nearest;
445 #endif // HAVE_QUADMATH
446 #endif // DUNE_QUADMATH_HH