Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport std integer comparison functions to C++11 #2805

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
613b062
backport std integer comparison functions to C++11
davebayer Nov 13, 2024
ae61685
Merge branch 'main' into backport_std_int_comp_funcs
davebayer Nov 13, 2024
76c88ba
fix sfinae
davebayer Nov 13, 2024
e14acb2
add missing `integral_constant.h` include
davebayer Nov 13, 2024
d8d3df9
add missing `_LIBCUDACXX_HIDE_FROM_ABI`
davebayer Nov 13, 2024
0812f59
change target c++ version to 14, use `_CCCL_TRAIT` for standard type …
davebayer Nov 14, 2024
7783358
fix typo
davebayer Nov 14, 2024
f6dc313
suppress MSVC warnings
davebayer Nov 14, 2024
d1360b7
Address review feedback
miscco Nov 15, 2024
dd928c6
Add missing include
miscco Nov 15, 2024
518920f
Fix invalid initialization issue with helper struct
miscco Nov 15, 2024
b2aacd8
Make tests work in C++14
miscco Nov 15, 2024
d560a77
Try and inhibit warning
miscco Nov 15, 2024
5e4be4a
Move implementation of `_LIBCUDACXX_TEMPLATE` to CCCL
miscco Nov 15, 2024
1a424d6
Just avoid the whole warning entirely and let the optimizer do the thing
miscco Nov 15, 2024
be9b176
Merge branch 'main' into pr/davebayer/2805
miscco Nov 15, 2024
bab2c75
Merge branch 'cccl_template_emulation' into pr/davebayer/2805
miscco Nov 15, 2024
40988e8
Make it work in C++11
miscco Nov 15, 2024
e97795a
Avoid old nvcc issues
miscco Nov 15, 2024
abfa826
Pacify MSVC
miscco Nov 15, 2024
f44ac1b
Merge branch 'main' into backport_std_int_comp_funcs
davebayer Nov 17, 2024
3fdfab3
Move implementation of `_LIBCUDACXX_TEMPLATE` to CCCL
miscco Nov 15, 2024
11cd4e7
Move back to the `concept_macros` file
miscco Nov 18, 2024
6093df2
Merge commit '11cd4e7ac1738f0ba3808a6e58be29317d1e58f4' into pr/daveb…
miscco Nov 18, 2024
4266526
Fix formatting
miscco Nov 18, 2024
01e610c
fix concept macros include
davebayer Nov 18, 2024
f2a175a
Merge branch 'main' into backport_std_int_comp_funcs
davebayer Nov 21, 2024
18e562d
Merge branch 'main' into backport_std_int_comp_funcs
miscco Nov 22, 2024
9422d15
Merge branch 'main' into backport_std_int_comp_funcs
davebayer Nov 25, 2024
a7a39e1
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Nov 25, 2024
4f25558
fix compilation for old nvcc
davebayer Nov 26, 2024
eaa609e
Merge branch 'main' into backport_std_int_comp_funcs
davebayer Nov 26, 2024
a4231e1
Drop newline
miscco Nov 26, 2024
8381859
fix msvc warnings once again
davebayer Nov 26, 2024
890cb8a
change implementation of `if constexpr`
davebayer Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 63 additions & 32 deletions libcudacxx/include/cuda/std/__utility/cmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
# pragma system_header
#endif // no system header

#include <cuda/std/__concepts/concept_macros.h>
#include <cuda/std/__type_traits/disjunction.h>
#include <cuda/std/__type_traits/enable_if.h>
#include <cuda/std/__type_traits/integral_constant.h>
#include <cuda/std/__type_traits/is_integral.h>
#include <cuda/std/__type_traits/is_same.h>
#include <cuda/std/__type_traits/is_signed.h>
Expand All @@ -31,99 +34,127 @@

_CCCL_PUSH_MACROS

_CCCL_DIAG_PUSH
_CCCL_DIAG_SUPPRESS_MSVC(4018) // required cast from signed to unsigned
_CCCL_DIAG_SUPPRESS_MSVC(4388) // required cast from signed to larger unsigned
_CCCL_DIAG_SUPPRESS_MSVC(4389) // signed/unsigned mismatch for == and !=

_LIBCUDACXX_BEGIN_NAMESPACE_STD

#if _CCCL_STD_VER > 2017
template <class _Tp, class... _Up>
struct _IsSameAsAny : _Or<_IsSame<_Tp, _Up>...>
{};
using __is_same_as_any = __fold_or<_CCCL_TRAIT(is_same, _Tp, _Up)...>;

template <class _Tp>
concept __is_safe_integral_cmp =
is_integral_v<_Tp>
&& !_IsSameAsAny<_Tp,
bool,
char,
char16_t,
char32_t
# ifndef _LIBCUDACXX_NO_HAS_CHAR8_T
,
char8_t
# endif
# ifndef _LIBCUDACXX_HAS_NO_WIDE_CHARACTERS
,
wchar_t
# endif
>::value;

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
struct __is_safe_integral_cmp
: bool_constant<_CCCL_TRAIT(is_integral, _Tp)
&& !__is_same_as_any<_Tp,
bool,
char,
char16_t,
char32_t
#ifndef _LIBCUDACXX_NO_HAS_CHAR8_T
,
char8_t
#endif // _LIBCUDACXX_NO_HAS_CHAR8_T
#ifndef _LIBCUDACXX_HAS_NO_WIDE_CHARACTERS
,
wchar_t
#endif // _LIBCUDACXX_HAS_NO_WIDE_CHARACTERS
>::value>
{};

