Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
206 changes: 18 additions & 188 deletions libcudacxx/include/cuda/__argument/argument.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
#include <cuda/std/__algorithm/min_element.h>
#include <cuda/std/__cccl/assert.h>
#include <cuda/std/__iterator/readable_traits.h>
#include <cuda/std/__ranges/concepts.h>
#include <cuda/std/__ranges/empty.h>
#include <cuda/std/__type_traits/is_arithmetic.h>
#include <cuda/std/__type_traits/is_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>
Expand Down Expand Up @@ -75,23 +78,12 @@ template <class _Tp>
using __element_type_of_t = typename __element_type_of<::cuda::std::remove_cvref_t<_Tp>>::type;

// =====================================================================
// __is_sequence_v / __is_single_value_v
// __is_sequence_v
// =====================================================================

template <class _Tp>
inline constexpr bool __is_sequence_v =
!::cuda::std::is_same_v<::cuda::std::remove_cvref_t<_Tp>, __element_type_of_t<_Tp>>;

template <class _Tp>
inline constexpr bool __is_single_value_v = !__is_sequence_v<_Tp>;

template <class _Tp, class = void>
inline constexpr bool __is_iterable_v = false;

template <class _Tp>
inline constexpr bool __is_iterable_v<_Tp,
::cuda::std::void_t<decltype(::cuda::std::declval<const _Tp&>().begin()),
decltype(::cuda::std::declval<const _Tp&>().end())>> = true;
::cuda::std::is_array_v<::cuda::std::remove_cvref_t<_Tp>> || ::cuda::std::ranges::range<_Tp>;

// =====================================================================
// __constant
Expand Down Expand Up @@ -121,138 +113,16 @@ struct __constant_sequence
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>, "constant sequence arguments must have a distinct element type");
static_assert(__is_sequence_v<value_type>, "The value type of __constant_sequence must be a range or an array");
static_assert(!::cuda::std::ranges::__empty::__fn{}(_Value),
"The value type of __constant_sequence must be a non-empty sequence");
Comment on lines +116 to +118

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

important: __constant_sequence now rejects empty sequences, but an existing test still expects empty sequences to compile.
Line 117 introduces a hard static_assert for non-empty sequences, while libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp still instantiates cuda::__argument::__constant_sequence<cuda::std::array<int, 0>{}> as a positive case (Lines 82-87 in that file). Please convert that case to a negative-compile test (or remove it), otherwise class-NTTP-enabled configurations will fail.


[[nodiscard]] _CCCL_API static constexpr value_type value() noexcept
{
return _Value;
}
};

// =====================================================================
// __assert_in_range
// =====================================================================

template <class _To, class _From>
_CCCL_API constexpr void __assert_in_range([[maybe_unused]] _From __val) noexcept
{
if constexpr (::cuda::std::__cccl_is_cv_integer_v<_To> && ::cuda::std::__cccl_is_cv_integer_v<_From>)
{
_CCCL_ASSERT(::cuda::std::in_range<::cuda::std::remove_cv_t<_To>>(__val),
"runtime bound value overflows the element type");
}
}

template <class _To, class _From>
[[nodiscard]] _CCCL_API constexpr _To __runtime_bound_cast(_From __val) noexcept
{
__assert_in_range<_To>(__val);
return static_cast<_To>(__val);
}

template <class _To, auto _Value>
_CCCL_API constexpr bool __static_bound_in_range() noexcept
{
using _RawTo = ::cuda::std::remove_cv_t<_To>;
using _RawFrom = ::cuda::std::remove_cv_t<decltype(_Value)>;

if constexpr (::cuda::std::__cccl_is_integer_v<_RawTo> && ::cuda::std::__cccl_is_integer_v<_RawFrom>)
{
return ::cuda::std::in_range<_RawTo>(_Value);
}
else if constexpr (::cuda::std::is_arithmetic_v<_RawTo> && ::cuda::std::is_arithmetic_v<_RawFrom>)
{
return static_cast<_RawFrom>(static_cast<_RawTo>(_Value)) == _Value;
}
else
{
return true;
}
}

template <class _ElementType, class _StaticBounds>
inline constexpr bool __valid_static_bounds_v = true;

