-
Notifications
You must be signed in to change notification settings - Fork 418
Rework constant_sequence taking a single auto NTTP to a variadic NTTP #9533
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
base: main
Are you sure you want to change the base?
Changes from 7 commits
2c9afd2
1001a74
7ed4d84
23f15cf
c7c27f9
a62cb39
6bf8684
f1a0426
1580330
199c312
bc66751
184a017
de72ed7
7e70275
1cdd0fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -28,8 +28,10 @@ | |||||
| #include <cuda/std/__iterator/iterator_traits.h> | ||||||
| #include <cuda/std/__iterator/readable_traits.h> | ||||||
| #include <cuda/std/__ranges/concepts.h> | ||||||
| #include <cuda/std/__type_traits/extent.h> | ||||||
| #include <cuda/std/__type_traits/is_arithmetic.h> | ||||||
| #include <cuda/std/__type_traits/is_array.h> | ||||||
| #include <cuda/std/__type_traits/is_bounded_array.h> | ||||||
| #include <cuda/std/__type_traits/is_integer.h> | ||||||
| #include <cuda/std/__type_traits/is_integral.h> | ||||||
| #include <cuda/std/__type_traits/is_same.h> | ||||||
|
|
@@ -40,6 +42,7 @@ | |||||
| #include <cuda/std/__utility/declval.h> | ||||||
| #include <cuda/std/__utility/forward.h> | ||||||
| #include <cuda/std/__utility/move.h> | ||||||
| #include <cuda/std/array> | ||||||
| #include <cuda/std/cstddef> | ||||||
| #include <cuda/std/limits> | ||||||
|
|
||||||
|
|
@@ -111,16 +114,63 @@ class constant | |||||
| }; | ||||||
|
|
||||||
| //! @brief Wraps a compile-time constant argument sequence. | ||||||
| template <auto _Value> | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| class __constant_sequence | ||||||
| { | ||||||
| public: | ||||||
| using value_type = ::cuda::std::remove_cvref_t<decltype(_Value)>; | ||||||
| using __element_type = __element_type_of_t<value_type>; | ||||||
|
|
||||||
| static_assert(__is_sequence_v<value_type>, "The value type of __constant_sequence must be a sequence"); | ||||||
| using __element_type = ::cuda::std::remove_cvref_t<_Tp>; | ||||||
| using value_type = ::cuda::std::array<__element_type, sizeof...(_Vs)>; | ||||||
| static constexpr ::cuda::std::size_t size = sizeof...(_Vs); | ||||||
| }; | ||||||
|
|
||||||
| template <class> | ||||||
| inline constexpr bool __always_false_v = false; | ||||||
|
|
||||||
| template <const auto& Arr, ::cuda::std::size_t... Is> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Template parameters must be made
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||||||
| _CCCL_API constexpr auto __make_constant_sequence_impl(::cuda::std::index_sequence<Is...>) | ||||||
| { | ||||||
| using raw_array = ::cuda::std::remove_const_t<::cuda::std::remove_reference_t<decltype(Arr)>>; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion applied. |
||||||
|
|
||||||
| if constexpr (::cuda::std::is_bounded_array_v<raw_array>) | ||||||
| { | ||||||
| using _Tp = ::cuda::std::remove_cv_t<::cuda::std::remove_extent_t<raw_array>>; | ||||||
| return __constant_sequence<_Tp, Arr[Is]...>{}; | ||||||
| } | ||||||
| else if constexpr (::cuda::std::__is_cuda_std_array_v<raw_array>) | ||||||
| { | ||||||
| using _Tp = typename raw_array::value_type; | ||||||
| return __constant_sequence<_Tp, Arr[Is]...>{}; | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| static_assert(__always_false_v<raw_array>, "unsupported array type"); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| //! @brief Makes a compile-time constant argument sequence. | ||||||
| //! In C++17, Arr must have static storage duration. | ||||||
| template <const auto& Arr> | ||||||
| _CCCL_API constexpr auto __make_constant_sequence() | ||||||
| { | ||||||
| using raw_array = ::cuda::std::remove_cv_t<::cuda::std::remove_reference_t<decltype(Arr)>>; | ||||||
|
|
||||||
| static_assert(::cuda::std::is_bounded_array_v<raw_array> || ::cuda::std::__is_cuda_std_array_v<raw_array>, | ||||||
| "make_constant_sequence requires a cuda::std::array or non-empty C-style array"); | ||||||
|
|
||||||
| constexpr ::cuda::std::size_t N = []() constexpr { | ||||||
| if constexpr (::cuda::std::is_bounded_array_v<raw_array>) | ||||||
| { | ||||||
| return ::cuda::std::extent_v<raw_array>; | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| return ::cuda::std::tuple_size_v<raw_array>; | ||||||
| } | ||||||
| }(); | ||||||
|
|
||||||
| return __make_constant_sequence_impl<Arr>(::cuda::std::make_index_sequence<N>{}); | ||||||
| } | ||||||
|
|
||||||
| // __assert_in_range | ||||||
| // ===================================================================== | ||||||
|
|
||||||
|
|
@@ -621,8 +671,8 @@ template <class _Arg, class _StaticBounds> | |||||
| inline constexpr bool __is_wrapper_v<immediate<_Arg, _StaticBounds>> = true; | ||||||
| template <auto _Value, class _Tp> | ||||||
| inline constexpr bool __is_wrapper_v<constant<_Value, _Tp>> = true; | ||||||
| template <auto _Value> | ||||||
| inline constexpr bool __is_wrapper_v<__constant_sequence<_Value>> = true; | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| inline constexpr bool __is_wrapper_v<__constant_sequence<_Tp, _Vs...>> = true; | ||||||
| template <class _Arg, class _StaticBounds> | ||||||
| inline constexpr bool __is_wrapper_v<__immediate_sequence<_Arg, _StaticBounds>> = true; | ||||||
| template <class _Arg, class _StaticBounds> | ||||||
|
|
@@ -662,11 +712,11 @@ __unwrap(const constant<_Value, _Tp>&) noexcept | |||||
| return constant<_Value, _Tp>::__get_value(); | ||||||
| } | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| [[nodiscard]] _CCCL_API constexpr ::cuda::std::remove_cvref_t<decltype(_Value)> | ||||||
| __unwrap(const __constant_sequence<_Value>&) noexcept | ||||||
| //! Unwraps a compile-time constant argument sequence into a canonical cuda::std::array value. | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| [[nodiscard]] _CCCL_API constexpr auto __unwrap(const __constant_sequence<_Tp, _Vs...>&) noexcept | ||||||
| { | ||||||
| return _Value; | ||||||
| return ::cuda::std::array<::cuda::std::remove_cvref_t<_Tp>, sizeof...(_Vs)>{_Vs...}; | ||||||
| } | ||||||
|
|
||||||
| template <class _Arg, class _StaticBounds> | ||||||
|
|
@@ -735,32 +785,48 @@ _CCCL_API constexpr auto __constant_compute_highest() noexcept | |||||
| return constant<_Value, _Tp>::__get_value(); | ||||||
| } | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| _CCCL_API constexpr auto __constant_sequence_compute_lowest() noexcept | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| _CCCL_API constexpr _Tp __constant_sequence_compute_lowest() noexcept | ||||||
| { | ||||||
| using _ElementType = __element_type_of_t<::cuda::std::remove_cvref_t<decltype(_Value)>>; | ||||||
| auto __first = _Value.begin(); | ||||||
| auto __last = _Value.end(); | ||||||
|
|
||||||
| if (__first == __last) | ||||||
| if constexpr (sizeof...(_Vs) == 0) | ||||||
| { | ||||||
| return ::cuda::std::numeric_limits<_ElementType>::lowest(); | ||||||
| return ::cuda::std::numeric_limits<_Tp>::lowest(); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| constexpr _Tp values[] = {_Vs...}; | ||||||
| _Tp __min = values[0]; | ||||||
| for (_Tp __v : values) | ||||||
| { | ||||||
| if (__v < __min) | ||||||
| { | ||||||
| __min = __v; | ||||||
| } | ||||||
| } | ||||||
| return __min; | ||||||
| } | ||||||
| return static_cast<_ElementType>(*::cuda::std::min_element(__first, __last)); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why no longer
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for your review! I think at one point during development I wasn't able to use it and replaced it here. Applied the same for the max computation too. |
||||||
| } | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| _CCCL_API constexpr auto __constant_sequence_compute_highest() noexcept | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| _CCCL_API constexpr _Tp __constant_sequence_compute_highest() noexcept | ||||||
| { | ||||||
| using _ElementType = __element_type_of_t<::cuda::std::remove_cvref_t<decltype(_Value)>>; | ||||||
| auto __first = _Value.begin(); | ||||||
| auto __last = _Value.end(); | ||||||
|
|
||||||
| if (__first == __last) | ||||||
| if constexpr (sizeof...(_Vs) == 0) | ||||||
| { | ||||||
| return (::cuda::std::numeric_limits<_ElementType>::max)(); | ||||||
| return (::cuda::std::numeric_limits<_Tp>::max)(); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| constexpr _Tp values[] = {_Vs...}; | ||||||
| _Tp __max = values[0]; | ||||||
| for (_Tp __v : values) | ||||||
| { | ||||||
| if (__v > __max) | ||||||
| { | ||||||
| __max = __v; | ||||||
| } | ||||||
| } | ||||||
| return __max; | ||||||
| } | ||||||
| return static_cast<_ElementType>(*::cuda::std::max_element(__first, __last)); | ||||||
| } | ||||||
|
|
||||||
| // ===================================================================== | ||||||
|
|
@@ -811,17 +877,16 @@ struct __traits_impl<immediate<_Arg, _StaticBounds>> | |||||
| static constexpr element_type highest = __wrapper_static_highest<element_type, _StaticBounds>(); | ||||||
| }; | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| struct __traits_impl<__constant_sequence<_Value>> | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| struct __traits_impl<__constant_sequence<_Tp, _Vs...>> | ||||||
| { | ||||||
| using value_type = ::cuda::std::remove_cvref_t<decltype(_Value)>; | ||||||
| using element_type = __element_type_of_t<value_type>; | ||||||
| static_assert(__is_sequence_v<value_type>, "The value type of __constant_sequence must be a sequence"); | ||||||
| using element_type = ::cuda::std::remove_cvref_t<_Tp>; | ||||||
| using value_type = ::cuda::std::array<element_type, sizeof...(_Vs)>; | ||||||
| static constexpr bool is_constant = true; | ||||||
| static constexpr bool is_deferred = false; | ||||||
| static constexpr bool is_single_value = false; | ||||||
| static constexpr element_type lowest = __constant_sequence_compute_lowest<_Value>(); | ||||||
| static constexpr element_type highest = __constant_sequence_compute_highest<_Value>(); | ||||||
| static constexpr element_type lowest = __constant_sequence_compute_lowest<_Tp, _Vs...>(); | ||||||
| static constexpr element_type highest = __constant_sequence_compute_highest<_Tp, _Vs...>(); | ||||||
| }; | ||||||
|
|
||||||
| template <class _Arg, class _StaticBounds> | ||||||
|
|
@@ -896,10 +961,10 @@ template <auto _Value, class _Tp> | |||||
| return __constant_compute_lowest<_Value, _Tp>(); | ||||||
| } | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| [[nodiscard]] _CCCL_API constexpr auto __lowest_(__constant_sequence<_Value>) noexcept | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| [[nodiscard]] _CCCL_API constexpr auto __lowest_(__constant_sequence<_Tp, _Vs...>) noexcept | ||||||
| { | ||||||
| return __constant_sequence_compute_lowest<_Value>(); | ||||||
| return __constant_sequence_compute_lowest<_Tp, _Vs...>(); | ||||||
| } | ||||||
|
|
||||||
| template <class _Arg, class _StaticBounds> | ||||||
|
|
@@ -949,10 +1014,10 @@ template <auto _Value, class _Tp> | |||||
| return __constant_compute_highest<_Value, _Tp>(); | ||||||
| } | ||||||
|
|
||||||
| template <auto _Value> | ||||||
| [[nodiscard]] _CCCL_API constexpr auto __highest_(__constant_sequence<_Value>) noexcept | ||||||
| template <class _Tp, _Tp... _Vs> | ||||||
| [[nodiscard]] _CCCL_API constexpr auto __highest_(__constant_sequence<_Tp, _Vs...>) noexcept | ||||||
| { | ||||||
| return __constant_sequence_compute_highest<_Value>(); | ||||||
| return __constant_sequence_compute_highest<_Tp, _Vs...>(); | ||||||
| } | ||||||
|
|
||||||
| template <class _Arg, class _StaticBounds> | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
cuda::std::__always_false_vinstead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed