From patchwork Thu Dec 4 21:28:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 125937 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 1EB724BB593C for ; Thu, 4 Dec 2025 21:32:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1EB724BB593C 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=TMnSrlIU X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by sourceware.org (Postfix) with ESMTPS id AE38C4BBCDB5 for ; Thu, 4 Dec 2025 21:26:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AE38C4BBCDB5 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 AE38C4BBCDB5 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883605; cv=none; b=x9iI4TCNciNBfEVKrQyq6xdAEz3ww9sWVUKH+0p6uB1kfKnXFvu959fdzXLTHvdyjUgvl2TmbAhh2JhMRE6vHmkRdDFzf8/WgnyP688LXHHXs/vrWaScAMf+Fks+G8LOqOMGkncO73G3zPyuva+ui/BBmQQtU1l8+caCYyECQC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764883605; c=relaxed/simple; bh=xOIXqIjHMbjrcb/hpQHcqErj1OF04Je8iYLTOLxkQA0=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=vFG/FC+j8oBk1ytbCft3qGy2IMysVUWyyqzRoXYmLzwJqsqXBpZdDZA0dsOlnIH3yF84z7TJjshVa+EE8Hb1CyT9jmrdrf54eT1D4R+HUwDHQ/wts/VVX/HC8ZKdtFFDtnG8ymlM1+qr/+Thqp8fnH1kxLnX2a6zjjph4TXcxNc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AE38C4BBCDB5 Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4779adb38d3so13154115e9.2 for ; Thu, 04 Dec 2025 13:26:45 -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=ZTXGtAxNv4kJke2HrPob/wqWmj7NPyUfRm99bykGVgE=; b=TMnSrlIU+e4piJ6k93azZzxLMtQgSG4rlFet+y9khWBd7mOpNSf1lxdIOB2AGLGJxL zLLFhaeFs7cTSxvvan5q7+QJZLBZ+3f25D4y5l3yZhlQ6PTzm4AG6qW7WRi2xzrRWlAU MmdAsfRHJBBFwmEITdUMVU8mlQAmaNqEZic0si1Z4g9sfP4yTmHTeNQ+P8WionMW1Da1 GOqn2J5geov98MFTBuibKEvh/GLphS3OjWFbujyemmWNziaqxhxCK07kM1QlD77vpc7u JjUToLGY6pdwzbSv3OshSmOZpavQMUbuvF65M5VKutKqWRku7l7QiqjwdWN+mamrb/yx qfPQ== 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=ZTXGtAxNv4kJke2HrPob/wqWmj7NPyUfRm99bykGVgE=; b=Z9pyWhJdHHSG+bIFdfyXnwgfiQgAVUSjc1ZTHnptyogc6K1OV4MUl21PcrdyVJmkXs thq5H+gb6smrfFBdi/k6P7GsLvwCVoXokfE09c3UAdbRipVn6uJzs6nKSroAYNWfCk4q 1YTW9jwMnwfqPLfxq/aGezYQ/RjYCAeeIbBqBm6zwEEJR60XekNBGiNXbhi16W+C2u/m otlcWSpVKvAfiESrlFe/+CN1fweuGlFlsNyDK1H4zhR/KNWk01tbiw34GemDsU1mc6q2 wRum+t+9NlxotRdc2ZyxjwCh/gsubDqGnnhzXKhwNprJiKhZpivPQRqJRE5IjGKKsVq/ Iouw== X-Gm-Message-State: AOJu0Yy1AolzY/zhWwWvUSFQ5A7c9Qkh1NzTfkQuIomeqh7mwQj/U1Om K1Kv3awXNGkyxsW0BicnvyBMgsssiQpLq3LIIBqVBd44GuBlYjtqXiKr2KQbGw== X-Gm-Gg: ASbGncvwZHdsHT4UkuxT7cmA2RtFylZMdKXznTm259z/2h7qvqEIRawDwuXlRzLVuzR +QExq6bfuGdS/pt69Un5bjLJXPiXr+RlJftqY7dImr3Mn2jYcvxeY5Onmapv62gbl6qXLvWMM9I PmCV+mwK5Y4g0pJACt5ymSmYk6/6yZ3UdbO7LvrXzfzcLOE/PZUKRSrqvr63vbOMd8FZG5sdhgi lvsKzeyv2FBppOSbhigL4FByVMN3xOzCd1CGT9QKYjYyKAJ/en920sKuC6qUhKF7x+KMMByPlRr Yc0gbThfL6n4Vlqvosf70DsDgJj1yKeg8pRJp+f1lG4kaFUTTdKF4mpDmskG7vIAOHEx/YA+fdg UOfHROGTUHa88uTRrUGsW2Sn14KZ1mCG72T0clWWimoTsC/JrFnrfpmcwL6AGYiHFbrrDlbnT0o lUwr+/+l/6lWmG6yBHdCviRUzRFfmV64u4+3bPTVYDxBPDPYoTzCWzAbeVOyTP2n9/my/q93I= X-Google-Smtp-Source: AGHT+IFSneJCrHpDeqPvvh7O1svJLqC5qPbFBChuYOg83zny2rL0tcal7oqQUDqXmKM170EYqBn2Eg== X-Received: by 2002:a05:600c:4592:b0:46e:53cb:9e7f with SMTP id 5b1f17b1804b1-4792f38615amr40949485e9.18.1764883604478; Thu, 04 Dec 2025 13:26:44 -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.43 (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 3/5] libstdc++: Implement submdspan_mapping for layout_stride. [PR110352] Date: Thu, 4 Dec 2025 22:28:44 +0100 Message-ID: <20251204212846.248887-4-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 Add submdspan_mapping for layout_stride as in P3663. PR libstdc++/110352 libstdc++-v3/ChangeLog: * include/std/mdspan (layout_stride::mapping::submdspan_mapping): New friend function. * testsuite/23_containers/mdspan/submdspan/submdspan.cc: Instantiate tests for layout_stride. * testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc: Ditto. * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: Add tests for layout_stride. Signed-off-by: Luc Grosheintz --- libstdc++-v3/include/std/mdspan | 25 +++++++++++++++++++ .../mdspan/submdspan/submdspan.cc | 1 + .../mdspan/submdspan/submdspan_mapping.cc | 18 +++++++++++++ .../mdspan/submdspan/submdspan_neg.cc | 9 +++++++ 4 files changed, 53 insertions(+) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index d8da7b41868..8b6c24885ae 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -1905,40 +1905,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type stride(rank_type __r) const noexcept { return _M_strides[__r]; } template<__mdspan::__mapping_alike _OMapping> requires ((extents_type::rank() == _OMapping::extents_type::rank()) && _OMapping::is_always_strided()) friend constexpr bool operator==(const mapping& __self, const _OMapping& __other) noexcept { if (__self.extents() != __other.extents()) return false; if constexpr (extents_type::rank() > 0) for (size_t __i = 0; __i < extents_type::rank(); ++__i) if (!cmp_equal(__self.stride(__i), __other.stride(__i))) return false; return __mdspan::__offset(__other) == 0; } private: +#if __glibcxx_submdspan + constexpr auto + _M_submdspan_mapping_impl() const + { return submdspan_mapping_result{*this, 0}; } + + template + requires (sizeof...(_Slices) > 0) + constexpr auto + _M_submdspan_mapping_impl(_Slices... __slices) const + { + auto __offset = __mdspan::__suboffset(*this, __slices...); + auto __sub_exts = __mdspan::__subextents(extents(), __slices...); + auto __sub_strides + = __mdspan::__substrides(*this, __slices...); + return submdspan_mapping_result{ + layout_stride::mapping(__sub_exts, __sub_strides), __offset}; + } + + template<__mdspan::__acceptable_slice_type... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mapping._M_submdspan_mapping_impl(__slices...); } +#endif + using _Strides = typename __array_traits::_Type; [[no_unique_address]] extents_type _M_extents; [[no_unique_address]] _Strides _M_strides; }; #ifdef __glibcxx_padded_layouts namespace __mdspan { constexpr size_t __least_multiple(size_t __x, size_t __y) { if (__x <= 1) return __y; return (__y / __x + (__y % __x != 0)) * __x ; } template constexpr bool __is_representable_least_multiple(size_t __x, size_t __y) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc index cd6e9454b17..645c4711294 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc @@ -349,22 +349,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(); + 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 cc832cdb415..cf6167dc3b0 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc @@ -106,37 +106,55 @@ template 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; } +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; +} + 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_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; } 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 5d977822dfe..8ee8af08fc1 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc @@ -8,120 +8,129 @@ template 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" } +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" } +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" } +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" } +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" } +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" } +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" } +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" } +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" } +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