_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_equal(_Tp __t, _Up __u) noexcept
{
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
#if !defined(_CCCL_NO_IF_CONSTEXPR)
if constexpr (_CCCL_TRAIT(is_signed, _Tp) == _CCCL_TRAIT(is_signed, _Up))
{
return __t == __u;
}
else if constexpr (is_signed_v<_Tp>)
else if constexpr (_CCCL_TRAIT(is_signed, _Tp))
{
return __t < 0 ? false : make_unsigned_t<_Tp>(__t) == __u;
}
else
{
return __u < 0 ? false : __t == make_unsigned_t<_Up>(__u);
}
_CCCL_UNREACHABLE();
#else // ^^^ !_CCCL_NO_IF_CONSTEXPR ^^^ / vvv _CCCL_NO_IF_CONSTEXPR vvv
return ((_CCCL_TRAIT(is_signed, _Tp) == _CCCL_TRAIT(is_signed, _Up))
? (__t == __u)
: (_CCCL_TRAIT(is_signed, _Tp) ? (__t < 0 ? false : make_unsigned_t<_Tp>(__t) == __u)
: (__u < 0 ? false : __t == make_unsigned_t<_Up>(__u))));
#endif // _CCCL_NO_IF_CONSTEXPR
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_not_equal(_Tp __t, _Up __u) noexcept
{
return !_CUDA_VSTD::cmp_equal(__t, __u);
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_less(_Tp __t, _Up __u) noexcept
{
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
#if !defined(_CCCL_NO_IF_CONSTEXPR)
if constexpr (_CCCL_TRAIT(is_signed, _Tp) == _CCCL_TRAIT(is_signed, _Up))
{
return __t < __u;
}
else if constexpr (is_signed_v<_Tp>)
else if constexpr (_CCCL_TRAIT(is_signed, _Tp))
{
return __t < 0 ? true : make_unsigned_t<_Tp>(__t) < __u;
}
else
{
return __u < 0 ? false : __t < make_unsigned_t<_Up>(__u);
}
_CCCL_UNREACHABLE();
#else // ^^^ !_CCCL_NO_IF_CONSTEXPR ^^^ / vvv _CCCL_NO_IF_CONSTEXPR vvv
return ((_CCCL_TRAIT(is_signed, _Tp) == _CCCL_TRAIT(is_signed, _Up))
? (__t < __u)
: (_CCCL_TRAIT(is_signed, _Tp) ? (__t < 0 ? true : make_unsigned_t<_Tp>(__t) < __u)
: (__u < 0 ? false : __t < make_unsigned_t<_Up>(__u))));
#endif // _CCCL_NO_IF_CONSTEXPR
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_greater(_Tp __t, _Up __u) noexcept
{
return _CUDA_VSTD::cmp_less(__u, __t);
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_less_equal(_Tp __t, _Up __u) noexcept
{
return !_CUDA_VSTD::cmp_greater(__t, __u);
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool cmp_greater_equal(_Tp __t, _Up __u) noexcept
{
return !_CUDA_VSTD::cmp_less(__t, __u);
}

template <__is_safe_integral_cmp _Tp, __is_safe_integral_cmp _Up>
_CCCL_TEMPLATE(class _Tp, class _Up)
_CCCL_REQUIRES(__is_safe_integral_cmp<_Tp>::value _CCCL_AND __is_safe_integral_cmp<_Up>::value)
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool in_range(_Up __u) noexcept
{
return _CUDA_VSTD::cmp_less_equal(__u, numeric_limits<_Tp>::max())
&& _CUDA_VSTD::cmp_greater_equal(__u, numeric_limits<_Tp>::min());
}
#endif // _CCCL_STD_VER > 2017

_LIBCUDACXX_END_NAMESPACE_STD

_CCCL_DIAG_POP

_CCCL_POP_MACROS

#endif // _LIBCUDACXX___UTILITY_CMP_H
12 changes: 6 additions & 6 deletions libcudacxx/include/cuda/std/version
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@
# define __cccl_lib_exchange_function 201304L
# define __cccl_lib_expected 202211L
// # define __cccl_lib_generic_associative_lookup 201304L
# define __cccl_lib_integer_sequence 201304L
# define __cccl_lib_integral_constant_callable 201304L
# define __cccl_lib_is_final 201402L
# define __cccl_lib_is_null_pointer 201309L
# define __cccl_lib_make_reverse_iterator 201402L
# define __cccl_lib_integer_sequence 201304L
# define __cccl_lib_integer_comparison_functions 202002L
# define __cccl_lib_integral_constant_callable 201304L
# define __cccl_lib_is_final 201402L
# define __cccl_lib_is_null_pointer 201309L
# define __cccl_lib_make_reverse_iterator 201402L
// # define __cccl_lib_make_unique 201304L
# if !_CCCL_COMPILER(MSVC) || _CCCL_STD_VER >= 2020
# define __cccl_lib_mdspan 202207L
Expand Down Expand Up @@ -178,7 +179,6 @@
// # define __cccl_lib_format 202106L
// # define __cccl_lib_generic_unordered_lookup 201811L
// # define __cccl_lib_int_pow2 202002L
// # define __cccl_lib_integer_comparison_functions 202002L
// # define __cccl_lib_interpolate 201902L
# ifdef _CCCL_BUILTIN_IS_CONSTANT_EVALUATED
# define __cccl_lib_is_constant_evaluated 201811L
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

miscco marked this conversation as resolved.
Show resolved Hide resolved
// <utility>

// template<class T, class U>
// constexpr bool cmp_equal(T t, U u) noexcept; // C++20
// constexpr bool cmp_equal(T t, U u) noexcept;

#include <cuda/std/cassert>
#include <cuda/std/limits>
Expand All @@ -24,28 +22,17 @@
template <typename T>
struct Tuple
{
T min;
T max;
T mid;
__host__ __device__ constexpr Tuple()
{
min = cuda::std::numeric_limits<T>::min();
max = cuda::std::numeric_limits<T>::max();
if constexpr (cuda::std::is_signed_v<T>)
{
mid = T(-1);
}
else
{
mid = max >> 1;
}
}
T min = cuda::std::numeric_limits<T>::min();
T max = cuda::std::numeric_limits<T>::max();
T mid = cuda::std::is_signed<T>::value ? T(-1) : max >> 1;

__host__ __device__ constexpr Tuple() noexcept {}
};

template <typename T>
__host__ __device__ constexpr void test_cmp_equal1()
__host__ __device__ TEST_CONSTEXPR_CXX14 void test1()
{
constexpr Tuple<T> tup;
constexpr Tuple<T> tup{};
assert(cuda::std::cmp_equal(T(0), T(0)));
assert(cuda::std::cmp_equal(T(10), T(10)));
assert(cuda::std::cmp_equal(tup.min, tup.min));
Expand All @@ -68,10 +55,10 @@ __host__ __device__ constexpr void test_cmp_equal1()
}

template <typename T, typename U>
__host__ __device__ constexpr void test_cmp_equal2()
__host__ __device__ TEST_CONSTEXPR_CXX14 void test2()
{
constexpr Tuple<T> ttup;
constexpr Tuple<U> utup;
constexpr Tuple<T> ttup{};
constexpr Tuple<U> utup{};
assert(cuda::std::cmp_equal(T(0), U(0)));
assert(cuda::std::cmp_equal(T(10), U(10)));
assert(!cuda::std::cmp_equal(T(0), U(1)));
Expand All @@ -82,51 +69,51 @@ __host__ __device__ constexpr void test_cmp_equal2()
assert(!cuda::std::cmp_equal(utup.min, ttup.max));
}

template <class... Ts>
__host__ __device__ constexpr void test1(const cuda::std::tuple<Ts...>&)
{
(test_cmp_equal1<Ts>(), ...);
}

template <class T, class... Us>
__host__ __device__ constexpr void test2_impl(const cuda::std::tuple<Us...>&)
template <class T>
__host__ __device__ TEST_CONSTEXPR_CXX14 void test()
{
(test_cmp_equal2<T, Us>(), ...);
}

template <class... Ts, class UTuple>
__host__ __device__ constexpr void test2(const cuda::std::tuple<Ts...>&, const UTuple& utuple)
{
(test2_impl<Ts>(utuple), ...);
test1<T>();
#ifndef TEST_HAS_NO_INT128_T
test2<T, __int128_t>();
test2<T, __uint128_t>();
#endif // TEST_HAS_NO_INT128_T
test2<T, unsigned long long>();
test2<T, long long>();
test2<T, unsigned long>();
test2<T, long>();
test2<T, unsigned int>();
test2<T, int>();
test2<T, unsigned short>();
test2<T, short>();
test2<T, unsigned char>();
test2<T, signed char>();
}

__host__ __device__ constexpr bool test()
__host__ __device__ TEST_CONSTEXPR_CXX14 bool test()
{
cuda::std::tuple<
#ifndef TEST_HAS_NO_INT128_T
__int128_t,
__uint128_t,
#endif
unsigned long long,
long long,
unsigned long,
long,
unsigned int,
int,
unsigned short,
short,
unsigned char,
signed char>
types;
test1(types);
test2(types, types);
test<__int128_t>();
test<__uint128_t>();
#endif // TEST_HAS_NO_INT128_T
test<unsigned long long>();
test<long long>();
test<unsigned long>();
test<long>();
test<unsigned int>();
test<int>();
test<unsigned short>();
test<short>();
test<unsigned char>();
test<signed char>();
return true;
}

int main(int, char**)
{
ASSERT_NOEXCEPT(cuda::std::cmp_equal(0, 0));
test();
static_assert(test());
#if TEST_STD_VER >= 2014
static_assert(test(), "");
#endif // TEST_STD_VER >= 2014
return 0;
}
Loading