Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <cuda/numeric>
#include <cuda/std/cassert>
#include <cuda/std/cstdint>
#include <cuda/std/limits>
#include <cuda/std/tuple>
#include <cuda/std/type_traits>
Expand Down Expand Up @@ -83,6 +84,7 @@ TEST_FUNC constexpr bool test_type()
test_mul_overflow<Res, L, R>(17, 14, 238);
test_mul_overflow<Res, L, R>(-254, 127, -32258);
test_mul_overflow<Res, L, R>(1657, -13748, -22780436);
test_mul_overflow<Res, L, R>(-50000, -50000, 2500000000);
test_mul_overflow<Res, L, R>(-2147483647, 4294967295, -9223372030412324865);
if constexpr (cuda::std::is_unsigned_v<L> && cuda::std::is_unsigned_v<Res>)
{
Expand All @@ -93,6 +95,44 @@ TEST_FUNC constexpr bool test_type()
sizeof(L) >= sizeof(Res));
}

// 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))
{
constexpr auto __max_nbits = cuda::std::max(cuda::std::__num_bits_v<L>, cuda::std::__num_bits_v<R>);
using _Up = cuda::std::__make_nbit_int_t<2 * __max_nbits, cuda::std::is_signed_v<L> || cuda::std::is_signed_v<R>>;
test_mul_overflow<Res, L, R>(cuda::std::numeric_limits<L>::min(),
cuda::std::numeric_limits<R>::min(),
_Up{cuda::std::numeric_limits<L>::min()} * _Up{cuda::std::numeric_limits<R>::min()});
test_mul_overflow<Res, L, R>(cuda::std::numeric_limits<L>::max(),
cuda::std::numeric_limits<R>::max(),
_Up{cuda::std::numeric_limits<L>::max()} * _Up{cuda::std::numeric_limits<R>::max()});
}

#if _CCCL_HAS_INT128()
// 6. Test __uint128_t multiplication and overflow cases
if constexpr (cuda::std::is_same_v<Res, __uint128_t> && cuda::std::is_same_v<R, __uint128_t>)
{
if constexpr (cuda::std::is_same_v<L, __uint128_t>)
{
test_mul_overflow<Res, L, R>(
__uint128_t{~0ull}, // 2^64 - 1
__uint128_t{1ull} << 63, // 2^63
(__uint128_t{0x7fffffffffffffffULL} << 64) | __uint128_t{0x8000000000000000ULL},
false);
test_mul_overflow<Res, L, R>(__uint128_t{1} << 100, __uint128_t{1} << 100, __uint128_t{0}, true);
test_mul_overflow<Res, L, R>(
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<L, unsigned long long>)
{
test_mul_overflow<Res, L, R>(
~0ull, __uint128_t{5} << 100, __uint128_t{0xffffffb000000000ULL} << 64 | __uint128_t{0}, true);
}
}
#endif // _CCCL_HAS_INT128()
return true;
}

Expand All @@ -102,7 +142,7 @@ using TypeList = cuda::std::tuple<
short,
unsigned short,
int,
unsigned long,
unsigned int,
long,
unsigned long,
long long,
Expand Down