mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 02:37:36 +02:00
Add __float128 support
This commit is contained in:
@ -234,10 +234,10 @@ template <typename F> struct basic_fp {
|
|||||||
// The predecessor is closer if n is a normalized power of 2 (f == 0) other
|
// The predecessor is closer if n is a normalized power of 2 (f == 0) other
|
||||||
// than the smallest normalized number (biased_e > 1).
|
// than the smallest normalized number (biased_e > 1).
|
||||||
auto is_predecessor_closer = f == 0 && biased_e > 1;
|
auto is_predecessor_closer = f == 0 && biased_e > 1;
|
||||||
if (biased_e != 0)
|
if (biased_e == 0)
|
||||||
f += static_cast<F>(implicit_bit);
|
|
||||||
else
|
|
||||||
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
|
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
|
||||||
|
else if (has_implicit_bit<Float>())
|
||||||
|
f += static_cast<F>(implicit_bit);
|
||||||
e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
|
e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
|
||||||
if (!has_implicit_bit<Float>()) ++e;
|
if (!has_implicit_bit<Float>()) ++e;
|
||||||
return is_predecessor_closer;
|
return is_predecessor_closer;
|
||||||
@ -2049,9 +2049,9 @@ enum dragon {
|
|||||||
// Formats a floating-point number using a variation of the Fixed-Precision
|
// Formats a floating-point number using a variation of the Fixed-Precision
|
||||||
// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
|
// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
|
||||||
// https://fmt.dev/papers/p372-steele.pdf.
|
// https://fmt.dev/papers/p372-steele.pdf.
|
||||||
FMT_CONSTEXPR20 inline void format_dragon(fp value, unsigned flags,
|
FMT_CONSTEXPR20 inline void format_dragon(basic_fp<uint128_t> value,
|
||||||
int num_digits, buffer<char>& buf,
|
unsigned flags, int num_digits,
|
||||||
int& exp10) {
|
buffer<char>& buf, int& exp10) {
|
||||||
bigint numerator; // 2 * R in (FPP)^2.
|
bigint numerator; // 2 * R in (FPP)^2.
|
||||||
bigint denominator; // 2 * S in (FPP)^2.
|
bigint denominator; // 2 * S in (FPP)^2.
|
||||||
// lower and upper are differences between value and corresponding boundaries.
|
// lower and upper are differences between value and corresponding boundaries.
|
||||||
@ -2255,7 +2255,7 @@ FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (use_dragon) {
|
if (use_dragon) {
|
||||||
auto f = fp();
|
auto f = basic_fp<uint128_t>();
|
||||||
bool is_predecessor_closer = specs.binary32
|
bool is_predecessor_closer = specs.binary32
|
||||||
? f.assign(static_cast<float>(value))
|
? f.assign(static_cast<float>(value))
|
||||||
: f.assign(converted_value);
|
: f.assign(converted_value);
|
||||||
|
@ -336,24 +336,26 @@ class uint128_fallback {
|
|||||||
return static_cast<T>(lo_);
|
return static_cast<T>(lo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend auto operator==(const uint128_fallback& lhs,
|
friend constexpr auto operator==(const uint128_fallback& lhs,
|
||||||
const uint128_fallback& rhs) -> bool {
|
const uint128_fallback& rhs) -> bool {
|
||||||
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
|
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
|
||||||
}
|
}
|
||||||
friend auto operator!=(const uint128_fallback& lhs,
|
friend constexpr auto operator!=(const uint128_fallback& lhs,
|
||||||
const uint128_fallback& rhs) -> bool {
|
const uint128_fallback& rhs) -> bool {
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
friend auto operator>(const uint128_fallback& lhs,
|
friend constexpr auto operator>(const uint128_fallback& lhs,
|
||||||
const uint128_fallback& rhs) -> bool {
|
const uint128_fallback& rhs) -> bool {
|
||||||
return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
|
return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
|
||||||
}
|
}
|
||||||
friend auto operator|(const uint128_fallback& lhs,
|
friend constexpr auto operator|(const uint128_fallback& lhs,
|
||||||
const uint128_fallback& rhs) -> uint128_fallback {
|
const uint128_fallback& rhs)
|
||||||
|
-> uint128_fallback {
|
||||||
return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
|
return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
|
||||||
}
|
}
|
||||||
friend auto operator&(const uint128_fallback& lhs,
|
friend constexpr auto operator&(const uint128_fallback& lhs,
|
||||||
const uint128_fallback& rhs) -> uint128_fallback {
|
const uint128_fallback& rhs)
|
||||||
|
-> uint128_fallback {
|
||||||
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
|
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
|
||||||
}
|
}
|
||||||
friend auto operator+(const uint128_fallback& lhs,
|
friend auto operator+(const uint128_fallback& lhs,
|
||||||
@ -366,12 +368,13 @@ class uint128_fallback {
|
|||||||
-> uint128_fallback {
|
-> uint128_fallback {
|
||||||
FMT_ASSERT(lhs.hi_ == 0, "");
|
FMT_ASSERT(lhs.hi_ == 0, "");
|
||||||
uint64_t hi = (lhs.lo_ >> 32) * rhs;
|
uint64_t hi = (lhs.lo_ >> 32) * rhs;
|
||||||
return {hi >> 32, (hi << 32) + (lhs.lo_ & ~uint32_t()) * rhs};
|
uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
|
||||||
|
uint64_t new_lo = (hi << 32) + lo;
|
||||||
|
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
|
||||||
}
|
}
|
||||||
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
||||||
-> uint128_fallback {
|
-> uint128_fallback {
|
||||||
FMT_ASSERT(lhs.lo_ >= rhs, "");
|
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
|
||||||
return {lhs.hi_, lhs.lo_ - rhs};
|
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
|
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
|
||||||
if (shift == 64) return {0, hi_};
|
if (shift == 64) return {0, hi_};
|
||||||
|
@ -75,6 +75,12 @@ TEST(uint128_test, plus_assign) {
|
|||||||
EXPECT_EQ(n, uint128_fallback(1) << 64);
|
EXPECT_EQ(n, uint128_fallback(1) << 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(uint128_test, multiply) {
|
||||||
|
auto n = uint128_fallback(2251799813685247);
|
||||||
|
n = n * 3611864890;
|
||||||
|
EXPECT_EQ(static_cast<uint64_t>(n >> 64), 440901);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Float> void check_isfinite() {
|
template <typename Float> void check_isfinite() {
|
||||||
using fmt::detail::isfinite;
|
using fmt::detail::isfinite;
|
||||||
EXPECT_TRUE(isfinite(Float(0.0)));
|
EXPECT_TRUE(isfinite(Float(0.0)));
|
||||||
|
Reference in New Issue
Block a user