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 diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 89f038b0..1f8a0eb8 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 { @@ -220,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__) || defined(_M_X64) || defined(_M_IX86) return lhs.low == rhs.low && lhs.high == rhs.high; @@ -293,10 +294,27 @@ 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; + #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; @@ -374,7 +392,33 @@ 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); + + #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; + + #endif } template @@ -431,7 +475,33 @@ 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); + + #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; + + #endif } template @@ -488,7 +558,33 @@ 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); + + #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; + + #endif } template @@ -545,7 +641,33 @@ 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); + + #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; + + #endif } template @@ -1054,16 +1176,57 @@ constexpr int128_t& int128_t::operator++(int) noexcept namespace detail { -BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, const int128_t rhs) noexcept +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) && !defined(_WIN32) + + if (BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) + { + return library_add(lhs, rhs); + } + 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 {}; + + std::memcpy(&builtin_lhs, &lhs, sizeof(builtin_lhs)); + std::memcpy(&builtin_rhs, &rhs, sizeof(builtin_rhs)); + + const auto builtin_res {builtin_lhs + builtin_rhs}; + + int128_t result {}; + + std::memcpy(&result, &builtin_res, sizeof(result)); + + return result; + + #if defined(__GNUC__) && __GNUC__ >= 8 + # pragma GCC diagnostic pop + #endif + } + + #else + + return library_add(lhs, rhs); + + #endif +} + template BOOST_INT128_FORCE_INLINE constexpr int128_t default_add(const int128_t lhs, const Integer rhs) noexcept { diff --git a/test/benchmark_i128.cpp b/test/benchmark_i128.cpp index ba9664dc..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 @@ -158,7 +158,8 @@ 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 t_total = 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 +168,100 @@ 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::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; + + 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::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; + + 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::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; + + 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::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; + + 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::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; + + 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::cerr << "GE <" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; - std::cout << "comp<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t1 ) / 1us << " us (s=" << s << ")\n"; + std::cerr << "SUM<" << std::left << std::setw(11) << label << ">: " << std::setw( 10 ) << ( t2 - t_total ) / 1us << " us (s=" << s << ")\n\n"; } template @@ -199,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() @@ -208,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>(); @@ -230,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"); @@ -239,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"); @@ -247,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"); @@ -255,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"); @@ -263,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>(); @@ -290,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"); @@ -299,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"); @@ -307,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"); @@ -315,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"); @@ -323,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>(); @@ -351,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"); @@ -360,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"); @@ -368,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"); @@ -376,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"); @@ -384,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>(); @@ -412,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"); @@ -421,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"); @@ -429,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"); @@ -437,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"); @@ -445,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>(); @@ -473,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"); @@ -482,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"); @@ -490,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"); @@ -498,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"); @@ -506,7 +589,7 @@ int main() test_two_element_operation(library_vector, std::divides<>(), "div", "Library"); - std::cout << std::endl; + std::cerr << std::endl; */ } @@ -517,7 +600,7 @@ int main() int main() { - std::cout << "Benchmarks Not Run" << std::endl; + std::cerr << "Benchmarks Not Run" << std::endl; return 1; } 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);