diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 9e539ec7..a55c3cd0 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -188,11 +188,6 @@ FMT_FUNC auto vsystem_error(int error_code, string_view fmt, format_args args) namespace detail { -template -inline auto operator==(basic_fp x, basic_fp y) -> bool { - return x.f == y.f && x.e == y.e; -} - // Compilers should be able to optimize this into the ror instruction. FMT_INLINE auto rotr(uint32_t n, uint32_t r) noexcept -> uint32_t { r &= 31; @@ -1397,32 +1392,6 @@ small_divisor_case_label: } // namespace dragonbox } // namespace detail -template <> struct formatter { - FMT_CONSTEXPR auto parse(format_parse_context& ctx) - -> format_parse_context::iterator { - return ctx.begin(); - } - - auto format(const detail::bigint& n, format_context& ctx) const - -> format_context::iterator { - auto out = ctx.out(); - bool first = true; - for (auto i = n.bigits_.size(); i > 0; --i) { - auto value = n.bigits_[i - 1u]; - if (first) { - out = fmt::format_to(out, FMT_STRING("{:x}"), value); - first = false; - continue; - } - out = fmt::format_to(out, FMT_STRING("{:08x}"), value); - } - if (n.exp_ > 0) - out = fmt::format_to(out, FMT_STRING("p{}"), - n.exp_ * detail::bigint::bigit_bits); - return out; - } -}; - FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { for_each_codepoint(s, [this](uint32_t cp, string_view) { if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8")); @@ -1464,6 +1433,11 @@ FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string { namespace detail { +// Compares two characters for equality. +inline auto equal2(const char* lhs, const char* rhs) -> bool { + return memcmp(lhs, rhs, 2) == 0; +} + FMT_FUNC void vformat_to(buffer& buf, string_view fmt, format_args args, locale_ref loc) { auto out = appender(buf); diff --git a/include/fmt/format.h b/include/fmt/format.h index b3e3fb86..77b8df4a 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1389,14 +1389,6 @@ extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; FMT_END_EXPORT #endif // FMT_HEADER_ONLY -// Compares two characters for equality. -template auto equal2(const Char* lhs, const char* rhs) -> bool { - return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); -} -inline auto equal2(const char* lhs, const char* rhs) -> bool { - return memcmp(lhs, rhs, 2) == 0; -} - // Writes a two-digit value to out. template FMT_CONSTEXPR20 FMT_INLINE void write2digits(Char* out, size_t value) { @@ -1842,11 +1834,7 @@ template struct basic_fp { F f; int e; - static constexpr int num_significand_bits = - static_cast(sizeof(F) * num_bits()); - constexpr basic_fp() : f(0), e(0) {} - constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} // Constructs fp from an IEEE754 floating-point number. template FMT_CONSTEXPR basic_fp(Float n) { assign(n); } @@ -1884,48 +1872,6 @@ template struct basic_fp { } }; -using fp = basic_fp; - -// Normalizes the value converted from double and multiplied by (1 << SHIFT). -template -FMT_CONSTEXPR auto normalize(basic_fp value) -> basic_fp { - // Handle subnormals. - const auto implicit_bit = F(1) << num_significand_bits(); - const auto shifted_implicit_bit = implicit_bit << SHIFT; - while ((value.f & shifted_implicit_bit) == 0) { - value.f <<= 1; - --value.e; - } - // Subtract 1 to account for hidden bit. - const auto offset = basic_fp::num_significand_bits - - num_significand_bits() - SHIFT - 1; - value.f <<= offset; - value.e -= offset; - return value; -} - -// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. -FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t { -#if FMT_USE_INT128 - auto product = static_cast(lhs) * rhs; - auto f = static_cast(product >> 64); - return (static_cast(product) & (1ULL << 63)) != 0 ? f + 1 : f; -#else - // Multiply 32-bit parts of significands. - uint64_t mask = (1ULL << 32) - 1; - uint64_t a = lhs >> 32, b = lhs & mask; - uint64_t c = rhs >> 32, d = rhs & mask; - uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; - // Compute mid 64-bit of result and round. - uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); - return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); -#endif -} - -FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp { - return {multiply(x.f, y.f), x.e + y.e + 64}; -} - template () == num_bits()> using convert_float_result = conditional_t::value || doublish, double, T>; diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 8d6a675a..7d942bc5 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -15,9 +15,36 @@ #include "gmock/gmock.h" using fmt::detail::bigint; -using fmt::detail::fp; using fmt::detail::max_value; +FMT_BEGIN_NAMESPACE +template <> struct formatter { + FMT_CONSTEXPR auto parse(format_parse_context& ctx) + -> format_parse_context::iterator { + return ctx.begin(); + } + + auto format(const detail::bigint& n, format_context& ctx) const + -> format_context::iterator { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = fmt::format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = fmt::format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = fmt::format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; +FMT_END_NAMESPACE + static_assert(!std::is_copy_constructible::value, ""); static_assert(!std::is_copy_assignable::value, ""); @@ -171,29 +198,15 @@ template void run_double_tests() { template <> void run_double_tests() { // Construct from double. - EXPECT_EQ(fp(1.23), fp(0x13ae147ae147aeu, -52)); + auto v = fmt::detail::basic_fp(1.23); + EXPECT_EQ(v.f, 0x13ae147ae147aeu); + EXPECT_EQ(v.e, -52); } TEST(fp_test, double_tests) { run_double_tests::is_iec559>(); } -TEST(fp_test, normalize) { - const auto v = fp(0xbeef, 42); - auto normalized = normalize(v); - EXPECT_EQ(normalized.f, 0xbeef000000000000); - EXPECT_EQ(normalized.e, -6); -} - -TEST(fp_test, multiply) { - auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7); - EXPECT_EQ(v.f, 123u * 56u); - EXPECT_EQ(v.e, 4 + 7 + 64); - v = fp(123ULL << 32, 4) * fp(567ULL << 31, 8); - EXPECT_EQ(v.f, (123 * 567 + 1u) / 2); - EXPECT_EQ(v.e, 4 + 8 + 64); -} - TEST(fp_test, dragonbox_max_k) { using fmt::detail::dragonbox::floor_log10_pow2; using float_info = fmt::detail::dragonbox::float_info;