From 4ddab8901cb7d8bafb7ad6fe15bab46635734e32 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 17 Feb 2022 21:24:10 -0800 Subject: [PATCH] Merge accumulator into int128_fallback --- include/fmt/format-inl.h | 29 ++--------------------------- include/fmt/format.h | 17 +++++++++++++---- test/format-impl-test.cc | 17 ----------------- 3 files changed, 15 insertions(+), 48 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 99be0d4d..c4340cf4 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -142,7 +142,7 @@ FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, namespace detail { template <> FMT_FUNC int count_digits<4>(detail::uintptr_fallback n) { - // fallback_uintptr is always stored in little endian. + // uintptr_fallback is always stored in little endian. int i = static_cast(sizeof(void*)) - 1; while (i > 0 && n.value[i] == 0) --i; auto char_digits = std::numeric_limits::digits / 4; @@ -347,29 +347,6 @@ FMT_CONSTEXPR inline fp get_cached_power(int min_exponent, impl_data::pow10_exponents[index]}; } -// A simple accumulator to hold the sums of terms in bigint::square if uint128_t -// is not available. -struct accumulator { - uint64_t lower; - uint64_t upper; - - constexpr accumulator() : lower(0), upper(0) {} - constexpr explicit operator uint32_t() const { - return static_cast(lower); - } - - FMT_CONSTEXPR void operator+=(uint64_t n) { - lower += n; - if (lower < n) ++upper; - } - FMT_CONSTEXPR void operator>>=(int shift) { - FMT_ASSERT(shift == 32, ""); - (void)shift; - lower = (upper << 32) | (lower >> 32); - upper >>= 32; - } -}; - class bigint { private: // A bigint is stored as an array of bigits (big digits), with bigit at index @@ -558,9 +535,7 @@ class bigint { int num_result_bigits = 2 * num_bigits; basic_memory_buffer n(std::move(bigits_)); bigits_.resize(to_unsigned(num_result_bigits)); - using accumulator_t = - conditional_t; - auto sum = accumulator_t(); + auto sum = uint128_t(); for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { // Compute bigit at position bigit_index of the result by adding // cross-product terms n[i] * n[j] such that i + j == bigit_index. diff --git a/include/fmt/format.h b/include/fmt/format.h index a32c2b53..2ac466ff 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -346,8 +346,12 @@ class uint128_fallback { public: constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} - explicit operator int() const { return static_cast(lo_); } - explicit operator uint64_t() const { return lo_; } + + template ::value)> + constexpr explicit operator T() const { + return static_cast(lo_); + } + friend auto operator==(const uint128_fallback& lhs, const uint128_fallback& rhs) -> bool { return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; @@ -361,14 +365,19 @@ class uint128_fallback { FMT_ASSERT(lhs.lo_ >= rhs, ""); return {lhs.hi_, lhs.lo_ - rhs}; } - auto operator>>(int shift) const -> uint128_fallback { + FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { if (shift == 64) return {0, hi_}; return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; } - auto operator<<(int shift) const -> uint128_fallback { + FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { if (shift == 64) return {lo_, 0}; return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; } + FMT_CONSTEXPR void operator>>=(int shift) { *this = *this >> shift; } + FMT_CONSTEXPR void operator+=(uint64_t n) { + lo_ += n; + if (lo_ < n) ++hi_; + } }; using uint128_t = conditional_t; diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 90105b5a..194cfa92 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -96,23 +96,6 @@ TEST(bigint_test, multiply) { EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", bigmax)); } -TEST(bigint_test, accumulator) { - fmt::detail::accumulator acc; - EXPECT_EQ(acc.lower, 0); - EXPECT_EQ(acc.upper, 0); - acc.upper = 12; - acc.lower = 34; - EXPECT_EQ(static_cast(acc), 34); - acc += 56; - EXPECT_EQ(acc.lower, 90); - acc += max_value(); - EXPECT_EQ(acc.upper, 13); - EXPECT_EQ(acc.lower, 89); - acc >>= 32; - EXPECT_EQ(acc.upper, 0); - EXPECT_EQ(acc.lower, 13 * 0x100000000); -} - TEST(bigint_test, square) { bigint n0(0); n0.square();