From patchwork Thu Dec 4 21:28:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 125938 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 20D1C4B1A361 for ; Thu, 4 Dec 2025 21:33:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 20D1C4B1A361 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=YZUcweRp X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by sourceware.org (Postfix) with ESMTPS id 10C3A4BC7EDF for ; Thu, 4 Dec 2025 21:26:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 10C3A4BC7EDF Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 10C3A4BC7EDF Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883607; cv=none; b=jfVPRZJ8xbjljK9xHu1CmOj3GgdV2Me8ONCTvqa5YkE7EGol3bJuVqvR3fDDumvzxmlaZGPf/byfcjRtumEBTciDeDLGmgn3/6WojjEVX8nQ3l+MM8QTU1Fe9hoLLb2YDFNQtjj+4lX4IgjeW4hx7vEK/+113/Dc8tLXcFrL4xs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883607; c=relaxed/simple; bh=C0lpsC+ZLldJrGDLMy2OQKD5OzI/G9kML5kTqSI6wk4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=b3PebQcTywWRq7SeGFDZaaP6fikdJtt8tFO4nOd7xmSoby5x1Vy4vTgoV0GDfH90Co2LTdR1y7Xjrj1ceinNOcR63n1xakSgAzf25MevCdGQgoBSyv3qpl/uT5+FyDBFY/b9ANI4EAcq0TAekxjpcPx0yINXgH2brwb0egZpvco= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 10C3A4BC7EDF Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-42e2e167067so733926f8f.2 for ; Thu, 04 Dec 2025 13:26:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764883606; x=1765488406; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=44mmVcNXGoBS8wyZEN1+F+nHzy0GbOgIjFX4kwDUmFY=; b=YZUcweRpOdAu0GWxR9YYQyNshmBZxzWQ3YA9/iQlE77QBzrr7Jm9kYZ0szPCGdRhyG cnCj0yeOe3C5g3WbRQBrZDyvujpIYjn9kDXSeesdFgkDZu2Nc98mrwfbuDSpvV806LXi WbvB+wbw5uhXb+u6sURlTbEUAzQMcWjfJSeQ4vLpLOtEjcKTCh4E0cE4hGTEh0t0blOo mToAcUz2GtZKCLtatadus6L8cHqgm++NQ84luRXcoWleWT/Z2ZkXuLtEmkeK9VtNg4EZ NmQgwuPpKtb6tBwSErOT7SbtFmAGzpgxyj8IOBtNPo/+1U2ggpbOH07SglIInJk/2ayd K/4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764883606; x=1765488406; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=44mmVcNXGoBS8wyZEN1+F+nHzy0GbOgIjFX4kwDUmFY=; b=Y974iZ/lSePDWfuprm9c2C92m7xwmsCv2ITQ6ts4WPv2ifLA4DNRaQ/OwU6dLaw/Al SHbD6zFWtHfPm4POfzXyZlaic67MHtrDFE9PrvehVzML9ElxNH83uj7v5itxedFx5GfT b+GdOJBFMaBU3JiKYicB1vvGkcDj8EENlMJfoK93sU+CULDywXA8StR7i0NcvQItde76 RB7l7z9G+vqe3zDpVnn1XhZ90FTjt5EeC9x9oJnsYHgrVOP1xw2p7nXampqnVIPq2rMJ V6DNlGNojq9FW7NUCMZUut5GyPW6FgsFG/pRoo7P46uaeIW0tMHTZkLrBGzxsAxZ0n+B I76w== X-Gm-Message-State: AOJu0YzlVt48JREpuWm53LDHm7OArc9ejlsIhsBlzlh60X4x1dPYuvFK hns5CH0azW0MyCjDlXIwwNAIK+WnlrFgWKGui+zqOlRW9Ca3UJF3iXK3 X-Gm-Gg: ASbGncuvlfogoN/JsS8/Z4tzI0T66R5qq8OuuJkf5nD376mS/8B77mb53aogQ/t8CnG KfkOO3JClLw5X/Uss8Hr7q4RXMMOncC+Z0Hx5CuLBKE2UulZdn34AZiUAVTLtjkNM77AcZ0HKL4 KeEZMbGKMtAKu4hnArN1CwK3MCf5BT5myZA49WbdHZpnE3gBSf6O3eXzGNoknmOC69YbvCz84d7 E76qcHsYrs7qGx1ip5dhKXxOxM1Lt8wIThhiabECdGy2wiulkNmlUpUJ+nad2+TNugOTWA3bW6o 7yRq8mzwcU/gZrDa9Awd5UMQW8h1xr72nxPmmHAOj6hoej+yYbFIonfcJvi/DA6fI6a0dIJhVkI T/J2c3eQPlSR5kZ0OwXaVQQlZnc1LgEQcMzf2BO5TTRw7fWNiYLc5D1t8B8F/2AAqaxFVjqP7oo Nd+bqifLG3+6BXmDAdVEFX7peHV1HIDKBtcI6K33tHc8Ihr0Jj/hngK+ssUFfh X-Google-Smtp-Source: AGHT+IEaagbF2huD8QLoxn2lzCw/AGBPxHGnKsxmwMuMZQvb17YRWRdijPaKXte6/RtKnsp9Z27XOA== X-Received: by 2002:a05:6000:4011:b0:429:d4e1:cbb5 with SMTP id ffacd0b85a97d-42f7317420cmr8510098f8f.8.1764883605716; Thu, 04 Dec 2025 13:26:45 -0800 (PST) Received: from piglet.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42f7d331e29sm5354432f8f.32.2025.12.04.13.26.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Dec 2025 13:26:45 -0800 (PST) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v4 4/5] libstdc++: Implement submdspan_mapping for layout_left_padded. [PR110352] Date: Thu, 4 Dec 2025 22:28:45 +0100 Message-ID: <20251204212846.248887-5-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251204212846.248887-1-luc.grosheintz@gmail.com> References: <20251204212846.248887-1-luc.grosheintz@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Implements submdspan for layout_left_padded as described in P3663. PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/std/mdspan (layout_left_padded::submdspan_mapping): New friend method. * testsuite/23_containers/mdspan/layout_traits.h (LayoutTraits::layout_same_padded): New template type alias. * testsuite/23_containers/mdspan/submdspan/submdspan.cc: Restructed and new tests for layout_left_padded. * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: Ditto. Signed-off-by: Luc Grosheintz --- libstdc++-v3/include/std/mdspan | 55 +++++- .../23_containers/mdspan/layout_traits.h | 4 + .../mdspan/submdspan/submdspan.cc | 3 + .../mdspan/submdspan/submdspan_mapping.cc | 179 ++++++++++++++++-- 4 files changed, 216 insertions(+), 25 deletions(-) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 8b6c24885ae..21dbe6def22 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -795,40 +795,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION || (__static_quotient<_Extents, _IndexType>() != 0); template concept __mapping_of = is_same_v, _Mapping>; template typename _Layout, typename _Mapping> concept __padded_mapping_of = __mapping_of< _Layout<_Mapping::padding_value>, _Mapping>; #ifdef __glibcxx_padded_layouts template constexpr bool __is_left_padded_mapping = __padded_mapping_of< layout_left_padded, _Mapping>; template constexpr bool __is_right_padded_mapping = __padded_mapping_of< layout_right_padded, _Mapping>; + + template + constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping> + || __is_right_padded_mapping<_Mapping>; #endif template consteval size_t __get_static_stride() { return _PaddedMapping::_PaddedStorage::_S_static_stride; } template concept __standardized_mapping = __mapping_of || __mapping_of || __mapping_of #ifdef __glibcxx_padded_layouts || __is_left_padded_mapping<_Mapping> || __is_right_padded_mapping<_Mapping> #endif ; // A tag type to create internal ctors. class __internal_ctor { }; @@ -1257,110 +1261,144 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<_LayoutSide _Side, size_t _SubRank, size_t _Nm> static consteval size_t __padded_block_begin(span __slice_kinds) { if constexpr (_Side == _LayoutSide::__left) return __mdspan::__padded_block_begin_generic<_SubRank>(__slice_kinds); else { std::array<_SliceKind, _Nm> __rev_slice_kinds; for(size_t __i = 0; __i < _Nm; ++__i) __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i]; auto __u = __mdspan::__padded_block_begin_generic<_SubRank>( std::span(__rev_slice_kinds)); return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u; } } - template<_LayoutSide _Side> + template<_LayoutSide _Side, bool _Padded> struct _SubMdspanMapping; template<> - struct _SubMdspanMapping<_LayoutSide::__left> + struct _SubMdspanMapping<_LayoutSide::__left, false> { using _Layout = layout_left; template using _PaddedLayout = layout_left_padded<_Pad>; template static consteval size_t _S_pad() { using _Extents = typename _Mapping::extents_type; constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us); if constexpr (!__mdspan::__all_static(__sta_exts)) return dynamic_extent; else return __mdspan::__fwd_prod(__sta_exts); } template static consteval bool _S_is_unpadded_submdspan(span __slice_kinds) { return __mdspan::__is_block<_SubRank>(__slice_kinds); } }; template<> - struct _SubMdspanMapping<_LayoutSide::__right> + struct _SubMdspanMapping<_LayoutSide::__left, true> + { + using _Layout = layout_left; + template using _PaddedLayout = layout_left_padded<_Pad>; + + template + static consteval size_t + _S_pad() + { + using _Extents = typename _Mapping::extents_type; + constexpr auto __sta_exts + = __mdspan::__static_extents<_Extents>(1, _Us); + constexpr auto __sta_padstride + = __mdspan::__get_static_stride<_Mapping>(); + if constexpr (__sta_padstride == dynamic_extent + || !__mdspan::__all_static(__sta_exts)) + return dynamic_extent; + else + return __sta_padstride * __mdspan::__fwd_prod(__sta_exts); + } + + template + static consteval bool + _S_is_unpadded_submdspan(span __slice_kinds) + { + if constexpr (_SubRank == 1) + return __slice_kinds[0] == _SliceKind::__unit_strided_slice + || __slice_kinds[0] == _SliceKind::__full; + else + return false; + } + }; + + template<> + struct _SubMdspanMapping<_LayoutSide::__right, false> { using _Layout = layout_right; template using _PaddedLayout = layout_right_padded<_Pad>; template static consteval size_t _S_pad() { using _Extents = typename _Mapping::extents_type; constexpr auto __rank = _Extents::rank(); constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(_Us + 1, __rank); if constexpr (!__mdspan::__all_static(__sta_exts)) return dynamic_extent; else return __fwd_prod(__sta_exts); } template static consteval bool _S_is_unpadded_submdspan(span __slice_kinds) { auto __rev_slice_kinds = array<_SliceKind, _Nm>{}; for(size_t __i = 0; __i < _Nm; ++__i) __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i]; return __mdspan::__is_block<_SubRank>(span(__rev_slice_kinds)); } }; template constexpr auto __submdspan_mapping_impl(const _Mapping& __mapping) { return submdspan_mapping_result{__mapping, 0}; } template requires (sizeof...(_Slices) > 0) constexpr auto __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices) { constexpr auto __side = __mdspan::__mapping_side<_Mapping>(); - using _Trait = _SubMdspanMapping<__side>; + using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>; constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>(); auto __offset = __mdspan::__suboffset(__mapping, __slices...); auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...); using _SubExts = decltype(__sub_exts); constexpr auto __sub_rank = _SubExts::rank(); if constexpr (__sub_rank == 0) return submdspan_mapping_result{ typename _Trait::_Layout::mapping(__sub_exts), __offset}; else if constexpr ( _Trait::template _S_is_unpadded_submdspan<__sub_rank>( std::span(__slice_kinds))) return submdspan_mapping_result{ typename _Trait::_Layout::mapping(__sub_exts), __offset}; else if constexpr ( constexpr auto __u = __padded_block_begin<__side, __sub_rank>( span(__slice_kinds)); __u != dynamic_extent) { constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>(); @@ -2536,40 +2574,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type stride(rank_type __r) const noexcept { __glibcxx_assert(__r < _S_rank); if (__r == 0) return 1; else return static_cast( static_cast(_M_padstride()) * static_cast(__mdspan::__fwd_prod(extents(), 1, __r))); } template requires(__mdspan::__is_left_padded_mapping<_LeftpadMapping> && _LeftpadMapping::extents_type::rank() == _S_rank) friend constexpr bool operator==(const mapping& __self, const _LeftpadMapping& __other) noexcept { return __self._M_storage._M_equal(__other); } + + private: +#if __glibcxx_submdspan + template<__mdspan::__acceptable_slice_type... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); } +#endif // __glibcxx_submdspan }; template template class layout_right_padded<_PaddingValue>::mapping { public: static constexpr size_t padding_value = _PaddingValue; using extents_type = _Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right_padded<_PaddingValue>; private: static constexpr size_t _S_rank = extents_type::rank(); using _PaddedStorage = __mdspan::_PaddedStorage<_PaddingValue, _Extents, __mdspan::_RightPaddedLayoutTraits<_S_rank>>; [[no_unique_address]] _PaddedStorage _M_storage; consteval friend size_t diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h index 619cab53b9e..f0aeac320de 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h @@ -70,79 +70,83 @@ struct DeducePaddingSide constexpr static PaddingSide from_typename() { if constexpr (std::same_as) return PaddingSide::Left; else if constexpr (is_left_padded) return PaddingSide::Left; else return PaddingSide::Right; } }; template struct LayoutTraits; template<> struct LayoutTraits { using layout_same = std::layout_left; using layout_other = std::layout_right; + template + using layout_same_padded = std::layout_left_padded; template using extents_type = Extents; template constexpr static extents_type make_extents(const Extents& exts) { return exts; } template constexpr static std::array make_array(const std::array& a) { return a; } template constexpr static auto make_indices(Indices... indices) { return std::array{indices...}; } template constexpr static std::tuple make_tuple(const std::tuple& tup) { return tup; } template constexpr static auto padded_stride(const Mapping& m) { return m.stride(1); } template constexpr static auto padded_extent(const Extents& exts) { return exts.extent(0); } }; template<> struct LayoutTraits { using layout_same = std::layout_right; + template + using layout_same_padded = std::layout_right_padded; using layout_other = std::layout_left; template constexpr static auto make_extents(const std::extents& exts) { constexpr size_t rank = sizeof...(Extents); auto impl = [&](std::index_sequence) { auto dyn_exts = make_array(dynamic_extents_array(exts)); return std::extents(dyn_exts); }; return impl(std::make_index_sequence()); } template using extents_type = decltype(make_extents(std::declval())); template constexpr static std::array diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc index 645c4711294..927b5d06c6b 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc @@ -348,24 +348,27 @@ template }; run(std::extents(3, 5, 7)); run(std::extents{}); return true; } template constexpr bool test_all() { test_all_cheap(); test_all_expensive(); return true; } int main() { test_all(); + test_all>(); + test_all>(); + test_all>(); test_all(); test_all(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc index cf6167dc3b0..50836968a06 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc @@ -1,69 +1,63 @@ // { dg-do run { target c++26 } } #include #include // TODO remove #include "../layout_traits.h" #include constexpr size_t dyn = std::dynamic_extent; +constexpr auto all = std::full_extent; template constexpr auto call_submdspan_mapping(const Mapping& m, std::tuple slices) { auto impl = [&](std::index_sequence) { return submdspan_mapping(m, get(slices)...); }; return impl(std::make_index_sequence()); } template constexpr bool - test_layout_unpadded_return_types() + test_layout_common_return_types() { constexpr auto padding_side = DeducePaddingSide::from_typename(); using Traits = LayoutTraits; + using layout_unpadded = typename Traits::layout_same; { auto m0 = typename Layout::mapping(std::extents()); auto result = submdspan_mapping(m0); using layout_type = typename decltype(result.mapping)::layout_type; static_assert(std::same_as); } auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13)); auto m = typename Layout::mapping(exts); - auto all = std::full_extent; auto s251 = std::strided_slice{2, 5, std::cw<1>}; { auto slices = std::tuple{0, 0, 0, 0, 0}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); using layout_type = typename decltype(result.mapping)::layout_type; - static_assert(std::same_as); - } - - { - auto slices = std::tuple{all, all, all, s251, 0}; - auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); - using layout_type = typename decltype(result.mapping)::layout_type; - static_assert(std::same_as); + static_assert(std::same_as); } { auto s0 = std::strided_slice{1, 1, std::cw<1>}; auto slices = std::tuple{s0, all, all, s251, 0}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); using layout_type = typename decltype(result.mapping)::layout_type; static_assert(is_same_padded); } { auto s0 = std::strided_slice{1, 2, std::cw<1>}; auto slices = std::tuple{s0, all, all, s251, 0}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); using layout_type = typename decltype(result.mapping)::layout_type; static_assert(is_same_padded); } { auto s0 = std::strided_slice{1, 2, std::cw<1>}; @@ -81,80 +75,223 @@ template static_assert(std::same_as); } { auto slices = std::tuple{1, all, all, s251, 0}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); using layout_type = decltype(result.mapping)::layout_type; static_assert(std::same_as); } { auto s3 = std::strided_slice{2, std::cw<7>, std::cw<2>}; auto slices = std::tuple{all, all, all, s3, 0}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); using layout_type = decltype(result.mapping)::layout_type; static_assert(std::same_as); } return true; } +template + constexpr bool + test_layout_unpadded_return_types() + { + constexpr auto padding_side = DeducePaddingSide::from_typename(); + using Traits = LayoutTraits; + + auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13)); + auto m = typename Layout::mapping(exts); + auto s251 = std::strided_slice{2, 5, std::cw<1>}; + + { + auto slices = std::tuple{all, all, all, s251, 0}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + using layout_type = typename decltype(result.mapping)::layout_type; + static_assert(std::same_as); + } + return true; + } + +template + constexpr bool + test_layout_padded_return_types() + { + constexpr auto padding_side = DeducePaddingSide::from_typename(); + using Traits = LayoutTraits; + + auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13)); + auto m = typename Layout::mapping(exts); + auto s251 = std::strided_slice{2, 5, std::cw<1>}; + + { + auto slices = std::tuple{all, all, all, s251, 0}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + using layout_type = typename decltype(result.mapping)::layout_type; + using layout_expected = typename Traits::layout_same_padded; + static_assert(std::same_as); + } + + { + auto slices = std::tuple{all, 0, 0, 0, 0}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + using layout_type = typename decltype(result.mapping)::layout_type; + using layout_expected = typename Traits::layout_same; + static_assert(std::same_as); + } + + { + auto s121 = std::strided_slice{1, 2, std::cw<1>}; + auto slices = std::tuple{s121, 0, 0, 0, 0}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + using layout_type = typename decltype(result.mapping)::layout_type; + using layout_expected = typename Traits::layout_same; + static_assert(std::same_as); + } + + { + auto s121 = std::strided_slice{1, 2, std::cw<1>}; + auto slices = std::tuple{0, s121, 0, 0, 0}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + using layout_type = typename decltype(result.mapping)::layout_type; + static_assert(std::same_as); + } + return true; + } + template constexpr bool test_layout_unpadded_padding_value() { using Traits = LayoutTraits()>; auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw}; auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw}; - auto all = std::full_extent; auto check = [&](auto exts, size_t expected) { auto m = typename Layout::mapping(Traits::make_extents(exts)); auto slices = std::tuple{s0, size_t(0), all, s3, size_t(0)}; auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); auto padding_value = decltype(result.mapping)::padding_value; VERIFY(padding_value == expected); }; check(std::extents(std::cw<3>, std::cw<5>, std::cw<7>, 11, 13), 3*5); check(std::extents(std::cw<3>, std::cw<5>, 7, 11, 13), 3*5); check(std::extents(std::cw<3>, 5, 7, 11, 13), dyn); check(std::extents(3, 5, 7, 11, 13), dyn); return true; } +template +constexpr size_t static_padding_value = 1; + +template +constexpr size_t static_padding_value> = PaddingValue; + +template +constexpr size_t static_padding_value> = PaddingValue; + +template + constexpr bool + test_layout_padded_padding_value() + { + using Traits = LayoutTraits()>; + auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw}; + auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw}; + + auto check = [&](auto exts, size_t expected) + { + auto m = typename Layout::mapping(Traits::make_extents(exts)); + auto slices = std::tuple{s0, size_t(0), all, s3, size_t(0)}; + auto result = call_submdspan_mapping(m, Traits::make_tuple(slices)); + auto padding_value = decltype(result.mapping)::padding_value; + VERIFY(padding_value == expected); + }; + + auto pad = [](int n, int m) -> size_t + { + constexpr auto padding_value = static_padding_value; + if constexpr (padding_value != dyn) + { + auto npad = ((n + padding_value - 1) / padding_value) * padding_value; + return npad * m; + } + else + return dyn; + }; + + check(std::extents(std::cw<3>, std::cw<5>, std::cw<7>, 11, 13), pad(3, 5)); + check(std::extents(std::cw<3>, std::cw<5>, 7, 11, 13), pad(3, 5)); + check(std::extents(std::cw<3>, std::cw<6>, 7, 11, 13), pad(3, 6)); + check(std::extents(std::cw<3>, 5, 7, 11, 13), dyn); + check(std::extents(3, 5, 7, 11, 13), dyn); + return true; + } + constexpr bool test_layout_stride_return_types() { auto exts = std::extents(3, 5); auto m = std::layout_stride::mapping(exts, std::array{2, 12}); using index_type = decltype(exts)::index_type; auto s1 = std::strided_slice{index_type(2), index_type(2), std::cw}; auto result = submdspan_mapping(m, index_type(1), s1); using layout_type = decltype(result.mapping)::layout_type; static_assert(std::same_as); return true; } +template + constexpr bool + test_return_types_all() + { + return true; + } + +template + constexpr bool + test_return_types_unpadded_all() + { + test_layout_common_return_types(); + static_assert(test_layout_common_return_types()); + + test_layout_unpadded_return_types(); + static_assert(test_layout_unpadded_return_types()); + + test_layout_unpadded_padding_value(); + static_assert(test_layout_unpadded_padding_value()); + return true; + } + +template + constexpr bool + test_return_types_padded_all() + { + test_layout_common_return_types(); + static_assert(test_layout_common_return_types()); + + test_layout_padded_return_types(); + static_assert(test_layout_padded_return_types()); + + test_layout_padded_padding_value(); + static_assert(test_layout_padded_padding_value()); + return true; + } + int main() { - test_layout_unpadded_return_types(); - static_assert(test_layout_unpadded_return_types()); + test_return_types_unpadded_all(); + test_return_types_unpadded_all(); - test_layout_unpadded_return_types(); - static_assert(test_layout_unpadded_return_types()); + test_return_types_padded_all>(); + test_return_types_padded_all>(); + test_return_types_padded_all>(); test_layout_stride_return_types(); static_assert(test_layout_stride_return_types()); - - test_layout_unpadded_padding_value(); - static_assert(test_layout_unpadded_padding_value()); - - test_layout_unpadded_padding_value(); - static_assert(test_layout_unpadded_padding_value()); return 0; }