From b98926b73ba35dd750be2a6c1db345e46d775172 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Mon, 2 Feb 2026 19:13:14 -0800 Subject: [PATCH] uint128_fallback -> uint128 --- include/fmt/base.h | 4 +-- include/fmt/format-inl.h | 24 ++++++------- include/fmt/format.h | 78 ++++++++++++++++++---------------------- test/format-test.cc | 37 ++++++++++--------- 4 files changed, 65 insertions(+), 78 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index 6102044f..72115cf9 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -404,9 +404,9 @@ inline auto map(native_uint128 x) -> native_uint128 { return x; } # define FMT_USE_INT128 0 #endif #if !FMT_USE_INT128 -enum class native_int128 {}; // A fallback to reduce conditional compilation. +// Fallbacks to reduce conditional compilation and SFINAE. +enum class native_int128 {}; enum class native_uint128 {}; -// Reduce template instantiations. inline auto map(native_int128) -> monostate { return {}; } inline auto map(native_uint128) -> monostate { return {}; } #endif diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 4383c924..a9d4b8ea 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -209,10 +209,9 @@ inline auto umul96_upper64(uint32_t x, uint64_t y) noexcept -> uint64_t { // Computes lower 128 bits of multiplication of a 64-bit unsigned integer and a // 128-bit unsigned integer. -inline auto umul192_lower128(uint64_t x, uint128_fallback y) noexcept - -> uint128_fallback { +inline auto umul192_lower128(uint64_t x, uint128 y) noexcept -> uint128 { uint64_t high = x * y.high(); - uint128_fallback high_low = umul128(x, y.low()); + uint128 high_low = umul128(x, y.low()); return {high + high_low.high(), high_low.low()}; } @@ -380,13 +379,13 @@ template <> struct cache_accessor { template <> struct cache_accessor { using carrier_uint = float_info::carrier_uint; - using cache_entry_type = uint128_fallback; + using cache_entry_type = uint128; - static auto get_cached_power(int k) noexcept -> uint128_fallback { + static auto get_cached_power(int k) noexcept -> uint128 { FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, "k is out of range"); - static constexpr uint128_fallback pow10_significands[] = { + static constexpr uint128 pow10_significands[] = { #if FMT_USE_FULL_CACHE_DRAGONBOX {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, {0x9faacf3df73609b1, 0x77b191618c54e9ad}, @@ -1072,7 +1071,7 @@ template <> struct cache_accessor { int offset = k - kb; // Get base cache. - uint128_fallback base_cache = pow10_significands[cache_index]; + uint128 base_cache = pow10_significands[cache_index]; if (offset == 0) return base_cache; // Compute the required amount of bit-shift. @@ -1081,17 +1080,16 @@ template <> struct cache_accessor { // Try to recover the real cache. uint64_t pow5 = powers_of_5_64[offset]; - uint128_fallback recovered_cache = umul128(base_cache.high(), pow5); - uint128_fallback middle_low = umul128(base_cache.low(), pow5); + uint128 recovered_cache = umul128(base_cache.high(), pow5); + uint128 middle_low = umul128(base_cache.low(), pow5); recovered_cache += middle_low.high(); uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); - recovered_cache = - uint128_fallback{(recovered_cache.low() >> alpha) | high_to_middle, - ((middle_low.low() >> alpha) | middle_to_low)}; + recovered_cache = uint128{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; FMT_ASSERT(recovered_cache.low() + 1 != 0, ""); return {recovered_cache.high(), recovered_cache.low() + 1}; #endif @@ -1152,7 +1150,7 @@ template <> struct cache_accessor { } }; -FMT_FUNC auto get_cached_power(int k) noexcept -> uint128_fallback { +FMT_FUNC auto get_cached_power(int k) noexcept -> uint128 { return cache_accessor::get_cached_power(k); } diff --git a/include/fmt/format.h b/include/fmt/format.h index b04708a4..cf61a8d2 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -291,13 +291,13 @@ inline auto is_big_endian() -> bool { #endif } -class uint128_fallback { +class uint128 { private: uint64_t lo_, hi_; public: - constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} - constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} + constexpr uint128(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} + constexpr uint128(uint64_t value = 0) : lo_(value), hi_(0) {} constexpr auto high() const noexcept -> uint64_t { return hi_; } constexpr auto low() const noexcept -> uint64_t { return lo_; } @@ -307,77 +307,69 @@ class uint128_fallback { return static_cast(lo_); } - friend constexpr auto operator==(const uint128_fallback& lhs, - const uint128_fallback& rhs) -> bool { + friend constexpr auto operator==(const uint128& lhs, const uint128& rhs) + -> bool { return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; } - friend constexpr auto operator!=(const uint128_fallback& lhs, - const uint128_fallback& rhs) -> bool { + friend constexpr auto operator!=(const uint128& lhs, const uint128& rhs) + -> bool { return !(lhs == rhs); } - friend constexpr auto operator>(const uint128_fallback& lhs, - const uint128_fallback& rhs) -> bool { + friend constexpr auto operator>(const uint128& lhs, const uint128& rhs) + -> bool { return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_; } - friend constexpr auto operator|(const uint128_fallback& lhs, - const uint128_fallback& rhs) - -> uint128_fallback { + friend constexpr auto operator|(const uint128& lhs, const uint128& rhs) + -> uint128 { return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_}; } - friend constexpr auto operator&(const uint128_fallback& lhs, - const uint128_fallback& rhs) - -> uint128_fallback { + friend constexpr auto operator&(const uint128& lhs, const uint128& rhs) + -> uint128 { return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; } - friend constexpr auto operator~(const uint128_fallback& n) - -> uint128_fallback { - return {~n.hi_, ~n.lo_}; - } - friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs, - const uint128_fallback& rhs) - -> uint128_fallback { - auto result = uint128_fallback(lhs); + friend FMT_CONSTEXPR auto operator+(const uint128& lhs, const uint128& rhs) + -> uint128 { + auto result = uint128(lhs); result += rhs; return result; } - friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs) - -> uint128_fallback { + friend FMT_CONSTEXPR auto operator*(const uint128& lhs, uint32_t rhs) + -> uint128 { FMT_ASSERT(lhs.hi_ == 0, ""); uint64_t hi = (lhs.lo_ >> 32) * rhs; uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs; uint64_t new_lo = (hi << 32) + lo; return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo}; } - friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs) - -> uint128_fallback { + friend constexpr auto operator-(const uint128& lhs, uint64_t rhs) -> uint128 { return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs}; } - FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { + FMT_CONSTEXPR auto operator>>(int shift) const -> uint128 { if (shift == 64) return {0, hi_}; - if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64); + 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_fallback { + FMT_CONSTEXPR auto operator<<(int shift) const -> uint128 { if (shift == 64) return {lo_, 0}; - if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64); + if (shift > 64) return uint128(lo_, 0) << (shift - 64); return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; } - FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { + FMT_CONSTEXPR auto operator>>=(int shift) -> uint128& { return *this = *this >> shift; } - FMT_CONSTEXPR void operator+=(uint128_fallback n) { + FMT_CONSTEXPR void operator+=(uint128 n) { uint64_t new_lo = lo_ + n.lo_; uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0); FMT_ASSERT(new_hi >= hi_, ""); lo_ = new_lo; hi_ = new_hi; } - FMT_CONSTEXPR void operator&=(uint128_fallback n) { + FMT_CONSTEXPR void operator&=(uint128 n) { lo_ &= n.lo_; hi_ &= n.hi_; } - FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& { + FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128& { if (is_constant_evaluated()) { lo_ += n; hi_ += (lo_ < n ? 1 : 0); @@ -403,8 +395,7 @@ class uint128_fallback { } }; -using uint128_t = - conditional_t; +using uint128_t = conditional_t; #ifdef UINTPTR_MAX using uintptr_t = ::uintptr_t; @@ -423,10 +414,10 @@ template constexpr auto num_bits() -> int { // std::numeric_limits::digits may return 0 for 128-bit ints. template <> constexpr auto num_bits() -> int { return 128; } template <> constexpr auto num_bits() -> int { return 128; } -template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } // A heterogeneous bit_cast used for converting 96-bit long double to uint128_t -// and 128-bit pointers to uint128_fallback. +// and 128-bit pointers to uint128. template sizeof(From))> inline auto bit_cast(const From& from) -> To { constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned short)); @@ -1472,7 +1463,7 @@ template class to_utf8 { }; // Computes 128-bit result of multiplication of two 64-bit unsigned integers. -FMT_INLINE auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback { +FMT_INLINE auto umul128(uint64_t x, uint64_t y) noexcept -> uint128 { #if FMT_USE_INT128 auto p = static_cast(x) * static_cast(y); return {static_cast(p >> 64), static_cast(p)}; @@ -1528,14 +1519,13 @@ inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t { // Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a // 128-bit unsigned integer. -inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept - -> uint128_fallback { - uint128_fallback r = umul128(x, y.high()); +inline auto umul192_upper128(uint64_t x, uint128 y) noexcept -> uint128 { + uint128 r = umul128(x, y.high()); r += umul128_upper64(x, y.low()); return r; } -FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback; +FMT_API auto get_cached_power(int k) noexcept -> uint128; // Type-specific information that Dragonbox uses. template struct float_info; diff --git a/test/format-test.cc b/test/format-test.cc index 1d287377..3c4a3964 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -43,7 +43,7 @@ using fmt::memory_buffer; using fmt::runtime; using fmt::string_view; using fmt::detail::max_value; -using fmt::detail::uint128_fallback; +using fmt::detail::uint128; using testing::Return; using testing::StrictMock; @@ -55,15 +55,15 @@ static_assert(std::output_iterator); enum { buffer_size = 256 }; TEST(uint128_test, ctor) { - auto n = uint128_fallback(); + auto n = uint128(); EXPECT_EQ(n, 0); - n = uint128_fallback(42); + n = uint128(42); EXPECT_EQ(n, 42); EXPECT_EQ(static_cast(n), 42); } TEST(uint128_test, shift) { - auto n = uint128_fallback(42); + auto n = uint128(42); n = n << 64; EXPECT_EQ(static_cast(n), 0); n = n >> 64; @@ -73,26 +73,26 @@ TEST(uint128_test, shift) { EXPECT_EQ(static_cast(n), 0x8000000000000000); n = n >> 62; EXPECT_EQ(static_cast(n), 42); - EXPECT_EQ(uint128_fallback(1) << 112, uint128_fallback(0x1000000000000, 0)); - EXPECT_EQ(uint128_fallback(0x1000000000000, 0) >> 112, uint128_fallback(1)); + EXPECT_EQ(uint128(1) << 112, uint128(0x1000000000000, 0)); + EXPECT_EQ(uint128(0x1000000000000, 0) >> 112, uint128(1)); } TEST(uint128_test, minus) { - auto n = uint128_fallback(42); + auto n = uint128(42); EXPECT_EQ(n - 2, 40); } TEST(uint128_test, plus_assign) { - auto n = uint128_fallback(32); - n += uint128_fallback(10); + auto n = uint128(32); + n += uint128(10); EXPECT_EQ(n, 42); - n = uint128_fallback(max_value()); - n += uint128_fallback(1); - EXPECT_EQ(n, uint128_fallback(1) << 64); + n = uint128(max_value()); + n += uint128(1); + EXPECT_EQ(n, uint128(1) << 64); } TEST(uint128_test, multiply) { - auto n = uint128_fallback(2251799813685247); + auto n = uint128(2251799813685247); n = n * 3611864890; EXPECT_EQ(static_cast(n >> 64), 440901); } @@ -1723,14 +1723,13 @@ TEST(format_test, format_pointer) { } TEST(format_test, write_uintptr_fallback) { - // Test that formatting a pointer by converting it to uint128_fallback works. + // Test that formatting a pointer by converting it to uint128 works. // This is needed to support systems without uintptr_t. auto s = std::string(); - fmt::detail::write_ptr( - std::back_inserter(s), - fmt::detail::bit_cast( - reinterpret_cast(0xface)), - nullptr); + fmt::detail::write_ptr(std::back_inserter(s), + fmt::detail::bit_cast( + reinterpret_cast(0xface)), + nullptr); EXPECT_EQ(s, "0xface"); }