diff options
| author | Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> | 2025-12-18 12:28:37 +0200 |
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> | 2025-12-18 12:35:28 +0200 |
| commit | 06ebb8835022b92ea64c5b10bdb3f5afbad0e5f8 (patch) | |
| tree | 49066a5d691626d097169e9c8c5b051b7bf423e4 /ext/mdspan/include/experimental/__p2642_bits | |
| parent | 44e660203bcbab509b0ad08b0038192ec471a8de (diff) | |
Update mdspan headers to 546d4dd63697c6a331554adb6fe650e09b690812
Diffstat (limited to 'ext/mdspan/include/experimental/__p2642_bits')
| -rw-r--r-- | ext/mdspan/include/experimental/__p2642_bits/layout_padded.hpp | 496 | ||||
| -rw-r--r-- | ext/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp | 86 |
2 files changed, 401 insertions, 181 deletions
diff --git a/ext/mdspan/include/experimental/__p2642_bits/layout_padded.hpp b/ext/mdspan/include/experimental/__p2642_bits/layout_padded.hpp index a714090..d91313b 100644 --- a/ext/mdspan/include/experimental/__p2642_bits/layout_padded.hpp +++ b/ext/mdspan/include/experimental/__p2642_bits/layout_padded.hpp @@ -27,36 +27,43 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { - namespace detail { -template<class _T> +template<class T, class U> MDSPAN_INLINE_FUNCTION -constexpr _T -find_next_multiple(_T alignment, _T offset) +constexpr T +find_next_multiple(T alignment, U offset) { - if ( alignment == 0 ) { - return _T(0); + if ( alignment == T(0) ) { + return T(0); } else { return ( ( offset + alignment - 1 ) / alignment) * alignment; } } -template <class _ExtentsType, size_t _PaddingValue, size_t _ExtentToPadIdx> +template <class ExtentsType, size_t PaddingValue, size_t ExtentToPadIdx> MDSPAN_INLINE_FUNCTION constexpr size_t get_actual_static_padding_value() { - constexpr auto rank = _ExtentsType::rank(); + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range; + constexpr auto rank = ExtentsType::rank(); - if constexpr (rank <= typename _ExtentsType::rank_type(1)) { + if constexpr (rank <= typename ExtentsType::rank_type(1)) { return 0; - } else if constexpr (_PaddingValue != dynamic_extent && - _ExtentsType::static_extent(_ExtentToPadIdx) != + } else if constexpr (PaddingValue != dynamic_extent && + ExtentsType::static_extent(ExtentToPadIdx) != dynamic_extent) { static_assert( - (_PaddingValue != 0) || - (_ExtentsType::static_extent(_ExtentToPadIdx) == 0), + (PaddingValue != 0) || + (ExtentsType::static_extent(ExtentToPadIdx) == 0), "padding stride can be 0 only if " "extents_type::static_extent(extent-to-pad) is 0 or dynamic_extent"); - return find_next_multiple(_PaddingValue, - _ExtentsType::static_extent(_ExtentToPadIdx)); + constexpr auto ret = find_next_multiple( + PaddingValue, ExtentsType::static_extent(ExtentToPadIdx)); + + using index_type = typename ExtentsType::index_type; + static_assert(in_range<index_type>(ret), + "The least multiple of padding_value and first-static-extent " + "must be representable by index_type"); + + return ret; } else { return dynamic_extent; } @@ -66,44 +73,46 @@ MDSPAN_INLINE_FUNCTION constexpr size_t get_actual_static_padding_value() { #endif } -template <size_t _PaddingValue, typename _Extents, size_t _ExtentToPadIdx, size_t _Rank, typename Enabled = void> -struct static_array_type_for_padded_extent -{ - static constexpr size_t padding_value = _PaddingValue; - using index_type = typename _Extents::index_type; - using extents_type = _Extents; +template <size_t PaddingValue, typename Extents, size_t ExtentToPadIdx, + size_t Rank, typename Enabled = void> +struct static_array_type_for_padded_extent { + static constexpr size_t padding_value = PaddingValue; + using index_type = typename Extents::index_type; + using extents_type = Extents; using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::maybe_static_array< index_type, size_t, dynamic_extent, - ::MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::get_actual_static_padding_value<extents_type, _PaddingValue, - _ExtentToPadIdx>()>; + ::MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::detail:: + get_actual_static_padding_value<extents_type, PaddingValue, + ExtentToPadIdx>()>; }; -template <size_t _PaddingValue, typename _Extents, size_t _ExtentToPadIdx, size_t Rank> -struct static_array_type_for_padded_extent<_PaddingValue, _Extents, - _ExtentToPadIdx, Rank, std::enable_if_t<Rank <= 1>> { - using index_type = typename _Extents::index_type; - using extents_type = _Extents; - using type = - ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::maybe_static_array< - index_type, size_t, dynamic_extent, 0>; +template <size_t PaddingValue, typename Extents, size_t ExtentToPadIdx, + size_t Rank> +struct static_array_type_for_padded_extent< + PaddingValue, Extents, ExtentToPadIdx, Rank, std::enable_if_t<Rank <= 1>> { + using index_type = typename Extents::index_type; + using extents_type = Extents; + using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::maybe_static_array< + index_type, size_t, dynamic_extent, 0>; }; -template <size_t _PaddingValue, typename _Extents, size_t _ExtentToPadIdx> +template <size_t PaddingValue, typename Extents, size_t ExtentToPadIdx> struct padded_extent { - static constexpr size_t padding_value = _PaddingValue; - using index_type = typename _Extents::index_type; - using extents_type = _Extents; + static constexpr size_t padding_value = PaddingValue; + using index_type = typename Extents::index_type; + using extents_type = Extents; using static_array_type = typename static_array_type_for_padded_extent< - padding_value, _Extents, _ExtentToPadIdx, _Extents::rank()>::type; + padding_value, Extents, ExtentToPadIdx, Extents::rank()>::type; MDSPAN_INLINE_FUNCTION - static constexpr auto static_value() { return static_array_type::static_value(0); } + static constexpr auto static_value() { + return static_array_type::static_value(0); + } MDSPAN_INLINE_FUNCTION - static constexpr static_array_type - init_padding(const _Extents &exts) { - if constexpr ((_Extents::rank() > 1) && (padding_value == dynamic_extent)) { - return {exts.extent(_ExtentToPadIdx)}; + static constexpr static_array_type init_padding(const Extents &exts) { + if constexpr ((Extents::rank() > 1) && (padding_value == dynamic_extent)) { + return {exts.extent(ExtentToPadIdx)}; } else { return init_padding(exts, padding_value); } @@ -114,11 +123,13 @@ struct padded_extent { } MDSPAN_INLINE_FUNCTION static constexpr static_array_type - init_padding([[maybe_unused]] const _Extents &exts, - [[maybe_unused]] index_type pv) { - if constexpr (_Extents::rank() > 1) { - return {find_next_multiple(pv, - exts.extent(_ExtentToPadIdx))}; + init_padding([[maybe_unused]] const Extents &exts, + [[maybe_unused]] size_t pv) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range; + if constexpr (Extents::rank() > 1) { + auto strd = find_next_multiple(pv, exts.extent(ExtentToPadIdx)); + MDSPAN_IMPL_PRECONDITION(in_range<index_type>(strd)); + return {strd}; } else { return {}; } @@ -128,12 +139,12 @@ struct padded_extent { #endif } - template <typename _Mapping, size_t _PaddingStrideIdx> + template <typename Mapping, size_t PaddingStrideIdx> MDSPAN_INLINE_FUNCTION static constexpr static_array_type - init_padding([[maybe_unused]] const _Mapping &other_mapping, - std::integral_constant<size_t, _PaddingStrideIdx>) { - if constexpr (_Extents::rank() > 1) { - return {other_mapping.stride(_PaddingStrideIdx)}; + init_padding([[maybe_unused]] const Mapping &other_mapping, + std::integral_constant<size_t, PaddingStrideIdx>) { + if constexpr (Extents::rank() > 1) { + return {other_mapping.stride(PaddingStrideIdx)}; } else { return {}; } @@ -143,6 +154,148 @@ struct padded_extent { #endif } }; + +template <typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_static_extents_representability() { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + // We cannot check statically for sure if the extents are representable + // if we have dynamic values -- this can only be checked by a precondition + // We can check if the product of only the static extents is representable though... + using index_type = typename Extents::index_type; + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + if constexpr ( Extents::rank() > 0 ) { + auto prod = index_type(1); + for (size_t i = 0; i < Extents::rank(); ++i) { + if (Extents::static_extent(i) == dynamic_extent) + continue; + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast<index_type>(Extents::static_extent(i)))) + return false; + prod *= Extents::static_extent(i); + } + } + + return true; +} + +template <typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_extents_representability(const Extents &exts) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + using index_type = typename Extents::index_type; + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + if constexpr ( Extents::rank() > 0 ) { + auto prod = index_type(1); + for (size_t i = 0; i < Extents::rank(); ++i) { + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast<index_type>(exts.extent(i)))) + return false; + prod *= exts.extent(i); + } + } + + return true; +} + +template <typename CheckType, size_t StaticPaddingValue, typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_static_extents_and_left_padding_representability() { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + if constexpr (Extents::rank() < 2) { + return true; + } + + // We cannot check statically for sure if the product of the extents and padding value + // are representable if we have dynamic values -- this can only be checked by a precondition + // We can check if the product of only the static extents and potentially the padding value (if it is static) + // is representable though... + // We already checked that StaticPaddingValue is representable by index_type + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + if constexpr ( Extents::rank() > 0 ) { + auto prod = (StaticPaddingValue != dynamic_extent) ? static_cast< CheckType >(StaticPaddingValue) : CheckType(1); + for (size_t i = 1; i < Extents::rank(); ++i) { + if (Extents::static_extent(i) == dynamic_extent) + continue; + if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(Extents::static_extent(i)))) + return false; + prod *= Extents::static_extent(i); + } + } + + return true; +} + +template <typename CheckType, typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_extents_and_left_padding_representability(const Extents &exts, + [[maybe_unused]] size_t dynamic_padding_value) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + // And also a rank 1 layout cannot overflow + if constexpr ( Extents::rank() > 1 ) { + auto prod = static_cast<CheckType>(dynamic_padding_value); + for (size_t i = 1; i < Extents::rank(); ++i) { + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast<CheckType>(exts.extent(i)))) + return false; + prod *= exts.extent(i); + } + } + + return true; +} + +template <typename CheckType, size_t StaticPaddingValue, typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_static_extents_and_right_padding_representability() { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + + // We cannot check statically for sure if the product of the extents and padding value + // are representable if we have dynamic values -- this can only be checked by a precondition + // We can check if the product of only the static extents and potentially the padding value (if it is static) + // is representable though... + // We already checked that StaticPaddingValue is representable by index_type + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + // And also a rank 1 layout cannot overflow + if constexpr ( Extents::rank() > 1 ) { + auto prod = (StaticPaddingValue != dynamic_extent) ? static_cast< CheckType >(StaticPaddingValue) : CheckType(1); + for (size_t i = 0; i < Extents::rank() - 1; ++i) { + if (Extents::static_extent(i) == dynamic_extent) + continue; + if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(Extents::static_extent(i)))) + return false; + prod *= Extents::static_extent(i); + } + } + + return true; +} + +template <typename CheckType, typename Extents> +MDSPAN_INLINE_FUNCTION constexpr bool +check_extents_and_right_padding_representability(const Extents &exts, + [[maybe_unused]] size_t dynamic_padding_value) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + + // get rid of NVCC warning "pointless comparison of unsigned integer with zero" + // And also a rank 1 layout cannot overflow + if constexpr ( Extents::rank() > 1 ) { + auto prod = static_cast<CheckType>(dynamic_padding_value); + for (size_t i = 0; i < Extents::rank() - 1; ++i) { + if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(exts.extent(i)))) + return false; + prod *= exts.extent(i); + } + } + + return true; +} } // namespace detail template <size_t PaddingValue> @@ -168,11 +321,17 @@ private: || (extents_type::static_extent(extent_to_pad_idx) == 0) || (extents_type::static_extent(extent_to_pad_idx) == dynamic_extent), "out of bounds access for rank 0"); + static_assert(detail::check_static_extents_representability<extents_type>(), "The size of the muiltidimensional index space given by the extents must be representable as a value of index_type"); + static_assert((padding_value == dynamic_extent) || MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range<index_type>(padding_value), "padding_value must be representable as a value of type index_type"); using padded_stride_type = detail::padded_extent< padding_value, extents_type, extent_to_pad_idx >; static constexpr size_t static_padding_stride = padded_stride_type::static_value(); + static_assert(detail::check_static_extents_and_left_padding_representability<index_type, static_padding_stride, extents_type>() + && detail::check_static_extents_and_left_padding_representability<size_t, static_padding_stride, extents_type>(), + "the product of static_padding_stride and static extents 1 through rank must be representable as a value of type size_t and index_type"); + typename padded_stride_type::static_array_type padded_stride = {}; extents_type exts = {}; @@ -233,7 +392,12 @@ public: MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type& ext) : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) - {} + { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + ext, padded_stride.value(0))); + } /** * Initializes the mapping with the given extents and the specified padding value. @@ -245,17 +409,21 @@ public: * \param padding_value the padding value */ MDSPAN_TEMPLATE_REQUIRES( - class _Size, + class Size, /* requires */ ( - std::is_convertible_v<_Size, index_type> - && std::is_nothrow_constructible_v<index_type, _Size> + std::is_convertible_v<Size, index_type> + && std::is_nothrow_constructible_v<index_type, Size> ) ) MDSPAN_INLINE_FUNCTION - constexpr mapping(const extents_type &ext, _Size dynamic_padding_value) + constexpr mapping(const extents_type &ext, Size dynamic_padding_value) : padded_stride(padded_stride_type::init_padding(ext, dynamic_padding_value)), exts(ext) { assert((padding_value == dynamic_extent) || (static_cast<index_type>(padding_value) == static_cast<index_type>(dynamic_padding_value))); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + ext, dynamic_padding_value)); } /** @@ -269,22 +437,26 @@ public: * `padding_value` greater than or equal to `extents_type::static_extent(0)` */ MDSPAN_TEMPLATE_REQUIRES( - class _OtherExtents, - /* requires */ (std::is_constructible_v<extents_type, _OtherExtents>)) + class OtherExtents, + /* requires */ (std::is_constructible_v<extents_type, OtherExtents>)) MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v<_OtherExtents, extents_type>)) + (!std::is_convertible_v<OtherExtents, extents_type>)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const layout_left::mapping<_OtherExtents> &other_mapping) + constexpr mapping(const layout_left::mapping<OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), exts(other_mapping.extents()) { static_assert( - (_OtherExtents::rank() > 1) || + (OtherExtents::rank() > 1) || (static_padding_stride != dynamic_extent) || - (_OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || + (OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || (static_padding_stride == - _OtherExtents::static_extent(extent_to_pad_idx))); + OtherExtents::static_extent(extent_to_pad_idx))); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + exts, padded_stride.value(0))); } /** @@ -294,15 +466,20 @@ public: * `is_constructible_v<extents_type, OtherExtents>` is true */ MDSPAN_TEMPLATE_REQUIRES( - class _OtherExtents, - /* requires */ (std::is_constructible_v<extents_type, _OtherExtents>)) + class OtherExtents, + /* requires */ (std::is_constructible_v<extents_type, OtherExtents>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const layout_stride::mapping<_OtherExtents> &other_mapping) + constexpr mapping(const layout_stride::mapping<OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), - exts(other_mapping.extents()) {} + exts(other_mapping.extents()) { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + exts, padded_stride.value(0))); + } /** * Converting constructor from `layout_left_padded::mapping`. @@ -313,22 +490,26 @@ public: * `padding_value == OtherPaddingStride`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value + class Mapping, + /* requires */ (detail::is_layout_left_padded_mapping<Mapping>::value &&std::is_constructible_v< - extents_type, typename _Mapping::extents_type>)) + extents_type, typename Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 1 && (padding_value == dynamic_extent || - _Mapping::padding_value == dynamic_extent))) + Mapping::padding_value == dynamic_extent))) MDSPAN_INLINE_FUNCTION - constexpr mapping(const _Mapping &other_mapping) + constexpr mapping(const Mapping &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), exts(other_mapping.extents()) { static_assert(padding_value == dynamic_extent || - _Mapping::padding_value == dynamic_extent || - padding_value == _Mapping::padding_value); + Mapping::padding_value == dynamic_extent || + padding_value == Mapping::padding_value); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + exts, padded_stride.value(0))); } /** @@ -339,19 +520,24 @@ public: * OtherExtents>` is `true`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value + class Mapping, + /* requires */ (detail::is_layout_right_padded_mapping<Mapping>::value &&extents_type::rank() <= 1 && std::is_constructible_v<extents_type, - typename _Mapping::extents_type>)) + typename Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v<typename _Mapping::extents_type, extents_type>)) + (!std::is_convertible_v<typename Mapping::extents_type, extents_type>)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const _Mapping &other_mapping) noexcept + constexpr mapping(const Mapping &other_mapping) noexcept : padded_stride(padded_stride_type::init_padding( static_cast<extents_type>(other_mapping.extents()), other_mapping.extents().extent(extent_to_pad_idx))), - exts(other_mapping.extents()) {} + exts(other_mapping.extents()) { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_left_padding_representability<index_type>( + exts, padded_stride.value(0))); + } MDSPAN_INLINE_FUNCTION constexpr const extents_type & extents() const noexcept { @@ -390,7 +576,7 @@ public: for (rank_type r = 1; r < extents_type::rank(); ++r) { value *= exts.extent(r); } - return value; + return value == 0 ? 0 : value + exts.extent(0) - padded_stride.value(0); } } @@ -403,17 +589,17 @@ public: * - (is_nothrow_constructible_v<index_type, Indices> && ...) is true. */ MDSPAN_TEMPLATE_REQUIRES( - class... _Indices, - /* requires */ (sizeof...(_Indices) == extents_type::rank() && + class... Indices, + /* requires */ (sizeof...(Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: - are_valid_indices<index_type, _Indices...>()))) + are_valid_indices<index_type, Indices...>()))) MDSPAN_INLINE_FUNCTION constexpr size_t - operator()(_Indices... idxs) const noexcept { + operator()(Indices... idxs) const noexcept { #if !defined(NDEBUG) ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_all_indices(this->extents(), idxs...); #endif // ! NDEBUG - return compute_offset(std::index_sequence_for<_Indices...>{}, idxs...); + return compute_offset(std::index_sequence_for<Indices...>{}, idxs...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { @@ -464,11 +650,11 @@ public: * Extents>`. However, this makes `padding_value` non-deducible. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value && - (_Mapping::extents_type::rank() == extents_type::rank()))) + class Mapping, + /* requires */ (detail::is_layout_left_padded_mapping<Mapping>::value && + (Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool - operator==(const mapping &left, const _Mapping &right) noexcept { + operator==(const mapping &left, const Mapping &right) noexcept { // Workaround for some compilers not short-circuiting properly with // compile-time checks i.e. we can't access stride(_padding_stride_idx) of a // rank 0 mapping @@ -488,11 +674,11 @@ public: * `OtherExtents::rank() == extents_type::rank()`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value && - (_Mapping::extents_type::rank() == extents_type::rank()))) + class Mapping, + /* requires */ (detail::is_layout_left_padded_mapping<Mapping>::value && + (Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool - operator!=(const mapping &left, const _Mapping &right) noexcept { + operator!=(const mapping &left, const Mapping &right) noexcept { return !(left == right); } #endif @@ -534,10 +720,17 @@ public: || (extents_type::static_extent(extent_to_pad_idx) == 0) || (extents_type::static_extent(extent_to_pad_idx) == dynamic_extent), "if padding stride is 0, static_extent(extent-to-pad-rank) must also be 0 or dynamic_extent"); + static_assert(detail::check_static_extents_representability<extents_type>(), "The size of the muiltidimensional index space given by the extents must be representable as a value of index_type"); + static_assert((padding_value == dynamic_extent) || MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range<index_type>(padding_value), "padding_value must be representable as a value of type index_type"); + using padded_stride_type = detail::padded_extent< padding_value, extents_type, extent_to_pad_idx >; static constexpr size_t static_padding_stride = padded_stride_type::static_value(); + static_assert(detail::check_static_extents_and_right_padding_representability<index_type, static_padding_stride, extents_type>() + && detail::check_static_extents_and_right_padding_representability<size_t, static_padding_stride, extents_type>(), + "the product of static_padding_stride and static extents 1 through rank must be representable as a value of type size_t and index_type"); + typename padded_stride_type::static_array_type padded_stride = {}; extents_type exts = {}; @@ -595,7 +788,12 @@ public: */ MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type &ext) - : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) {} + : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + ext, padded_stride.value(0))); + } /** * Initializes the mapping with the given extents and the specified padding value. @@ -607,18 +805,22 @@ public: * \param padding_value the padding value */ MDSPAN_TEMPLATE_REQUIRES( - class _Size, + class Size, /* requires */ ( - std::is_convertible_v<_Size, index_type> - && std::is_nothrow_constructible_v<index_type, _Size> + std::is_convertible_v<Size, index_type> + && std::is_nothrow_constructible_v<index_type, Size> ) ) MDSPAN_INLINE_FUNCTION - constexpr mapping(const extents_type &ext, _Size dynamic_padding_value) + constexpr mapping(const extents_type &ext, Size dynamic_padding_value) : padded_stride(padded_stride_type::init_padding(ext, static_cast<index_type>(dynamic_padding_value))), exts(ext) { assert((padding_value == dynamic_extent) || (static_cast<index_type>(padding_value) == static_cast<index_type>(dynamic_padding_value))); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + ext, dynamic_padding_value)); } /** @@ -629,22 +831,26 @@ public: * otherwise, `OtherExtents::static_extent(0)` must be equal to the least multiple of `padding_value` greater than or equal to `extents_type::static_extent(0)` */ MDSPAN_TEMPLATE_REQUIRES( - class _OtherExtents, - /* requires */ (std::is_constructible_v<extents_type, _OtherExtents>)) + class OtherExtents, + /* requires */ (std::is_constructible_v<extents_type, OtherExtents>)) MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v<_OtherExtents, extents_type>)) + (!std::is_convertible_v<OtherExtents, extents_type>)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const layout_right::mapping<_OtherExtents> &other_mapping) + constexpr mapping(const layout_right::mapping<OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), exts(other_mapping.extents()) { static_assert( - (_OtherExtents::rank() > 1) || + (OtherExtents::rank() > 1) || (padded_stride_type::static_value() != dynamic_extent) || - (_OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || + (OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || (padded_stride_type::static_value() == - _OtherExtents::static_extent(extent_to_pad_idx))); + OtherExtents::static_extent(extent_to_pad_idx))); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + exts, padded_stride.value(0))); } /** @@ -654,15 +860,20 @@ public: * `is_constructible_v<extents_type, OtherExtents>` is true */ MDSPAN_TEMPLATE_REQUIRES( - class _OtherExtents, - /* requires */ (std::is_constructible_v<extents_type, _OtherExtents>)) + class OtherExtents, + /* requires */ (std::is_constructible_v<extents_type, OtherExtents>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const layout_stride::mapping<_OtherExtents> &other_mapping) + constexpr mapping(const layout_stride::mapping<OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), - exts(other_mapping.extents()) {} + exts(other_mapping.extents()) { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + exts, padded_stride.value(0))); + } /** * Converting constructor from `layout_right_padded::mapping`. @@ -673,22 +884,26 @@ public: * `padding_value == OtherPaddingStride`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value + class Mapping, + /* requires */ (detail::is_layout_right_padded_mapping<Mapping>::value &&std::is_constructible_v< - extents_type, typename _Mapping::extents_type>)) + extents_type, typename Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 1 && (padding_value == dynamic_extent || - _Mapping::padding_value == dynamic_extent))) + Mapping::padding_value == dynamic_extent))) MDSPAN_INLINE_FUNCTION - constexpr mapping(const _Mapping &other_mapping) + constexpr mapping(const Mapping &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant<size_t, padded_stride_idx>{})), exts(other_mapping.extents()) { static_assert(padding_value == dynamic_extent || - _Mapping::padding_value == dynamic_extent || - padding_value == _Mapping::padding_value); + Mapping::padding_value == dynamic_extent || + padding_value == Mapping::padding_value); + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + exts, padded_stride.value(0))); } /** @@ -699,19 +914,24 @@ public: * OtherExtents>` is `true`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value + class Mapping, + /* requires */ (detail::is_layout_left_padded_mapping<Mapping>::value &&extents_type::rank() <= 1 && std::is_constructible_v<extents_type, - typename _Mapping::extents_type>)) + typename Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v<typename _Mapping::extents_type, extents_type>)) + (!std::is_convertible_v<typename Mapping::extents_type, extents_type>)) MDSPAN_INLINE_FUNCTION - constexpr mapping(const _Mapping &other_mapping) noexcept + constexpr mapping(const Mapping &other_mapping) noexcept : padded_stride(padded_stride_type::init_padding( static_cast<extents_type>(other_mapping.extents()), other_mapping.extents().extent(extent_to_pad_idx))), - exts(other_mapping.extents()) {} + exts(other_mapping.extents()) { + MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(exts)); + MDSPAN_IMPL_PRECONDITION( + detail::check_extents_and_right_padding_representability<index_type>( + exts, padded_stride.value(0))); + } MDSPAN_INLINE_FUNCTION constexpr const extents_type & extents() const noexcept { @@ -745,11 +965,11 @@ public: } else if constexpr (extents_type::rank() == 1) { return exts.extent(0); } else { - index_type value = 1; + index_type value = padded_stride.value(0); for (rank_type r = 0; r < extent_to_pad_idx; ++r) { value *= exts.extent(r); } - return value * padded_stride.value(0); + return value == 0 ? 0 : value + exts.extent(extent_to_pad_idx) - padded_stride.value(0); } } @@ -762,13 +982,13 @@ public: * - (is_nothrow_constructible_v<index_type, Indices> && ...) is true. */ MDSPAN_TEMPLATE_REQUIRES( - class... _Indices, - /* requires */ (sizeof...(_Indices) == extents_type::rank() && + class... Indices, + /* requires */ (sizeof...(Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: - are_valid_indices<index_type, _Indices...>()))) + are_valid_indices<index_type, Indices...>()))) MDSPAN_INLINE_FUNCTION constexpr size_t - operator()(_Indices... idxs) const noexcept { - return compute_offset(std::index_sequence_for<_Indices...>{}, idxs...); + operator()(Indices... idxs) const noexcept { + return compute_offset(std::index_sequence_for<Indices...>{}, idxs...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { @@ -819,11 +1039,11 @@ public: * Extents>`. However, this makes `padding_value` non-deducible. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value && - (_Mapping::extents_type::rank() == extents_type::rank()))) + class Mapping, + /* requires */ (detail::is_layout_right_padded_mapping<Mapping>::value && + (Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool - operator==(const mapping &left, const _Mapping &right) noexcept { + operator==(const mapping &left, const Mapping &right) noexcept { // Workaround for some compilers not short-circuiting properly with // compile-time checks i.e. we can't access stride(_padding_stride_idx) of a // rank 0 mapping @@ -843,11 +1063,11 @@ public: * `OtherExtents::rank() == extents_type::rank()`. */ MDSPAN_TEMPLATE_REQUIRES( - class _Mapping, - /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value && - (_Mapping::extents_type::rank() == extents_type::rank()))) + class Mapping, + /* requires */ (detail::is_layout_right_padded_mapping<Mapping>::value && + (Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool - operator!=(const mapping &left, const _Mapping &right) noexcept { + operator!=(const mapping &left, const Mapping &right) noexcept { return !(left == right); } #endif diff --git a/ext/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp b/ext/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp index 3f141ff..481b1d5 100644 --- a/ext/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp +++ b/ext/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp @@ -24,110 +24,110 @@ namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { template <size_t padding_value = dynamic_extent> struct layout_left_padded { - template <class _Extents> + template <class Extents> class mapping; }; template <size_t padding_value = dynamic_extent> struct layout_right_padded { - template <class _Extents> + template <class Extents> class mapping; }; namespace detail { // The layout_padded_constants structs are only useful if rank > 1, otherwise they may wrap -template <class _Layout, class _ExtentsType> +template <class Layout, class ExtentsType> struct layout_padded_constants; -template <class _ExtentsType, size_t _PaddingStride> -struct layout_padded_constants<layout_left_padded<_PaddingStride>, _ExtentsType> +template <class ExtentsType, size_t PaddingStride> +struct layout_padded_constants<layout_left_padded<PaddingStride>, ExtentsType> { - using rank_type = typename _ExtentsType::rank_type; + using rank_type = typename ExtentsType::rank_type; static constexpr rank_type padded_stride_idx = 1; static constexpr rank_type extent_to_pad_idx = 0; }; -template <class _ExtentsType, size_t _PaddingStride> -struct layout_padded_constants<layout_right_padded<_PaddingStride>, _ExtentsType> +template <class ExtentsType, size_t PaddingStride> +struct layout_padded_constants<layout_right_padded<PaddingStride>, ExtentsType> { - using rank_type = typename _ExtentsType::rank_type; - static constexpr rank_type padded_stride_idx = _ExtentsType::rank() - 2; - static constexpr rank_type extent_to_pad_idx = _ExtentsType::rank() - 1; + using rank_type = typename ExtentsType::rank_type; + static constexpr rank_type padded_stride_idx = ExtentsType::rank() - 2; + static constexpr rank_type extent_to_pad_idx = ExtentsType::rank() - 1; }; -template <class _Layout> +template <class Layout> struct is_layout_left_padded : std::false_type {}; -template <size_t _PaddingStride> -struct is_layout_left_padded<layout_left_padded<_PaddingStride>> : std::true_type {}; +template <size_t PaddingStride> +struct is_layout_left_padded<layout_left_padded<PaddingStride>> : std::true_type {}; -template <class _Mapping, class _Enabled = void> +template <class Mapping, class Enabled = void> struct is_layout_left_padded_mapping : std::false_type {}; -template <class _Mapping> -struct is_layout_left_padded_mapping<_Mapping, - std::enable_if_t<std::is_same<_Mapping, typename layout_left_padded<_Mapping::padding_value>::template mapping<typename _Mapping::extents_type>>::value>> +template <class Mapping> +struct is_layout_left_padded_mapping<Mapping, + std::enable_if_t<std::is_same<Mapping, typename layout_left_padded<Mapping::padding_value>::template mapping<typename Mapping::extents_type>>::value>> : std::true_type {}; -template <class _Layout> +template <class Layout> struct is_layout_right_padded : std::false_type {}; -template <size_t _PaddingStride> -struct is_layout_right_padded<layout_right_padded<_PaddingStride>> : std::true_type {}; +template <size_t PaddingStride> +struct is_layout_right_padded<layout_right_padded<PaddingStride>> : std::true_type {}; -template <class _Mapping, class _Enabled = void> +template <class Mapping, class Enabled = void> struct is_layout_right_padded_mapping : std::false_type {}; -template <class _Mapping> -struct is_layout_right_padded_mapping<_Mapping, - std::enable_if_t<std::is_same<_Mapping, typename layout_right_padded<_Mapping::padding_value>::template mapping<typename _Mapping::extents_type>>::value>> +template <class Mapping> +struct is_layout_right_padded_mapping<Mapping, + std::enable_if_t<std::is_same<Mapping, typename layout_right_padded<Mapping::padding_value>::template mapping<typename Mapping::extents_type>>::value>> : std::true_type {}; -template <class _LayoutExtentsType, class _PaddedLayoutMappingType> +template <class LayoutExtentsType, class PaddedLayoutMappingType> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>) {} -template <class _LayoutExtentsType, class _PaddedLayoutMappingType> +template <class LayoutExtentsType, class PaddedLayoutMappingType> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>) {} -template <class _LayoutExtentsType, class _PaddedLayoutMappingType, std::size_t N> +template <class LayoutExtentsType, class PaddedLayoutMappingType, std::size_t N> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<N>) { - using extents_type = typename _PaddedLayoutMappingType::extents_type; - constexpr auto padding_value = _PaddedLayoutMappingType::padding_value; - constexpr auto idx = layout_padded_constants<typename _PaddedLayoutMappingType::layout_type, _LayoutExtentsType >::extent_to_pad_idx; + using extents_type = typename PaddedLayoutMappingType::extents_type; + constexpr auto padding_value = PaddedLayoutMappingType::padding_value; + constexpr auto idx = layout_padded_constants<typename PaddedLayoutMappingType::layout_type, LayoutExtentsType >::extent_to_pad_idx; constexpr auto statically_determinable = - (_LayoutExtentsType::static_extent(idx) != dynamic_extent) && + (LayoutExtentsType::static_extent(idx) != dynamic_extent) && (extents_type::static_extent(idx) != dynamic_extent) && (padding_value != dynamic_extent); static_assert(!statically_determinable || (padding_value == 0 - ? _LayoutExtentsType::static_extent(idx) == 0 - : _LayoutExtentsType::static_extent(idx) % padding_value == 0), + ? LayoutExtentsType::static_extent(idx) == 0 + : LayoutExtentsType::static_extent(idx) % padding_value == 0), ""); } -template <typename _ExtentsType, typename _OtherMapping> +template <typename ExtentsType, typename OtherMapping> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>, - const _OtherMapping&) {} -template <typename _ExtentsType, typename _OtherMapping> + const OtherMapping&) {} +template <typename ExtentsType, typename OtherMapping> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>, - const _OtherMapping&) {} -template <typename _ExtentsType, typename _OtherMapping, std::size_t N> + const OtherMapping&) {} +template <typename ExtentsType, typename OtherMapping, std::size_t N> MDSPAN_INLINE_FUNCTION constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<N>, - const _OtherMapping &other_mapping) { + const OtherMapping &other_mapping) { constexpr auto padded_stride_idx = - layout_padded_constants<typename _OtherMapping::layout_type, - _ExtentsType>::padded_stride_idx; - constexpr auto extent_to_pad_idx = layout_padded_constants<typename _OtherMapping::layout_type, _ExtentsType>::extent_to_pad_idx; + layout_padded_constants<typename OtherMapping::layout_type, + ExtentsType>::padded_stride_idx; + constexpr auto extent_to_pad_idx = layout_padded_constants<typename OtherMapping::layout_type, ExtentsType>::extent_to_pad_idx; MDSPAN_IMPL_PRECONDITION(other_mapping.stride(padded_stride_idx) == other_mapping.extents().extent(extent_to_pad_idx)); } |
