From 3da98f465be91ae8a00e76abe9c34c402057c3d1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 09:39:40 -0400 Subject: [PATCH 01/22] Increase granularity of comparisons benchmarks --- test/benchmark_i128.cpp | 94 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index ba9664dc..ff474afe 100644 --- a/test/benchmark_i128.cpp +++ b/test/benchmark_i128.cpp @@ -158,7 +158,7 @@ std::vector generate_random_vector(std::size_t size = N, unsigned seed = 42U) template BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, const char* label) { - const auto t1 = std::chrono::steady_clock::now(); + auto t1 = std::chrono::steady_clock::now(); std::size_t s = 0; // discard variable for (std::size_t k {}; k < K; ++k) @@ -167,18 +167,98 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con { const auto val1 = data_vec[i]; const auto val2 = data_vec[i + 1]; - s += static_cast(val1 > val2); - s += static_cast(val1 >= val2); - s += static_cast(val1 < val2); - s += static_cast(val1 <= val2); s += static_cast(val1 == val2); + } + } + + auto t2 = std::chrono::steady_clock::now(); + + std::cout << "EQ<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + t1 = std::chrono::steady_clock::now(); + s = 0; + + for (std::size_t k {}; k < K; ++k) + { + for (std::size_t i {}; i < data_vec.size() - 1U; ++i) + { + const auto val1 = data_vec[i]; + const auto val2 = data_vec[i + 1]; s += static_cast(val1 != val2); } } - const auto t2 = std::chrono::steady_clock::now(); + t2 = std::chrono::steady_clock::now(); + + std::cout << "NE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + t1 = std::chrono::steady_clock::now(); + s = 0; + + for (std::size_t k {}; k < K; ++k) + { + for (std::size_t i {}; i < data_vec.size() - 1U; ++i) + { + const auto val1 = data_vec[i]; + const auto val2 = data_vec[i + 1]; + s += static_cast(val1 < val2); + } + } + + t2 = std::chrono::steady_clock::now(); + + std::cout << "LT<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + t1 = std::chrono::steady_clock::now(); + s = 0; + + for (std::size_t k {}; k < K; ++k) + { + for (std::size_t i {}; i < data_vec.size() - 1U; ++i) + { + const auto val1 = data_vec[i]; + const auto val2 = data_vec[i + 1]; + s += static_cast(val1 <= val2); + } + } + + t2 = std::chrono::steady_clock::now(); + + std::cout << "LE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + t1 = std::chrono::steady_clock::now(); + s = 0; + + for (std::size_t k {}; k < K; ++k) + { + for (std::size_t i {}; i < data_vec.size() - 1U; ++i) + { + const auto val1 = data_vec[i]; + const auto val2 = data_vec[i + 1]; + s += static_cast(val1 > val2); + } + } + + t2 = std::chrono::steady_clock::now(); + + std::cout << "GT<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + t1 = std::chrono::steady_clock::now(); + s = 0; + + for (std::size_t k {}; k < K; ++k) + { + for (std::size_t i {}; i < data_vec.size() - 1U; ++i) + { + const auto val1 = data_vec[i]; + const auto val2 = data_vec[i + 1]; + s += static_cast(val1 >= val2); + } + } + + t2 = std::chrono::steady_clock::now(); - std::cout << "comp<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "GE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; } template From 520585f858a2a5b8969618132079f4e806f4f92b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 09:58:12 -0400 Subject: [PATCH 02/22] Add collection of total runtime --- test/benchmark_i128.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index ff474afe..09d13e55 100644 --- a/test/benchmark_i128.cpp +++ b/test/benchmark_i128.cpp @@ -158,6 +158,7 @@ std::vector generate_random_vector(std::size_t size = N, unsigned seed = 42U) template BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, const char* label) { + auto t_total = std::chrono::steady_clock::now(); auto t1 = std::chrono::steady_clock::now(); std::size_t s = 0; // discard variable @@ -259,6 +260,8 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); std::cout << "GE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + + std::cout << "Total<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; } template From 88f06ebf8787ad2be64ea8075c545aba3b9ea614 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 10:29:13 -0400 Subject: [PATCH 03/22] Fix formatting --- test/benchmark_i128.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index 09d13e55..2d7f0f47 100644 --- a/test/benchmark_i128.cpp +++ b/test/benchmark_i128.cpp @@ -174,7 +174,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con auto t2 = std::chrono::steady_clock::now(); - std::cout << "EQ<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "EQ <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -191,7 +191,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "NE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "NE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -208,7 +208,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "LT<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "LT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -225,7 +225,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "LE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "LE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -242,7 +242,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "GT<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "GT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -259,9 +259,9 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "GE<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << "GE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; - std::cout << "Total<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; + std::cout << "SUM<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; } template @@ -282,7 +282,7 @@ BOOST_INT128_NO_INLINE void test_two_element_operation(const std::vector& dat const auto t2 = std::chrono::steady_clock::now(); - std::cout << operation << " <" << std::left << std::setw(11) << type << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cout << operation << "<" << std::left << std::setw(11) << type << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; } int main() From 10081eae5c137e07e85259bd075cf7e53c872470 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 11:48:52 -0400 Subject: [PATCH 04/22] Change ARM mac with clang compiler LT method --- include/boost/int128/detail/int128_imp.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 89f038b0..69c953e6 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -374,7 +374,16 @@ constexpr bool operator!=(const detail::builtin_u128 lhs, const int128_t rhs) no constexpr bool operator<(const int128_t lhs, const int128_t rhs) noexcept { + // On ARM macs only with the clang compiler is casting to __int128 uniformly better (and seemingly cost free) + #if defined(__aarch64__) && defined(__APPLE__) && defined(__clang__) + + return static_cast(lhs) < static_cast(rhs); + + #else + return lhs.high == rhs.high ? lhs.low < rhs.low : lhs.high < rhs.high; + + #endif } template From 7856d41fa56e4f5a739223ab42a6d4c4a7da82fa Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 11:49:49 -0400 Subject: [PATCH 05/22] Change ARM mac with clang compiler LE method --- include/boost/int128/detail/int128_imp.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 69c953e6..41caa3c8 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -497,7 +497,16 @@ constexpr bool operator>(const detail::builtin_u128 lhs, const int128_t rhs) noe constexpr bool operator<=(const int128_t lhs, const int128_t rhs) noexcept { + // On ARM macs only with the clang compiler is casting to __int128 uniformly better (and seemingly cost free) + #if defined(__aarch64__) && defined(__APPLE__) && defined(__clang__) + + return static_cast(lhs) <= static_cast(rhs); + + #else + return lhs.high == rhs.high ? lhs.low <= rhs.low : lhs.high <= rhs.high; + + #endif } template From e11b52d772e9dff5b50aabe877f299538840f940 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 11:50:34 -0400 Subject: [PATCH 06/22] Change ARM mac with clang compiler GT method --- include/boost/int128/detail/int128_imp.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 41caa3c8..f869068c 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -440,7 +440,16 @@ constexpr bool operator<(const detail::builtin_u128 lhs, const int128_t rhs) noe constexpr bool operator>(const int128_t lhs, const int128_t rhs) noexcept { + // On ARM macs only with the clang compiler is casting to __int128 uniformly better (and seemingly cost free) + #if defined(__aarch64__) && defined(__APPLE__) && defined(__clang__) + + return static_cast(lhs) > static_cast(rhs); + + #else + return lhs.high == rhs.high ? lhs.low > rhs.low : lhs.high > rhs.high; + + #endif } template From 62f94017d0e2d84fbdcdcee65041a854b479ef01 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 11:51:37 -0400 Subject: [PATCH 07/22] Change ARM mac with clang compiler GE method --- include/boost/int128/detail/int128_imp.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index f869068c..49278a68 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -572,7 +572,16 @@ constexpr bool operator<=(const detail::builtin_u128 lhs, const int128_t rhs) no constexpr bool operator>=(const int128_t lhs, const int128_t rhs) noexcept { + // On ARM macs only with the clang compiler is casting to __int128 uniformly better (and seemingly cost free) + #if defined(__aarch64__) && defined(__APPLE__) && defined(__clang__) + + return static_cast(lhs) >= static_cast(rhs); + + #else + return lhs.high == rhs.high ? lhs.low >= rhs.low : lhs.high >= rhs.high; + + #endif } template From f68f072e4c1c3b8e01d476c0450fb524c3393d43 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 12:15:15 -0400 Subject: [PATCH 08/22] Add x64 intrinsic macros --- include/boost/int128/detail/config.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/int128/detail/config.hpp b/include/boost/int128/detail/config.hpp index 167dc1b2..0bd6393f 100644 --- a/include/boost/int128/detail/config.hpp +++ b/include/boost/int128/detail/config.hpp @@ -99,4 +99,17 @@ using builtin_u128 = unsigned __int128; # define BOOST_INT128_FORCE_INLINE inline #endif +#ifdef __x86_64__ + +# include +# ifdef __ADX__ +# define BOOST_INT128_ADD_CARRY _addcarryx_u64 +# define BOOST_INT128_SUB_CARRY _subcarryx_u64 +# else +# define BOOST_INT128_ADD_CARRY _addcarry_u64 +# define BOOST_INT128_SUB_CARRY _subcarry_u64 +#endif + +#endif // x64 macros + #endif // BOOST_INT128_DETAIL_CONFIG_HPP From a552d47faac1938ef245dbaec5495d071327819a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 12:16:07 -0400 Subject: [PATCH 09/22] Try ADX based addition for x64 --- include/boost/int128/detail/int128_imp.hpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 49278a68..dc75c8e6 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1092,12 +1092,39 @@ namespace detail { BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, const int128_t rhs) noexcept { + #if defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + const auto new_low {lhs.low + rhs.low}; + const auto new_high {static_cast(lhs.high) + + static_cast(rhs.high) + + static_cast(new_low < lhs.low)}; + + return int128_t{static_cast(new_high), new_low}; + } + else + { + unsigned long long int new_high {}; + unsigned long long int new_low {}; + unsigned char carry = BOOST_INT128_ADD_CARRY(0, lhs.low, rhs.low, &new_low); + BOOST_INT128_ADD_CARRY(carry, static_cast(lhs.high), + static_cast(rhs.high), &new_high); + + return int128_t{static_cast(new_high), static_cast(new_low)}; + + } + + #else + const auto new_low {lhs.low + rhs.low}; const auto new_high {static_cast(lhs.high) + static_cast(rhs.high) + static_cast(new_low < lhs.low)}; return int128_t{static_cast(new_high), new_low}; + + #endif } template From 92eea41f47042b5497b93a927cc25f7bff618f3e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 13:29:17 -0400 Subject: [PATCH 10/22] Use memcpy on x64 to do builtin addition --- include/boost/int128/detail/int128_imp.hpp | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index dc75c8e6..4cf2c2af 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace boost { namespace int128 { @@ -1090,39 +1091,44 @@ constexpr int128_t& int128_t::operator++(int) noexcept namespace detail { +BOOST_INT128_FORCE_INLINE constexpr int128_t library_add(const int128_t lhs, const int128_t rhs) noexcept +{ + const auto new_low {lhs.low + rhs.low}; + const auto new_high {static_cast(lhs.high) + + static_cast(rhs.high) + + static_cast(new_low < lhs.low)}; + + return int128_t{static_cast(new_high), new_low}; +} + BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, const int128_t rhs) noexcept { #if defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) { - const auto new_low {lhs.low + rhs.low}; - const auto new_high {static_cast(lhs.high) + - static_cast(rhs.high) + - static_cast(new_low < lhs.low)}; - - return int128_t{static_cast(new_high), new_low}; + return library_add(lhs, rhs); } else { - unsigned long long int new_high {}; - unsigned long long int new_low {}; - unsigned char carry = BOOST_INT128_ADD_CARRY(0, lhs.low, rhs.low, &new_low); - BOOST_INT128_ADD_CARRY(carry, static_cast(lhs.high), - static_cast(rhs.high), &new_high); + builtin_i128 builtin_lhs {}; + builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + const auto builtin_res {builtin_lhs + builtin_rhs}; - return int128_t{static_cast(new_high), static_cast(new_low)}; + int128_t result {}; + std::memcpy(&result, &builtin_res, sizeof(result)); + + return result; } #else - const auto new_low {lhs.low + rhs.low}; - const auto new_high {static_cast(lhs.high) + - static_cast(rhs.high) + - static_cast(new_low < lhs.low)}; - - return int128_t{static_cast(new_high), new_low}; + return library_add(lhs, rhs); #endif } From 7984463cd6160ced23feef93d15f8b3be3a17973 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 13:36:49 -0400 Subject: [PATCH 11/22] Ignore class-memaccess warning --- include/boost/int128/detail/int128_imp.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 4cf2c2af..335ebc46 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1111,6 +1111,11 @@ BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, con } else { + #if defined(__GNUC__) && __GNUC__ >= 8 + # pragma GCC diagnostic push + # pragma GCC diagnostic ignored "-Wclass-memaccess" + #endif + builtin_i128 builtin_lhs {}; builtin_i128 builtin_rhs {}; @@ -1124,6 +1129,10 @@ BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, con std::memcpy(&result, &builtin_res, sizeof(result)); return result; + + #if defined(__GNUC__) && __GNUC__ >= 8 + # pragma GCC diagnostic pop + #endif } #else From 69b06231b196b1a1640cb6bcc9fe7fa6586d6e11 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 13:55:59 -0400 Subject: [PATCH 12/22] Try different GE for GCC x64 --- include/boost/int128/detail/int128_imp.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 335ebc46..25d51dc6 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -578,6 +578,23 @@ constexpr bool operator>=(const int128_t lhs, const int128_t rhs) noexcept return static_cast(lhs) >= static_cast(rhs); + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !defined(__clang__) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return lhs.high == rhs.high ? lhs.low >= rhs.low : lhs.high >= rhs.high; + } + else + { + detail::builtin_i128 builtin_lhs {}; + detail::builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + return builtin_lhs >= builtin_rhs; + } + #else return lhs.high == rhs.high ? lhs.low >= rhs.low : lhs.high >= rhs.high; From aa57171af0198a4cfd51c4aab5cd1ebb141719d7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 14:05:27 -0400 Subject: [PATCH 13/22] Try reverse order of operations --- include/boost/int128/detail/int128_imp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 25d51dc6..b96ba80f 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -221,7 +221,7 @@ constexpr bool operator==(const int128_t lhs, const int128_t rhs) noexcept { // x64 and ARM64 like the values in opposite directions - #if defined(__aarch64__) || defined(_M_ARM64) + #if defined(__aarch64__) || defined(_M_ARM64) || defined(__x86_64__) return lhs.low == rhs.low && lhs.high == rhs.high; From 09f9e983faf810c1f0a8a7f64eb67c1712452488 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 14:33:24 -0400 Subject: [PATCH 14/22] Try memcpy trick for operator NE --- include/boost/int128/detail/int128_imp.hpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index b96ba80f..94881009 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -298,6 +298,23 @@ constexpr bool operator!=(const int128_t lhs, const int128_t rhs) noexcept return lhs.low != rhs.low || lhs.high != rhs.high; + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && defined(__GNUC__) && !defined(__clang__) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return lhs.high != rhs.high || lhs.low != rhs.low; + } + else + { + detail::builtin_i128 builtin_lhs {}; + detail::builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + return builtin_lhs != builtin_rhs; + } + #else return lhs.high != rhs.high || lhs.low != rhs.low; @@ -578,7 +595,7 @@ constexpr bool operator>=(const int128_t lhs, const int128_t rhs) noexcept return static_cast(lhs) >= static_cast(rhs); - #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !defined(__clang__) + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && defined(__GNUC__) && !defined(__clang__) if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) { From 26c42c058d1987bd97d4ad40fc851929a9efcd1c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:11:10 -0400 Subject: [PATCH 15/22] Use memcpy trick for operator< --- include/boost/int128/detail/int128_imp.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 94881009..4b058503 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -397,6 +397,23 @@ constexpr bool operator<(const int128_t lhs, const int128_t rhs) noexcept return static_cast(lhs) < static_cast(rhs); + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && defined(__GNUC__) && !defined(__clang__) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return lhs.high == rhs.high ? lhs.low < rhs.low : lhs.high < rhs.high; + } + else + { + detail::builtin_i128 builtin_lhs {}; + detail::builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + return builtin_lhs < builtin_rhs; + } + #else return lhs.high == rhs.high ? lhs.low < rhs.low : lhs.high < rhs.high; From ff3c828a9c2291d3bb74819f9914395bb504b108 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:12:53 -0400 Subject: [PATCH 16/22] Use memcpy for operator> --- include/boost/int128/detail/int128_imp.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 4b058503..d3126111 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -480,6 +480,23 @@ constexpr bool operator>(const int128_t lhs, const int128_t rhs) noexcept return static_cast(lhs) > static_cast(rhs); + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && defined(__GNUC__) && !defined(__clang__) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return lhs.high == rhs.high ? lhs.low > rhs.low : lhs.high > rhs.high; + } + else + { + detail::builtin_i128 builtin_lhs {}; + detail::builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + return builtin_lhs > builtin_rhs; + } + #else return lhs.high == rhs.high ? lhs.low > rhs.low : lhs.high > rhs.high; From e25c7c00e27ea0cc4a1dbd27fe3b88ff5fff4422 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:13:10 -0400 Subject: [PATCH 17/22] memcpy for operator<= --- include/boost/int128/detail/int128_imp.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index d3126111..cd29c953 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -563,6 +563,23 @@ constexpr bool operator<=(const int128_t lhs, const int128_t rhs) noexcept return static_cast(lhs) <= static_cast(rhs); + #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && defined(__GNUC__) && !defined(__clang__) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return lhs.high == rhs.high ? lhs.low <= rhs.low : lhs.high <= rhs.high; + } + else + { + detail::builtin_i128 builtin_lhs {}; + detail::builtin_i128 builtin_rhs {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + return builtin_lhs <= builtin_rhs; + } + #else return lhs.high == rhs.high ? lhs.low <= rhs.low : lhs.high <= rhs.high; From d08511cad44d2bf8115320bc35ab8f74d1bc0745 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:36:06 -0400 Subject: [PATCH 18/22] Reverse word order for MSVC --- include/boost/int128/detail/int128_imp.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index cd29c953..dcb05f0c 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -221,7 +221,7 @@ constexpr bool operator==(const int128_t lhs, const int128_t rhs) noexcept { // x64 and ARM64 like the values in opposite directions - #if defined(__aarch64__) || defined(_M_ARM64) || defined(__x86_64__) + #if defined(__aarch64__) || defined(_M_ARM64) || defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) return lhs.low == rhs.low && lhs.high == rhs.high; @@ -294,7 +294,7 @@ constexpr bool operator!=(const int128_t lhs, const int128_t rhs) noexcept { // x64 and ARM64 like the values in opposite directions - #if defined(__aarch64__) || defined(_M_ARM64) + #if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_X64) || defined(_M_IX86) return lhs.low != rhs.low || lhs.high != rhs.high; From 5023337ef894b06b33297e473c2b60bf3ca662b8 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:47:31 -0400 Subject: [PATCH 19/22] Replace cout with cerr --- test/benchmark_i128.cpp | 98 ++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index 2d7f0f47..e020afec 100644 --- a/test/benchmark_i128.cpp +++ b/test/benchmark_i128.cpp @@ -174,7 +174,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con auto t2 = std::chrono::steady_clock::now(); - std::cout << "EQ <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "EQ <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -191,7 +191,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "NE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "NE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -208,7 +208,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "LT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "LT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -225,7 +225,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "LE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "LE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -242,7 +242,7 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "GT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "GT <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; t1 = std::chrono::steady_clock::now(); s = 0; @@ -259,9 +259,9 @@ BOOST_INT128_NO_INLINE void test_comparisons(const std::vector& data_vec, con t2 = std::chrono::steady_clock::now(); - std::cout << "GE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "GE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; - std::cout << "SUM<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; + std::cerr << "SUM<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; } template @@ -282,7 +282,7 @@ BOOST_INT128_NO_INLINE void test_two_element_operation(const std::vector& dat const auto t2 = std::chrono::steady_clock::now(); - std::cout << operation << "<" << std::left << std::setw(11) << type << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << operation << "<" << std::left << std::setw(11) << type << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; } int main() @@ -291,9 +291,9 @@ int main() // Two word operations { - std::cout << "\n---------------------------\n"; - std::cout << "Two Word Operations\n"; - std::cout << "---------------------------\n\n"; + std::cerr << "\n---------------------------\n"; + std::cerr << "Two Word Operations\n"; + std::cerr << "---------------------------\n\n"; const auto library_vector = generate_random_vector<0, int128_t>(); const auto mp_vector = generate_random_vector<0, mp_i128>(); @@ -313,7 +313,7 @@ int main() test_comparisons(library_vector, "library"); test_comparisons(mp_vector, "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::plus<>(), "add", "Builtin"); @@ -322,7 +322,7 @@ int main() test_two_element_operation(library_vector, std::plus<>(), "add", "Library"); test_two_element_operation(library_vector, std::plus<>(), "add", "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; /* #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::minus<>(), "sub", "Builtin"); @@ -330,7 +330,7 @@ int main() test_two_element_operation(library_vector, std::minus<>(), "sub", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::multiplies<>(), "mul", "Builtin"); @@ -338,7 +338,7 @@ int main() test_two_element_operation(library_vector, std::multiplies<>(), "mul", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::divides<>(), "div", "Builtin"); @@ -346,14 +346,14 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } // Single word operations { - std::cout << "\n---------------------------\n"; - std::cout << "One Word Operations\n"; - std::cout << "---------------------------\n\n"; + std::cerr << "\n---------------------------\n"; + std::cerr << "One Word Operations\n"; + std::cerr << "---------------------------\n\n"; const auto library_vector = generate_random_vector<1, int128_t>(); const auto mp_vector = generate_random_vector<1, mp_i128>(); @@ -373,7 +373,7 @@ int main() test_comparisons(library_vector, "library"); test_comparisons(mp_vector, "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::plus<>(), "add", "Builtin"); @@ -382,7 +382,7 @@ int main() test_two_element_operation(library_vector, std::plus<>(), "add", "Library"); test_two_element_operation(library_vector, std::plus<>(), "add", "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; /* #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::minus<>(), "sub", "Builtin"); @@ -390,7 +390,7 @@ int main() test_two_element_operation(library_vector, std::minus<>(), "sub", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::multiplies<>(), "mul", "Builtin"); @@ -398,7 +398,7 @@ int main() test_two_element_operation(library_vector, std::multiplies<>(), "mul", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::divides<>(), "div", "Builtin"); @@ -406,15 +406,15 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } { // Two word and one word operations Even = 2, odd = 1 - std::cout << "\n---------------------------\n"; - std::cout << "Two-One Word Operations\n"; - std::cout << "---------------------------\n\n"; + std::cerr << "\n---------------------------\n"; + std::cerr << "Two-One Word Operations\n"; + std::cerr << "---------------------------\n\n"; const auto library_vector = generate_random_vector<2, int128_t>(); const auto mp_vector = generate_random_vector<2, mp_i128>(); @@ -434,7 +434,7 @@ int main() test_comparisons(library_vector, "library"); test_comparisons(mp_vector, "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::plus<>(), "add", "Builtin"); @@ -443,7 +443,7 @@ int main() test_two_element_operation(library_vector, std::plus<>(), "add", "Library"); test_two_element_operation(library_vector, std::plus<>(), "add", "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; /* #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::minus<>(), "sub", "Builtin"); @@ -451,7 +451,7 @@ int main() test_two_element_operation(library_vector, std::minus<>(), "sub", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::multiplies<>(), "mul", "Builtin"); @@ -459,7 +459,7 @@ int main() test_two_element_operation(library_vector, std::multiplies<>(), "mul", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::divides<>(), "div", "Builtin"); @@ -467,15 +467,15 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } { // Two word and one word operations Even = 1, odd = 2 - std::cout << "\n---------------------------\n"; - std::cout << "One-Two Word Operations\n"; - std::cout << "---------------------------\n\n"; + std::cerr << "\n---------------------------\n"; + std::cerr << "One-Two Word Operations\n"; + std::cerr << "---------------------------\n\n"; const auto library_vector = generate_random_vector<3, int128_t>(); const auto mp_vector = generate_random_vector<3, mp_i128>(); @@ -495,7 +495,7 @@ int main() test_comparisons(library_vector, "library"); test_comparisons(mp_vector, "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::plus<>(), "add", "Builtin"); @@ -504,7 +504,7 @@ int main() test_two_element_operation(library_vector, std::plus<>(), "add", "Library"); test_two_element_operation(library_vector, std::plus<>(), "add", "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; /* #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::minus<>(), "sub", "Builtin"); @@ -512,7 +512,7 @@ int main() test_two_element_operation(library_vector, std::minus<>(), "sub", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::multiplies<>(), "mul", "Builtin"); @@ -520,7 +520,7 @@ int main() test_two_element_operation(library_vector, std::multiplies<>(), "mul", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::divides<>(), "div", "Builtin"); @@ -528,15 +528,15 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } { // Two word and one word operations Even = 1, odd = 2 - std::cout << "\n---------------------------\n"; - std::cout << "Random Width Operations\n"; - std::cout << "---------------------------\n\n"; + std::cerr << "\n---------------------------\n"; + std::cerr << "Random Width Operations\n"; + std::cerr << "---------------------------\n\n"; const auto library_vector = generate_random_vector<4, int128_t>(); const auto mp_vector = generate_random_vector<4, mp_i128>(); @@ -556,7 +556,7 @@ int main() test_comparisons(library_vector, "library"); test_comparisons(mp_vector, "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::plus<>(), "add", "Builtin"); @@ -565,7 +565,7 @@ int main() test_two_element_operation(library_vector, std::plus<>(), "add", "Library"); test_two_element_operation(library_vector, std::plus<>(), "add", "mp::i128"); - std::cout << std::endl; + std::cerr << std::endl; /* #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::minus<>(), "sub", "Builtin"); @@ -573,7 +573,7 @@ int main() test_two_element_operation(library_vector, std::minus<>(), "sub", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::multiplies<>(), "mul", "Builtin"); @@ -581,7 +581,7 @@ int main() test_two_element_operation(library_vector, std::multiplies<>(), "mul", "Library"); - std::cout << std::endl; + std::cerr << std::endl; #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INTERNAL_I128) test_two_element_operation(builtin_vector, std::divides<>(), "div", "Builtin"); @@ -589,7 +589,7 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } @@ -600,7 +600,7 @@ int main() int main() { - std::cout << "Benchmarks Not Run" << std::endl; + std::cerr << "Benchmarks Not Run" << std::endl; return 1; } From 42702c930dbb6b32e933f88b84aa0420db455850 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 15:48:35 -0400 Subject: [PATCH 20/22] Fix win clang error --- include/boost/int128/detail/int128_imp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index dcb05f0c..1f8a0eb8 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1188,7 +1188,7 @@ BOOST_INT128_FORCE_INLINE constexpr int128_t library_add(const int128_t lhs, con BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, const int128_t rhs) noexcept { - #if defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) + #if defined(__x86_64__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !defined(_WIN32) if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) { From 9e7b3e5b04ece6e2176bd16c01daa3cbb9921174 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 1 Apr 2025 16:15:36 -0400 Subject: [PATCH 21/22] Don't run UBSAN on benchmarks --- test/benchmark_i128.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index e020afec..009f80ec 100644 --- a/test/benchmark_i128.cpp +++ b/test/benchmark_i128.cpp @@ -2,7 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#ifdef NDEBUG +#if defined(NDEBUG) && !defined(UBSAN) #define BOOST_INT128_BENCHMARK_I128 #endif // NDEBUG From 0c23b6e7998643a765f774daf51ad8a24405141d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 2 Apr 2025 10:47:23 -0400 Subject: [PATCH 22/22] Avoid UB in check for UB --- test/test_i128.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/test_i128.cpp b/test/test_i128.cpp index f706f00a..8d3faa7b 100644 --- a/test/test_i128.cpp +++ b/test/test_i128.cpp @@ -633,13 +633,10 @@ void test_operator_add() IntType value2 {dist(rng)}; // Avoid UB from signed rollover - if (std::is_same::value) + if (std::is_same::value || std::is_same::value) { - while (value + value2 > (static_cast(1) << 127)) - { - value /= 10; - value2 /= 10; - } + value /= 100; + value2 /= 100; } auto builtin_value = static_cast(value);