Simplify hexfloat rounding and test long double ties

Avoids shifting by zero, which is undefined for the fallback uint128.
The float tie test duplicated the double one; floats format as doubles.
This commit is contained in:
Victor Zverovich 2026-11-07 12:48:37 -08:00
parent dcdef1b80e
commit b2b9b074d4
2 changed files with 5 additions and 12 deletions

View File

@ -3366,18 +3366,10 @@ FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs,
int print_xdigits = num_xdigits - 1;
if (specs.precision >= 0 && print_xdigits > specs.precision) {
const int shift = ((print_xdigits - specs.precision - 1) * 4);
const auto mask = carrier_uint(0xF) << shift;
const auto v = static_cast<uint32_t>((f.f & mask) >> shift);
const int shift = (print_xdigits - specs.precision) * 4;
const auto inc = carrier_uint(1) << shift;
// Round half to even like printf.
const bool odd = ((f.f >> (shift + 4)) & 1) != 0;
const bool rest_is_zero = (f.f & ((carrier_uint(1) << shift) - 1)) == 0;
if (v > 8 || (v == 8 && (odd || !rest_is_zero))) {
const auto inc = carrier_uint(1) << (shift + 4);
f.f += inc;
f.f &= ~(inc - 1);
}
f.f += (inc >> 1) - 1 + ((f.f >> shift) & 1);
// Check long double overflow.
if (!has_implicit_bit<Float>()) {

View File

@ -1756,7 +1756,8 @@ TEST(format_test, format_double) {
EXPECT_EQ(fmt::format("{:.1a}", 1.03125), "0x1.0p+0");
EXPECT_EQ(fmt::format("{:.1a}", 1.09375), "0x1.2p+0");
EXPECT_EQ(fmt::format("{:.1a}", 1.0322265625), "0x1.1p+0");
EXPECT_EQ(fmt::format("{:.1A}", 1.03125f), "0X1.0P+0");
if (std::numeric_limits<long double>::digits == 64)
EXPECT_EQ(fmt::format("{:.0a}", 1.0625l), "0x8p-3");
EXPECT_EQ(fmt::format("{:a}", -42.0), "-0x1.5p+5");
EXPECT_EQ(fmt::format("{:A}", -42.0), "-0X1.5P+5");