Fix shifting the fallback uint128 by zero

A shift of 0 evaluated lo_ >> 64 or hi_ << 64, which is undefined.
This commit is contained in:
Victor Zverovich 2026-11-07 13:44:54 -08:00
parent b2b9b074d4
commit d93446e3dd
2 changed files with 7 additions and 0 deletions

View File

@ -342,11 +342,13 @@ class uint128 {
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
}
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128 {
if (shift == 0) return *this;
if (shift == 64) return {0, hi_};
if (shift > 64) return uint128(0, hi_) >> (shift - 64);
return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
}
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128 {
if (shift == 0) return *this;
if (shift == 64) return {lo_, 0};
if (shift > 64) return uint128(lo_, 0) << (shift - 64);
return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};

View File

@ -76,6 +76,11 @@ TEST(uint128_test, shift) {
EXPECT_EQ(static_cast<uint64_t>(n), 42);
EXPECT_EQ(uint128(1) << 112, uint128(0x1000000000000, 0));
EXPECT_EQ(uint128(0x1000000000000, 0) >> 112, uint128(1));
// FMT_CONSTEXPR turns an undefined shift into a compile error.
FMT_CONSTEXPR auto lshift = uint128(1, 2) << 0;
FMT_CONSTEXPR auto rshift = uint128(1, 2) >> 0;
EXPECT_EQ(lshift, uint128(1, 2));
EXPECT_EQ(rshift, uint128(1, 2));
}
TEST(uint128_test, minus) {