From 8b70c47693eb3d34510022b20d80e594ce30cd9f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 09:26:44 -0500 Subject: [PATCH 01/12] Make conversions between lib types explicit --- include/boost/int128/detail/int128_imp.hpp | 4 ++-- include/boost/int128/detail/uint128_imp.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 1a4dcc5a..25c740cc 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -55,8 +55,8 @@ int128_t constexpr int128_t& operator=(const int128_t&) noexcept = default; constexpr int128_t& operator=(int128_t&&) noexcept = default; - // Requires conversion file to be implemented - constexpr int128_t(const uint128_t& v) noexcept; + // Requires a conversion file to be implemented + explicit constexpr int128_t(const uint128_t& v) noexcept; // Construct from integral types #if BOOST_INT128_ENDIAN_LITTLE_BYTE diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 987d29c2..2126c16b 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -56,8 +56,8 @@ uint128_t constexpr uint128_t& operator=(const uint128_t&) noexcept = default; constexpr uint128_t& operator=(uint128_t&&) noexcept = default; - // Requires conversion file to be implemented - constexpr uint128_t(const int128_t& v) noexcept; + // Requires a conversion file to be implemented + explicit constexpr uint128_t(const int128_t& v) noexcept; // Construct from integral types #if BOOST_INT128_ENDIAN_LITTLE_BYTE From 4cd88ade54b16b9079ade7bc722d259b99b5065d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 09:26:58 -0500 Subject: [PATCH 02/12] Fix instances of potential sign conversion --- include/boost/int128/detail/mini_from_chars.hpp | 4 ++-- include/boost/int128/fmt_format.hpp | 2 +- include/boost/int128/format.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/int128/detail/mini_from_chars.hpp b/include/boost/int128/detail/mini_from_chars.hpp index c7aca800..b6661b48 100644 --- a/include/boost/int128/detail/mini_from_chars.hpp +++ b/include/boost/int128/detail/mini_from_chars.hpp @@ -76,8 +76,8 @@ constexpr int from_chars_integer_impl(const char* first, const char* last, Integ ++next; } - overflow_value = (std::numeric_limits::max)(); - max_digit = (std::numeric_limits::max)(); + overflow_value = static_cast((std::numeric_limits::max)()); + max_digit = static_cast((std::numeric_limits::max)()); if (is_negative) { diff --git a/include/boost/int128/fmt_format.hpp b/include/boost/int128/fmt_format.hpp index 6df48626..e328e638 100644 --- a/include/boost/int128/fmt_format.hpp +++ b/include/boost/int128/fmt_format.hpp @@ -280,7 +280,7 @@ struct formatter } else { - abs_v = v; + abs_v = static_cast(v); } const auto end = detail::mini_to_chars(buffer, abs_v, base, is_upper); diff --git a/include/boost/int128/format.hpp b/include/boost/int128/format.hpp index d6e235ad..16289415 100644 --- a/include/boost/int128/format.hpp +++ b/include/boost/int128/format.hpp @@ -269,7 +269,7 @@ struct formatter } else { - abs_v = v; + abs_v = static_cast(v); } const auto end = boost::int128::detail::mini_to_chars(buffer, abs_v, base, is_upper); From fdcd1f1cc754995de915781134e00c3c3e9287cf Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 09:46:45 -0500 Subject: [PATCH 03/12] Implement mixed type comparisons when sign compare is defined --- include/boost/int128/detail/conversions.hpp | 195 +++++++++++++++++++- 1 file changed, 189 insertions(+), 6 deletions(-) diff --git a/include/boost/int128/detail/conversions.hpp b/include/boost/int128/detail/conversions.hpp index 02319668..4fe33440 100644 --- a/include/boost/int128/detail/conversions.hpp +++ b/include/boost/int128/detail/conversions.hpp @@ -42,46 +42,225 @@ constexpr uint128_t::uint128_t(const int128_t& v) noexcept : high {static_cast && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator==(T, U) noexcept +constexpr bool operator==(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return false; + } + + return static_cast(lhs) == rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return false; + } + + return lhs == static_cast(rhs); + } + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator!=(T, U) noexcept +constexpr bool operator!=(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return false; + } + + return static_cast(lhs) != rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return false; + } + + return lhs != static_cast(rhs); + } + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator<(T, U) noexcept +constexpr bool operator<(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return true; + } + + return static_cast(lhs) < rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return false; + } + + return lhs < static_cast(rhs); + } + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator<=(T, U) noexcept +constexpr bool operator<=(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return true; + } + + return static_cast(lhs) <= rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return false; + } + + return lhs <= static_cast(rhs); + } + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator>(T, U) noexcept +constexpr bool operator>(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return false; + } + + return static_cast(lhs) > rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return true; + } + + return lhs > static_cast(rhs); + } + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr bool operator>=(T, U) noexcept +constexpr bool operator>=(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_COMPARE + static_assert(std::is_same::value, "Sign Compare Error, cast one type to the other for this operation"); + static_cast(lhs); + static_cast(rhs); return true; + + #else + + BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + { + if (lhs < T{0}) + { + return false; + } + + return static_cast(lhs) >= rhs; + } + else + { + static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); + + if (rhs < T{0}) + { + return true; + } + + return lhs >= static_cast(rhs); + } + + #endif } //===================================== @@ -123,6 +302,10 @@ constexpr T operator%(T lhs, U) noexcept return lhs; } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } // namespace int128 } // namespace boost From 3b945da6b6eb964ae40a56236a9e4896607d5cc6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 10:11:33 -0500 Subject: [PATCH 04/12] Add testing of mixed type compare when allowed --- test/Jamfile | 1 + test/test_mixed_type_compare.cpp | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 test/test_mixed_type_compare.cpp diff --git a/test/Jamfile b/test/Jamfile index 3f7de536..1166a9ce 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -69,6 +69,7 @@ run test_stream.cpp ; compile-fail test_mixed_type_ops.cpp ; compile-fail test_mixed_arithmetic.cpp ; +run test_mixed_type_compare.cpp ; run test_consteval_funcs.cpp ; run test_sign_compare.cpp ; diff --git a/test/test_mixed_type_compare.cpp b/test/test_mixed_type_compare.cpp new file mode 100644 index 00000000..80b843b3 --- /dev/null +++ b/test/test_mixed_type_compare.cpp @@ -0,0 +1,82 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#define BOOST_INT128_ALLOW_SIGN_COMPARE + +#include +#include +#include + +static std::mt19937_64 rng{42}; +static std::uniform_int_distribution u_dist{0, UINT64_MAX}; +static std::uniform_int_distribution i_dist{0, INT64_MAX}; +static constexpr std::size_t N {1024U}; + +using namespace boost::int128; + +void test_left_unsigned() +{ + for (std::size_t i {0}; i < N; ++i) + { + const auto lhs {u_dist(rng)}; + const auto rhs {i_dist(rng)}; + + const uint128_t lib_lhs {lhs}; + const int128_t lib_rhs {rhs}; + + BOOST_TEST_EQ(lib_lhs == lib_rhs, lhs == rhs); + BOOST_TEST_EQ(lib_lhs != lib_rhs, lhs != rhs); + BOOST_TEST_EQ(lib_lhs > lib_rhs, lhs > rhs); + BOOST_TEST_EQ(lib_lhs >= lib_rhs, lhs >= rhs); + BOOST_TEST_EQ(lib_lhs < lib_rhs, lhs < rhs); + BOOST_TEST_EQ(lib_lhs <= lib_rhs, lhs <= rhs); + } + + const uint128_t lhs {42u}; + const int128_t rhs {-42}; + + BOOST_TEST_EQ(lhs == rhs, false); + BOOST_TEST_EQ(lhs != rhs, true); + BOOST_TEST_EQ(lhs < rhs, false); + BOOST_TEST_EQ(lhs <= rhs, false); + BOOST_TEST_EQ(lhs > rhs, true); + BOOST_TEST_EQ(lhs >= rhs, true); +} + +void test_right_unsigned() +{ + for (std::size_t i {0}; i < N; ++i) + { + const auto lhs {i_dist(rng)}; + const auto rhs {u_dist(rng)}; + + const int128_t lib_lhs {lhs}; + const uint128_t lib_rhs {rhs}; + + BOOST_TEST_EQ(lib_lhs == lib_rhs, lhs == rhs); + BOOST_TEST_EQ(lib_lhs != lib_rhs, lhs != rhs); + BOOST_TEST_EQ(lib_lhs > lib_rhs, lhs > rhs); + BOOST_TEST_EQ(lib_lhs >= lib_rhs, lhs >= rhs); + BOOST_TEST_EQ(lib_lhs < lib_rhs, lhs < rhs); + BOOST_TEST_EQ(lib_lhs <= lib_rhs, lhs <= rhs); + } + + const int128_t lhs {-42}; + const uint128_t rhs {42u}; + + BOOST_TEST_EQ(lhs == rhs, false); + BOOST_TEST_EQ(lhs != rhs, true); + BOOST_TEST_EQ(lhs < rhs, true); + BOOST_TEST_EQ(lhs <= rhs, true); + BOOST_TEST_EQ(lhs > rhs, false); + BOOST_TEST_EQ(lhs >= rhs, false); +} + +int main() +{ + test_left_unsigned(); + test_right_unsigned(); + + return boost::report_errors(); +} From 01bf86e8b5784db96c03864f9775bab012c4f84d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 10:11:43 -0500 Subject: [PATCH 05/12] Bug fix and logic improvement --- include/boost/int128/detail/conversions.hpp | 28 ++++++--------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/include/boost/int128/detail/conversions.hpp b/include/boost/int128/detail/conversions.hpp index 4fe33440..4d0523d3 100644 --- a/include/boost/int128/detail/conversions.hpp +++ b/include/boost/int128/detail/conversions.hpp @@ -59,7 +59,7 @@ constexpr bool operator==(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { @@ -70,8 +70,6 @@ constexpr bool operator==(const T lhs, const U rhs) noexcept } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { return false; @@ -95,22 +93,20 @@ constexpr bool operator!=(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { - return false; + return true; } return static_cast(lhs) != rhs; } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { - return false; + return true; } return lhs != static_cast(rhs); @@ -131,7 +127,7 @@ constexpr bool operator<(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { @@ -142,8 +138,6 @@ constexpr bool operator<(const T lhs, const U rhs) noexcept } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { return false; @@ -167,7 +161,7 @@ constexpr bool operator<=(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { @@ -178,8 +172,6 @@ constexpr bool operator<=(const T lhs, const U rhs) noexcept } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { return false; @@ -203,7 +195,7 @@ constexpr bool operator>(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { @@ -214,8 +206,6 @@ constexpr bool operator>(const T lhs, const U rhs) noexcept } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { return true; @@ -239,7 +229,7 @@ constexpr bool operator>=(const T lhs, const U rhs) noexcept #else - BOOST_INT128_IF_CONSTEXPR (std::numeric_limits::is_signed) + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (lhs < T{0}) { @@ -250,8 +240,6 @@ constexpr bool operator>=(const T lhs, const U rhs) noexcept } else { - static_assert(std::numeric_limits::is_signed, "Wrong sign detected. Please open a bug report at https://github.com/cppalliance/int128"); - if (rhs < T{0}) { return true; From 861e2c5841c3d51c5a6cd2c04a1d528ba6832c32 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 10:24:32 -0500 Subject: [PATCH 06/12] Rename test file --- test/Jamfile | 2 +- ..._mixed_type_compare.cpp => test_mixed_type_sign_compare.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{test_mixed_type_compare.cpp => test_mixed_type_sign_compare.cpp} (100%) diff --git a/test/Jamfile b/test/Jamfile index 1166a9ce..8d3b774d 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -69,7 +69,7 @@ run test_stream.cpp ; compile-fail test_mixed_type_ops.cpp ; compile-fail test_mixed_arithmetic.cpp ; -run test_mixed_type_compare.cpp ; +run test_mixed_type_sign_compare.cpp ; run test_consteval_funcs.cpp ; run test_sign_compare.cpp ; diff --git a/test/test_mixed_type_compare.cpp b/test/test_mixed_type_sign_compare.cpp similarity index 100% rename from test/test_mixed_type_compare.cpp rename to test/test_mixed_type_sign_compare.cpp From 50d664d6cce504b44ca20f4e968d1b84a50efbe4 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 16:10:13 -0500 Subject: [PATCH 07/12] Add mixed type operations --- include/boost/int128/detail/conversions.hpp | 65 +++++++++++++++++---- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/include/boost/int128/detail/conversions.hpp b/include/boost/int128/detail/conversions.hpp index 4d0523d3..397a5e3b 100644 --- a/include/boost/int128/detail/conversions.hpp +++ b/include/boost/int128/detail/conversions.hpp @@ -256,38 +256,83 @@ constexpr bool operator>=(const T lhs, const U rhs) noexcept //===================================== template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr T operator+(T lhs, U) noexcept +constexpr uint128_t operator+(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION + static_assert(std::is_same::value, "Sign Conversion Error, cast one type to the other for this operation"); - return lhs; + static_cast(rhs); + return static_cast(lhs); + + #else + + return static_cast(lhs) + static_cast(rhs); + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr T operator-(T lhs, U) noexcept +constexpr uint128_t operator-(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION + static_assert(std::is_same::value, "Sign Conversion Error, cast one type to the other for this operation"); - return lhs; + static_cast(rhs); + return static_cast(lhs); + + #else + + return static_cast(lhs) - static_cast(rhs); + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr T operator*(T lhs, U) noexcept +constexpr uint128_t operator*(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION + static_assert(std::is_same::value, "Sign Conversion Error, cast one type to the other for this operation"); - return lhs; + static_cast(rhs); + return static_cast(lhs); + + #else + + return static_cast(lhs) * static_cast(rhs); + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr T operator/(T lhs, U) noexcept +constexpr uint128_t operator/(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION + static_assert(std::is_same::value, "Sign Conversion Error, cast one type to the other for this operation"); - return lhs; + static_cast(rhs); + return static_cast(lhs); + + #else + + return static_cast(lhs) / static_cast(rhs); + + #endif } template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> -constexpr T operator%(T lhs, U) noexcept +constexpr uint128_t operator%(const T lhs, const U rhs) noexcept { + #ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION + static_assert(std::is_same::value, "Sign Conversion Error, cast one type to the other for this operation"); - return lhs; + static_cast(rhs); + return static_cast(lhs); + + #else + + return static_cast(lhs) % static_cast(rhs); + + #endif } #ifdef _MSC_VER From 3c03ec1e5d2f9bb42d51e86d084922a1e10aa95e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 16:10:25 -0500 Subject: [PATCH 08/12] Add sign conversion testing --- test/Jamfile | 1 + test/test_mixed_type_sign_conversion.cpp | 56 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/test_mixed_type_sign_conversion.cpp diff --git a/test/Jamfile b/test/Jamfile index 8d3b774d..fd3f9325 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -70,6 +70,7 @@ run test_stream.cpp ; compile-fail test_mixed_type_ops.cpp ; compile-fail test_mixed_arithmetic.cpp ; run test_mixed_type_sign_compare.cpp ; +run test_mixed_type_sign_conversion.cpp ; run test_consteval_funcs.cpp ; run test_sign_compare.cpp ; diff --git a/test/test_mixed_type_sign_conversion.cpp b/test/test_mixed_type_sign_conversion.cpp new file mode 100644 index 00000000..a5605d84 --- /dev/null +++ b/test/test_mixed_type_sign_conversion.cpp @@ -0,0 +1,56 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#define BOOST_INT128_ALLOW_SIGN_CONVERSION + +#include +#include +#include +#include + +static std::mt19937_64 rng{42}; +static std::uniform_int_distribution u_dist{0, static_cast(std::sqrt(UINT64_MAX))}; +static std::uniform_int_distribution i_dist{0, static_cast(std::sqrt(INT64_MAX))}; +static constexpr std::size_t N {1024U}; + +using namespace boost::int128; + +void test() +{ + for (std::size_t i {0}; i < N; ++i) + { + const auto u_val {u_dist(rng)}; + const auto i_val {i_dist(rng)}; + + if (u_val > static_cast(i_val)) + { + const uint128_t lhs {u_val}; + const int128_t rhs {i_val}; + + BOOST_TEST_EQ(lhs + rhs, u_val + static_cast(i_val)); + BOOST_TEST_EQ(lhs - rhs, u_val - static_cast(i_val)); + BOOST_TEST_EQ(lhs * rhs, u_val * static_cast(i_val)); + BOOST_TEST_EQ(lhs / rhs, u_val / static_cast(i_val)); + BOOST_TEST_EQ(lhs % rhs, u_val % static_cast(i_val)); + } + else + { + const int128_t lhs {i_val}; + const uint128_t rhs {u_val}; + + BOOST_TEST_EQ(lhs + rhs, static_cast(i_val) + u_val); + BOOST_TEST_EQ(lhs - rhs, static_cast(i_val) - u_val); + BOOST_TEST_EQ(lhs * rhs, static_cast(i_val) * u_val); + BOOST_TEST_EQ(lhs / rhs, static_cast(i_val) / u_val); + BOOST_TEST_EQ(lhs % rhs, static_cast(i_val) % u_val); + } + } +} + +int main() +{ + test(); + + return boost::report_errors(); +} \ No newline at end of file From b95a72277e8f101c5de7d5ef42bcd14048eb15f7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 16:22:52 -0500 Subject: [PATCH 09/12] Fix conversion error --- include/boost/int128/detail/uint128_imp.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 2126c16b..eed003fb 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -1855,7 +1855,7 @@ BOOST_INT128_EXPORT constexpr uint128_t operator<<(const uint128_t lhs, const ui { if (rhs.high > UINT64_C(0) || rhs.low >= UINT64_C(128)) { - return 0; + return uint128_t{0}; } return lhs << rhs.low; @@ -2057,7 +2057,7 @@ BOOST_INT128_EXPORT constexpr uint128_t operator>>(const uint128_t lhs, const ui { if (rhs.high > UINT64_C(0) || rhs.low >= UINT64_C(128)) { - return 0; + return uint128_t{0}; } return lhs >> rhs.low; From b0b6f79cc3511adf83feb22109eb6d4f2d8d0543 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 18:42:33 -0500 Subject: [PATCH 10/12] Ignore GCC warnings --- test/test_mixed_type_sign_compare.cpp | 5 +++++ test/test_mixed_type_sign_conversion.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/test/test_mixed_type_sign_compare.cpp b/test/test_mixed_type_sign_compare.cpp index 80b843b3..47b452ff 100644 --- a/test/test_mixed_type_sign_compare.cpp +++ b/test/test_mixed_type_sign_compare.cpp @@ -8,6 +8,11 @@ #include #include +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-compare" +#endif + static std::mt19937_64 rng{42}; static std::uniform_int_distribution u_dist{0, UINT64_MAX}; static std::uniform_int_distribution i_dist{0, INT64_MAX}; diff --git a/test/test_mixed_type_sign_conversion.cpp b/test/test_mixed_type_sign_conversion.cpp index a5605d84..79f6106c 100644 --- a/test/test_mixed_type_sign_conversion.cpp +++ b/test/test_mixed_type_sign_conversion.cpp @@ -9,6 +9,12 @@ #include #include +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-compare" +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + static std::mt19937_64 rng{42}; static std::uniform_int_distribution u_dist{0, static_cast(std::sqrt(UINT64_MAX))}; static std::uniform_int_distribution i_dist{0, static_cast(std::sqrt(INT64_MAX))}; From 113be1bc8a2af3300d0862f5ed7a75b502f0daf0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 2 Mar 2026 18:42:53 -0500 Subject: [PATCH 11/12] Various windows fail fixes --- include/boost/int128/detail/int128_imp.hpp | 2 +- include/boost/int128/numeric.hpp | 2 +- test/test_bit.cpp | 2 +- test/test_u128.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 25c740cc..9b1ddfe5 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1541,7 +1541,7 @@ constexpr int128_t operator^(const UnsignedInteger lhs, const int128_t rhs) noex static_assert(detail::is_signed_integer_v, "Sign Conversion Error"); static_cast(lhs); static_cast(rhs); - return true; + return int128_t{}; #endif } diff --git a/include/boost/int128/numeric.hpp b/include/boost/int128/numeric.hpp index fa22f7c5..6aab714a 100644 --- a/include/boost/int128/numeric.hpp +++ b/include/boost/int128/numeric.hpp @@ -350,7 +350,7 @@ constexpr uint128_t lcm(uint128_t a, uint128_t b) noexcept { if (a == 0U || b == 0U) { - return 0; + return uint128_t{0}; } diff --git a/test/test_bit.cpp b/test/test_bit.cpp index 54a42b48..8085c628 100644 --- a/test/test_bit.cpp +++ b/test/test_bit.cpp @@ -51,7 +51,7 @@ void test_countl_zero() void test_bit_width() { - BOOST_TEST_EQ(boost::int128::bit_width(0), 0); + BOOST_TEST_EQ(boost::int128::bit_width(boost::int128::uint128_t{0}), 0); boost::int128::uint128_t x {1}; diff --git a/test/test_u128.cpp b/test/test_u128.cpp index b1a7c05f..81a9b5c7 100644 --- a/test/test_u128.cpp +++ b/test/test_u128.cpp @@ -1361,7 +1361,7 @@ int main() test_spot_div(-3237361348456748317LL, 8011834041509972187LL); - test_spot_div(boost::int128::uint128_t{50012077812411ULL, 6429278683030093824ULL}, boost::int128::uint128_t{542101086ULL, 4477988020393345024ULL}, 92256); + test_spot_div(boost::int128::uint128_t{50012077812411ULL, 6429278683030093824ULL}, boost::int128::uint128_t{542101086ULL, 4477988020393345024ULL}, boost::int128::uint128_t{92256}); return boost::report_errors(); } From dd01ce0a5cff10e15f32888369640b497e0b0152 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 3 Mar 2026 10:44:46 -0500 Subject: [PATCH 12/12] More MSVC warning fixes --- test/test_mixed_type_sign_compare.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/test_mixed_type_sign_compare.cpp b/test/test_mixed_type_sign_compare.cpp index 47b452ff..ebd99a88 100644 --- a/test/test_mixed_type_sign_compare.cpp +++ b/test/test_mixed_type_sign_compare.cpp @@ -30,12 +30,12 @@ void test_left_unsigned() const uint128_t lib_lhs {lhs}; const int128_t lib_rhs {rhs}; - BOOST_TEST_EQ(lib_lhs == lib_rhs, lhs == rhs); - BOOST_TEST_EQ(lib_lhs != lib_rhs, lhs != rhs); - BOOST_TEST_EQ(lib_lhs > lib_rhs, lhs > rhs); - BOOST_TEST_EQ(lib_lhs >= lib_rhs, lhs >= rhs); - BOOST_TEST_EQ(lib_lhs < lib_rhs, lhs < rhs); - BOOST_TEST_EQ(lib_lhs <= lib_rhs, lhs <= rhs); + BOOST_TEST_EQ(lib_lhs == lib_rhs, lhs == static_cast(rhs)); + BOOST_TEST_EQ(lib_lhs != lib_rhs, lhs != static_cast(rhs)); + BOOST_TEST_EQ(lib_lhs > lib_rhs, lhs > static_cast(rhs)); + BOOST_TEST_EQ(lib_lhs >= lib_rhs, lhs >= static_cast(rhs)); + BOOST_TEST_EQ(lib_lhs < lib_rhs, lhs < static_cast(rhs)); + BOOST_TEST_EQ(lib_lhs <= lib_rhs, lhs <= static_cast(rhs)); } const uint128_t lhs {42u}; @@ -59,12 +59,12 @@ void test_right_unsigned() const int128_t lib_lhs {lhs}; const uint128_t lib_rhs {rhs}; - BOOST_TEST_EQ(lib_lhs == lib_rhs, lhs == rhs); - BOOST_TEST_EQ(lib_lhs != lib_rhs, lhs != rhs); - BOOST_TEST_EQ(lib_lhs > lib_rhs, lhs > rhs); - BOOST_TEST_EQ(lib_lhs >= lib_rhs, lhs >= rhs); - BOOST_TEST_EQ(lib_lhs < lib_rhs, lhs < rhs); - BOOST_TEST_EQ(lib_lhs <= lib_rhs, lhs <= rhs); + BOOST_TEST_EQ(lib_lhs == lib_rhs, static_cast(lhs) == rhs); + BOOST_TEST_EQ(lib_lhs != lib_rhs, static_cast(lhs) != rhs); + BOOST_TEST_EQ(lib_lhs > lib_rhs, static_cast(lhs) > rhs); + BOOST_TEST_EQ(lib_lhs >= lib_rhs, static_cast(lhs) >= rhs); + BOOST_TEST_EQ(lib_lhs < lib_rhs, static_cast(lhs) < rhs); + BOOST_TEST_EQ(lib_lhs <= lib_rhs, static_cast(lhs) <= rhs); } const int128_t lhs {-42};