From 19d4770fc7fe0513d2c07b8662bcb552607f9a15 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 09:13:34 -0400 Subject: [PATCH 01/19] Add reproducer --- test/Jamfile | 1 + test/github_issue_477.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/github_issue_477.cpp diff --git a/test/Jamfile b/test/Jamfile index 1575d839..c2bb88c8 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -141,6 +141,7 @@ run github_issue_221.cpp ; run github_issue_272.cpp ; run github_issue_377.cpp ; run github_issue_432.cpp ; +compile github_issue_477.cpp ; # Compilation of individual headers compile compile_tests/int128_master_header_compile.cpp ; diff --git a/test/github_issue_477.cpp b/test/github_issue_477.cpp new file mode 100644 index 00000000..00e6cbb8 --- /dev/null +++ b/test/github_issue_477.cpp @@ -0,0 +1,29 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// See: https://github.com/cppalliance/int128/issues/477 + +#include + +constexpr boost::int128::uint128 value{1, 0}; + +constexpr bool a = value; +static_assert(a, "Wrong value"); + +constexpr bool b(value); +static_assert(b, "Wrong value"); + +constexpr bool c = static_cast(value); +static_assert(c, "Wrong value"); + +constexpr boost::int128::int128 signed_value{1, 0}; + +constexpr bool d = signed_value; +static_assert(d, "Wrong value"); + +constexpr bool e(signed_value); +static_assert(e, "Wrong value"); + +constexpr bool f = static_cast(signed_value); +static_assert(f, "Wrong value"); From 9ae5b2639cc9deb631a5cc6468d3b3480bdcf9f6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 09:21:36 -0400 Subject: [PATCH 02/19] Add bool path in UnsignedInteger coversion Closes: #477 --- include/boost/int128/detail/int128_imp.hpp | 21 ++++++++++++++++++++- include/boost/int128/detail/uint128_imp.hpp | 21 ++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 9fc10e39..6cfc37dc 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -111,8 +111,27 @@ int128 template BOOST_INT128_HOST_DEVICE constexpr operator SignedInteger() const noexcept { return static_cast(low); } + #ifdef _MSC_VER + # pragma warning(push) + # pragma warning(disable:4127) + #endif + template - BOOST_INT128_HOST_DEVICE constexpr operator UnsignedInteger() const noexcept { return static_cast(low); } + BOOST_INT128_HOST_DEVICE constexpr operator UnsignedInteger() const noexcept + { + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) + { + return low || high; + } + else + { + return static_cast(low); + } + } + + #ifdef _MSC_VER + # pragma warning(pop) + #endif #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INT128) diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 701c64f5..0ab7f63c 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -117,8 +117,27 @@ uint128 template BOOST_INT128_HOST_DEVICE constexpr operator SignedInteger() const noexcept { return static_cast(low); } + #ifdef _MSC_VER + # pragma warning(push) + # pragma warning(disable:4127) + #endif + template - BOOST_INT128_HOST_DEVICE constexpr operator UnsignedInteger() const noexcept { return static_cast(low); } + BOOST_INT128_HOST_DEVICE constexpr operator UnsignedInteger() const noexcept + { + BOOST_INT128_IF_CONSTEXPR (std::is_same::value) + { + return low || high; + } + else + { + return static_cast(low); + } + } + + #ifdef _MSC_VER + # pragma warning(pop) + #endif #if defined(BOOST_INT128_HAS_INT128) || defined(BOOST_INT128_HAS_MSVC_INT128) From 3ae5829d2355d65375d236a1a2b06921bc68c6ba Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 09:27:28 -0400 Subject: [PATCH 03/19] Fix unpopped warning suppression Closes: 478 --- include/boost/int128/detail/int128_imp.hpp | 4 ++++ include/boost/int128/detail/uint128_imp.hpp | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 6cfc37dc..0812b4af 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -2330,6 +2330,10 @@ BOOST_INT128_HOST_DEVICE constexpr int128 operator/(const SignedInteger lhs, con } } +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + #ifdef _MSC_VER # pragma warning(pop) #endif diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 0ab7f63c..1a7164b2 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -2525,6 +2525,12 @@ BOOST_INT128_HOST_DEVICE inline uint128& uint128::operator/=(const Integer rhs) #endif // BOOST_INT128_HAS_MSVC_INT128 +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + //===================================== // Modulo Operator //===================================== From b1857582ac0dbb8a4ba07f19ea3caaf910c50f6c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 09:55:25 -0400 Subject: [PATCH 04/19] Add reproducer test set --- test/Jamfile | 1 + test/github_issue_479.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/github_issue_479.cpp diff --git a/test/Jamfile b/test/Jamfile index c2bb88c8..1d42f815 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -142,6 +142,7 @@ run github_issue_272.cpp ; run github_issue_377.cpp ; run github_issue_432.cpp ; compile github_issue_477.cpp ; +run github_issue_479.cpp ; # Compilation of individual headers compile compile_tests/int128_master_header_compile.cpp ; diff --git a/test/github_issue_479.cpp b/test/github_issue_479.cpp new file mode 100644 index 00000000..281c0782 --- /dev/null +++ b/test/github_issue_479.cpp @@ -0,0 +1,23 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// See: https://github.com/cppalliance/int128/issues/479 + +#include +#include + +template +void test() +{ + constexpr auto value = T{1} << 127; + BOOST_TEST_EQ(value, boost::int128::saturating_mul(value, T{1})); +} + +int main() +{ + test(); + test(); + + return boost::report_errors(); +} From 157075bfef51a8ceae91d4afd82b9efc62f40d8e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:01:03 -0400 Subject: [PATCH 05/19] Ignore warning --- examples/math_and_random.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/math_and_random.cpp b/examples/math_and_random.cpp index 4d0f4b4a..fa3e952c 100644 --- a/examples/math_and_random.cpp +++ b/examples/math_and_random.cpp @@ -12,9 +12,11 @@ #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wundef" #pragma clang diagnostic ignored "-Wstring-conversion" +#pragma clang diagnostic ignored "-Wsign-conversion" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic ignored "-Wsign-conversion" #endif // end::exclude[] From d2093ef31e64b7f7c822391152ba859b1aae8aee Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:15:32 -0400 Subject: [PATCH 06/19] Use ckd_mul for better saturating mul behavior Closes: #479 --- include/boost/int128/numeric.hpp | 28 +++++++--------------------- test/test_saturating_arith.cpp | 6 +++--- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/include/boost/int128/numeric.hpp b/include/boost/int128/numeric.hpp index 5a184bcb..bff6d6ef 100644 --- a/include/boost/int128/numeric.hpp +++ b/include/boost/int128/numeric.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifndef BOOST_INT128_BUILD_MODULE @@ -140,35 +141,20 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr int128 saturating_sub(con BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr uint128 saturating_mul(const uint128 x, const uint128 y) noexcept { - const auto x_bits {bit_width(x)}; - const auto y_bits {bit_width(y)}; - - if ((x_bits + y_bits) > std::numeric_limits::digits) - { - return (std::numeric_limits::max)(); - } - - return x * y; + uint128 res {}; + return ckd_mul(&res, x, y) ? (std::numeric_limits::max)() : res; } BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr int128 saturating_mul(const int128 x, const int128 y) noexcept { - const auto x_bits {bit_width(static_cast(abs(x)))}; - const auto y_bits {bit_width(static_cast(abs(y)))}; + int128 res {}; + const auto overflowed {ckd_mul(&res, x, y)}; - if ((x_bits + y_bits) > std::numeric_limits::digits) + if (overflowed) { - if ((x < 0) != (y < 0)) - { - return (std::numeric_limits::min)(); - } - else - { - return (std::numeric_limits::max)(); - } + return (x < 0) != (y < 0) ? (std::numeric_limits::min)() : (std::numeric_limits::max)(); } - const int128 res {x * y}; return res; } diff --git a/test/test_saturating_arith.cpp b/test/test_saturating_arith.cpp index 58f20be3..7740b28e 100644 --- a/test/test_saturating_arith.cpp +++ b/test/test_saturating_arith.cpp @@ -347,8 +347,8 @@ void test_mul_sat() boost::int128::int128 x {2}; boost::int128::int128 y {2}; int bit_count {4}; - - while (bit_count < 128) + + while (bit_count <= 128) { const auto sat_res {saturating_mul(x, y)}; BOOST_TEST(sat_res < std::numeric_limits::max()); @@ -381,7 +381,7 @@ void test_mul_sat() boost::int128::int128 y {-2}; int bit_count {4}; - while (bit_count < 128) + while (bit_count <= 128) { const auto sat_res {saturating_mul(x, y)}; BOOST_TEST(sat_res < std::numeric_limits::max()); From 6e7208c9c5efb5ddab576389f6e601600a220fcf Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:19:36 -0400 Subject: [PATCH 07/19] Add reproducer test set --- test/Jamfile | 1 + test/github_issue_480.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 test/github_issue_480.cpp diff --git a/test/Jamfile b/test/Jamfile index 1d42f815..d191bc86 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -143,6 +143,7 @@ run github_issue_377.cpp ; run github_issue_432.cpp ; compile github_issue_477.cpp ; run github_issue_479.cpp ; +compile github_issue_480.cpp ; # Compilation of individual headers compile compile_tests/int128_master_header_compile.cpp ; diff --git a/test/github_issue_480.cpp b/test/github_issue_480.cpp new file mode 100644 index 00000000..274d55b3 --- /dev/null +++ b/test/github_issue_480.cpp @@ -0,0 +1,14 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// See: https://github.com/cppalliance/int128/issues/479 + +#define BOOST_HAS_INT128 +#define BOOST_INT128_NO_BUILTIN_INT128 + +#include + +#ifdef BOOST_INT128_HAS_INT128 +#error "Should not be defined" +#endif From 659e24c8c06435f61b8fdcc279f8a70ece36887b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:20:02 -0400 Subject: [PATCH 08/19] Fix user disabled usage of builtin 128-bit ints Closes: #480 --- include/boost/int128/detail/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/int128/detail/config.hpp b/include/boost/int128/detail/config.hpp index 7770da71..5293d056 100644 --- a/include/boost/int128/detail/config.hpp +++ b/include/boost/int128/detail/config.hpp @@ -25,7 +25,7 @@ // Use 128-bit integers. // The SYCL device target (spir64) has no native 128-bit integer, so on the device pass // we fall back to the portable path (the same one used on platforms without __int128). -#if (defined(BOOST_HAS_INT128) || (defined(__SIZEOF_INT128__) && !defined(_MSC_VER)) && !defined(BOOST_INT128_NO_BUILTIN_INT128)) && !defined(__SYCL_DEVICE_ONLY__) +#if (defined(BOOST_HAS_INT128) || (defined(__SIZEOF_INT128__) && !defined(_MSC_VER))) && !defined(__SYCL_DEVICE_ONLY__) && !defined(BOOST_INT128_NO_BUILTIN_INT128) #define BOOST_INT128_HAS_INT128 From 3efa66f177151eb7d97ef3972d7665413f908415 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:20:12 -0400 Subject: [PATCH 09/19] Update doc on automatic config --- doc/modules/ROOT/pages/config.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/modules/ROOT/pages/config.adoc b/doc/modules/ROOT/pages/config.adoc index fffc150f..5e8c8bfe 100644 --- a/doc/modules/ROOT/pages/config.adoc +++ b/doc/modules/ROOT/pages/config.adoc @@ -93,7 +93,7 @@ They are most useful for writing code that has to adapt to what the platform pro #endif ---- -- `BOOST_INT128_HAS_INT128`: This is defined when compiling on a platform that has builtin `pass:[__int128]` or `pass:[unsigned __int128]` types (e.g. `pass:[__x86_64__]`). +- `BOOST_INT128_HAS_INT128`: This is defined when compiling on a platform that has builtin `pass:[__int128]` or `pass:[unsigned __int128]` types (e.g. `pass:[__x86_64__]`), and not user disabled by `BOOST_INT128_NO_BUILTIN_INT128`. - `BOOST_INT128_ENDIAN_LITTLE_BYTE`: This is defined to `1` when compiling on a little endian architecture, otherwise `0`. From ce0091fd1e02db4f91ede8bd9c689aa9fc45ace3 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:22:11 -0400 Subject: [PATCH 10/19] Fix boost::random type trait overload Closes: #481 --- include/boost/int128/random.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/int128/random.hpp b/include/boost/int128/random.hpp index adc58bdb..abf99dc9 100644 --- a/include/boost/int128/random.hpp +++ b/include/boost/int128/random.hpp @@ -38,7 +38,7 @@ struct make_unsigned template <> struct make_unsigned { - using type = int128::int128; + using type = int128::uint128; }; template From 0ed656f199a143c19f4bc8ea6e43a5d3eb6cf9af Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:29:02 -0400 Subject: [PATCH 11/19] Add spaceship operator testing --- test/test_mixed_type_sign_compare.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/test_mixed_type_sign_compare.cpp b/test/test_mixed_type_sign_compare.cpp index 833e2a8b..7465537e 100644 --- a/test/test_mixed_type_sign_compare.cpp +++ b/test/test_mixed_type_sign_compare.cpp @@ -6,6 +6,10 @@ #include #include +#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR +#include +#endif + #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wsign-compare" @@ -43,6 +47,12 @@ void test_left_unsigned() BOOST_TEST_EQ(lib_lhs >= lib_rhs, builtin_lhs >= builtin_rhs); BOOST_TEST_EQ(lib_lhs < lib_rhs, builtin_lhs < builtin_rhs); BOOST_TEST_EQ(lib_lhs <= lib_rhs, builtin_lhs <= builtin_rhs); + + #ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + + BOOST_TEST((lib_lhs <=> lib_rhs) == (builtin_lhs <=> builtin_rhs)); + + #endif } // Edge cases that the old deviations would have answered differently @@ -81,6 +91,12 @@ void test_right_unsigned() BOOST_TEST_EQ(lib_lhs >= lib_rhs, builtin_lhs >= builtin_rhs); BOOST_TEST_EQ(lib_lhs < lib_rhs, builtin_lhs < builtin_rhs); BOOST_TEST_EQ(lib_lhs <= lib_rhs, builtin_lhs <= builtin_rhs); + + #ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + + BOOST_TEST((lib_lhs <=> lib_rhs) == (builtin_lhs <=> builtin_rhs)); + + #endif } { From 10a95e235b86a4aafdc8a0ed6e5fdbd3de233bc9 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:29:48 -0400 Subject: [PATCH 12/19] Add missing cross type spaceship operator Closes: #482 --- include/boost/int128/detail/conversions.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/int128/detail/conversions.hpp b/include/boost/int128/detail/conversions.hpp index 5d165724..d4e07086 100644 --- a/include/boost/int128/detail/conversions.hpp +++ b/include/boost/int128/detail/conversions.hpp @@ -83,6 +83,16 @@ BOOST_INT128_HOST_DEVICE constexpr bool operator>=(const T lhs, const U rhs) noe return static_cast(lhs) >= static_cast(rhs); } +#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + +template && detail::is_valid_overload_v && !std::is_same::value, bool> = true> +BOOST_INT128_HOST_DEVICE constexpr std::strong_ordering operator<=>(const T lhs, const U rhs) noexcept +{ + return static_cast(lhs) <=> static_cast(rhs); +} + +#endif + //===================================== // Arithmetic Operators //===================================== From 6a11e40004e56b676ef1129e292add9a01cf3e8a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:33:52 -0400 Subject: [PATCH 13/19] div should trap on division by 0 Closes: #483 --- include/boost/int128/cstdlib.hpp | 8 ++++---- test/test_div.cpp | 6 ------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/include/boost/int128/cstdlib.hpp b/include/boost/int128/cstdlib.hpp index a9957487..249fcba6 100644 --- a/include/boost/int128/cstdlib.hpp +++ b/include/boost/int128/cstdlib.hpp @@ -24,9 +24,9 @@ BOOST_INT128_EXPORT struct i128div_t BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr u128div_t div(const uint128 x, const uint128 y) noexcept { - if (BOOST_INT128_UNLIKELY(x == 0U || y == 0U)) + if (y == 0U) { - return u128div_t{0U, 0U}; + BOOST_INT128_UNREACHABLE; } if (x < y) @@ -56,9 +56,9 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr u128div_t div(const uint1 BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr i128div_t div(const int128 x, const int128 y) noexcept { - if (BOOST_INT128_UNLIKELY(x == 0 || y == 0)) + if (y == 0) { - return i128div_t{0, 0}; + BOOST_INT128_UNREACHABLE; } const auto abs_lhs {static_cast(abs(x))}; diff --git a/test/test_div.cpp b/test/test_div.cpp index 1e24106f..dbdcc606 100644 --- a/test/test_div.cpp +++ b/test/test_div.cpp @@ -73,9 +73,6 @@ void test_unsigned_div() uint128 lhs {dist(rng), dist(rng)}; uint128 zero {dist(rng) * 0U, dist(rng) * 0U}; - const auto lhs_num {boost::int128::div(lhs, zero)}; - BOOST_TEST_EQ(lhs_num.quot, 0U); - BOOST_TEST_EQ(lhs_num.rem, 0U); const auto lhs_denom {boost::int128::div(zero, lhs)}; BOOST_TEST_EQ(lhs_denom.quot, 0U); @@ -123,9 +120,6 @@ void test_signed_div() int128 lhs {idist(rng), dist(rng)}; int128 zero {idist(rng) * 0, dist(rng) * 0U}; - const auto lhs_num {boost::int128::div(lhs, zero)}; - BOOST_TEST_EQ(lhs_num.quot, 0); - BOOST_TEST_EQ(lhs_num.rem, 0); const auto lhs_denom {boost::int128::div(zero, lhs)}; BOOST_TEST_EQ(lhs_denom.quot, 0); From 9a3066271585b220af42f1807e4641d4c605bc2f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 10:35:39 -0400 Subject: [PATCH 14/19] Remove leftover BOOST_DECIMAL macro from port Closes: #484 --- include/boost/int128/format.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/int128/format.hpp b/include/boost/int128/format.hpp index d5589f1e..725eecb0 100644 --- a/include/boost/int128/format.hpp +++ b/include/boost/int128/format.hpp @@ -5,7 +5,7 @@ #ifndef BOOST_INT128_FORMAT_HPP #define BOOST_INT128_FORMAT_HPP -#if __has_include() && defined(__cpp_lib_format) && __cpp_lib_format >= 201907L && !defined(BOOST_DECIMAL_DISABLE_CLIB) +#if __has_include() && defined(__cpp_lib_format) && __cpp_lib_format >= 201907L #include #include From 90e34fd3ac3e9d0e91e6fd7b9a9f06c027b9bc10 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 13:25:09 -0400 Subject: [PATCH 15/19] Ignore new MSVC complaints --- test/github_issue_477.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/github_issue_477.cpp b/test/github_issue_477.cpp index 00e6cbb8..12f67924 100644 --- a/test/github_issue_477.cpp +++ b/test/github_issue_477.cpp @@ -6,6 +6,11 @@ #include +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4459) +#endif + constexpr boost::int128::uint128 value{1, 0}; constexpr bool a = value; From 3ce1e88fd4c659ed59fcd3658b607a1683bff439 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 13:39:04 -0400 Subject: [PATCH 16/19] Fix MINGW failure --- include/boost/int128/bit.hpp | 4 ++-- include/boost/int128/detail/clz.hpp | 4 ++-- include/boost/int128/detail/common_mul.hpp | 2 +- include/boost/int128/detail/config.hpp | 4 ++++ include/boost/int128/detail/ctz.hpp | 2 +- include/boost/int128/detail/int128_imp.hpp | 4 ++-- include/boost/int128/detail/uint128_imp.hpp | 4 ++-- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/boost/int128/bit.hpp b/include/boost/int128/bit.hpp index 8c386095..81efd85c 100644 --- a/include/boost/int128/bit.hpp +++ b/include/boost/int128/bit.hpp @@ -144,7 +144,7 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr int popcount(const uint12 return __builtin_popcountll(x.high) + __builtin_popcountll(x.low); - #elif defined(_M_AMD64) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) + #elif defined(_M_AMD64) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) if (BOOST_INT128_IS_CONSTANT_EVALUATED(x)) { @@ -163,7 +163,7 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr int popcount(const uint12 #endif } - #elif defined(_M_IX86) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) + #elif defined(_M_IX86) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) if (BOOST_INT128_IS_CONSTANT_EVALUATED(x)) { diff --git a/include/boost/int128/detail/clz.hpp b/include/boost/int128/detail/clz.hpp index b7ecab8b..eb073872 100644 --- a/include/boost/int128/detail/clz.hpp +++ b/include/boost/int128/detail/clz.hpp @@ -122,7 +122,7 @@ constexpr int countl_impl(unsigned long long x) noexcept return x ? __builtin_clzll(x) : std::numeric_limits::digits; } -#elif (defined(_M_AMD64) || defined(_M_ARM64)) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !(defined(__CUDACC__) && defined(BOOST_INT128_ENABLE_CUDA)) +#elif (defined(_M_AMD64) || defined(_M_ARM64)) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !(defined(__CUDACC__) && defined(BOOST_INT128_ENABLE_CUDA)) constexpr int countl_impl(std::uint32_t x) noexcept { @@ -166,7 +166,7 @@ constexpr int countl_impl(std::uint64_t x) noexcept } } -#elif defined(_M_IX86) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) +#elif defined(_M_IX86) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) constexpr int countl_impl(std::uint32_t x) noexcept { diff --git a/include/boost/int128/detail/common_mul.hpp b/include/boost/int128/detail/common_mul.hpp index 0b361043..b10927be 100644 --- a/include/boost/int128/detail/common_mul.hpp +++ b/include/boost/int128/detail/common_mul.hpp @@ -68,7 +68,7 @@ BOOST_INT128_HOST_DEVICE BOOST_INT128_FORCE_INLINE constexpr std::uint64_t umul( return _umul128(a, b, &hi); - #elif defined(_M_ARM64) && !defined(__CUDA_ARCH__) && !defined(__SYCL_DEVICE_ONLY__) + #elif defined(_M_ARM64) && !defined(__GNUC__) && !defined(__CUDA_ARCH__) && !defined(__SYCL_DEVICE_ONLY__) hi = __umulh(a, b); return a * b; diff --git a/include/boost/int128/detail/config.hpp b/include/boost/int128/detail/config.hpp index 5293d056..e8833458 100644 --- a/include/boost/int128/detail/config.hpp +++ b/include/boost/int128/detail/config.hpp @@ -157,6 +157,10 @@ BOOST_int128EST_EXPORT using builtin_u128 = std::_Unsigned128; # define BOOST_INT128_FORCE_INLINE inline #endif +// MinGW defines the MSVC platform macros (_M_AMD64, _M_IX86, _M_ARM64) for source +// compatibility, but it provides the GNU intrinsics rather than the MSVC ones. Every +// guard selecting an MSVC-only intrinsic (__shiftleft128, _umul128, __umulh, _BitScan*, +// __popcnt*, ...) therefore has to exclude GNU-mode compilers with !defined(__GNUC__). #ifdef __x86_64__ #ifndef BOOST_INT128_BUILD_MODULE diff --git a/include/boost/int128/detail/ctz.hpp b/include/boost/int128/detail/ctz.hpp index 2c78ddcd..7684733d 100644 --- a/include/boost/int128/detail/ctz.hpp +++ b/include/boost/int128/detail/ctz.hpp @@ -109,7 +109,7 @@ BOOST_INT128_HOST_DEVICE constexpr int countr_impl(std::uint32_t x) noexcept #endif -#if (defined(_M_AMD64) || defined(_M_ARM64)) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !BOOST_INT128_HAS_BUILTIN(__builtin_ctz) && !(defined(__CUDACC__) && defined(BOOST_INT128_ENABLE_CUDA)) +#if (defined(_M_AMD64) || defined(_M_ARM64)) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) && !BOOST_INT128_HAS_BUILTIN(__builtin_ctz) && !(defined(__CUDACC__) && defined(BOOST_INT128_ENABLE_CUDA)) constexpr int countr_impl(std::uint64_t x) noexcept { diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 0812b4af..0809c623 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1319,7 +1319,7 @@ BOOST_INT128_HOST_DEVICE int128 intrinsic_ls_impl(const int128 lhs, const Intege # endif - #elif defined(_M_AMD64) + #elif defined(_M_AMD64) && !defined(__GNUC__) if (rhs >= 64) { @@ -1516,7 +1516,7 @@ BOOST_INT128_HOST_DEVICE int128 intrinsic_rs_impl(const int128 lhs, const Intege # endif - #elif defined(_M_AMD64) + #elif defined(_M_AMD64) && !defined(__GNUC__) if (rhs >= 64) { diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 1a7164b2..7061657b 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -2154,7 +2154,7 @@ BOOST_INT128_HOST_DEVICE BOOST_INT128_FORCE_INLINE uint128 msvc_mul(const uint12 return result; } -#elif defined(_M_ARM64) +#elif defined(_M_ARM64) && !defined(__GNUC__) BOOST_INT128_HOST_DEVICE BOOST_INT128_FORCE_INLINE uint128 msvc_mul(const uint128 lhs, const uint128 rhs) noexcept { @@ -2221,7 +2221,7 @@ BOOST_INT128_HOST_DEVICE BOOST_INT128_FORCE_INLINE constexpr uint128 default_mul // s390x intentionally falls through to the synthetic low_word_mul below. Casting to builtin_u128 // makes GCC reconstruct the value through a vector-unit stack round-trip that is several times // slower, and the memcpy path is unsafe for the narrow (scalar rhs) overloads on big-endian. - #elif ((defined(_M_AMD64) && !defined(__GNUC__)) || defined(_M_ARM64)) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) + #elif (defined(_M_AMD64) || defined(_M_ARM64)) && !defined(__GNUC__) && !defined(BOOST_INT128_NO_CONSTEVAL_DETECTION) if (!BOOST_INT128_IS_CONSTANT_EVALUATED(lhs)) { From f4f5a00ee64a8d69912b144f682d70f7e8d95081 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 13:48:24 -0400 Subject: [PATCH 17/19] Fix bad macro exclusions --- include/boost/int128/detail/int128_imp.hpp | 2 +- include/boost/int128/detail/uint128_imp.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 0809c623..e94c7644 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1771,7 +1771,7 @@ BOOST_INT128_HOST_DEVICE BOOST_INT128_FORCE_INLINE constexpr int128 default_sub( return detail::from_bits(result_high, result_low); - #elif defined(__aarch64__) && !defined(__APPLE__) + #elif defined(__aarch64__) && !defined(__APPLE__) && defined(BOOST_INT128_HAS_INT128) // Unsigned wrap for consistent two's-complement semantics return int128{static_cast(lhs) - static_cast(rhs)}; diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 7061657b..5009a6ff 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -458,7 +458,7 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr bool operator==(const uin return lhs.low == rhs.low && lhs.high == rhs.high; - #elif defined (__x86_64__) && !defined(BOOST_INT128_NO_BUILTIN_INT128) + #elif defined(__x86_64__) && defined(BOOST_INT128_HAS_INT128) return static_cast(lhs) == static_cast(rhs); @@ -554,7 +554,7 @@ BOOST_INT128_EXPORT BOOST_INT128_HOST_DEVICE constexpr bool operator!=(const uin return lhs.low != rhs.low || lhs.high != rhs.high; - #elif defined(__x86_64__) && !defined(BOOST_INT128_NO_BUILTIN_INT128) + #elif defined(__x86_64__) && defined(BOOST_INT128_HAS_INT128) return static_cast(lhs) != static_cast(rhs); From 9be96dcdf2efb8bd42c0751e1bbb3dc829ad1754 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 14:19:33 -0400 Subject: [PATCH 18/19] Rename for MSVC --- test/github_issue_477.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/github_issue_477.cpp b/test/github_issue_477.cpp index 12f67924..916e54ed 100644 --- a/test/github_issue_477.cpp +++ b/test/github_issue_477.cpp @@ -11,15 +11,15 @@ # pragma warning(disable:4459) #endif -constexpr boost::int128::uint128 value{1, 0}; +constexpr boost::int128::uint128 unsigned_value{1, 0}; -constexpr bool a = value; +constexpr bool a = unsigned_value; static_assert(a, "Wrong value"); -constexpr bool b(value); +constexpr bool b(unsigned_value); static_assert(b, "Wrong value"); -constexpr bool c = static_cast(value); +constexpr bool c = static_cast(unsigned_value); static_assert(c, "Wrong value"); constexpr boost::int128::int128 signed_value{1, 0}; From 26255c7db69c8c615e9e0c90287989e9c269dcf6 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Fri, 31 Jul 2026 14:43:52 -0400 Subject: [PATCH 19/19] Fix macro redefinition --- test/github_issue_480.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/github_issue_480.cpp b/test/github_issue_480.cpp index 274d55b3..869f7168 100644 --- a/test/github_issue_480.cpp +++ b/test/github_issue_480.cpp @@ -5,7 +5,10 @@ // See: https://github.com/cppalliance/int128/issues/479 #define BOOST_HAS_INT128 + +#ifndef BOOST_INT128_NO_BUILTIN_INT128 #define BOOST_INT128_NO_BUILTIN_INT128 +#endif #include