From patchwork Thu Dec 4 21:28:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 125935 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 AF3B34C318AC for ; Thu, 4 Dec 2025 21:29:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AF3B34C318AC 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=aO/ySdNI X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) by sourceware.org (Postfix) with ESMTPS id D95CE4B1A361 for ; Thu, 4 Dec 2025 21:26:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D95CE4B1A361 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 D95CE4B1A361 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883605; cv=none; b=Y+JW8Qws3mW/ltyg5VBkYii5Pc/TBQtOHPyEPCnmp02i00RVXe0uHNjWiuBfk/aSGhS5DuD8RtWAKuKcSEtEYVjzezYUdk8UyIjVT0+8olN3ug/urJN5AVYxHOki92tQkeun5E3pf9HwGX5hTpL0X34sd4Y0oBFyNktX2qlyGgI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883605; c=relaxed/simple; bh=tcNcss8Qw09hQwvZr8XIFNYiDpvtaIip5F2N1z07Ed4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=EiTca2Hl4QHOF1+t7FQ0rlm28hxvr2IlhIxf5Zc9dUmlbo8qcO30/XcgpQPJ4iLGPSthR5MMTyaqBYKu2xPGMAG2exDRLH6QF0aJq5VZ0MgcIJzVeux/vD4WyFRz9JdnYmgsmbLZRg5QH66fcAKfmdzTx0eql8VWPKcAeHq+bTg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D95CE4B1A361 Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-42e2e2eccd2so981596f8f.1 for ; Thu, 04 Dec 2025 13:26:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764883604; x=1765488404; 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=9oS/cTCabovLNYVAOv0lbdpNIs5SPJ9FWb0s81VJ9G0=; b=aO/ySdNImzGQ3ebD0S/QbUnfKcegmuqGHQY3D+lUwRohlaLLmQIcUmJ/7bALhn/Krr gf4DIpZU+mu9QBQWkJxubpWVUxl6BgePqzjY+Jlk9OAjsdGlmDiezTlRZ80k+xpRPIKz es+FPblnBe6EJQLOm466rPy5F1V8aTV9Tgw4S0NaGzgWkFYaO7ysBOPlnoEKCgvNuZlh +mjqPg+XQ2d81tLyXVl1KYMSqst84jZi6PwJvIHf9P0Ed5uU8NIqwEnidCbp8oGbCNp7 EyiB6OQjhjlhuJCu9RxooYybXDp+mlGviu+wQpAC3UbMev2yY7uljTZeuAar2cW36Fee oXBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764883604; x=1765488404; 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=9oS/cTCabovLNYVAOv0lbdpNIs5SPJ9FWb0s81VJ9G0=; b=uHmcQMs30YNdWRMp3IK3txc/GdvsTejFc7ChPIfI+VAlyaYfFeQ0CcSAj65n4nVnCn cBWScgP4YXEZeJfVYPU4A9cv+OyIRUiX3L04mrD3TRhVK5TQdaftm1owLjho/Tu2yMwX KCTk/PVuLY0ZfTxKDld74R2LvslgIQEja+6z4rWslq6MOvzaZz4p25dnm8qoY88/rDEF NfNBB33KS1jWFkPdN8+eulhYq/7v2zLTIXsN+UwZbjfR7L4fqr9jctwJ2GQVZyjvYbEF sPdpOXn3Afb0a31XWg9ZBfSpEESyrJkS2wFw8Y4CBRZT/51l1awsXcvn2+7DQtrCnW6P wRrg== X-Gm-Message-State: AOJu0YxXQttU2+W1tVxq0nAS2r474ajwoA4hx/60UL7sfgIuoHbj8E2E qERSFXb6xg0IlDl/6dwp/H7lQsLhEKnAYKkx7zaICcH5lLWkRMM+dVMhoaTcqg== X-Gm-Gg: ASbGncvJ+ccR+psJ/5+j9O76XgjG3WTkBA2BR07JEZiCbEf/ZCthI/TGt9+o13NG8Qr v8ScM0wj8ZJ29HFi3dLhBIDNd/3ms4KU7zJogC3l+XRRCGUY9rYS3xROgSItRhv0phf8O+7ZGf3 +Tez/QfkHYrRwzLplNR73SHGMkZgO8aBLLtRzFR9Sly2JzmNT306WA+YvHm6qA6HyldloNPGswo n0eIl2leiURrqSqTfCPI4L7XCNZJX3YGXPt8fCNZW5hlXXCuuQ3ucnShjMETFmRwR5tfT6tU8AW 4wMAfvHbwimHxRPdmEggHjH3AiSW+U8gBq5xrYwcb2KCGYQNczPnHQxpp7Zg9osHQAH7ruBJrON P5mWI/VhZVheyH09hvAZ59TWIzfL2U7LsesNtMq963W+EWgUDFKboDDELUkGng2+yREE/pZtBro NX5O4SprnCRrJ6LIFGW+Itt8Nm87+nt3zNK6R312xvVhXiw8Zpk+S8qxnOH/wBrcGE6WP1JaE= X-Google-Smtp-Source: AGHT+IHYD2EAWCspPRizhXJMstMt5pb5P5WVGUkjmiiHLuF42VKcpAP+bUd6VoD5qn5fr/Mu+GRXmA== X-Received: by 2002:a05:6000:1a8a:b0:42b:5628:f4a3 with SMTP id ffacd0b85a97d-42f731678e9mr8197158f8f.1.1764883603527; Thu, 04 Dec 2025 13:26:43 -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.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Dec 2025 13:26:43 -0800 (PST) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v4 2/5] libstdc++: Implement submdspan_mapping for layout_right. [PR110352] Date: Thu, 4 Dec 2025 22:28:43 +0100 Message-ID: <20251204212846.248887-3-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=-11.5 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=ham 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 Adds submdspan_mapping for layout_right as described in P3663. PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/std/mdspan (layout_right::mapping::submdspan_mapping): New friend function. * testsuite/23_containers/mdspan/submdspan/submdspan.cc: Instantiate tests for layout_right. * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: Ditto. * testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc: Ditto. Signed-off-by: Luc Grosheintz --- libstdc++-v3/include/std/mdspan | 39 +++++++++++++++++++ .../mdspan/submdspan/submdspan.cc | 1 + .../mdspan/submdspan/submdspan_mapping.cc | 6 +++ .../mdspan/submdspan/submdspan_neg.cc | 9 +++++ 4 files changed, 55 insertions(+) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 54739c0008d..d8da7b41868 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -1284,40 +1284,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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> + { + 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>; 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{ @@ -1656,40 +1687,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template requires (extents_type::rank() == _OExtents::rank()) friend constexpr bool operator==(const mapping& __self, const mapping<_OExtents>& __other) noexcept { return __self.extents() == __other.extents(); } private: template constexpr explicit mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept : _M_extents(__oexts) { static_assert(__mdspan::__representable_size<_OExtents, index_type>, "The size of OtherExtents must be representable as index_type"); __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } +#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 + [[no_unique_address]] extents_type _M_extents{}; }; namespace __mdspan { template concept __mapping_alike = requires { requires __is_extents; { _Mp::is_always_strided() } -> same_as; { _Mp::is_always_exhaustive() } -> same_as; { _Mp::is_always_unique() } -> same_as; bool_constant<_Mp::is_always_strided()>::value; bool_constant<_Mp::is_always_exhaustive()>::value; bool_constant<_Mp::is_always_unique()>::value; }; template constexpr typename _Mapping::index_type __linear_index_strides(const _Mapping& __m, _Indices... __indices) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc index 53e91407a9c..cd6e9454b17 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc @@ -348,22 +348,23 @@ 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(); 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 a37d3cd588f..cc832cdb415 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc @@ -112,25 +112,31 @@ template 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; } int main() { test_layout_unpadded_return_types(); static_assert(test_layout_unpadded_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()); + + test_layout_unpadded_padding_value(); + static_assert(test_layout_unpadded_padding_value()); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc index cdc8a2b7e23..5d977822dfe 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc @@ -7,112 +7,121 @@ template constexpr bool check_slice_range(Slices... slices) { auto m = typename Layout::mapping>{}; auto storage = std::vector(m.required_span_size()); auto md = std::mdspan(storage.data(), m); auto submd = submdspan(md, slices...); // { dg-error "expansion of" } (void) submd; return true; } template constexpr bool test_int_under() { check_slice_range(1, -1, 2); // { dg-error "expansion of" } return true; } static_assert(test_int_under()); // { dg-error "expansion of" } +static_assert(test_int_under()); // { dg-error "expansion of" } template constexpr bool test_int_over() { check_slice_range(1, 5, 2); // { dg-error "expansion of" } return true; } static_assert(test_int_over()); // { dg-error "expansion of" } +static_assert(test_int_over()); // { dg-error "expansion of" } template constexpr bool test_tuple_under() { check_slice_range(1, std::tuple{-1, 2}, 2); // { dg-error "expansion of" } return true; } static_assert(test_tuple_under()); // { dg-error "expansion of" } +static_assert(test_tuple_under()); // { dg-error "expansion of" } template constexpr bool test_tuple_reversed() { check_slice_range(1, std::tuple{3, 2}, 2); // { dg-error "expansion of" } return true; } static_assert(test_tuple_reversed()); // { dg-error "expansion of" } +static_assert(test_tuple_reversed()); // { dg-error "expansion of" } template constexpr bool test_tuple_over() { check_slice_range(1, std::tuple{0, 6}, 2); // { dg-error "expansion of" } return true; } static_assert(test_tuple_over()); // { dg-error "expansion of" } +static_assert(test_tuple_over()); // { dg-error "expansion of" } template constexpr bool test_strided_slice_zero() { check_slice_range(1, std::strided_slice{1, 1, 0}, 2); // { dg-error "expansion of" } return true; } static_assert(test_strided_slice_zero()); // { dg-error "expansion of" } +static_assert(test_strided_slice_zero()); // { dg-error "expansion of" } template constexpr bool test_strided_slice_offset_under() { check_slice_range(1, std::strided_slice{-1, 1, 1}, 2); // { dg-error "expansion of" } return true; } static_assert(test_strided_slice_offset_under()); // { dg-error "expansion of" } +static_assert(test_strided_slice_offset_under()); // { dg-error "expansion of" } template constexpr bool test_strided_slice_offset_over() { check_slice_range(1, std::strided_slice{6, 0, 1}, 2); // { dg-error "expansion of" } return true; } static_assert(test_strided_slice_offset_over()); // { dg-error "expansion of" } +static_assert(test_strided_slice_offset_over()); // { dg-error "expansion of" } template constexpr bool test_strided_slice_extent_over() { check_slice_range(1, std::strided_slice{1, 5, 1}, 2); // { dg-error "expansion of" } return true; } static_assert(test_strided_slice_extent_over()); // { dg-error "expansion of" } +static_assert(test_strided_slice_extent_over()); // { dg-error "expansion of" } namespace adl { struct NoFull { template class mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; private: friend constexpr auto submdspan_mapping(mapping, int) { return std::submdspan_mapping_result{mapping{}, 0}; } }; }; struct WrongReturnValue