From 15c2a3baccf4271cf60d47cc8db3d2e525c49cd8 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 17 Feb 2022 19:05:25 -0800 Subject: [PATCH] int128_t -> int128_opt --- include/fmt/core.h | 56 ++++++++++++---------------------------- include/fmt/format-inl.h | 7 ++--- include/fmt/format.h | 47 +++++++++++++++++++++++++++------ test/core-test.cc | 27 ------------------- test/format-test.cc | 27 +++++++++++++++++++ 5 files changed, 86 insertions(+), 78 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index db6cf669..09625c5a 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -380,8 +380,8 @@ template struct std_string_view {}; #elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \ !(FMT_CLANG_VERSION && FMT_MSC_VER) # define FMT_USE_INT128 1 -using int128_t = __int128_t; -using uint128_t = __uint128_t; +using int128_opt = __int128_t; // An optional 128-bit integer. +using uint128_opt = __uint128_t; template inline auto convert_for_visit(T value) -> T { return value; } @@ -389,36 +389,8 @@ template inline auto convert_for_visit(T value) -> T { # define FMT_USE_INT128 0 #endif #if !FMT_USE_INT128 -enum class int128_t {}; -class uint128_t { - private: - uint64_t lo_, hi_; - constexpr uint128_t(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} - - public: - constexpr uint128_t(uint64_t value = 0) : hi_(0), lo_(value) {} - explicit operator int() const { return lo_; } - explicit operator uint64_t() const { return lo_; } - friend auto operator==(const uint128_t& lhs, const uint128_t& rhs) -> bool { - return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; - } - friend auto operator&(const uint128_t& lhs, const uint128_t& rhs) - -> uint128_t { - return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; - } - friend auto operator-(const uint128_t& lhs, uint64_t rhs) -> uint128_t { - FMT_ASSERT(lhs.lo_ >= rhs, ""); - return {lhs.hi_, lhs.lo_ - rhs}; - } - auto operator>>(int shift) const -> uint128_t { - if (shift == 64) return {0, hi_}; - return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; - } - auto operator<<(int shift) const -> uint128_t { - if (shift == 64) return {lo_, 0}; - return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; - } -}; +enum class int128_opt {}; +enum class uint128_opt {}; // Reduce template instantiations. template inline auto convert_for_visit(T) -> monostate { return {}; @@ -1168,8 +1140,8 @@ FMT_TYPE_CONSTANT(int, int_type); FMT_TYPE_CONSTANT(unsigned, uint_type); FMT_TYPE_CONSTANT(long long, long_long_type); FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); -FMT_TYPE_CONSTANT(int128_t, int128_type); -FMT_TYPE_CONSTANT(uint128_t, uint128_type); +FMT_TYPE_CONSTANT(int128_opt, int128_type); +FMT_TYPE_CONSTANT(uint128_opt, uint128_type); FMT_TYPE_CONSTANT(bool, bool_type); FMT_TYPE_CONSTANT(Char, char_type); FMT_TYPE_CONSTANT(float, float_type); @@ -1219,8 +1191,8 @@ template class value { unsigned uint_value; long long long_long_value; unsigned long long ulong_long_value; - int128_t int128_value; - uint128_t uint128_value; + int128_opt int128_value; + uint128_opt uint128_value; bool bool_value; char_type char_value; float float_value; @@ -1237,8 +1209,8 @@ template class value { constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} constexpr FMT_INLINE value(long long val) : long_long_value(val) {} constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} - FMT_INLINE value(int128_t val) : int128_value(val) {} - FMT_INLINE value(uint128_t val) : uint128_value(val) {} + FMT_INLINE value(int128_opt val) : int128_value(val) {} + FMT_INLINE value(uint128_opt val) : uint128_value(val) {} constexpr FMT_INLINE value(float val) : float_value(val) {} constexpr FMT_INLINE value(double val) : double_value(val) {} FMT_INLINE value(long double val) : long_double_value(val) {} @@ -1321,8 +1293,12 @@ template struct arg_mapper { -> unsigned long long { return val; } - FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; } - FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt { + return val; + } FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; } template ::value || diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index db539346..4f9d98f8 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -558,7 +558,8 @@ class bigint { int num_result_bigits = 2 * num_bigits; basic_memory_buffer n(std::move(bigits_)); bigits_.resize(to_unsigned(num_result_bigits)); - using accumulator_t = conditional_t; + using accumulator_t = + conditional_t; auto sum = accumulator_t(); for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { // Compute bigit at position bigit_index of the result by adding @@ -833,7 +834,7 @@ namespace dragonbox { // Computes 128-bit result of multiplication of two 64-bit unsigned integers. inline uint128_wrapper umul128(uint64_t x, uint64_t y) noexcept { #if FMT_USE_INT128 - auto p = static_cast(x) * static_cast(y); + auto p = static_cast(x) * static_cast(y); return {static_cast(p >> 64), static_cast(p)}; #elif defined(_MSC_VER) && defined(_M_X64) uint128_wrapper result; @@ -863,7 +864,7 @@ inline uint128_wrapper umul128(uint64_t x, uint64_t y) noexcept { // Computes upper 64 bits of multiplication of two 64-bit unsigned integers. inline uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept { #if FMT_USE_INT128 - auto p = static_cast(x) * static_cast(y); + auto p = static_cast(x) * static_cast(y); return static_cast(p >> 64); #elif defined(_MSC_VER) && defined(_M_X64) return __umulh(x, y); diff --git a/include/fmt/format.h b/include/fmt/format.h index 84b9e7ae..5b2fcae9 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -339,6 +339,36 @@ inline auto to_uintptr(const void* p) -> fallback_uintptr { } #endif +class uint128_t { + private: + uint64_t lo_, hi_; + constexpr uint128_t(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} + + public: + constexpr uint128_t(uint64_t value = 0) : lo_(value), hi_(0) {} + explicit operator int() const { return static_cast(lo_); } + explicit operator uint64_t() const { return lo_; } + friend auto operator==(const uint128_t& lhs, const uint128_t& rhs) -> bool { + return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; + } + friend auto operator&(const uint128_t& lhs, const uint128_t& rhs) + -> uint128_t { + return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; + } + friend auto operator-(const uint128_t& lhs, uint64_t rhs) -> uint128_t { + FMT_ASSERT(lhs.lo_ >= rhs, ""); + return {lhs.hi_, lhs.lo_ - rhs}; + } + auto operator>>(int shift) const -> uint128_t { + if (shift == 64) return {0, hi_}; + return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; + } + auto operator<<(int shift) const -> uint128_t { + if (shift == 64) return {lo_, 0}; + return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; + } +}; + // Returns the largest possible value for type T. Same as // std::numeric_limits::max() but shorter and not affected by the max macro. template constexpr auto max_value() -> T { @@ -348,7 +378,7 @@ template constexpr auto num_bits() -> int { return std::numeric_limits::digits; } // 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 static_cast(sizeof(void*) * @@ -876,13 +906,13 @@ constexpr auto compile_string_to_view(detail::std_string_view s) FMT_BEGIN_DETAIL_NAMESPACE template struct is_integral : std::is_integral {}; -template <> struct is_integral : std::true_type {}; +template <> struct is_integral : std::true_type {}; template <> struct is_integral : std::true_type {}; template using is_signed = std::integral_constant::is_signed || - std::is_same::value>; + std::is_same::value>; // Returns true if value is negative, false otherwise. // Same as `value < 0` but doesn't produce warnings if T is an unsigned type. @@ -908,9 +938,10 @@ template using uint32_or_64_or_128_t = conditional_t() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, - conditional_t() <= 64, uint64_t, uint128_t>>; + conditional_t() <= 64, uint64_t, uint128_opt>>; template -using uint64_or_128_t = conditional_t() <= 64, uint64_t, uint128_t>; +using uint64_or_128_t = + conditional_t() <= 64, uint64_t, uint128_opt>; #define FMT_POWERS_OF_10(factor) \ factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ @@ -950,7 +981,7 @@ template FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { } } #if FMT_USE_INT128 -FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int { +FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int { return count_digits_fallback(n); } #endif @@ -1044,7 +1075,7 @@ FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { template constexpr auto digits10() noexcept -> int { return std::numeric_limits::digits10; } -template <> constexpr auto digits10() noexcept -> int { return 38; } +template <> constexpr auto digits10() noexcept -> int { return 38; } template <> constexpr auto digits10() noexcept -> int { return 38; } template struct thousands_sep_result { @@ -1250,7 +1281,7 @@ template <> struct float_info { template struct float_info::value && std::numeric_limits::digits == 64>> { - using carrier_uint = detail::uint128_t; + using carrier_uint = detail::uint128_opt; static const int significand_bits = 64; static const int exponent_bits = 15; }; diff --git a/test/core-test.cc b/test/core-test.cc index fcc988b1..a040d241 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -33,33 +33,6 @@ using testing::Return; # error core-test includes format.h #endif -TEST(uint128_test, ctor) { - using fmt::detail::uint128_t; - auto n = uint128_t(); - EXPECT_EQ(n, 0); - n = uint128_t(42); - EXPECT_EQ(n, 42); - EXPECT_EQ(static_cast(n), 42); -} - -TEST(uint128_test, shift) { - auto n = fmt::detail::uint128_t(42); - n = n << 64; - EXPECT_EQ(static_cast(n), 0); - n = n >> 64; - EXPECT_EQ(static_cast(n), 42); - n = n << 62; - EXPECT_EQ(static_cast(n >> 64), 0xa); - EXPECT_EQ(static_cast(n), 0x8000000000000000); - n = n >> 62; - EXPECT_EQ(static_cast(n), 42); -} - -TEST(uint128_test, minus) { - auto n = fmt::detail::uint128_t(42); - EXPECT_EQ(n - 2, 40); -} - TEST(string_view_test, value_type) { static_assert(std::is_same::value, ""); } diff --git a/test/format-test.cc b/test/format-test.cc index b63445ea..92dcfd21 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -39,6 +39,33 @@ using testing::StrictMock; enum { buffer_size = 256 }; +TEST(uint128_test, ctor) { + using fmt::detail::uint128_t; + auto n = uint128_t(); + EXPECT_EQ(n, 0); + n = uint128_t(42); + EXPECT_EQ(n, 42); + EXPECT_EQ(static_cast(n), 42); +} + +TEST(uint128_test, shift) { + auto n = fmt::detail::uint128_t(42); + n = n << 64; + EXPECT_EQ(static_cast(n), 0); + n = n >> 64; + EXPECT_EQ(static_cast(n), 42); + n = n << 62; + EXPECT_EQ(static_cast(n >> 64), 0xa); + EXPECT_EQ(static_cast(n), 0x8000000000000000); + n = n >> 62; + EXPECT_EQ(static_cast(n), 42); +} + +TEST(uint128_test, minus) { + auto n = fmt::detail::uint128_t(42); + EXPECT_EQ(n - 2, 40); +} + struct uint32_pair { uint32_t u[2]; };