diff --git a/include/experimental/__p0009_bits/config.hpp b/include/experimental/__p0009_bits/config.hpp index 3102aa54..785447a3 100644 --- a/include/experimental/__p0009_bits/config.hpp +++ b/include/experimental/__p0009_bits/config.hpp @@ -45,11 +45,13 @@ #else #define MDSPAN_CXX_STD_23 202100L #endif +#define MDSPAN_CXX_STD_26 202603L #define MDSPAN_HAS_CXX_14 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_14) #define MDSPAN_HAS_CXX_17 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_17) #define MDSPAN_HAS_CXX_20 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_20) #define MDSPAN_HAS_CXX_23 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_23) +#define MDSPAN_HAS_CXX_26 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_26) static_assert(MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_14, "mdspan requires C++14 or later."); diff --git a/include/experimental/__p2630_bits/submdspan.hpp b/include/experimental/__p2630_bits/submdspan.hpp index f2f18e17..d170ebed 100644 --- a/include/experimental/__p2630_bits/submdspan.hpp +++ b/include/experimental/__p2630_bits/submdspan.hpp @@ -27,7 +27,10 @@ MDSPAN_INLINE_FUNCTION constexpr auto submdspan(const mdspan &src, SliceSpecifiers... slices) { - const auto sub_submdspan_mapping_result = submdspan_mapping(src.mapping(), slices...); + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + + const auto sub_submdspan_mapping_result = submdspan_mapping(src.mapping(), + detail::canonical_slice(slices)...); // NVCC has a problem with the deduction so lets figure out the type using sub_mapping_t = std::remove_cv_t; using sub_extents_t = typename sub_mapping_t::extents_type; diff --git a/include/experimental/__p2630_bits/submdspan_canonicalize_slices.hpp b/include/experimental/__p2630_bits/submdspan_canonicalize_slices.hpp index 84e91351..d9de78c6 100644 --- a/include/experimental/__p2630_bits/submdspan_canonicalize_slices.hpp +++ b/include/experimental/__p2630_bits/submdspan_canonicalize_slices.hpp @@ -274,6 +274,15 @@ constexpr bool check_submdspan_slice_mandate( return true; } +template +MDSPAN_INLINE_FUNCTION +constexpr bool check_submdspan_slice_mandates( + const std::index_sequence& , + [[maybe_unused]] const Slices& ... slices) +{ + return (check_submdspan_slice_mandate(slices) && ... && true); +} + // ============================================================ // canonical_slice: canonicalize a single slice // diff --git a/include/experimental/__p2630_bits/submdspan_extents.hpp b/include/experimental/__p2630_bits/submdspan_extents.hpp index 789307a8..abada9f0 100644 --- a/include/experimental/__p2630_bits/submdspan_extents.hpp +++ b/include/experimental/__p2630_bits/submdspan_extents.hpp @@ -55,37 +55,6 @@ template struct is_strided_slice< strided_slice> : std::true_type {}; -// Helper for identifying valid pair like things -template struct index_pair_like : std::false_type {}; - -template -struct index_pair_like, IndexType> { - static constexpr bool value = std::is_convertible_v && - std::is_convertible_v; -}; - -template -struct index_pair_like, IndexType> { - static constexpr bool value = std::is_convertible_v && - std::is_convertible_v; -}; - -template -struct index_pair_like, IndexType> { - static constexpr bool value = std::is_convertible_v && - std::is_convertible_v; -}; - -template -struct index_pair_like, IndexType> { - static constexpr bool value = std::is_convertible_v; -}; - -template -struct index_pair_like, IndexType> { - static constexpr bool value = std::is_convertible_v; -}; - // first_of(slice): getting begin of slice specifier range MDSPAN_TEMPLATE_REQUIRES( class Integral, @@ -98,8 +67,8 @@ constexpr Integral first_of(const Integral &i) { template MDSPAN_INLINE_FUNCTION -constexpr Integral first_of(const std::integral_constant&) { - return integral_constant(); +constexpr auto first_of(const constant_wrapper&) { + return constant_wrapper(); } MDSPAN_INLINE_FUNCTION @@ -108,38 +77,6 @@ first_of(const ::MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t &) { return integral_constant(); } -MDSPAN_TEMPLATE_REQUIRES( - class Slice, - /* requires */(index_pair_like::value) -) -MDSPAN_INLINE_FUNCTION -constexpr auto first_of(const Slice &i) { - return get<0>(i); -} - -MDSPAN_TEMPLATE_REQUIRES( - class IdxT1, class IdxT2, - /* requires */ (index_pair_like, size_t>::value) - ) -constexpr auto first_of(const std::tuple& i) { - return get<0>(i); -} - -MDSPAN_TEMPLATE_REQUIRES( - class IdxT1, class IdxT2, - /* requires */ (index_pair_like, size_t>::value) - ) -MDSPAN_INLINE_FUNCTION -constexpr auto first_of(const std::pair& i) { - return i.first; -} - -template -MDSPAN_INLINE_FUNCTION -constexpr auto first_of(const std::complex &i) { - return i.real(); -} - template MDSPAN_INLINE_FUNCTION constexpr OffsetType @@ -161,39 +98,6 @@ constexpr Integral return i; } -MDSPAN_TEMPLATE_REQUIRES( - size_t k, class Extents, class Slice, - /* requires */(index_pair_like::value) -) -MDSPAN_INLINE_FUNCTION -constexpr auto last_of(std::integral_constant, const Extents &, - const Slice &i) { - return get<1>(i); -} - -MDSPAN_TEMPLATE_REQUIRES( - size_t k, class Extents, class IdxT1, class IdxT2, - /* requires */ (index_pair_like, size_t>::value) - ) -constexpr auto last_of(std::integral_constant, const Extents &, const std::tuple& i) { - return get<1>(i); -} - -MDSPAN_TEMPLATE_REQUIRES( - size_t k, class Extents, class IdxT1, class IdxT2, - /* requires */ (index_pair_like, size_t>::value) - ) -MDSPAN_INLINE_FUNCTION -constexpr auto last_of(std::integral_constant, const Extents &, const std::pair& i) { - return i.second; -} - -template -MDSPAN_INLINE_FUNCTION -constexpr auto last_of(std::integral_constant, const Extents &, const std::complex &i) { - return i.imag(); -} - // Suppress spurious warning with NVCC about no return statement. // This is a known issue in NVCC and NVC++ // Depending on the CUDA and GCC version we need both the builtin @@ -220,7 +124,7 @@ constexpr auto last_of(std::integral_constant, const Extents &ext, if constexpr (Extents::static_extent(k) == dynamic_extent) { return ext.extent(k); } else { - return integral_constant(); + return constant_wrapper(); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) // Even with CUDA_ARCH protection this thing warns about calling host function diff --git a/include/experimental/__p2630_bits/submdspan_mapping.hpp b/include/experimental/__p2630_bits/submdspan_mapping.hpp index cbd06678..be7fcfb2 100644 --- a/include/experimental/__p2630_bits/submdspan_mapping.hpp +++ b/include/experimental/__p2630_bits/submdspan_mapping.hpp @@ -102,14 +102,19 @@ MDSPAN_INLINE_FUNCTION constexpr auto construct_sub_strides( } template -struct is_range_slice { - constexpr static bool value = - std::is_same_v || - index_pair_like::value; -}; +constexpr bool is_range_slice_v = false; -template -constexpr bool is_range_slice_v = is_range_slice::value; +template +constexpr bool is_range_slice_v = true; + +template +constexpr bool is_range_slice_v< + strided_slice< + OffsetType, + ExtentType, + constant_wrapper>, + IndexType + > = (constant_wrapper::value == IndexType(1)); template struct is_index_slice { @@ -209,6 +214,9 @@ MDSPAN_INLINE_FUNCTION constexpr auto layout_left::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { + // Implements mandate check + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); @@ -272,6 +280,9 @@ MDSPAN_INLINE_FUNCTION constexpr auto layout_left_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { + // Implements mandate check + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); @@ -437,6 +448,9 @@ MDSPAN_INLINE_FUNCTION constexpr auto layout_right::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { + // Implements mandate check + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); @@ -502,6 +516,9 @@ MDSPAN_INLINE_FUNCTION constexpr auto layout_right_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { + // Implements mandate check + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); @@ -577,6 +594,10 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_stride::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { + + // Implements mandate check + detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); auto inv_map = detail::inv_map_rank(std::integral_constant(), diff --git a/tests/test_submdspan.cpp b/tests/test_submdspan.cpp index b14396de..b5564c17 100644 --- a/tests/test_submdspan.cpp +++ b/tests/test_submdspan.cpp @@ -141,7 +141,9 @@ using submdspan_test_types = // layout_right to layout_right Check Extents Preservation , std::tuple, args_t<10>, Kokkos::extents, Kokkos::full_extent_t> , std::tuple, args_t<10>, Kokkos::extents, std::pair> +#if defined(__cpp_lib_tuple_like) && (__cpp_lib_tuple_like >= 202311L) // submdspan uses structured binding for slices, which requires C++26 for complex , std::tuple, args_t<10>, Kokkos::extents, std::complex> +#endif , std::tuple, args_t<10>, Kokkos::extents, int> , std::tuple, args_t<10,20>, Kokkos::extents, Kokkos::full_extent_t, Kokkos::full_extent_t> , std::tuple, args_t<10,20>, Kokkos::extents, std::pair, Kokkos::full_extent_t>