From patchwork Thu Sep 11 11:39:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 120067 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D3E973858412 for ; Thu, 11 Sep 2025 11:42:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D3E973858412 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=jgNmLF7l X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by sourceware.org (Postfix) with ESMTPS id C7E513858408; Thu, 11 Sep 2025 11:39:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C7E513858408 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 C7E513858408 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::330 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590773; cv=none; b=cm1s7rkU41FxbncwV18d0qh9xdrTk1dZl47SI36Ty3hE3Gq4esiAGh3kJe50yyVNVkG5bIoQpuYGOare+Ps97MqMOvM3zFHj/2BI64xs6egirDUvyrPwrDQgM8Uc7P/FkvsV2iqP14S8EGSreJpN7/JYFyMxUqhw3BnrZhKjoKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590773; c=relaxed/simple; bh=yweHbbXUlavxMVEa1VB2WLc8wCy3PEgRR4cXM7Z7m2c=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=CygP0SOP8IkF1TJMtVftnktK8pqkRVZOo3f3M28SeM5Eq2EftnfTt3DJxP1bRPT/hQxG8mYc6TjkwxamXjockdZvSLg6VUA2qRNvf+bmf8TAobQYnLaNFsevG2MqmpSoXeB9O7PgZSgH/HQT/rXzG/Z4VG4FlOUYB5z8NtcZNx0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C7E513858408 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-45deccb2c1eso4779115e9.1; Thu, 11 Sep 2025 04:39:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757590771; x=1758195571; 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=zz87q7nGI1gCMRXD72I2o7WK+SL7WiSxjcHEXlaOQ1g=; b=jgNmLF7lUpafte8Fi6sNGC+KuE/N8+DPeJqQ1EPW5+0HvJBoBwnkh+wUfHp6KS/U0l wYF4Gm3aOc/cUUzKjId1nDNIwigum4kjGtrzPDjr6nffpX6XFPG2ijUZv2hJtB1rUkm7 X9WBZgg36TRVYVrP0ZkcPnI3GSuGKzNa9c8E0cnIL7YHHFaJ2e7jZ6G0OXeN9fhH3U41 EUUHzcTQ2klvDjVnNaX88YoqhxQaz42zBOstLOivExQZ88xVWZnYdDchoNUlLOR68uQx E9FGdMu6Ra+PQihlyE49Z76GVinWoD5pMZgnXB3Z0ltEdkjz+BHA2HMC1Qb+9BmVzjYo 5Y2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757590771; x=1758195571; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zz87q7nGI1gCMRXD72I2o7WK+SL7WiSxjcHEXlaOQ1g=; b=Yi6mAYwWN6Bdq/b6hDjqErhF+NdK4FhS5USctf5Z4XFU9wEZetlk+JrTSNMbV0MaoA cvvBID9SpMKsga/H/1ctWl+gk5nyiEJL60paYQOe+NvItNaUwiXlC/vh6nJIBRauFAXu YV9ldBb/Ua57GiRKD95s761b0czt+XvxA5yvKexcEMcJHKEUnwOT21kEPWZHn4ZelcS6 K+xfLpKSF8nJCgbvVde+64J6aPwUyWUPshKz4cz3vXB54HRchv6Jv7E16qJQPPAjF45W Z2hrTrQ0dyMXFtzrnnxvMZNEokoMv9oyEhizCQ+yvQOOu3BPl0tRNKkLeXOGWoBaN7Q3 SJdA== X-Gm-Message-State: AOJu0YxmIScfDPFVUc54eDLCcFXpcpU6aIS/FdvL2xQdf9Bb3i2Zm9hn Rr780iz/jzcg3Jj/48L2p83gp1FJwF6i4JM0e8ryW4zysu8vseW9a2paNZhiwg== X-Gm-Gg: ASbGncsBdvEPASdvo7laQNkcri4oEt0IzDr96wC9qpapBVHfo0xlKHSQd+ThmeLbAdX FDDGVne97cpfYSbOqwWH5Id4B4W88gAzrM/Ilcps0zYuZ56czl+ssJ60jnu4cq5bRcx0hBcPrZT zZAbfOZZcQl55jUhIfC4qPCon1rJRcI6a6BJ//iYU3RcKfISEcCR7W+ha3+EPfRCA2+O3h5Ozo5 1AmR0+Y2pV2GAXRESZ0m02SuByLbMqL3wYBbvb6ig8POTC9DvkmIBPPFLuzaxtVdFFOHa/jxAqM f3AinWK8KMsz4auqOiU5YQFzQhjHq3iGtePx/k59MIopb0VXWqekhmpHvXi2OxSj75dfaOWZQm3 8eHWciLtEgdzM0Jc6wuyeLbLZuclnFsx/2j8AnOGuC77jWSn2Fq6siK3/8gXQDT+tSlY7rA== X-Google-Smtp-Source: AGHT+IFwhOUTXGwjNZVCOwXnRxH6GX9kM4G5YBfPDjV4g/AEE37LEWRUqqamrmcM/fhMpnOesJ7yWQ== X-Received: by 2002:a05:600c:4513:b0:45b:9afe:ad48 with SMTP id 5b1f17b1804b1-45dddec3661mr216076015e9.16.1757590771392; Thu, 11 Sep 2025 04:39:31 -0700 (PDT) Received: from rogui.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45e037b922csm21272855e9.15.2025.09.11.04.39.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 04:39:31 -0700 (PDT) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v2 1/5] libstdc++: Refactor layout mapping tests to use a concept. Date: Thu, 11 Sep 2025 13:39:13 +0200 Message-ID: <20250911113917.350920-2-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250911113917.350920-1-luc.grosheintz@gmail.com> References: <20250911113917.350920-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_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 The layout mapping test include a check that applies if is_exhaustive is static. This commit introduces a concept to check if is_exhaustive is a static member function that's compatible with the upcoming layout_left_padded. libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/layouts/mapping.cc (has_static_is_exhaustive): New concept. (test_mapping_properties): Update test. Signed-off-by: Luc Grosheintz --- .../testsuite/23_containers/mdspan/layouts/mapping.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc index 58bce514435..ee902a3cc05 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -7,6 +7,15 @@ constexpr size_t dyn = std::dynamic_extent; +template + concept has_static_is_exhaustive = requires + { + { Mapping::is_exhaustive() } -> std::same_as; + }; + +static_assert(has_static_is_exhaustive>>); +static_assert(!has_static_is_exhaustive>>); + template constexpr bool test_mapping_properties() @@ -32,7 +41,7 @@ template static_assert(M::is_always_unique() && M::is_unique()); static_assert(M::is_always_strided() && M::is_strided()); - if constexpr (!std::is_same_v) + if constexpr (has_static_is_exhaustive) static_assert(M::is_always_exhaustive() && M::is_exhaustive()); return true; } From patchwork Thu Sep 11 11:39:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 120068 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9A841385841B for ; Thu, 11 Sep 2025 11:43:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9A841385841B 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=hGzVMsFP X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by sourceware.org (Postfix) with ESMTPS id 7FEBB385840B; Thu, 11 Sep 2025 11:39:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7FEBB385840B 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 7FEBB385840B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::329 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590773; cv=none; b=NDsAURqRDRfsDafb1IKdywmpvJQVRBPRrjXT2V9fhWJAjfTw1fQU+GCa9rBilDEdK1ODk5wEsAErhs1AuqYkWZ2E2QIlBKGyaXI9TlIgjLWdrJZysKSZHVG/vXxedFy1+ZJ6H4cfCnSzwoydCy4upVzxhvj7b0Y22CALo+QHZS0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590773; c=relaxed/simple; bh=D6T6XAtZaTNd+i+7IZxdwU/1zPk+PaqKPmfFqlvXuqY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=HCb+iSep9OvkO02vZFHVXcBnrdOr8jSRNEFbhDRxAbTm8HBtyaYkE067x7CFacu9Cu/qYPxXsW/Et1yJ5aSTEfRRueozRUHJNh/x4qpMvXWUlxNZF5ynzDPtonqM0fxLfW4VtycMNamcD2n7Cd5Kc5qdOinFRH499Wpb5Qk2/II= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7FEBB385840B Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-45df656889cso4172005e9.1; Thu, 11 Sep 2025 04:39:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757590772; x=1758195572; 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=of7wGOMyKu4UTx/Y3kPc7Pl19yb4jIuaxwTSdUq5nYs=; b=hGzVMsFP32YUAZU7rNku8t7kc8ME7v1ZbP4TOW82FBMEJeMNtY9Y8jhf+pWUyqmmGl sZxvfvb7fJ7KY3ERsCvWe0rAFM8eHpU/D/izBJdtTuUUT6gEYiuXBQyPruvzcmpnPnKT qerhf8UeelEmg42GS+P05z33gQSMwfw/17MMWdLxSNsntBUlyfT/DyQGnPp3ob/MtpRc JAXcTGZGFGyfAdfnQYk45HHBfRa7qZTPJx/uWwhEg6cHF3X+D88NL25XvM/KUzcda399 hKlvtgPMN3NGA3vag45KqAil3zcOp8Qu23lKvrTdzsRLCEv8Dj2Inb+R9x5PoODvRqNl 0eFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757590772; x=1758195572; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=of7wGOMyKu4UTx/Y3kPc7Pl19yb4jIuaxwTSdUq5nYs=; b=A9/Y0uFuDX4dHvUq22W9ORnMJtIEblEwp2kZLkNCIw+Ixe8rzmNbYJmfXgWatXpkU9 KjMKi1jADjzM8SyL/fARfF9thtgNr0aOLpejIV7qNsbLZKNMzCmuCnLQd2jafKC2ud4c ofPtYzpvaVdVqmcl1w/a4+yhd8HRv3MBwOyPeciaZRo46Bp17q92+I1dGpOefHJq+Qsl WPYXZuLPj8fl7OOZbHF/mer05y4O7/7sono5JJTtH3hI8e/S2T3LglHkBy+A1yZXQOWh z00A4kxhC5noO39kCYAgIAjvmW0GMybh5rcVnACsOXUN0fcrRH+7UxqpHbXYeDccxbji W65w== X-Gm-Message-State: AOJu0YyLWiOZVXjpK4mG3yiCdZxLqyzuzMNgB0QAeTcH3OA1e98evkOe ymcjPOUo7jbWAOk0X6Dt7ugwpEYEzffsKTGrklvZVg1g0229iC7T2nRhLEhykw== X-Gm-Gg: ASbGncv1Wk49mFai/+VqxpsRk2MJ2HI/jhxtjF/SVg1ycmrp7IWcEIimygdbj60rbuT iwgjrilOOBAgg2oopZHh6sHd2PINlT7mcoiZ1RL77U63Og0TAQHZizEPNllfPf6QfTBbsjyeDPC Uha9RJS6n0c4GINYAaAZtMH80u78Td1SAGPw4OXtqk5d3Tav5urGc3kj/IFmwbbzxi2yAPayXDe /SBPPSASKHVz45t6sN0OI0ZrCNrMFm0favcojLrCL2bizmn1OFKKc0kPOgs/BiMqY+JWcf2ki29 FSZ05KHhF5SI3gGFKGdH5DxrIvA+oChrkHV3zkTPsEpeXbltK6JE7b0ShMg9NJQCTaXc/h67Ok1 kTWSzIg8RjBaEEA+LU5ARF8eSGWIscWG8gD1BTaLo9O5Rhv5b5PRc+wTTsbEA83c5ZHvGVg== X-Google-Smtp-Source: AGHT+IGMISey0hA3tfcnl5VuQ/9wxITYU2kRLQe/7X8EtMQI37lDaK3y8j/yi8gD4qu6XrlHRb45Ig== X-Received: by 2002:a05:600c:3547:b0:456:18cf:66b5 with SMTP id 5b1f17b1804b1-45dddecd814mr167149265e9.22.1757590771985; Thu, 11 Sep 2025 04:39:31 -0700 (PDT) Received: from rogui.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45e037b922csm21272855e9.15.2025.09.11.04.39.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 04:39:31 -0700 (PDT) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v2 2/5] libstdc++: Fix bug in layout mapping tests. Date: Thu, 11 Sep 2025 13:39:14 +0200 Message-ID: <20250911113917.350920-3-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250911113917.350920-1-luc.grosheintz@gmail.com> References: <20250911113917.350920-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_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/layouts/mapping.cc (test_stride_1d): Fix test. Signed-off-by: Luc Grosheintz --- libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc index ee902a3cc05..1d9b7a27f28 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -315,7 +315,7 @@ template constexpr void test_stride_1d() { - std::layout_left::mapping> m; + typename Layout::mapping> m; VERIFY(m.stride(0) == 1); } From patchwork Thu Sep 11 11:39:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 120070 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CE9B83858433 for ; Thu, 11 Sep 2025 11:53:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CE9B83858433 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=Vban7RVl X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by sourceware.org (Postfix) with ESMTPS id 5B4293858413; Thu, 11 Sep 2025 11:39:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5B4293858413 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 5B4293858413 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::333 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590774; cv=none; b=AsyTHeLNq/ZSV3dRp9FKsYiVtSb0dkkEMWRrU3IHARPZg8B39Ike2z/trTA9DCQ1xwtyS3iiRkqUz0kNHlSefSlM307s4Rn3OiM+9oQVIsWQhzIuDXw2RoRXZ8d5umzt306IPa0aDfydDPCXPKpS71xRGf1ak+W7i2nn9NJG1/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590774; c=relaxed/simple; bh=8ZtGMfXFM8lFBUyvRHbnAfExqQWZmWBRMh0yexF7VP0=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=N1W7KS5BMl8Q025kGFKf2pkpgoSLwZWNJVP5flEDw77IjzuYzJjCr1YMlSqF1+NK8hEYSPkOctN0UE8mW32FfM+EWxYVFw/oYRmGfIicxU+fUKuUMQv5xseSBi1ssMJWQhsaePTnZdXzLYUH/wZbwodvA5+JIX/VXOEjJkyyXUI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5B4293858413 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-45de1084868so2983095e9.2; Thu, 11 Sep 2025 04:39:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757590773; x=1758195573; 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=9srnzPk1hevjJfodLLjhfxpQvwi4u0p8wtCXWmnqUrc=; b=Vban7RVl23AYDJ7hs1FsDvOmJShU30/umN9wrws0pCHFX3sGf0PEXGHl2x0p/HjfV5 YoG5WhJFhYF2LfwijUB/CUkqDuBxMDh6vauQjpgSm5i7zmGf/ksqbwH2hnqbTOeSK4FY CWwNEcgKGP2JZulrxG7RdscUqYKJiVt7BW8O17lBKzyZvb2qTlREUrTe9uvxo3sjlUhm y15V9ao42iQ89Kh5Ekv34tnMYb7y3ilboxki1YzGr/esdczere5bEst9AkvCfJnIAhir n93u8NNIjvnannmB/sBi1So8RJ/+w3Eqo7SPX275d2VTgs4qgnP+2SHtJJjX6Kw6Xw6w Ubcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757590773; x=1758195573; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9srnzPk1hevjJfodLLjhfxpQvwi4u0p8wtCXWmnqUrc=; b=KIK9n7FrEUZfcy6xWtjPgpqO6nOpVoaCZCauI7dSrISgy10hjX56iVpHguQ6bsYxg3 QlygT0wWwTLqKTpEKaQEMY0XwLz3T4Of39LciMjWFjRy8GZNY3QhAu1htcrfuAov3Ld/ UZrbqQVo20vJmAfZRVepCO1jZBocjfO9sepzZAngKRVb8A2FC+ez168a6G2kfr3BmR/x 6L8M2w7yj/tgvnwVbIXDQajBv9TyT/kg6ng87bgJCRGx6DYTFHgi56WxflJWL0+/elS1 u0uBFbT7ZjaN5OLhVIuLQmRtQeJn289lTyf7n1Q25iNy0l/tSURVYfuC/HrzMaL/BPVu gxPQ== X-Gm-Message-State: AOJu0YzDfDgcOFOz5tlYvWjb+8cRWJSa+IKexlY5eKBv2GABEGj/UgeD m3rmG6fi+42/RC4xuiHPR/C6Su56phvOWLxkqxv5PyQa0eTh2q0YmoXnv4YmwQ== X-Gm-Gg: ASbGnctxgcUzPyPF4n4IKSKROmyIarESvrUr6Cdqgf0rt9pr9cWnn9cNRQ1Nngby8Iy 1bkCyCo9QztU53qYzxB5y3/Y9WUE06ZsyXGy3FSAzYONmBdsz0hswp5KWVWqPfcjkCzZObK4A1M MAhL1GzO9+AqPf/NdBHPREgH3ZxRMB5Fw4/OMj5WdzK/4vLSaFSFysL12TPIYVfNEHsOb8Q7Nt0 rWXCvmXZEKjkQGNyzhU1oRsIL7nu2tW5IlMjl725VLCn16O95uTUgRcXrIViqRmDj667xdgRTw/ JbyPSCRq6FCjqaBMhl6qEzzJqzHOwlPHz524QzdNur0P0cgcbtoMBR/VabeAf93kQ832SyudO4W f0EKx1zRnZxI9dQ5pFxfGVenYQmTpjlgZgQGO4fE2J7UN1vd89d++6lHo9nn3LDe3+9In0g== X-Google-Smtp-Source: AGHT+IFahtBk2Qv+/zfM/Kl0/kCCPpC/jQ5QmrH/qwGFSAIB2GaxwMqYZr+XAbvNoNdF7Vb6S1yvGg== X-Received: by 2002:a05:600c:1d07:b0:45b:9c93:d236 with SMTP id 5b1f17b1804b1-45ddded246cmr164387165e9.27.1757590772600; Thu, 11 Sep 2025 04:39:32 -0700 (PDT) Received: from rogui.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45e037b922csm21272855e9.15.2025.09.11.04.39.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 04:39:32 -0700 (PDT) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v2 3/5] libstdc++: Prepare mapping layout tests for left padded. Date: Thu, 11 Sep 2025 13:39:15 +0200 Message-ID: <20250911113917.350920-4-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250911113917.350920-1-luc.grosheintz@gmail.com> References: <20250911113917.350920-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_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 The left padded layout is a template class. In order to be able to use partially specializes templates, functions need to be converted structs. libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/layouts/mapping.cc (test_stride_2d): Rewrite using a struct. (test_stride_3d): Ditto. Signed-off-by: Luc Grosheintz --- .../23_containers/mdspan/layouts/mapping.cc | 119 +++++++++++------- 1 file changed, 75 insertions(+), 44 deletions(-) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc index 1d9b7a27f28..db15e2a48f3 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -330,73 +330,104 @@ template<> } template - constexpr void - test_stride_2d(); +struct TestStride2D; template<> - constexpr void - test_stride_2d() + struct TestStride2D { - std::layout_left::mapping> m; - VERIFY(m.stride(0) == 1); - VERIFY(m.stride(1) == 3); - } + static constexpr void + run() + { + std::layout_left::mapping> m; + VERIFY(m.stride(0) == 1); + VERIFY(m.stride(1) == 3); + } + }; template<> - constexpr void - test_stride_2d() + struct TestStride2D { - std::layout_right::mapping> m; - VERIFY(m.stride(0) == 5); - VERIFY(m.stride(1) == 1); - } + static constexpr void + run() + { + std::layout_right::mapping> m; + VERIFY(m.stride(0) == 5); + VERIFY(m.stride(1) == 1); + } + }; template<> + struct TestStride2D + { + static constexpr void + run() + { + std::array strides{13, 2}; + std::layout_stride::mapping m(std::extents{}, strides); + VERIFY(m.stride(0) == strides[0]); + VERIFY(m.stride(1) == strides[1]); + VERIFY(m.strides() == strides); + } + }; + +template constexpr void - test_stride_2d() + test_stride_2d() { - std::array strides{13, 2}; - std::layout_stride::mapping m(std::extents{}, strides); - VERIFY(m.stride(0) == strides[0]); - VERIFY(m.stride(1) == strides[1]); - VERIFY(m.strides() == strides); + TestStride2D::run(); } template - constexpr void - test_stride_3d(); +struct TestStride3D; template<> - constexpr void - test_stride_3d() + struct TestStride3D { - std::layout_left::mapping m(std::dextents(3, 5, 7)); - VERIFY(m.stride(0) == 1); - VERIFY(m.stride(1) == 3); - VERIFY(m.stride(2) == 3*5); - } + static constexpr void + run() + { + std::layout_left::mapping m(std::dextents(3, 5, 7)); + VERIFY(m.stride(0) == 1); + VERIFY(m.stride(1) == 3); + VERIFY(m.stride(2) == 3*5); + } + }; + template<> - constexpr void - test_stride_3d() + struct TestStride3D { - std::layout_right::mapping m(std::dextents(3, 5, 7)); - VERIFY(m.stride(0) == 5*7); - VERIFY(m.stride(1) == 7); - VERIFY(m.stride(2) == 1); - } + static constexpr void + run() + { + std::layout_right::mapping m(std::dextents(3, 5, 7)); + VERIFY(m.stride(0) == 5*7); + VERIFY(m.stride(1) == 7); + VERIFY(m.stride(2) == 1); + } + }; template<> + struct TestStride3D + { + static constexpr void + run() + { + std::dextents exts(3, 5, 7); + std::array strides{11, 2, 41}; + std::layout_stride::mapping> m(exts, strides); + VERIFY(m.stride(0) == strides[0]); + VERIFY(m.stride(1) == strides[1]); + VERIFY(m.stride(2) == strides[2]); + VERIFY(m.strides() == strides); + } + }; + +template constexpr void - test_stride_3d() + test_stride_3d() { - std::dextents exts(3, 5, 7); - std::array strides{11, 2, 41}; - std::layout_stride::mapping> m(exts, strides); - VERIFY(m.stride(0) == strides[0]); - VERIFY(m.stride(1) == strides[1]); - VERIFY(m.stride(2) == strides[2]); - VERIFY(m.strides() == strides); + TestStride3D::run(); } template From patchwork Thu Sep 11 11:39:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 120069 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C8ADB3858434 for ; Thu, 11 Sep 2025 11:47:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C8ADB3858434 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=ELKBWwUT X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by sourceware.org (Postfix) with ESMTPS id DBBA1385841B; Thu, 11 Sep 2025 11:39:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DBBA1385841B 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 DBBA1385841B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::32c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590775; cv=none; b=GuZzngMPI/XLCktbJrbWWDVbJHq4zasB+JHKkJdVn7UZ6rH/99RDkF/eACdVOEW1oa+hHoOLP5pyHBREl4LY7f/oJBbBh1s9DqmShwPT9XgoHNEmAQeqh+NZLk8bZJlASmeVaQRaT+XVTYGFGCvNpLxVNNVKW1DGDVmiL0NvtY8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590775; c=relaxed/simple; bh=9gqG890vgctvuwFK91GTytBRDy1prz0Uh12xTZuOJxg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=o1Nqx8xGyl/WdrAcKBH2RbfKulEs38mhKEVtTgH0I77UTP/zWZwviCJ7rzk07Nu9TwgP+wXCZ6mID+NrkBec7dIKQHRLGV9Qlfa5rs7/MXL4mobig7A09iyODQkZbqnZy+UZd9koSJd8JsBerxY7vBlcfNCwE1nzC9ERnzl1rCg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DBBA1385841B Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-45deccb2c1eso4779365e9.1; Thu, 11 Sep 2025 04:39:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757590773; x=1758195573; 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=o2TJxhw51o10kyIDQTsU7LH02DwUdDvEZe+veBVIr8I=; b=ELKBWwUT9jUdDzlW8HH/LSKw6jdGynbxImvQ7o1osI9vQosMXxTK6lNWXTM8Rnxedl 0CIWE5wROhpFaSI02CmnKH5r/rqiIiwFSLnj4HA0zbHS6isKoNs9eF9PJQJQ6giXNmJh IDi8fEj2UPXUK2KONUDojq6cRThx2zWNa2dex5IBUyx+z2/H0LvNRqQSCx+u5p2+unS2 MEfobNvLa8YXH8UnSbk2Qg7cJAHIaPpRhycr5C+sJH4/AhJhWLDPXDImbw/51796xN6e GXj7RZtnxIVOr2XxcnrFMMKXsy9x9TpmQt80GtoaHCYF6yLIkydnTMmo9S18v3+TWAd9 FM2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757590773; x=1758195573; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=o2TJxhw51o10kyIDQTsU7LH02DwUdDvEZe+veBVIr8I=; b=UAbsDAmGtSqASWNidoi9f5i/4zlLpcvXWCHWbyLKvxeqo+JvOukZJ6COAQeLACT6Da RnHdLfXHBTbR/a4hff3FxgjNLMq6m9BdFTw4gePHJyOxB7grHaB4TN5uhnJmSmeH99Cv Qv5NoeQKj3bCMuWsVe+3yLPqs1y5kKpI3XUOIKXy79QR+5I4NLGtxQm4s/4zzuH+4AIW yIu0ZvG5qEq3OHioAn/+R3GhEiGfdY2dtBoqpCGy1XYV/oui0E5ywjB9wgJZiYl22Ax2 YMIjdFHRZy9AoUo7u6xE+70sL6mMvvYA3MtYNG0eMMoyr85OYB918fXMxkUcNA2UrCKx yiig== X-Gm-Message-State: AOJu0Ywa5toEVb2fXUkx9iUzYtfdzpGh1A2MSMRG5PPSoiE5U7Aceinf SSZUEndkXaBwX58jlXjDRkh2D8vnikwA6eoOO5QHsAPv3sx03ryzN75B1VgsgA== X-Gm-Gg: ASbGncvEkJjVa3UmTp06ePWPiRvNj2Gp2KChKeBVwcbbdYFsFL+ifE9cdatCcLAw+Rb o5EYLd2I5jo1vyj2jkEAulO0re1kEIH6zPiC1ya73pA909lMm+0sXAZFFRyAwgkwn3OlYy356co 4dWEI7zRnQu+dBcegGCQKeFdX0pOFauYP27YtcQK3ezF6OyGSFc8mswesvs/2g0z7TWMQ33wr/c nWaVcFYUI999GYcX6ZyAoi/lqf9cqFGw+s4f4lQNBdY4L+k6GHBtaf293aObHi0RkNkUal1VGMO aAWWQC+ERC+HZFuKaA1LFJPc3xcM2at57IFmOl2lFrxhuW1eBdZTqG5pr8JrP/fCAhw/UieoHdM G98DP+WY+fhs6Ue5+uEyLjA46WN+K3lePGT/xQWQZCoLLpkqSh4e0f7rIpli2gVSGHtq6XVUFpd QPsd/kVC1ro3+Ldl8= X-Google-Smtp-Source: AGHT+IF4g0O0LktKDIhB9i9xjXG/B7AiLe73Xwy8uHnpqLWM25Di7okSIUWdEswfX12MYIkUZpYnAQ== X-Received: by 2002:a05:600c:6304:b0:45b:43cc:e558 with SMTP id 5b1f17b1804b1-45dddef818cmr160800245e9.35.1757590773391; Thu, 11 Sep 2025 04:39:33 -0700 (PDT) Received: from rogui.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45e037b922csm21272855e9.15.2025.09.11.04.39.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 04:39:32 -0700 (PDT) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v2 4/5] libstdc++: Refactor __mdspan::__static_quotient. Date: Thu, 11 Sep 2025 13:39:16 +0200 Message-ID: <20250911113917.350920-5-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250911113917.350920-1-luc.grosheintz@gmail.com> References: <20250911113917.350920-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_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 For padded layouts we want to check that the product of the padded stride with the remaining extents is representable. Creating a second overload, allows passing in subspans of the static extents and retains the ergonomics for the common case of passing in all static extents. libstdc++-v3/ChangeLog: * include/std/mdspan (__static_quotient): New overload. Signed-off-by: Luc Grosheintz --- libstdc++-v3/include/std/mdspan | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 01d3b2cb6b1..9dd0c85f5b0 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -597,13 +597,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __res; } - template + template consteval _IndexType - __static_quotient(_IndexType __nom = __gnu_cxx::__int_traits<_IndexType> - ::__max) + __static_quotient(std::span __sta_exts, + _IndexType __nom = __gnu_cxx::__int_traits<_IndexType>::__max) { - std::span __sta_exts = __static_extents<_Extents>(); for (auto __factor : __sta_exts) { if (__factor != dynamic_extent) @@ -614,6 +612,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __nom; } + template + requires __is_extents<_Extents> + consteval _IndexType + __static_quotient(_IndexType __nom = __gnu_cxx::__int_traits<_IndexType> + ::__max) + { + std::span __sta_exts = __static_extents<_Extents>(); + return __static_quotient<_IndexType>(__sta_exts, __nom); + } + template constexpr bool __is_representable_extents(const _Extents& __exts) noexcept From patchwork Thu Sep 11 11:39:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Grosheintz X-Patchwork-Id: 120066 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BFA42385841B for ; Thu, 11 Sep 2025 11:42:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BFA42385841B 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=CsZV4gJ4 X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id 04E64385841C; Thu, 11 Sep 2025 11:39:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 04E64385841C 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 04E64385841C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::42c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590776; cv=none; b=sLrtbfy3NKe5Hx8i0T/N+mU2ay6Ru7O1DHzdPTGO8Agx+PsxuIXLWjrPouAXe5y0MUqz4c0gCr96PSX1xND9EHjs3tAUTGenkpaSmGOj2wv4MGA80n3r1cKf1WB+qFVI+oyovUy8O1R8B1NUJCWYOnJ5WR7LjDWjGV/vDXTJEAk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757590776; c=relaxed/simple; bh=DmjzWjF2RbJGlXZT39ixdqHWZKLUpJZ+qLUatW3RcEY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PBdl34MyoNLV9fsUfHkapFHZTKDd7lG52KQ6naFNSWQ6fGvZ7TDKb6fBa2IwQikfu9EZJMmwCtY542QbT7/jfcXzM5N3cNNIJVIlGzBIIDPTuvqV0CQXkV3g/rrQ/puOUA0LvGO919dGmtgiclz1w2XqpMM1EELo64qtADK1RMM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 04E64385841C Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-3b9edf4cf6cso545251f8f.3; Thu, 11 Sep 2025 04:39:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757590775; x=1758195575; 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=py0QhaOiC85kmGPmb1rVTGxyKWXG9kKtVsCt4QfHdE4=; b=CsZV4gJ4wOyjAEAUGFoKjL3U6jS0Jf2/pFgzZuootnlziRuUt+hPCG752fM8NFilAP Erapi+6XVuTe1K3p8hBO2x+c7bXELFr/suEjAA0jLrmyhSo/rtvysSUuSXIUJNf71OK+ pW6F2GBDzGbgH2cU7s8Gdyn+6PvpXGJNtPmJWOaBhb+8DBQp30+p47fUTlkENGTInDk/ kCkoLXc+w5hecGJWlIJltlscWx3duBofdxTD7hhx35EPodyDTP2cJgo+pttPz3V2FVIW OqnkJCp5XxpVPgTAVZMygrxRIUzleNZquajzpiPAz91fNyJWWbas3cQRzpFNEVKIoheQ xRyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757590775; x=1758195575; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=py0QhaOiC85kmGPmb1rVTGxyKWXG9kKtVsCt4QfHdE4=; b=dPrYXnRAwsGsCi7Wf4KFDyqUMaRLBFCBPKRfizIcfhOOj2Vsc/1I8fQ9Ec2L//WKKs jduD3RzlW114ROS4ZVf+OCBLw4YxEITHWLw3bcpIDUX7D7u79frP9fnFa7A+x/RhBbYj 9wIO4+NXlX5aghFUi3dE7uMC3o1A1RjJCP9X2B0blLN1ozpCLGddi03I3Z//LHnNtcUb CLTY8l8YTE5fDuzkGkM0jqcOLKEvLOECqbTVQzXBrI9okfytXi1rBEw0ErD4qE5oQ2r4 4JwGur+qQY19s37vFbpMbWQCqf7TWGwy8LRg+K3+mK4Sa2FHj09XvP5PrqGjqleZnIxT IcMQ== X-Gm-Message-State: AOJu0Yye7bLkib06TjoA2BrfuarPK/Y2++U+WXlORMJUZvL6iAqict2c nunWiEuL3onTZGRyISXhEd9oDxumgGjFG0CBtljUfxVyH4BnDlr0gRkzajbF6A== X-Gm-Gg: ASbGncsujEfyWBygqwA4iK2PuppmC3gqfVv1mLeTKXI0RiFl4mBegMQo8efSGB+Dm8K A+L5HBrxtoox6oV9JJK5Qr+MVfsxPPasAHgj7MnGb3EUXBrNPyTluodS7QGjqZ6+Ab/p8zq1hZM +3r4/bDEWFAUIzB9d54iYxgjat5uNPdsudlQfQtmM6IlxeBkFRO2Hifosdk+2Ex1fXvH/6e+Mkv 0SqAogUO2eau/7WPhmFsrVB5c1U57yf3ROYUbmmPEIrZrC/UpSHKp/Y6zeuEZpOszdGjnCC6pLb Bux1VRUOGYAOGPrq6GvYKY4fw5eWEGZHJEzIiic32ANcmZEW3F7ErjkFqntK9zNAc36YcRIrX3z or+xUYrG7gDE5fp6syrJIsZC6pN/jdxQrpAlCmXhGP7kZUiWZz16mYWYj5PgwfVE/UhynTiFg51 xUFitZ X-Google-Smtp-Source: AGHT+IEdKBJtH38QE1HFi4bhfbuXHuEaaiUHremAyaUgNUMvM/KZlJ8uNowkagbi0wpGAp8FlDoxug== X-Received: by 2002:a05:6000:2007:b0:3cf:74e0:55b9 with SMTP id ffacd0b85a97d-3e643eff35emr15346732f8f.63.1757590774176; Thu, 11 Sep 2025 04:39:34 -0700 (PDT) Received: from rogui.localdomain (212-51-146-223.fiber7.init7.net. [212.51.146.223]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-45e037b922csm21272855e9.15.2025.09.11.04.39.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 04:39:33 -0700 (PDT) From: Luc Grosheintz To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org, Luc Grosheintz Subject: [PATCH v2 5/5] libstdc++: Implement std::layout_left_padded. Date: Thu, 11 Sep 2025 13:39:17 +0200 Message-ID: <20250911113917.350920-6-luc.grosheintz@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250911113917.350920-1-luc.grosheintz@gmail.com> References: <20250911113917.350920-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_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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 This commit adds a new layout layout_left_padded as standardized in N5014 but with one deviation. It includes checking of all mandates and prerequisites. It adds a purely internal feature testing macro padded_layouts and registers layout_left_padded in the std module. The standard mandates that the padding_value is representable as index_type. However, padding_value can be dynamic_extent which is defined as `size_t(-1)`. Hence, it's impossible to use a dynamic padding_value if index_type is int. The deviation is to only require static padding values to be representable as index_type; and thereby allow dynamic padding values for every index_type. libstdc++-v3/ChangeLog: * include/bits/version.def (padded_layouts): Add as internal only. * include/bits/version.h: Regenerate. * include/std/mdspan (__fwd_prod): New overload. (layout_left_padded): Add declaration and implementation. (layout_right_padded): Add declaration only. (__is_left_padded_mapping): New concept. (__is_right_padded_mapping): Ditto. (__standardized_mapping): Recognize left and right padded mappings. (layout_left::mapping::mapping): New overload for left padded mappings. * src/c++23/std.cc.in (layout_left_padded): Add. * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: Add tests for layout_left_padded. * testsuite/23_containers/mdspan/layouts/ctors.cc: Ditto. * testsuite/23_containers/mdspan/layouts/empty.cc: Ditto. * testsuite/23_containers/mdspan/layouts/mapping.cc: Ditto. * testsuite/23_containers/mdspan/layouts/debug/padded_neg.cc: New test. * testsuite/23_containers/mdspan/layouts/padded.cc: Ditto. * testsuite/23_containers/mdspan/layouts/padded_neg.cc: Ditto. Signed-off-by: Luc Grosheintz --- libstdc++-v3/include/bits/version.def | 10 + libstdc++-v3/include/bits/version.h | 9 + libstdc++-v3/include/std/mdspan | 522 ++++++++++++++- libstdc++-v3/src/c++23/std.cc.in | 8 +- .../mdspan/layouts/class_mandate_neg.cc | 1 + .../23_containers/mdspan/layouts/ctors.cc | 61 +- .../mdspan/layouts/debug/padded_neg.cc | 22 + .../23_containers/mdspan/layouts/empty.cc | 12 +- .../23_containers/mdspan/layouts/mapping.cc | 72 ++- .../23_containers/mdspan/layouts/padded.cc | 611 ++++++++++++++++++ .../mdspan/layouts/padded_neg.cc | 280 ++++++++ 11 files changed, 1592 insertions(+), 16 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/padded_neg.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 65b9a278776..63e5f394a8f 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1050,6 +1050,16 @@ ftms = { cxxmin = 26; extra_cond = "__glibcxx_assume_aligned " "&& __glibcxx_is_sufficiently_aligned"; + }; +}; + +// Unofficial macro signaling presence of the two padded layouts. +ftms = { + name = padded_layouts; + no_stdname = true; // Don't change: it's not a standardized FTM. + values = { + v = 1; + cxxmin = 26; }; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index b05249857d2..6b4197e599d 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1178,6 +1178,15 @@ #endif /* !defined(__cpp_lib_aligned_accessor) && defined(__glibcxx_want_aligned_accessor) */ #undef __glibcxx_want_aligned_accessor +#if !defined(__cpp_lib_padded_layouts) +# if (__cplusplus > 202302L) +# define __glibcxx_padded_layouts 1L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_padded_layouts) +# endif +# endif +#endif /* !defined(__cpp_lib_padded_layouts) && defined(__glibcxx_want_padded_layouts) */ +#undef __glibcxx_want_padded_layouts + #if !defined(__cpp_lib_ssize) # if (__cplusplus >= 202002L) # define __glibcxx_ssize 201902L diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 9dd0c85f5b0..251566c7051 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -233,6 +233,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_static_extents() noexcept { return _Extents; } + static constexpr span + _S_static_extents(size_t __begin, size_t __end) noexcept + { return span(_Extents.data() + __begin, __end - __begin); } + constexpr span _M_dynamic_extents(size_t __begin, size_t __end) const noexcept requires (_Extents.size() > 0) @@ -261,6 +265,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __static_extents() noexcept { return _Extents::_Storage::_S_static_extents(); } + template + constexpr span + __static_extents(size_t __begin, size_t __end) noexcept + { return _Extents::_Storage::_S_static_extents(__begin, __end); } + // Pre-compute: \prod_{i = 0}^r _Extents[i], for r = 0,..., n (exclusive) template constexpr auto __fwd_partial_prods = [] consteval @@ -420,6 +429,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend const array& __mdspan::__static_extents(); + friend span + __mdspan::__static_extents(size_t __begin, size_t __end); + friend span __mdspan::__dynamic_extents(const extents&, size_t, size_t); @@ -476,6 +488,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Preconditions: _r < _Extents::rank() + template + constexpr typename _Extents::index_type + __fwd_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept + { + size_t __sta_prod = [__begin, __end] { + span __sta_exts = __static_extents<_Extents>(); + size_t __ret = 1; + for(auto __ext : __sta_exts.subspan(__begin, __end - __begin)) + if (__ext != dynamic_extent) + __ret *= __ext; + return __ret; + }(); + return __extents_prod(__exts, __sta_prod, __begin, __end); + } + template constexpr typename _Extents::index_type __fwd_prod(const _Extents& __exts, size_t __r) noexcept @@ -567,6 +594,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class mapping; }; +#ifdef __glibcxx_padded_layouts + template + struct layout_left_padded + { + template + class mapping; + }; + + template + struct layout_right_padded + { + template + class mapping; + }; +#endif + namespace __mdspan { template @@ -669,10 +712,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_same_v, _Mapping>; + template typename _Layout, typename _Mapping> + concept __is_padded_mapping_of = requires + { + typename _Mapping::extents_type; + { _Mapping::padding_value } -> same_as; + } + && same_as<_Mapping, typename _Layout<_Mapping::padding_value>::mapping< + typename _Mapping::extents_type>>; + +#ifdef __glibcxx_padded_layouts + template + constexpr bool __is_left_padded_mapping = __is_padded_mapping_of< + layout_left_padded, _Mapping>; + + template + constexpr bool __is_right_padded_mapping = __is_padded_mapping_of< + layout_right_padded, _Mapping>; +#endif + + template + consteval size_t + __get_static_stride() + { return _PaddedMapping::_S_static_stride; } + template concept __standardized_mapping = __mapping_of || __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 @@ -726,6 +798,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : mapping(__other.extents(), __mdspan::__internal_ctor{}) { __glibcxx_assert(*this == __other); } +#if __glibcxx_padded_layouts + template + requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping> + && is_constructible_v + constexpr + explicit(!is_convertible_v) + mapping(const _LeftPaddedMapping& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { + constexpr size_t __ostride_sta = __mdspan::__get_static_stride< + _LeftPaddedMapping>(); + + if constexpr (extents_type::rank() > 1 + && extents_type::static_extent(0) != dynamic_extent + && __ostride_sta != dynamic_extent) + static_assert(extents_type::static_extent(0) == __ostride_sta); + + __glibcxx_assert(extents_type::rank() <= 1 + || __other.stride(1) == __other.extents().extent(0)); + } +#endif + constexpr mapping& operator=(const mapping&) noexcept = default; @@ -1173,6 +1269,430 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[no_unique_address]] _Strides _M_strides; }; +#ifdef __glibcxx_padded_layouts + namespace __mdspan + { + constexpr size_t + __least_multiple_at_least(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) + { + constexpr auto __y_max = numeric_limits<_IndexType>::max(); + if(std::cmp_greater(__y, __y_max)) + return false; + + if(__x <= 1) + return true; + + auto __max_delta = __y_max - static_cast<_IndexType>(__y); + auto __delta = (__y % __x == 0) ? size_t(0) : (__x - (__y % __x)); + return std::cmp_less_equal(__delta, __max_delta); + } + + template + concept __valid_static_stride = (_Extents::rank() <= 1) + || (_PaddingValue == dynamic_extent) + || (_Extents::static_extent(0) == dynamic_extent) + || (__is_representable_least_multiple<_IndexType>( + _PaddingValue, _Extents::static_extent(0))); + + template + constexpr auto __make_left_padded_extent( + extents<_IndexType, _StaticStride1> __stride1, + const extents<_IndexType, _Extent0, _Extents...>& __exts) + { + auto __impl = [&](integer_sequence) + { + return extents<_IndexType, _StaticStride1, _Extents...>{ + __stride1.extent(0), __exts.extent(_Indices + 1)...}; + }; + return __impl(make_index_sequence()); + } + + template + constexpr bool + __is_representable_left_padded_size(const _Stride& __stride1, + const _Extents& __exts) + { + return __is_representable_extents( + __make_left_padded_extent(__stride1, __exts)); + } + + template + concept __valid_leftpad_size = (_Extents::rank() <= 1) + || (_PaddingValue == dynamic_extent) + || (!__all_static(__static_extents<_Extents>())) + || (__contains_zero(__static_extents<_Extents>())) + || (__static_quotient(__static_extents<_Extents>(1, _Extents::rank()), + numeric_limits<_TargetInt>::max() / __least_multiple_at_least( + _PaddingValue, _Extents::static_extent(0))) != 0); + + template + constexpr typename _Extents::index_type + __linear_index_leftpad(const _Extents& __exts, _Stride __stride, + _Indices... __indices) + { + // i0 + stride*(i1 + extents.extent(1)*...) + using _IndexType = typename _Extents::index_type; + _IndexType __res = 0; + if constexpr (sizeof...(__indices) > 0) + { + _IndexType __mult = 1; + + auto __update_rest = [&, __pos = 1u](_IndexType __idx) mutable + { + __res += __idx * __mult; + __mult *= __exts.extent(__pos); + ++__pos; + }; + + auto __update = [&](_IndexType __idx, auto... __rest) + { + __res += __idx; + __mult = __stride.extent(0); + (__update_rest(__rest), ...); + }; + __update(__indices...); + } + return __res; + } + } + + template + template + class layout_left_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_left_padded; + + static_assert(__mdspan::__representable_size, + "The size of extents_type must be representable as index_type"); + + static_assert(__mdspan::__valid_static_stride, + "stride(1) must be representable as index_type"); + + static_assert(__mdspan::__valid_static_stride, + "stride(1) must be representable as size_t"); + + static_assert(__mdspan::__valid_leftpad_size); + static_assert(__mdspan::__valid_leftpad_size); + + // DEVIATION the standard requires that _PaddingValue is representable + // as index_type. This seems unlikely, because if index_type < size_t + // then the mandate is violated for `padding_value == dynamic_extent`. + // Which means that padding_value == dynamic_extent only reliably work + // if index_type == size_t (e.g. it fails for index_type == int on a + // 64bit system). + static_assert((padding_value == dynamic_extent) + || (cmp_less_equal(padding_value, + numeric_limits::max())), + "padding_value must be representable as index_type"); + + private: + static constexpr size_t _S_rank = _Extents::rank(); + static constexpr size_t _S_static_stride = [] consteval + { + if constexpr (_S_rank <= 1) + return size_t(0); + else if constexpr (padding_value == dynamic_extent + || _Extents::static_extent(0) == dynamic_extent) + return dynamic_extent; + else + return __mdspan::__least_multiple_at_least( + padding_value, _Extents::static_extent(0)); + }(); + + consteval friend size_t + __mdspan::__get_static_stride(); + + public: + constexpr + mapping() noexcept + : mapping(extents_type{}) + { } + + constexpr + mapping(const mapping&) noexcept = default; + + constexpr + mapping(const extents_type& __exts) + : _M_extents(__exts) + { + __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); + if constexpr (_S_rank > 1) + { + if constexpr (padding_value != dynamic_extent) + __glibcxx_assert( + __mdspan::__is_representable_least_multiple( + padding_value, _M_extents.extent(0))); + + index_type __stride; + if constexpr (padding_value == dynamic_extent) + __stride = __exts.extent(0); + else if constexpr (__exts.static_extent(0) != dynamic_extent) + return; + else + { + __stride = static_cast( + __mdspan::__least_multiple_at_least(padding_value, + __exts.extent(0))); + __glibcxx_assert( + __mdspan::__is_representable_left_padded_size( + std::dextents{__stride}, + _M_extents)); + } + _M_stride = _Stride{__stride}; + } + } + + template<__mdspan::__valid_index_type _OIndexType> + constexpr mapping(const extents_type& __exts, _OIndexType __opad) + : _M_extents(__exts) + { + if constexpr (std::is_integral_v<_OIndexType>) + { + __glibcxx_assert(cmp_less_equal(__opad, + numeric_limits::max())); + if constexpr (std::is_signed_v<_OIndexType>) + __glibcxx_assert(__opad >= 0); + } + auto __pad = static_cast(std::move(__opad)); + if constexpr (std::is_signed_v) + __glibcxx_assert(__pad >= 0); + if constexpr (padding_value != dynamic_extent) + __glibcxx_assert(cmp_equal(padding_value, __pad)); + if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent) + { + __glibcxx_assert( + __mdspan::__is_representable_least_multiple( + __pad, _M_extents.extent(0))); + + _M_stride = _Stride{static_cast( + __mdspan::__least_multiple_at_least( + __pad, _M_extents.extent(0)))}; + + __glibcxx_assert( + __mdspan::__is_representable_left_padded_size( + _M_stride, _M_extents)); + } + } + + template + requires is_constructible_v + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const layout_left::mapping<_OExtents>& __other) + : mapping(extents_type(__other.extents())) + { + if constexpr (_OExtents::rank() > 1) + static_assert(_S_static_stride == dynamic_extent + || _OExtents::static_extent(0) == dynamic_extent + || _S_static_stride == _OExtents::static_extent(0), + "(*this).stride(1) must be compatible with other.stride(1)"); + + __glibcxx_assert((!(_S_rank > 1 && padding_value != dynamic_extent)) + || (std::cmp_equal(_M_stride.extent(0), + __other.extents().extent(0)))); + } + + template + requires is_constructible_v<_OExtents, extents_type> + constexpr explicit(_OExtents::rank() > 0) + mapping(const typename layout_stride::mapping<_OExtents>& __other) + : _M_extents(__other.extents()) + { + if constexpr (_S_rank > 1 && padding_value != dynamic_extent) + __glibcxx_assert(cmp_equal(__other.stride(1), + __mdspan::__least_multiple_at_least(padding_value, + __other.extents().extent(0)))); + + if constexpr (_S_rank > 0) + __glibcxx_assert(__other.stride(0) == 1); + + __glibcxx_assert(cmp_less_equal(__other.required_span_size(), + numeric_limits::max())); + + if constexpr (_S_rank > 1 && _S_static_stride == dynamic_extent) + _M_stride = _Stride{__other.stride(1)}; + + if constexpr (_S_rank > 2) + { + _GLIBCXX_DEBUG_ASSERT([&]() + { + for (size_t __i = 2; __i < _S_rank; ++__i) + if (stride(__i) != __other.stride(__i)) + return false; + return true; + }()); + } + } + + template + requires __mdspan::__is_left_padded_mapping<_LeftPaddedMapping> + && is_constructible_v + constexpr explicit(_S_rank > 1 && (padding_value != dynamic_extent + || _LeftPaddedMapping::padding_value == dynamic_extent)) + mapping(const _LeftPaddedMapping& __other) + : _M_extents(__other.extents()) + { + if constexpr (_S_rank > 1) + { + static_assert(padding_value == dynamic_extent + || _LeftPaddedMapping::padding_value == dynamic_extent + || padding_value == _LeftPaddedMapping::padding_value, + "If neither padding_value is dynamic_extent, then they must " + "be equal"); + + __glibcxx_assert((padding_value == dynamic_extent + || cmp_equal(__other.stride(1), + __mdspan::__least_multiple_at_least(padding_value, + __other.extents().extent(0)))) + && "other.stride(1) must be the next larger multiple of " + "padding_value that is greater or equal to other.extent(0)"); + } + __glibcxx_assert(cmp_less_equal(__other.required_span_size(), + numeric_limits::max())); + + if constexpr (_S_rank > 1 && (_S_static_stride == dynamic_extent)) + _M_stride = _Stride{__other.stride(1)}; + } + + template + requires (__mdspan::__is_right_padded_mapping<_RightPaddedMapping> + || __mdspan::__mapping_of) + && (_S_rank <= 1) + && is_constructible_v + constexpr explicit(!is_convertible_v< + typename _RightPaddedMapping::extents_type, extents_type>) + mapping(const _RightPaddedMapping& __other) noexcept + : _M_extents(__other.extents()) + { + __glibcxx_assert(cmp_less_equal(__other.required_span_size(), + numeric_limits::max())); + } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const extents_type& + extents() const noexcept { return _M_extents; } + + constexpr array + strides() const noexcept + { + array __ret; + if constexpr (_S_rank > 0) + __ret[0] = 1; + if constexpr (_S_rank > 1) + __ret[1] = _M_stride.extent(0); + if constexpr (_S_rank > 2) + for(size_t __i = 2; __i < _S_rank; ++__i) + __ret[__i] = __ret[__i - 1] * _M_extents.extent(__i - 1); + return __ret; + } + + constexpr index_type + required_span_size() const noexcept + { + if constexpr (_S_rank == 0) + return 1; + else if (__mdspan::__empty(_M_extents)) + return 0; + else + return _M_stride.extent(0) * __mdspan::__rev_prod(_M_extents, 0) + - (_M_stride.extent(0) - _M_extents.extent(0)); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4314. Missing move in mdspan layout mapping::operator() + template<__mdspan::__valid_index_type... _Indices> + requires (sizeof...(_Indices) == _S_rank) + constexpr index_type + operator()(_Indices... __indices) const noexcept + { + return __mdspan::__linear_index_leftpad(_M_extents, _M_stride, + static_cast(std::move(__indices))...); + } + + static constexpr bool + is_always_unique() noexcept { return true; } + + static constexpr bool + is_always_exhaustive() noexcept + { + if constexpr (_S_rank <= 1) + return true; + else + return extents_type::static_extent(0) != dynamic_extent + && _S_static_stride != dynamic_extent + && extents_type::static_extent(0) == _S_static_stride; + } + + static constexpr bool + is_always_strided() noexcept { return true; } + + static constexpr bool + is_unique() noexcept { return true; } + + constexpr bool + is_exhaustive() const noexcept + { + if constexpr (is_always_exhaustive()) + return true; + else + return _M_extents.extent(0) == _M_stride.extent(0); + } + + static constexpr bool + is_strided() noexcept { return true; } + + 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_stride.extent(0)) * + static_cast(__mdspan::__fwd_prod(_M_extents, 1, __r))); + } + + template + requires(__mdspan::__is_left_padded_mapping<_LeftPaddedMapping> + && _LeftPaddedMapping::extents_type::rank() == _S_rank) + friend constexpr bool + operator==(const mapping& __self, const _LeftPaddedMapping& __other) + noexcept + { + return __self.extents() == __other.extents() + && (_S_rank < 2 || cmp_equal(__self.stride(1), + __other.stride(1))); + } + + private: + using _Stride = std::extents; + [[no_unique_address]] _Stride _M_stride; + [[no_unique_address]] extents_type _M_extents{}; + }; +#endif + template struct default_accessor { diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index a217a87330b..8b2f4b24c9c 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1869,9 +1869,11 @@ export namespace std using std::aligned_accessor; #endif using std::mdspan; - // FIXME layout_left_padded, layout_right_padded, strided_slice, - // submdspan_mapping_result, full_extent_t, full_extent, submdspan_extents, - // mdsubspan +#if __glibcxx_padded_layouts + using std::layout_left_padded; +#endif + // FIXME layout_right_padded, strided_slice, submdspan_mapping_result, + // full_extent_t, full_extent, submdspan_extents, mdsubspan } #endif diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc index 7091153daba..edf07c983da 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc @@ -46,3 +46,4 @@ auto b6 = B<6, std::layout_stride, std::layout_left>(); // { dg-error "require auto b7 = B<7, std::layout_stride, std::layout_stride>(); // { dg-error "required from" } // { dg-prune-output "must be representable as index_type" } +// { dg-prune-output "static assertion failed" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc index 23c0a55dae1..54f79fcd6ec 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc @@ -6,6 +6,16 @@ constexpr size_t dyn = std::dynamic_extent; +template + constexpr bool + is_layout_leftpad = false; + +#ifdef __glibcxx_padded_layouts +template + constexpr bool + is_layout_leftpad> = true; +#endif + template constexpr void verify(std::extents oexts) @@ -27,7 +37,6 @@ template VERIFY(std::cmp_equal(m.stride(i), other.stride(i))); } - template constexpr void verify_convertible(From from) @@ -40,7 +49,10 @@ template constexpr void verify_nothrow_convertible(From from) { - static_assert(std::is_nothrow_constructible_v); + if constexpr (is_layout_leftpad) + static_assert(std::is_constructible_v); + else + static_assert(std::is_nothrow_constructible_v); verify_convertible(from); } @@ -57,7 +69,10 @@ template constexpr void verify_nothrow_constructible(From from) { - static_assert(std::is_nothrow_constructible_v); + if constexpr (is_layout_leftpad) + static_assert(std::is_constructible_v); + else + static_assert(std::is_nothrow_constructible_v); verify_constructible(from); } @@ -196,6 +211,16 @@ namespace from_extents // ctor: mapping(mapping) namespace from_same_layout { + template + constexpr void + verify_convertible(OExtents exts) + { + using Mapping = typename Layout::mapping; + using OMapping = typename Layout::mapping; + + ::verify_convertible(OMapping(exts)); + } + template constexpr void verify_nothrow_convertible(OExtents exts) @@ -223,8 +248,12 @@ namespace from_same_layout verify_nothrow_convertible>( std::extents{}); - verify_nothrow_constructible>( - std::extents{}); + if constexpr (!is_layout_leftpad) + verify_nothrow_constructible>( + std::extents{}); + else + verify_convertible>( + std::extents{}); assert_not_constructible< typename Layout::mapping>, @@ -234,8 +263,12 @@ namespace from_same_layout typename Layout::mapping>, typename Layout::mapping>>(); - verify_nothrow_constructible>( - std::extents{1}); + if constexpr (!is_layout_leftpad) + verify_nothrow_constructible>( + std::extents{1}); + else + verify_convertible>( + std::extents{1}); verify_nothrow_convertible>( std::extents{}); @@ -247,8 +280,12 @@ namespace from_same_layout verify_nothrow_constructible>( std::extents{1}); - verify_nothrow_convertible>( - std::extents{}); + if constexpr (!is_layout_leftpad) + verify_nothrow_convertible>( + std::extents{}); + else + verify_nothrow_constructible>( + std::extents{}); return true; } @@ -429,6 +466,12 @@ main() { test_all(); test_all(); +#ifdef __glibcxx_padded_layouts + test_all>(); + test_all>(); + test_all>(); + test_all>(); +#endif from_left_or_right::test_all(); from_left_or_right::test_all(); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/padded_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/padded_neg.cc new file mode 100644 index 00000000000..189becfb92f --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/padded_neg.cc @@ -0,0 +1,22 @@ +// { dg-do run { target c++26 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include +#include + +void +test_from_strided_mismatching_strides() +{ + auto exts = std::extents(3, 5, 7); + auto strides = std::array{1, 4, 21 /* != 20 */}; + auto ms = std::layout_stride::mapping(exts, strides); + auto m = std::layout_left_padded<2>::mapping>(ms); + (void) m; +} + +int +main() +{ + test_from_strided_mismatching_strides(); + return 0; +}; diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc index 655b9b6d6c3..123e3c61deb 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc @@ -35,7 +35,8 @@ test_static_overflow() { constexpr Int n1 = std::numeric_limits::max(); constexpr size_t n2 = std::dynamic_extent - 1; - constexpr size_t n = std::cmp_less(n1, n2) ? size_t(n1) : n2; + // Allow some room for padding. + constexpr size_t n = (std::cmp_less(n1, n2) ? size_t(n1) : n2) - 4; verify_all(typename Layout::mapping>{}); verify_all(typename Layout::mapping>{}); @@ -73,7 +74,8 @@ test_dynamic_overflow() { constexpr Int n1 = std::numeric_limits::max(); constexpr size_t n2 = std::dynamic_extent - 1; - constexpr Int n = std::cmp_less(n1, n2) ? n1 : Int(n2); + // Allow some room for padding. + constexpr Int n = (std::cmp_less(n1, n2) ? n1 : Int(n2)) - 4; verify_all(make_mapping( std::extents{n, n, n, n})); @@ -127,5 +129,11 @@ main() static_assert(test_all()); static_assert(test_all()); static_assert(test_all()); +#ifdef __glibcxx_padded_layouts + static_assert(test_all>()); + static_assert(test_all>()); + static_assert(test_all>()); + static_assert(test_all>()); +#endif return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc index db15e2a48f3..91d66ea87b8 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -370,6 +370,30 @@ template<> } }; +#if __glibcxx_padded_layouts +template + struct TestStride2D> + { + static constexpr void + run() + { + using Layout = std::layout_left_padded; + typename Layout::mapping> m; + size_t effective_pad = (PaddingValue == 0 || PaddingValue == dyn) + ? size_t(1) : PaddingValue; + + VERIFY(m.stride(0) == 1); + + // The next multiple of PaddingValue, that's greater or equal + // to exts.extent(0) is the unique value in the range: + // [exts.extent(0), exts.extent(0) + PaddingValue) + // that is divisible by PaddingValue. + VERIFY((m.stride(1) % effective_pad) == 0); + VERIFY(3 <= m.stride(1) && std::cmp_less(m.stride(1), 3 + effective_pad)); + } + }; +#endif + template constexpr void test_stride_2d() @@ -423,6 +447,32 @@ template<> } }; +#if __glibcxx_padded_layouts +template + struct TestStride3D> + { + static constexpr void + run() + { + using Layout = std::layout_left_padded; + typename Layout::mapping> m; + size_t effective_pad = (PaddingValue == 0 || PaddingValue == dyn) + ? size_t(1) : PaddingValue; + + VERIFY(m.stride(0) == 1); + + // The next multiple of PaddingValue, that's greater or equal + // to exts.extent(0) is the unique value in the range: + // [exts.extent(0), exts.extent(0) + PaddingValue) + // that is divisible by PaddingValue. + VERIFY((m.stride(1) % effective_pad) == 0); + VERIFY(3 <= m.stride(1) && std::cmp_less(m.stride(1), 3 + effective_pad)); + + VERIFY(m.stride(1) * 5 == m.stride(2)); + } + }; +#endif + template constexpr void test_stride_3d() @@ -451,7 +501,8 @@ template test_has_stride_0d() { using Mapping = typename Layout::mapping>; - constexpr bool expected = std::is_same_v; + constexpr bool expected = !(std::is_same_v + || std::is_same_v); static_assert(has_stride == expected); } @@ -601,10 +652,29 @@ main() test_all(); test_all(); test_all(); +#ifdef __glibcxx_padded_layouts + test_all>(); + test_all>(); + test_all>(); + test_all>(); + test_all>(); +#endif test_has_op_eq(); test_has_op_eq(); test_has_op_eq(); +#ifdef __glibcxx_padded_layouts + test_has_op_eq, false>(); + test_has_op_eq, false>(); + test_has_op_eq, false>(); + // The next one looks strange, because it's neither. Somehow, the + // conversion rules seem to be playing a critical role again. + // test_has_op_eq, false>(); + + test_has_op_eq, std::layout_left_padded<6>, true>(); + test_has_op_eq, std::layout_left_padded, true>(); +#endif + test_has_op_eq_peculiar(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc new file mode 100644 index 00000000000..a0cd30c39ff --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc @@ -0,0 +1,611 @@ +// { dg-do run { target c++26 } } +#include + +#include +#include "../int_like.h" +#include + +#include + +constexpr size_t dyn = std::dynamic_extent; + +constexpr bool +test_representable_least_multiple() +{ + VERIFY(std::__mdspan::__is_representable_least_multiple(0, 0)); + VERIFY(std::__mdspan::__is_representable_least_multiple(1, 0)); + VERIFY(std::__mdspan::__is_representable_least_multiple(0, 255)); + VERIFY(std::__mdspan::__is_representable_least_multiple(1, 255)); + VERIFY(std::__mdspan::__is_representable_least_multiple(2, 2)); + VERIFY(std::__mdspan::__is_representable_least_multiple(5, 254)); + VERIFY(std::__mdspan::__is_representable_least_multiple(5, 255)); + VERIFY(!std::__mdspan::__is_representable_least_multiple(2, 255)); + VERIFY(!std::__mdspan::__is_representable_least_multiple(128, 129)); + return true; +} + +constexpr bool +test_representable_padded_size() +{ + { + using E = std::extents; + [[maybe_unused]] std::layout_left_padded<1>::mapping m1; + } + + { + using E = std::extents; + [[maybe_unused]] std::layout_left_padded<0>::mapping m1; + [[maybe_unused]] std::layout_left_padded<1>::mapping m2; + [[maybe_unused]] std::layout_left_padded<128>::mapping m3; + [[maybe_unused]] std::layout_left_padded<255>::mapping m4; + } + + { + using E = std::extents; + [[maybe_unused]] std::layout_left_padded::mapping m1(E{}, 128); + [[maybe_unused]] std::layout_left_padded::mapping m2(E{}, 0); + [[maybe_unused]] std::layout_left_padded::mapping m3(E{}, 1); + [[maybe_unused]] std::layout_left_padded::mapping m4(E{}, 128); + } + + { + using E = std::extents; + [[maybe_unused]] std::layout_left_padded<0>::mapping m1; + [[maybe_unused]] std::layout_left_padded<1>::mapping m2; + [[maybe_unused]] std::layout_left_padded<128>::mapping m3; + [[maybe_unused]] std::layout_left_padded<255>::mapping m4; + } + return true; +} + +constexpr bool +test_default_ctor() +{ + { + using E = std::extents; + + std::layout_left_padded<2>::mapping msta; + VERIFY(msta.stride(0) == 1); + VERIFY(msta.stride(1) == 4); + + std::layout_left_padded::mapping mdyn; + VERIFY(mdyn.stride(0) == 1); + VERIFY(mdyn.stride(1) == 3); + } + + { + using E = std::extents; + + std::layout_left_padded<2>::mapping msta; + VERIFY(msta.stride(0) == 1); + VERIFY(msta.stride(1) == 0); + + std::layout_left_padded::mapping mdyn; + VERIFY(mdyn.stride(0) == 1); + VERIFY(mdyn.stride(1) == 0); + } + return true; +} + +constexpr bool +test_from_exts() +{ + auto exts = std::dextents{3, 5}; + + std::layout_left_padded<0>::mapping m0_sta(exts); + VERIFY(m0_sta.stride(1) == exts.extent(0)); + + std::layout_left_padded<1>::mapping m1_sta(exts); + VERIFY(m1_sta.stride(1) == exts.extent(0)); + + std::layout_left_padded<2>::mapping m2_sta(exts); + VERIFY(m2_sta.stride(1) == 4); + + std::layout_left_padded::mapping mdyn(exts); + VERIFY(mdyn.stride(1) == exts.extent(0)); + return true; +} + +template +constexpr bool +test_from_pad() +{ + using Layout = std::layout_left_padded; + auto pad = 3; + auto exts = std::dextents{pad + 1, 5, 7}; + typename Layout::mapping m(exts, CustomPadType{pad}); + VERIFY(std::cmp_equal(m.stride(1), 2*pad)); + VERIFY(m.extents() == exts); + return true; +} + +template +constexpr void +test_from_pad_all() +{ + test_from_pad(); + static_assert(test_from_pad()); + + test_from_pad(); + test_from_pad(); + test_from_pad(); + + using Layout = std::layout_left_padded; + using Extents = std::dims<3>; + using Mapping = Layout::template mapping; + static_assert(!std::is_constructible_v); + static_assert(!std::is_constructible_v); +} + +constexpr bool +is_same_mapping(const auto& lhs, const auto& rhs) +{ + if (lhs.extents().rank() != rhs.extents().rank()) + return false; + + if (lhs.extents() != rhs.extents()) + return false; + + for (size_t i = 0; i < lhs.extents().rank(); ++i) + if (lhs.stride(i) != rhs.stride(i)) + return false; + return true; +} + +enum class ConversionRule +{ + Never, + Always, + Regular +}; + +template +consteval bool +should_convert(auto rule) +{ + if constexpr (rule == ConversionRule::Never) + return false; + if constexpr (rule == ConversionRule::Always) + return true; + else + return std::is_convertible_v; +} + +template + constexpr void + check_convertible(const From& m, auto conversion_rule) + { + VERIFY(is_same_mapping(m, To(m))); + constexpr bool expected = should_convert(conversion_rule); + static_assert(std::is_convertible_v == expected); + } + +template +constexpr void +check_convertible_variants(auto msta, auto conversion_rule) +{ + using LayoutFrom = decltype(msta)::layout_type; + constexpr auto cregular = std::cw; + + // There's a twist when both mappings are left-padded. There's two distinct + // ctors: a defaulted copy ctor and a constrained template that enables + // construction from left-padded mappings even if their layout_type is + // different. The two ctors have different rules regarding conversion. + + if constexpr (!std::same_as) + check_convertible>(msta, conversion_rule); + else + check_convertible>(msta, cregular); + + check_convertible>(msta, conversion_rule); + + auto mdyn = typename LayoutFrom::mapping(msta); + check_convertible>(mdyn, conversion_rule); + if constexpr (!std::same_as) + check_convertible>(mdyn, conversion_rule); + else + check_convertible>(mdyn, cregular); + + static_assert(!std::is_constructible_v< + typename LayoutTo::mapping, typename LayoutFrom::mapping>); +}; + +template + constexpr void + test_from_left_1d() + { + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + constexpr auto cr = std::cw; + + auto msta = std::layout_left::mapping(E1{}); + check_convertible_variants(msta, cr); + } + +template + constexpr void + test_from_left_2d() + { + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + constexpr auto cr = std::cw; + + auto msta = std::layout_left::mapping(E1{}); + check_convertible_variants(msta, cr); + } + +constexpr bool +test_from_left() +{ + auto check = [](PaddedLayout) + { + test_from_left_1d(); + test_from_left_2d(); + }; + + check(std::layout_left_padded<0>{}); + check(std::layout_left_padded<1>{}); + check(std::layout_left_padded<2>{}); + check(std::layout_left_padded<6>{}); + check(std::layout_left_padded{}); + + // rank == 1 is more permissive: + test_from_left_1d>(); + return true; +} + +constexpr bool +test_from_stride() +{ + using E1 = std::extents; + using E2 = std::dims<3>; + using E3 = std::extents; + + auto check = [](PaddedLayout) + { + auto exts = E1{}; + auto strides = std::array{ + 1, exts.extent(0), exts.extent(0) * exts.extent(1)}; + constexpr auto cr = std::cw; + + auto m = std::layout_stride::mapping(exts, strides); + check_convertible_variants(m, cr); + }; + + check(std::layout_left_padded<0>{}); + check(std::layout_left_padded<1>{}); + check(std::layout_left_padded<2>{}); + check(std::layout_left_padded<6>{}); + check(std::layout_left_padded{}); + return true; +} + +constexpr void +test_from_leftpad_0d() +{ + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + + std::layout_left_padded<6>::mapping msta{E1{}}; + + auto check = [](To, auto m) + { + constexpr auto cr = std::cw; + check_convertible_variants(m, cr); + }; + + check(std::layout_left_padded<6>{}, msta); + check(std::layout_left_padded{}, msta); +} + +constexpr void +test_from_leftpad_1d() +{ + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + + std::layout_left_padded<6>::mapping msta{E1{}}; + std::layout_left_padded::mapping mdyn{E1{}}; + + auto check = [](To, auto m) + { + constexpr auto cr = std::cw; + check_convertible_variants(m, cr); + }; + + // Remember, for rank <= 1 the padding_value is irrelevant. + check(std::layout_left_padded<6>{}, msta); + check(std::layout_left_padded<6>{}, mdyn); + check(std::layout_left_padded{}, msta); + check(std::layout_left_padded{}, mdyn); +} + +constexpr void +test_from_leftpad_2d() +{ + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + + std::layout_left_padded<6>::mapping msta{E1{}}; + std::layout_left_padded::mapping mdyn{E1{}}; + + constexpr auto calways = std::cw; + constexpr auto cnever = std::cw; + + auto check = [](To, auto m, auto cr) + { check_convertible_variants(m, cr); }; + + check(std::layout_left_padded<6>{}, msta, cnever); + check(std::layout_left_padded<6>{}, mdyn, cnever); + check(std::layout_left_padded{}, msta, calways); + check(std::layout_left_padded{}, mdyn, cnever); +} + +constexpr bool +test_from_leftpad() +{ + test_from_leftpad_0d(); + test_from_leftpad_1d(); + test_from_leftpad_2d(); + return true; +} + +constexpr bool +test_from_right() +{ + using E1 = std::extents; + using E2 = std::dims<1>; + using E3 = std::extents; + constexpr auto cr = std::cw; + + auto msta = std::layout_right::mapping(E1{}); + + // Remember, the padding_value has no effect for rank <= 1. + check_convertible_variants, E1, E2, E3>(msta, cr); + check_convertible_variants, E1, E2, E3>(msta, cr); + check_convertible_variants, E1, E2, E3>(msta, cr); + check_convertible_variants, E1, E2, E3>(msta, cr); + check_convertible_variants, E1, E2, E3>(msta, cr); + check_convertible_variants, E1, E2, E3>(msta, cr); + return true; +} + +constexpr bool +test_to_left() +{ + using E1 = std::extents; + using E2 = std::extents; + using E3 = std::extents; + + auto exts_sta = E1{}; + + auto check = [](auto msta) + { + constexpr auto cr = std::cw; + check_convertible_variants(msta, cr); + }; + + check(std::layout_left_padded<0>::mapping(exts_sta)); + check(std::layout_left_padded<2>::mapping(exts_sta)); + check(std::layout_left_padded<6>::mapping(exts_sta)); + check(std::layout_left_padded::mapping(exts_sta, 0)); + check(std::layout_left_padded::mapping(exts_sta, 2)); + check(std::layout_left_padded::mapping(exts_sta, 6)); + return true; +} + +constexpr bool +test_never_to_right() +{ + using E1 = std::extents; + using E2 = std::dims<1>; + + auto mr_sta = std::layout_right::mapping(E1{}); + auto mlp_sta = std::layout_left_padded<2>::mapping{mr_sta}; + static_assert(!std::is_constructible_v); + + auto mr_dyn = std::layout_right::mapping(E2{E1{}}); + auto mlp_dyn = std::layout_left_padded<2>::mapping{mr_dyn}; + static_assert(!std::is_constructible_v); + return true; +} + +template +constexpr void +test_strides() +{ + auto check = [](auto exts) + { + auto m = typename Layout::mapping(exts); + using IndexType = typename decltype(m)::index_type; + constexpr size_t rank = decltype(m)::extents_type::rank(); + + auto strides = m.strides(); + static_assert(std::same_as>); + VERIFY(strides.size() == rank); + for (size_t i = 0; i < strides.size(); ++i) + VERIFY(strides[i] == m.stride(i)); + }; + + check(std::extents()); + check(std::extents(0)); + check(std::extents(3)); + check(std::extents(3, 5, 7)); + check(std::extents(3, 0, 7)); +} + +constexpr bool +test_strides_all() +{ + test_strides>(); + test_strides>(); + test_strides>(); + test_strides>(); + return true; +} + +constexpr void +test_exhaustive_0d() +{ + auto exts = std::extents{}; + + auto check = [](auto m) + { + static_assert(m.is_always_exhaustive()); + VERIFY(m.is_exhaustive()); + }; + + check(std::layout_left_padded<0>::mapping(exts)); + check(std::layout_left_padded<1>::mapping(exts)); + check(std::layout_left_padded<2>::mapping(exts)); + check(std::layout_left_padded::mapping(exts)); +} + +constexpr void +test_exhaustive_1d() +{ + auto check_dyn_and_sta = [](Layout) + { + auto check = [](auto exts) + { + auto m = typename Layout::mapping(exts); + static_assert(m.is_always_exhaustive()); + VERIFY(m.is_exhaustive()); + }; + + check(std::extents(4)); + check(std::extents{}); + }; + + check_dyn_and_sta(std::layout_left_padded<1>{}); + check_dyn_and_sta(std::layout_left_padded<2>{}); + check_dyn_and_sta(std::layout_left_padded<6>{}); + check_dyn_and_sta(std::layout_left_padded{}); +} + +constexpr void +test_exhaustive_3d() +{ + auto exts_dyn = std::extents(4, 5, 7); + auto exts_sta = std::extents{}; + auto ctrue = std::cw; + auto cfalse= std::cw; + + auto check = [](auto m, auto static_expected, auto runtime_expected) + { + static_assert(m.is_always_exhaustive() == static_expected); + VERIFY(m.is_exhaustive() == runtime_expected); + }; + + check(std::layout_left_padded<0>::mapping(exts_sta), ctrue, true); + check(std::layout_left_padded<0>::mapping(exts_dyn), cfalse, true); + check(std::layout_left_padded<1>::mapping(exts_sta), ctrue, true); + check(std::layout_left_padded<1>::mapping(exts_dyn), cfalse, true); + check(std::layout_left_padded<2>::mapping(exts_sta), ctrue, true); + check(std::layout_left_padded<2>::mapping(exts_dyn), cfalse, true); + check(std::layout_left_padded<6>::mapping(exts_dyn), cfalse, false); + check(std::layout_left_padded<6>::mapping(exts_sta), cfalse, false); + check(std::layout_left_padded::mapping(exts_sta), cfalse, true); + check(std::layout_left_padded::mapping(exts_dyn, 2), cfalse, true); + check(std::layout_left_padded::mapping(exts_dyn, 3), cfalse, false); +} + +constexpr bool +test_exhaustive() +{ + test_exhaustive_0d(); + test_exhaustive_1d(); + test_exhaustive_3d(); + return true; +} + +constexpr bool +test_op_eq() +{ + // The generic cases are handled in layouts/mapping.cc. Here we check special + // cases related to non exhaustive layouts. + using E1 = std::extents; + using E2 = std::dims<3>; + using E3 = std::extents; + + auto m1 = std::layout_left_padded<0>::mapping(E1{}); + auto m2 = std::layout_left_padded<7>::mapping(E1{}); + + VERIFY(m1 == std::layout_left_padded<0>::mapping(E1{})); + VERIFY(m1 == std::layout_left_padded<1>::mapping(E1{})); + VERIFY(m1 == std::layout_left_padded<2>::mapping(E1{})); + VERIFY(m1 == std::layout_left_padded<6>::mapping(E1{})); + VERIFY(m1 != std::layout_left_padded<7>::mapping(E1{})); + VERIFY(m1 == std::layout_left_padded::mapping(E1{})); + VERIFY(m1 != std::layout_left_padded::mapping(E1{}, 7)); + + VERIFY(m1 == std::layout_left_padded<0>::mapping(E2{E1{}})); + VERIFY(m1 == std::layout_left_padded<1>::mapping(E2{E1{}})); + VERIFY(m1 == std::layout_left_padded<2>::mapping(E2{E1{}})); + VERIFY(m1 == std::layout_left_padded<6>::mapping(E2{E1{}})); + VERIFY(m1 != std::layout_left_padded<7>::mapping(E2{E1{}})); + VERIFY(m1 == std::layout_left_padded::mapping(E2{E1{}})); + VERIFY(m1 != std::layout_left_padded::mapping(E2{E1{}}, 7)); + + VERIFY(m2 == std::layout_left_padded<7>::mapping(E1{})); + VERIFY(m2 == std::layout_left_padded::mapping(E1{}, 7)); + VERIFY(m2 == std::layout_left_padded<7>::mapping(E2{E1{}})); + VERIFY(m2 == std::layout_left_padded::mapping(E2{E1{}}, 7)); + + VERIFY(m2 != std::layout_left_padded<7>::mapping(E3{})); + VERIFY(m2 != std::layout_left_padded::mapping(E3{}, 7)); + return true; +} + +int +main() +{ + test_representable_least_multiple(); + static_assert(test_representable_least_multiple()); + + test_representable_padded_size(); + static_assert(test_representable_padded_size()); + + test_default_ctor(); + static_assert(test_default_ctor()); + + test_from_exts(); + static_assert(test_from_exts()); + + test_from_left(); + static_assert(test_from_left()); + + test_from_pad_all(); + test_from_pad_all<3>(); + + test_from_stride(); + static_assert(test_from_stride()); + + test_from_leftpad(); + static_assert(test_from_leftpad()); + + test_from_right(); + static_assert(test_from_right()); + + test_to_left(); + static_assert(test_to_left()); + + test_never_to_right(); + static_assert(test_never_to_right()); + + test_strides_all(); + static_assert(test_strides_all()); + + test_exhaustive(); + static_assert(test_exhaustive()); + + test_op_eq(); + static_assert(test_op_eq()); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc new file mode 100644 index 00000000000..72ef55ea87b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc @@ -0,0 +1,280 @@ +// { dg-do compile { target c++26 } } +#include + +#include + +constexpr size_t dyn = std::dynamic_extent; + +constexpr bool +test_from_extens_representable_sta() +{ + using E1 = std::extents; + auto m = std::layout_left_padded::mapping(E1{}); // { dg-error "from here" } + return true; +} +static_assert(test_from_extens_representable_sta()); + +constexpr bool +test_from_extents_representable_padded_size() +{ + using E1 = std::extents; + using E2 = std::dextents; + + auto m = std::layout_left_padded::mapping(E2{E1{}}); // { dg-error "expansion of" } + return true; +} +static_assert(test_from_extents_representable_padded_size()); + +constexpr bool +test_from_extents_representable_stride() +{ + using E1 = std::extents; + auto m = std::layout_left_padded<128>::mapping(E1{129}); // { dg-error "expansion of" } + return true; +} +static_assert(test_from_extents_representable_stride()); + +constexpr bool +test_from_pad_representable_stride() +{ + using E1 = std::dextents; + auto m = std::layout_left_padded::mapping(E1{129, 2}, 128); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_pad_representable_stride()); + +constexpr bool +test_from_pad_representable_padded_size() +{ + using E1 = std::dextents; + auto m = std::layout_left_padded::mapping(E1{64, 2}, 128); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_pad_representable_padded_size()); + +constexpr bool +test_from_left() +{ + auto exts = std::extents{4}; + auto ml = std::layout_left::mapping(exts); + + using Layout = std::layout_left_padded<4>; + Layout::mapping m(ml); // { dg-error "from here" } + return true; +} +static_assert(test_from_left()); + +constexpr bool +test_from_left_bad_runtime_stride() +{ + auto exts = std::extents{6, 4}; + auto ml = std::layout_left::mapping(exts); + + using Layout = std::layout_left_padded<4>; + Layout::mapping m(ml); // { dg-error "expansion of" } + return true; +} +static_assert(test_from_left_bad_runtime_stride()); + +constexpr bool +test_from_left_representable_extents() +{ + auto exts = std::extents{8, 128}; + auto ml = std::layout_left::mapping(exts); + + using Layout = std::layout_left_padded<8>; + Layout::mapping> m(ml); // { dg-error "expansion of" } + return true; +} +static_assert(test_from_left_representable_extents()); + +template + constexpr bool + test_pad_overflow() + { + auto exts = std::extents{4}; + auto n = size_t(1) << 9; + auto m = typename std::layout_left_padded::mapping(exts, n); + (void) m; + return true; + } +static_assert(test_pad_overflow<1>()); // { dg-error "expansion of" } +static_assert(test_pad_overflow()); // { dg-error "expansion of" } + +template + constexpr bool + test_from_pad_negative() + { + auto exts = std::extents(4); + auto m = typename std::layout_left_padded::mapping(exts, -1); + (void) m; + return true; + } +static_assert(test_from_pad_negative<1>()); // { dg-error "expansion of" } +static_assert(test_from_pad_negative()); // { dg-error "expansion of" } + +template + constexpr bool + test_static_pad_same() + { + using Extents = std::extents; + using Mapping = typename std::layout_left_padded::mapping; + auto exts = Extents{4}; + auto m = Mapping(exts, Pad + 1); // { dg-error "expansion of" } + (void) m; + return true; + } +static_assert(test_static_pad_same<1>()); // { dg-error "expansion of" } +static_assert(test_static_pad_same<3>()); // { dg-error "expansion of" } + +constexpr bool +test_from_stride_wrong_stride0() +{ + using Extents = std::dextents; + auto e = Extents{3, 5}; + auto ms = std::layout_stride::mapping(e, std::array{2, 7}); + auto m = std::layout_left_padded::mapping(ms); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_stride_wrong_stride0()); + +constexpr bool +test_from_stride_wrong_stride1() +{ + using Extents = std::dextents; + auto e = Extents{3, 5}; + auto ms = std::layout_stride::mapping(e, std::array{1, 3}); + auto m = std::layout_left_padded<2>::mapping(ms); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_stride_wrong_stride1()); + +constexpr bool +test_from_stride_wrong_stride2() +{ + using Extents = std::dims<3>; + auto e = Extents{3, 5, 7}; + auto ms = std::layout_stride::mapping(e, std::array{1, 4, 21}); + auto m = std::layout_left_padded::mapping(ms); // here (not implemented) + (void) m; + return true; +} +static_assert(test_from_stride_wrong_stride2()); + +constexpr bool +test_from_stride_oversized() +{ + auto exts = std::extents{2, 6}; + auto ms = std::layout_stride::mapping(exts, std::array{1, 128}); + + using Layout = std::layout_left_padded; + Layout::mapping> m(ms); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_stride_oversized()); + +constexpr bool +test_from_leftpad_dyn() +{ + using Extents = std::dextents; + auto e = Extents{3, 5}; + auto mlp = std::layout_left_padded::mapping(e); + auto m = std::layout_left_padded<2>::mapping(mlp); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_leftpad_dyn()); + +constexpr bool +test_from_leftpad_sta() +{ + using Extents = std::dextents; + auto e = Extents{3, 5}; + auto mlp = std::layout_left_padded<3>::mapping(e); + auto m = std::layout_left_padded<2>::mapping(mlp); // { dg-error "required from" } + (void) m; + return true; +} +static_assert(test_from_leftpad_sta()); + +constexpr bool +test_from_leftpad_oversized() +{ + using E1 = std::extents; + using E2 = std::extents; + auto mlp = std::layout_left_padded::mapping(E1{}); + auto m = std::layout_left_padded::mapping(mlp); // { dg-error "expansion of" } + (void) m; + return true; +} +static_assert(test_from_leftpad_oversized()); + +template + constexpr bool + test_to_left_not_exhaustive() + { + using E1 = std::extents; + using E2 = std::extents; + + [[maybe_unused]] auto msta = std::layout_left_padded<7>::mapping(E1{}); + if constexpr (RunId == 0) + { + auto m = std::layout_left::mapping(msta); // { dg-error "required from" } + (void) m; + } + if constexpr (RunId == 1) + { + auto m = std::layout_left::mapping(msta); // { dg-error "expansion of" } + (void) m; + } + + [[maybe_unused]] auto mdyn = std::layout_left_padded::mapping(E2{E1{}}, 7); + if constexpr (RunId == 2) + { + auto m = std::layout_left::mapping(mdyn); // { dg-error "expansion of" } + (void) m; + } + if constexpr (RunId == 3) + { + auto m = std::layout_left::mapping(mdyn); // { dg-error "expansion of" } + (void) m; + } + return true; + } +static_assert(test_to_left_not_exhaustive<0>()); +static_assert(test_to_left_not_exhaustive<1>()); +static_assert(test_to_left_not_exhaustive<2>()); +static_assert(test_to_left_not_exhaustive<3>()); + +constexpr bool +test_statically_bad_padding_value() +{ + using Extents = std::extents; + std::layout_left_padded<2>::mapping m; // { dg-error "required from here" } + return true; +} +static_assert(test_statically_bad_padding_value()); + +constexpr bool +test_statically_oversized() +{ + using Extents = std::extents; + std::layout_left_padded<128>::mapping m; // { dg-error "required from here" } + return true; +} +static_assert(test_statically_oversized()); + +// { dg-prune-output "padding_value must be representable as index_type" } +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "called in a constant expression" } +// { dg-prune-output "no matching function" } +// { dg-prune-output "static assertion failed" } +// { dg-prune-output "__glibcxx_assert_fail()" } +// { dg-prune-output "must be compatible with other.stride" } +// { dg-prune-output "padding_value is dynamic_extent" } +// { dg-prune-output "_S_rank <= 1" }