From 32c21be6d0691a4d9b14fc0ff3b6fb41448a75be Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Fri, 10 Jul 2026 11:20:57 -0500 Subject: [PATCH 1/7] Test for corner-cases in mul_overflow.pass.cpp --- .../overflow.arithmetic/mul_overflow.pass.cpp | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index bd2b1ea2c17..18bb7f7f89b 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -92,17 +92,71 @@ TEST_FUNC constexpr bool test_type() static_cast(cuda::std::numeric_limits::max()) << 2, sizeof(L) >= sizeof(Res)); } - return true; } +TEST_FUNC constexpr void test_corner_cases() +{ + constexpr auto int_max = cuda::std::numeric_limits::max(); + constexpr auto int_min = cuda::std::numeric_limits::min(); + constexpr auto uint_max = cuda::std::numeric_limits::max(); + + // 1. Boundary edge-cases + test_mul_overflow(int_min, 0, 0, false); + test_mul_overflow(0, int_max, 0, false); + test_mul_overflow(-1, int_min, int_min, true); + test_mul_overflow(int_min, -1, int_min, true); + test_mul_overflow(int_min, int_min, 0, true); + test_mul_overflow(2, int_max, static_cast(int_max) * 2u, false); + test_mul_overflow(uint_max, 2u, uint_max - 1, true); + + // 2. Explicit wider Result type + test_mul_overflow(int_min, -1, int64_t{int_min} * (-1ll), false); + test_mul_overflow( + int_min, int_min, static_cast(int_min) * static_cast(int_min), false); + test_mul_overflow( + static_cast(uint_max), static_cast(uint_max), static_cast(uint_max * uint_max), false); + test_mul_overflow( + uint_max, uint_max, static_cast(uint_max) * static_cast(uint_max), false); + test_mul_overflow(uint_max, uint_max, -8589934591, true); + + // 3. Both operands negative, large magnitude (non-overflow and overflow) + test_mul_overflow(-40000, -50000, 2000000000, false); + test_mul_overflow(-50000, -50000, -1794967296, true); + + // 4. Overflow from downcasting + test_mul_overflow(1000, 1000, static_cast(64), true); + test_mul_overflow( + static_cast(17), static_cast(14), static_cast(-18), true); + + // 5. __uint128_t + const auto uint128_max = ~static_cast<__uint128_t>(0); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>(3, 4, 12, false); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( + static_cast<__uint128_t>(~0ull), // 2^64 - 1 + static_cast<__uint128_t>(1ull) << 63, // 2^63 + (static_cast<__uint128_t>(0x7fffffffffffffffULL) << 64) | static_cast<__uint128_t>(0x8000000000000000ULL), + false); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( + static_cast<__uint128_t>(1) << 100, static_cast<__uint128_t>(1) << 100, static_cast<__uint128_t>(0), true); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( + uint128_max, static_cast<__uint128_t>(2), uint128_max - 1, true); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( + uint128_max, static_cast<__uint128_t>(0), static_cast<__uint128_t>(0), false); + test_mul_overflow<__uint128_t, long long, __uint128_t>( + ~0ull, + static_cast<__uint128_t>(5) << 100, + (static_cast<__uint128_t>(0xffffffb000000000ULL) << 64) | static_cast<__uint128_t>(0), + false); +} + using TypeList = cuda::std::tuple< signed char, unsigned char, short, unsigned short, int, - unsigned long, + unsigned int, long, unsigned long, long long, @@ -117,11 +171,11 @@ using TypeList = cuda::std::tuple< using TypeListIndexSeq = cuda::std::make_index_sequence>; template -TEST_FUNC constexpr void test(cuda::std::index_sequence) +TEST_FUNC constexpr void test_exhaustive(cuda::std::index_sequence) { if constexpr (sizeof...(Ts) < 3) { - (test>(TypeListIndexSeq{}), ...); + (test_exhaustive>(TypeListIndexSeq{}), ...); } else { @@ -132,6 +186,7 @@ TEST_FUNC constexpr void test(cuda::std::index_sequence) int main(int arg, char** argv) { - test(TypeListIndexSeq{}); + test_exhaustive(TypeListIndexSeq{}); + test_corner_cases(); return 0; } From a478b26c8b8d296bc7a71e9f51f6c5646fe97678 Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Fri, 10 Jul 2026 17:35:29 -0500 Subject: [PATCH 2/7] Wrap __uint128_t tests in _CCCL_HAS_INT128 pragma block --- .../cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index 18bb7f7f89b..1814a1dff1d 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -129,8 +129,10 @@ TEST_FUNC constexpr void test_corner_cases() test_mul_overflow( static_cast(17), static_cast(14), static_cast(-18), true); +#if _CCCL_HAS_INT128() // 5. __uint128_t - const auto uint128_max = ~static_cast<__uint128_t>(0); + constexpr auto uint128_max = cuda::std::numeric_limits<__uint128_t>::max(); + test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>(3, 4, 12, false); test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( static_cast<__uint128_t>(~0ull), // 2^64 - 1 @@ -148,6 +150,7 @@ TEST_FUNC constexpr void test_corner_cases() static_cast<__uint128_t>(5) << 100, (static_cast<__uint128_t>(0xffffffb000000000ULL) << 64) | static_cast<__uint128_t>(0), false); +#endif // _CCCL_HAS_INT128() } using TypeList = cuda::std::tuple< From a5127d05f862d89c9e64f4ccfdde54add0d17b4b Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Fri, 10 Jul 2026 17:36:19 -0500 Subject: [PATCH 3/7] Make sure operand types match template types --- .../cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index 1814a1dff1d..963064933c5 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -108,7 +108,7 @@ TEST_FUNC constexpr void test_corner_cases() test_mul_overflow(int_min, -1, int_min, true); test_mul_overflow(int_min, int_min, 0, true); test_mul_overflow(2, int_max, static_cast(int_max) * 2u, false); - test_mul_overflow(uint_max, 2u, uint_max - 1, true); + test_mul_overflow(uint_max, 2ull, uint_max - 1ull, true); // 2. Explicit wider Result type test_mul_overflow(int_min, -1, int64_t{int_min} * (-1ll), false); @@ -145,11 +145,11 @@ TEST_FUNC constexpr void test_corner_cases() uint128_max, static_cast<__uint128_t>(2), uint128_max - 1, true); test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( uint128_max, static_cast<__uint128_t>(0), static_cast<__uint128_t>(0), false); - test_mul_overflow<__uint128_t, long long, __uint128_t>( + test_mul_overflow<__uint128_t, unsigned long long, __uint128_t>( ~0ull, static_cast<__uint128_t>(5) << 100, (static_cast<__uint128_t>(0xffffffb000000000ULL) << 64) | static_cast<__uint128_t>(0), - false); + true); #endif // _CCCL_HAS_INT128() } From ece89392a3d7605746784981da216f890aec8eb4 Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Fri, 10 Jul 2026 18:16:50 -0500 Subject: [PATCH 4/7] Explicitly use fixed-width integer types --- .../overflow.arithmetic/mul_overflow.pass.cpp | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index 963064933c5..aaed82b04a3 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -97,21 +98,28 @@ TEST_FUNC constexpr bool test_type() TEST_FUNC constexpr void test_corner_cases() { - constexpr auto int_max = cuda::std::numeric_limits::max(); - constexpr auto int_min = cuda::std::numeric_limits::min(); - constexpr auto uint_max = cuda::std::numeric_limits::max(); + using cuda::std::int32_t; + using cuda::std::int64_t; + using cuda::std::int8_t; + using cuda::std::uint32_t; + using cuda::std::uint64_t; + using cuda::std::uint8_t; + + constexpr auto int_max = cuda::std::numeric_limits::max(); + constexpr auto int_min = cuda::std::numeric_limits::min(); + constexpr auto uint_max = cuda::std::numeric_limits::max(); // 1. Boundary edge-cases - test_mul_overflow(int_min, 0, 0, false); - test_mul_overflow(0, int_max, 0, false); - test_mul_overflow(-1, int_min, int_min, true); - test_mul_overflow(int_min, -1, int_min, true); - test_mul_overflow(int_min, int_min, 0, true); - test_mul_overflow(2, int_max, static_cast(int_max) * 2u, false); - test_mul_overflow(uint_max, 2ull, uint_max - 1ull, true); + test_mul_overflow(int_min, 0, 0, false); + test_mul_overflow(0, int_max, 0, false); + test_mul_overflow(-1, int_min, int_min, true); + test_mul_overflow(int_min, -1, int_min, true); + test_mul_overflow(int_min, int_min, 0, true); + test_mul_overflow(2, int_max, static_cast(int_max) * 2u, false); + test_mul_overflow(uint_max, 2ull, uint_max - 1ull, true); // 2. Explicit wider Result type - test_mul_overflow(int_min, -1, int64_t{int_min} * (-1ll), false); + test_mul_overflow(int_min, -1, static_cast(int_min) * (-1ll), false); test_mul_overflow( int_min, int_min, static_cast(int_min) * static_cast(int_min), false); test_mul_overflow( @@ -121,13 +129,13 @@ TEST_FUNC constexpr void test_corner_cases() test_mul_overflow(uint_max, uint_max, -8589934591, true); // 3. Both operands negative, large magnitude (non-overflow and overflow) - test_mul_overflow(-40000, -50000, 2000000000, false); - test_mul_overflow(-50000, -50000, -1794967296, true); + test_mul_overflow(-40000, -50000, 2000000000, false); + test_mul_overflow(-50000, -50000, -1794967296, true); // 4. Overflow from downcasting test_mul_overflow(1000, 1000, static_cast(64), true); - test_mul_overflow( - static_cast(17), static_cast(14), static_cast(-18), true); + test_mul_overflow( + static_cast(17), static_cast(14), static_cast(-18), true); #if _CCCL_HAS_INT128() // 5. __uint128_t @@ -145,7 +153,7 @@ TEST_FUNC constexpr void test_corner_cases() uint128_max, static_cast<__uint128_t>(2), uint128_max - 1, true); test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( uint128_max, static_cast<__uint128_t>(0), static_cast<__uint128_t>(0), false); - test_mul_overflow<__uint128_t, unsigned long long, __uint128_t>( + test_mul_overflow<__uint128_t, uint64_t, __uint128_t>( ~0ull, static_cast<__uint128_t>(5) << 100, (static_cast<__uint128_t>(0xffffffb000000000ULL) << 64) | static_cast<__uint128_t>(0), From cbf6542f7fb060a038b16a92f3a65eab5c5869d1 Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Mon, 13 Jul 2026 22:07:12 -0500 Subject: [PATCH 5/7] Clean up test corner-cases using generics --- .../overflow.arithmetic/mul_overflow.pass.cpp | 101 +++++++++--------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index aaed82b04a3..42b5fa4c98d 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -98,66 +98,67 @@ TEST_FUNC constexpr bool test_type() TEST_FUNC constexpr void test_corner_cases() { - using cuda::std::int32_t; - using cuda::std::int64_t; - using cuda::std::int8_t; - using cuda::std::uint32_t; - using cuda::std::uint64_t; - using cuda::std::uint8_t; - - constexpr auto int_max = cuda::std::numeric_limits::max(); - constexpr auto int_min = cuda::std::numeric_limits::min(); - constexpr auto uint_max = cuda::std::numeric_limits::max(); - // 1. Boundary edge-cases - test_mul_overflow(int_min, 0, 0, false); - test_mul_overflow(0, int_max, 0, false); - test_mul_overflow(-1, int_min, int_min, true); - test_mul_overflow(int_min, -1, int_min, true); - test_mul_overflow(int_min, int_min, 0, true); - test_mul_overflow(2, int_max, static_cast(int_max) * 2u, false); - test_mul_overflow(uint_max, 2ull, uint_max - 1ull, true); + { + using T = cuda::std::int32_t; + using U = cuda::std::uint32_t; + constexpr auto max = cuda::std::numeric_limits::max(); + constexpr auto min = cuda::std::numeric_limits::min(); + constexpr auto umax = cuda::std::numeric_limits::max(); + test_mul_overflow(min, min, T{0}, true); + test_mul_overflow(2, max, U{max} * 2u, false); + test_mul_overflow(umax, 2ull, umax - 1ull, true); + } // 2. Explicit wider Result type - test_mul_overflow(int_min, -1, static_cast(int_min) * (-1ll), false); - test_mul_overflow( - int_min, int_min, static_cast(int_min) * static_cast(int_min), false); - test_mul_overflow( - static_cast(uint_max), static_cast(uint_max), static_cast(uint_max * uint_max), false); - test_mul_overflow( - uint_max, uint_max, static_cast(uint_max) * static_cast(uint_max), false); - test_mul_overflow(uint_max, uint_max, -8589934591, true); + { + using T = cuda::std::int32_t; + using T2x = cuda::std::int64_t; + using U = cuda::std::uint32_t; + using U2x = cuda::std::uint64_t; + constexpr auto min = cuda::std::numeric_limits::min(); + constexpr auto umax = cuda::std::numeric_limits::max(); + test_mul_overflow(min, -1, T2x{min} * (-1ll), false); + test_mul_overflow(min, min, T2x{min} * T2x{min}, false); + test_mul_overflow(T{umax}, T{umax}, T2x{umax * umax}, false); + test_mul_overflow(umax, umax, U2x{umax} * U2x{umax}, false); + test_mul_overflow(umax, umax, -8589934591, true); + } // 3. Both operands negative, large magnitude (non-overflow and overflow) - test_mul_overflow(-40000, -50000, 2000000000, false); - test_mul_overflow(-50000, -50000, -1794967296, true); + { + using T = cuda::std::int32_t; + test_mul_overflow(-40000, -50000, 2000000000, false); + test_mul_overflow(-50000, -50000, -1794967296, true); + } // 4. Overflow from downcasting - test_mul_overflow(1000, 1000, static_cast(64), true); - test_mul_overflow( - static_cast(17), static_cast(14), static_cast(-18), true); + { + using T = cuda::std::int8_t; + using T4x = cuda::std::int32_t; + using U4x = cuda::std::uint32_t; + test_mul_overflow(1000, 1000, T{64}, true); + test_mul_overflow(T{17}, U4x{14}, T{-18}, true); + } #if _CCCL_HAS_INT128() // 5. __uint128_t - constexpr auto uint128_max = cuda::std::numeric_limits<__uint128_t>::max(); - - test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>(3, 4, 12, false); - test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( - static_cast<__uint128_t>(~0ull), // 2^64 - 1 - static_cast<__uint128_t>(1ull) << 63, // 2^63 - (static_cast<__uint128_t>(0x7fffffffffffffffULL) << 64) | static_cast<__uint128_t>(0x8000000000000000ULL), - false); - test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( - static_cast<__uint128_t>(1) << 100, static_cast<__uint128_t>(1) << 100, static_cast<__uint128_t>(0), true); - test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( - uint128_max, static_cast<__uint128_t>(2), uint128_max - 1, true); - test_mul_overflow<__uint128_t, __uint128_t, __uint128_t>( - uint128_max, static_cast<__uint128_t>(0), static_cast<__uint128_t>(0), false); - test_mul_overflow<__uint128_t, uint64_t, __uint128_t>( - ~0ull, - static_cast<__uint128_t>(5) << 100, - (static_cast<__uint128_t>(0xffffffb000000000ULL) << 64) | static_cast<__uint128_t>(0), - true); + { + using U = cuda::std::uint64_t; + using U2x = __uint128_t; + constexpr auto umax2x = cuda::std::numeric_limits::max(); + + test_mul_overflow(3, 4, 12, false); + test_mul_overflow( + U2x{~0ull}, // 2^64 - 1 + U2x{1ull} << 63, // 2^63 + (U2x{0x7fffffffffffffffULL} << 64) | U2x{0x8000000000000000ULL}, + false); + test_mul_overflow(U2x{1} << 100, U2x{1} << 100, U2x{0}, true); + test_mul_overflow(umax2x, U2x{2}, umax2x - 1, true); + test_mul_overflow(umax2x, U2x{0}, U2x{0}, false); + test_mul_overflow(~0ull, U2x{5} << 100, (U2x{0xffffffb000000000ULL} << 64) | U2x{0}, true); + } #endif // _CCCL_HAS_INT128() } From 98ee6644dec23e12685b3196b0ac78daefbf8730 Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Mon, 13 Jul 2026 22:36:26 -0500 Subject: [PATCH 6/7] Improve type usage testing multiplying int32_t::max --- .../cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index 42b5fa4c98d..3b1d7c68ad8 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -117,10 +117,11 @@ TEST_FUNC constexpr void test_corner_cases() using U = cuda::std::uint32_t; using U2x = cuda::std::uint64_t; constexpr auto min = cuda::std::numeric_limits::min(); + constexpr auto max = cuda::std::numeric_limits::max(); constexpr auto umax = cuda::std::numeric_limits::max(); test_mul_overflow(min, -1, T2x{min} * (-1ll), false); test_mul_overflow(min, min, T2x{min} * T2x{min}, false); - test_mul_overflow(T{umax}, T{umax}, T2x{umax * umax}, false); + test_mul_overflow(max, max, T2x{max} * T2x{max}, false); test_mul_overflow(umax, umax, U2x{umax} * U2x{umax}, false); test_mul_overflow(umax, umax, -8589934591, true); } From 513c0556e72ef0af4fc94b174580e5ce10ab20ee Mon Sep 17 00:00:00 2001 From: Andres Guzman-Ballen Date: Thu, 16 Jul 2026 17:33:15 -0500 Subject: [PATCH 7/7] Generalize corner-case tests --- .../overflow.arithmetic/mul_overflow.pass.cpp | 100 +++++++----------- 1 file changed, 36 insertions(+), 64 deletions(-) diff --git a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp index 3b1d7c68ad8..bc0f6950275 100644 --- a/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp +++ b/libcudacxx/test/libcudacxx/cuda/numeric/overflow.arithmetic/mul_overflow.pass.cpp @@ -84,6 +84,7 @@ TEST_FUNC constexpr bool test_type() test_mul_overflow(17, 14, 238); test_mul_overflow(-254, 127, -32258); test_mul_overflow(1657, -13748, -22780436); + test_mul_overflow(-50000, -50000, 2500000000); test_mul_overflow(-2147483647, 4294967295, -9223372030412324865); if constexpr (cuda::std::is_unsigned_v && cuda::std::is_unsigned_v) { @@ -93,74 +94,46 @@ TEST_FUNC constexpr bool test_type() static_cast(cuda::std::numeric_limits::max()) << 2, sizeof(L) >= sizeof(Res)); } - return true; -} -TEST_FUNC constexpr void test_corner_cases() -{ - // 1. Boundary edge-cases + // 5. Test T_MIN * T_MIN and T_MAX * T_MAX + if constexpr (sizeof(L) < sizeof(cuda::std::__cccl_uintmax_t) && sizeof(R) < sizeof(cuda::std::__cccl_uintmax_t)) { - using T = cuda::std::int32_t; - using U = cuda::std::uint32_t; - constexpr auto max = cuda::std::numeric_limits::max(); - constexpr auto min = cuda::std::numeric_limits::min(); - constexpr auto umax = cuda::std::numeric_limits::max(); - test_mul_overflow(min, min, T{0}, true); - test_mul_overflow(2, max, U{max} * 2u, false); - test_mul_overflow(umax, 2ull, umax - 1ull, true); - } - - // 2. Explicit wider Result type - { - using T = cuda::std::int32_t; - using T2x = cuda::std::int64_t; - using U = cuda::std::uint32_t; - using U2x = cuda::std::uint64_t; - constexpr auto min = cuda::std::numeric_limits::min(); - constexpr auto max = cuda::std::numeric_limits::max(); - constexpr auto umax = cuda::std::numeric_limits::max(); - test_mul_overflow(min, -1, T2x{min} * (-1ll), false); - test_mul_overflow(min, min, T2x{min} * T2x{min}, false); - test_mul_overflow(max, max, T2x{max} * T2x{max}, false); - test_mul_overflow(umax, umax, U2x{umax} * U2x{umax}, false); - test_mul_overflow(umax, umax, -8589934591, true); - } - - // 3. Both operands negative, large magnitude (non-overflow and overflow) - { - using T = cuda::std::int32_t; - test_mul_overflow(-40000, -50000, 2000000000, false); - test_mul_overflow(-50000, -50000, -1794967296, true); - } - - // 4. Overflow from downcasting - { - using T = cuda::std::int8_t; - using T4x = cuda::std::int32_t; - using U4x = cuda::std::uint32_t; - test_mul_overflow(1000, 1000, T{64}, true); - test_mul_overflow(T{17}, U4x{14}, T{-18}, true); + constexpr auto __max_nbits = cuda::std::max(cuda::std::__num_bits_v, cuda::std::__num_bits_v); + using _Up = cuda::std::__make_nbit_int_t<2 * __max_nbits, cuda::std::is_signed_v || cuda::std::is_signed_v>; + test_mul_overflow(cuda::std::numeric_limits::min(), + cuda::std::numeric_limits::min(), + _Up{cuda::std::numeric_limits::min()} * _Up{cuda::std::numeric_limits::min()}); + test_mul_overflow(cuda::std::numeric_limits::max(), + cuda::std::numeric_limits::max(), + _Up{cuda::std::numeric_limits::max()} * _Up{cuda::std::numeric_limits::max()}); } #if _CCCL_HAS_INT128() - // 5. __uint128_t + // 6. Test __uint128_t multiplication and overflow cases + if constexpr (cuda::std::is_same_v && cuda::std::is_same_v) { - using U = cuda::std::uint64_t; - using U2x = __uint128_t; - constexpr auto umax2x = cuda::std::numeric_limits::max(); - - test_mul_overflow(3, 4, 12, false); - test_mul_overflow( - U2x{~0ull}, // 2^64 - 1 - U2x{1ull} << 63, // 2^63 - (U2x{0x7fffffffffffffffULL} << 64) | U2x{0x8000000000000000ULL}, - false); - test_mul_overflow(U2x{1} << 100, U2x{1} << 100, U2x{0}, true); - test_mul_overflow(umax2x, U2x{2}, umax2x - 1, true); - test_mul_overflow(umax2x, U2x{0}, U2x{0}, false); - test_mul_overflow(~0ull, U2x{5} << 100, (U2x{0xffffffb000000000ULL} << 64) | U2x{0}, true); + if constexpr (cuda::std::is_same_v) + { + test_mul_overflow( + __uint128_t{~0ull}, // 2^64 - 1 + __uint128_t{1ull} << 63, // 2^63 + (__uint128_t{0x7fffffffffffffffULL} << 64) | __uint128_t{0x8000000000000000ULL}, + false); + test_mul_overflow(__uint128_t{1} << 100, __uint128_t{1} << 100, __uint128_t{0}, true); + test_mul_overflow( + cuda::std::numeric_limits<__uint128_t>::max(), + __uint128_t{2}, + cuda::std::numeric_limits<__uint128_t>::max() - 1, + true); + } + else if constexpr (cuda::std::is_same_v) + { + test_mul_overflow( + ~0ull, __uint128_t{5} << 100, __uint128_t{0xffffffb000000000ULL} << 64 | __uint128_t{0}, true); + } } #endif // _CCCL_HAS_INT128() + return true; } using TypeList = cuda::std::tuple< @@ -184,11 +157,11 @@ using TypeList = cuda::std::tuple< using TypeListIndexSeq = cuda::std::make_index_sequence>; template -TEST_FUNC constexpr void test_exhaustive(cuda::std::index_sequence) +TEST_FUNC constexpr void test(cuda::std::index_sequence) { if constexpr (sizeof...(Ts) < 3) { - (test_exhaustive>(TypeListIndexSeq{}), ...); + (test>(TypeListIndexSeq{}), ...); } else { @@ -199,7 +172,6 @@ TEST_FUNC constexpr void test_exhaustive(cuda::std::index_sequence) int main(int arg, char** argv) { - test_exhaustive(TypeListIndexSeq{}); - test_corner_cases(); + test(TypeListIndexSeq{}); return 0; }