Implement 128-bit constant mul in bigint

This commit is contained in:
Victor Zverovich 2022-04-03 07:12:24 -07:00
parent 02eb215f2f
commit 686de58886
3 changed files with 15 additions and 10 deletions

View File

@ -371,13 +371,16 @@ class bigint {
template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value || template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
std::is_same<UInt, uint128_t>::value)> std::is_same<UInt, uint128_t>::value)>
FMT_CONSTEXPR20 void multiply(UInt value) { FMT_CONSTEXPR20 void multiply(UInt value) {
const UInt lower = static_cast<bigit>(value); using half_uint =
const UInt upper = value >> bigit_bits; conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>;
const int shift = num_bits<half_uint>() - bigit_bits;
const UInt lower = static_cast<half_uint>(value);
const UInt upper = value >> num_bits<half_uint>();
UInt carry = 0; UInt carry = 0;
for (size_t i = 0, n = bigits_.size(); i < n; ++i) { for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
UInt result = lower * bigits_[i] + static_cast<bigit>(carry); UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
carry = carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
upper * bigits_[i] + (result >> bigit_bits) + (carry >> bigit_bits); (carry >> bigit_bits);
bigits_[i] = static_cast<bigit>(result); bigits_[i] = static_cast<bigit>(result);
} }
while (carry != 0) { while (carry != 0) {

View File

@ -362,9 +362,11 @@ class uint128_fallback {
result += rhs; result += rhs;
return result; return result;
} }
friend auto operator*(const uint128_fallback&, uint32_t) -> uint128_fallback { friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
FMT_ASSERT(false, ""); -> uint128_fallback {
return {}; 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) friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
-> uint128_fallback { -> uint128_fallback {

View File

@ -101,9 +101,9 @@ TEST(bigint_test, multiply) {
const auto max128 = (fmt::detail::uint128_t(max64) << 64) | max64; const auto max128 = (fmt::detail::uint128_t(max64) << 64) | max64;
bigmax = max128; bigmax = max128;
// bigmax *= max128; bigmax *= max128;
// EXPECT_EQ(fmt::to_string(bigmax), EXPECT_EQ(fmt::to_string(bigmax),
// "fffffffffffffffffffffffffffffffe00000000000000000000000000000001"); "fffffffffffffffffffffffffffffffe00000000000000000000000000000001");
} }
TEST(bigint_test, square) { TEST(bigint_test, square) {