Merge accumulator into int128_fallback

This commit is contained in:
Victor Zverovich 2022-02-17 21:24:10 -08:00
parent d38f72aff2
commit 4ddab8901c
3 changed files with 15 additions and 48 deletions

View File

@ -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<int>(sizeof(void*)) - 1;
while (i > 0 && n.value[i] == 0) --i;
auto char_digits = std::numeric_limits<unsigned char>::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<uint32_t>(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<bigit, bigits_capacity> n(std::move(bigits_));
bigits_.resize(to_unsigned(num_result_bigits));
using accumulator_t =
conditional_t<FMT_USE_INT128, uint128_opt, accumulator>;
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.

View File

@ -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<int>(lo_); }
explicit operator uint64_t() const { return lo_; }
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
constexpr explicit operator T() const {
return static_cast<T>(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<FMT_USE_INT128, uint128_opt, uint128_fallback>;

View File

@ -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<uint32_t>(acc), 34);
acc += 56;
EXPECT_EQ(acc.lower, 90);
acc += max_value<uint64_t>();
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();