diff --git a/include/fmt/format.h b/include/fmt/format.h index 7053040e17627..32976ab90f75f 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3116,63 +3116,54 @@ FMT_CONSTEXPR20 inline void format_dragon(basic_fp value, } // Formats a floating-point number with snprintf using the hexfloat format. -template ::value)> +template FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, float_specs specs, buffer& buf) { // float is passed as double to reduce the number of instantiations and to // simplify implementation. static_assert(!std::is_same::value, ""); - static_assert(std::numeric_limits::digits <= 113, "unsupported FP"); using info = dragonbox::float_info; // Assume Float is in the format [sign][exponent][significand]. using carrier_uint = typename info::carrier_uint; - carrier_uint f; - int e; - - constexpr auto num_significand_bits = detail::num_significand_bits(); - const auto implicit_bit = carrier_uint(1) << num_significand_bits; - const auto significand_mask = implicit_bit - 1; - auto u = bit_cast(value); - f = static_cast(u & significand_mask); - auto biased_e = - static_cast((u & exponent_mask()) >> num_significand_bits); + constexpr auto num_float_significand_bits = + detail::num_significand_bits(); - if (biased_e == 0) - biased_e = 1; // Subnormals use biased exponent 1 (min exponent). - else if (has_implicit_bit()) - f += static_cast(implicit_bit); - - e = biased_e - (1 << (info::exponent_bits - 1)) + 1; + basic_fp f(value); + f.e += num_float_significand_bits; + if (!has_implicit_bit()) --f.e; constexpr auto num_fraction_bits = - num_significand_bits + (has_implicit_bit() ? 1 : 0); + num_float_significand_bits + (has_implicit_bit() ? 1 : 0); constexpr auto num_xdigits = (num_fraction_bits + 3) / 4; constexpr auto leading_shift = ((num_xdigits - 1) * 4); const auto leading_mask = carrier_uint(0xF) << leading_shift; const auto leading_v = - static_cast((f & leading_mask) >> leading_shift); - if (leading_v > 1) e -= (32 - FMT_BUILTIN_CLZ(leading_v) - 1); + static_cast((f.f & leading_mask) >> leading_shift); + if (leading_v > 1) f.e -= (32 - FMT_BUILTIN_CLZ(leading_v) - 1); int print_xdigits = num_xdigits - 1; if (precision >= 0 && print_xdigits > precision) { const int shift = ((print_xdigits - precision - 1) * 4); const auto mask = carrier_uint(0xF) << shift; - const auto v = static_cast((f & mask) >> shift); + const auto v = static_cast((f.f & mask) >> shift); if (v >= 8) { const auto inc = carrier_uint(1) << (shift + 4); - f += inc; - f &= ~(inc - 1); + f.f += inc; + f.f &= ~(inc - 1); } - // long double overflow - if (!has_implicit_bit() && ((f & implicit_bit) == implicit_bit)) { - f >>= 4; - e += 4; + // Check long double overflow + if (!has_implicit_bit()) { + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + if ((f.f & implicit_bit) == implicit_bit) { + f.f >>= 4; + f.e += 4; + } } print_xdigits = precision; @@ -3180,7 +3171,7 @@ FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, char xdigits[num_bits() / 4]; detail::fill_n(xdigits, sizeof(xdigits), '0'); - format_uint<4>(xdigits, f, num_xdigits, specs.upper); + format_uint<4>(xdigits, f.f, num_xdigits, specs.upper); // Remove zero tail while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; @@ -3196,23 +3187,16 @@ FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, buf.push_back(specs.upper ? 'P' : 'p'); uint32_t abs_e; - if (e < 0) { + if (f.e < 0) { buf.push_back('-'); - abs_e = static_cast(-e); + abs_e = static_cast(-f.e); } else { buf.push_back('+'); - abs_e = static_cast(e); + abs_e = static_cast(f.e); } format_decimal(appender(buf), abs_e, detail::count_digits(abs_e)); } -template ::value)> -FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, - float_specs specs, buffer& buf) { - static_assert(std::numeric_limits::is_iec559, "unsupported FP"); - format_hexfloat(static_cast(value), precision, specs, buf); -} - template FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, buffer& buf) -> int {