diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 43deb497..0febc002 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -371,13 +371,16 @@ class bigint { template ::value || std::is_same::value)> FMT_CONSTEXPR20 void multiply(UInt value) { - const UInt lower = static_cast(value); - const UInt upper = value >> bigit_bits; + using half_uint = + conditional_t::value, uint64_t, uint32_t>; + const int shift = num_bits() - bigit_bits; + const UInt lower = static_cast(value); + const UInt upper = value >> num_bits(); UInt carry = 0; for (size_t i = 0, n = bigits_.size(); i < n; ++i) { UInt result = lower * bigits_[i] + static_cast(carry); - carry = - upper * bigits_[i] + (result >> bigit_bits) + (carry >> bigit_bits); + carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) + + (carry >> bigit_bits); bigits_[i] = static_cast(result); } while (carry != 0) { diff --git a/include/fmt/format.h b/include/fmt/format.h index ac72ad2d..63eed8bb 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -362,9 +362,11 @@ class uint128_fallback { result += rhs; return result; } - friend auto operator*(const uint128_fallback&, uint32_t) -> uint128_fallback { - FMT_ASSERT(false, ""); - return {}; + friend auto operator*(const uint128_fallback& lhs, uint32_t rhs) + -> uint128_fallback { + FMT_ASSERT(lhs.hi_ == 0, ""); + uint64_t hi = (lhs.lo_ >> 32) * rhs; + return {hi >> 32, (hi << 32) + (lhs.lo_ & ~uint32_t()) * rhs}; } friend auto operator-(const uint128_fallback& lhs, uint64_t rhs) -> uint128_fallback { diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 0276391b..1ce392d0 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -101,9 +101,9 @@ TEST(bigint_test, multiply) { const auto max128 = (fmt::detail::uint128_t(max64) << 64) | max64; bigmax = max128; - // bigmax *= max128; - // EXPECT_EQ(fmt::to_string(bigmax), - // "fffffffffffffffffffffffffffffffe00000000000000000000000000000001"); + bigmax *= max128; + EXPECT_EQ(fmt::to_string(bigmax), + "fffffffffffffffffffffffffffffffe00000000000000000000000000000001"); } TEST(bigint_test, square) {