template <class _ElementType, auto _Lowest, auto _Highest>
inline constexpr bool __valid_static_bounds_v<_ElementType, __static_bounds<_Lowest, _Highest>> =
__static_bound_in_range<_ElementType, _Lowest>() && __static_bound_in_range<_ElementType, _Highest>();

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_lowest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return ::cuda::std::numeric_limits<_ElementType>::lowest();
}
else
{
return static_cast<_ElementType>(_StaticBounds::lower());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __wrapper_static_highest() noexcept
{
if constexpr (::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
return (::cuda::std::numeric_limits<_ElementType>::max)();
}
else
{
return static_cast<_ElementType>(_StaticBounds::upper());
}
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_lowest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_lowest = __wrapper_static_lowest<_ElementType, _StaticBounds>();
return __static_lowest > __runtime_bounds.lower() ? __static_lowest : __runtime_bounds.lower();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr _ElementType __effective_highest(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
auto __static_highest = __wrapper_static_highest<_ElementType, _StaticBounds>();
return __static_highest < __runtime_bounds.upper() ? __static_highest : __runtime_bounds.upper();
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr bool __has_bounds_intersection(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
return __effective_lowest<_ElementType, _StaticBounds>(__runtime_bounds)
<= __effective_highest<_ElementType, _StaticBounds>(__runtime_bounds);
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_bounds_intersection(__runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
static_assert(__valid_static_bounds_v<_ElementType, _StaticBounds>,
"static argument bounds cannot be represented by the element type");
_CCCL_VERIFY((__has_bounds_intersection<_ElementType, _StaticBounds>(__runtime_bounds)),
"static and runtime argument bounds do not intersect");
}

template <class _ElementType, class _StaticBounds>
_CCCL_API constexpr void __validate_static_element_bounds([[maybe_unused]] const _ElementType& __val) noexcept
{
if constexpr (!::cuda::std::is_same_v<_StaticBounds, __no_bounds>)
{
_CCCL_ASSERT((__val >= __wrapper_static_lowest<_ElementType, _StaticBounds>()),
"immediate argument value is below static lowest bound");
_CCCL_ASSERT((__val <= __wrapper_static_highest<_ElementType, _StaticBounds>()),
"immediate argument value is above static highest bound");
}
}

template <class _ElementType>
_CCCL_API constexpr void __validate_runtime_element_bounds(
[[maybe_unused]] const _ElementType& __val, [[maybe_unused]] __runtime_bounds<_ElementType> __runtime_bounds) noexcept
{
_CCCL_ASSERT((__val >= __runtime_bounds.lower()), "immediate argument value is below runtime lower bound");
_CCCL_ASSERT((__val <= __runtime_bounds.upper()), "immediate argument value is above runtime upper bound");
}

// =====================================================================
// __immediate
// =====================================================================
Expand Down Expand Up @@ -332,7 +202,7 @@ struct __immediate_sequence

_CCCL_API constexpr void __validate_value() const noexcept
{
if constexpr (__is_iterable_v<_Arg> && ::cuda::std::is_arithmetic_v<__element_type>)
if constexpr (__is_sequence_v<_Arg> && ::cuda::std::is_arithmetic_v<__element_type>)
{
for (const auto& __a : __arg_)
{
Expand Down Expand Up @@ -616,46 +486,6 @@ template <class _Arg, class _StaticBounds>
return ::cuda::std::move(__arg.__arg_);
}

template <auto _Value>
_CCCL_API constexpr auto __constant_compute_lowest() noexcept
{
return _Value;
}

template <auto _Value>
_CCCL_API constexpr auto __constant_compute_highest() noexcept
{
return _Value;
}

template <auto _Value>
_CCCL_API constexpr auto __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)
{
return ::cuda::std::numeric_limits<_ElementType>::lowest();
}
return static_cast<_ElementType>(*::cuda::std::min_element(__first, __last));
}

template <auto _Value>
_CCCL_API constexpr auto __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)
{
return (::cuda::std::numeric_limits<_ElementType>::max)();
}
return static_cast<_ElementType>(*::cuda::std::max_element(__first, __last));
}

// =====================================================================
// __traits
// =====================================================================
Expand All @@ -671,7 +501,7 @@ struct __traits_impl
using element_type = __element_type_of_t<_Tp>;
static constexpr bool is_constant = false;
static constexpr bool is_deferred = false;
static constexpr bool is_single_value = __is_single_value_v<_Tp>;
static constexpr bool is_single_value = !__is_sequence_v<_Tp>;
static constexpr element_type lowest = ::cuda::std::numeric_limits<element_type>::lowest();
static constexpr element_type highest = (::cuda::std::numeric_limits<element_type>::max)();
};
Expand All @@ -684,8 +514,8 @@ struct __traits_impl<__constant<_Value>>
static constexpr bool is_constant = true;
static constexpr bool is_deferred = false;
static constexpr bool is_single_value = true;
static constexpr element_type lowest = __constant_compute_lowest<_Value>();
static constexpr element_type highest = __constant_compute_highest<_Value>();
static constexpr element_type lowest = _Value;
static constexpr element_type highest = _Value;
};

template <class _Arg, class _StaticBounds>
Expand All @@ -712,8 +542,8 @@ struct __traits_impl<__constant_sequence<_Value>>
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 = *::cuda::std::min_element(_Value.begin(), _Value.end());
static constexpr element_type highest = *::cuda::std::max_element(_Value.begin(), _Value.end());
};

template <class _Arg, class _StaticBounds>
Expand Down Expand Up @@ -781,13 +611,13 @@ _CCCL_REQUIRES((!__is_wrapper_v<::cuda::std::remove_cv_t<_Tp>>) )
template <auto _Value>
[[nodiscard]] _CCCL_API constexpr auto __lowest_(__constant<_Value>) noexcept
{
return __constant_compute_lowest<_Value>();
return _Value;
}

template <auto _Value>
[[nodiscard]] _CCCL_API constexpr auto __lowest_(__constant_sequence<_Value>) noexcept
{
return __constant_sequence_compute_lowest<_Value>();
return *::cuda::std::min_element(_Value.begin(), _Value.end());
}

template <class _Arg, class _StaticBounds>
Expand Down Expand Up @@ -831,13 +661,13 @@ _CCCL_REQUIRES((!__is_wrapper_v<::cuda::std::remove_cv_t<_Tp>>) )
template <auto _Value>
[[nodiscard]] _CCCL_API constexpr auto __highest_(__constant<_Value>) noexcept
{
return __constant_compute_highest<_Value>();
return _Value;
}

template <auto _Value>
[[nodiscard]] _CCCL_API constexpr auto __highest_(__constant_sequence<_Value>) noexcept
{
return __constant_sequence_compute_highest<_Value>();
return *::cuda::std::max_element(_Value.begin(), _Value.end());
}

template <class _Arg, class _StaticBounds>
Expand Down
Loading
Loading