[{"id":3677252,"web_url":"http://patchwork.ozlabs.org/comment/3677252/","msgid":"<ad5YyzOtG2XV6r2j@zen.kayari.org>","list_archive_url":null,"date":"2026-04-14T15:10:03","subject":"Re: [PATCH] libstdc++: Fix philox_engine counter increment carry","submitter":{"id":48004,"url":"http://patchwork.ozlabs.org/api/people/48004/","name":"Jonathan Wakely","email":"jwakely@redhat.com"},"content":"On Tue, 14 Apr 2026 at 15:04 +0000, Tyuleneva, Elena wrote:\n>Hello!\n>\n>The philox counter increment that happens in philox_engine::_M_transition(),\n>applies +1 to _M_x[0] before the bitwise OR with (_M_x[1] << __w), so the carry\n>from _M_x[0] is merged into the _M_x[1] portion rather\n>than being added to it. This causes the counter to cycle prematurely\n>and never advance past {0, 0, 1, 2^w - 1}.\n>\n>Fix by changing operations order, which results in forming the full-width value\n>from _M_x[1]:_M_x[0] and then adding 1 on both the n == 4 and n == 2 paths.\n\nThanks for the patch. I'll take a look at it tomorrow, but for now\nI've CC'd the libstdc++ mailing list which should be included for\nlibstdc++ patches.\n\n\n>libstdc++-v3/ChangeLog:\n>\n>    * include/bits/random.tcc (philox_engine::operator()): Fix counter\n>   increment to propagate carry correctly.\n>    * testsuite/26_numerics/random/philox_engine/operators/counter_carry.cc:\n>    New test.\n>\n>Signed-off-by: ElenaTyuleneva elena.tyuleneva@intel.com<mailto:elena.tyuleneva@intel.com>\n>---\n>libstdc++-v3/include/bits/random.tcc          |  8 +-\n>.../philox_engine/operators/counter_carry.cc  | 83 +++++++++++++++++++\n>2 files changed, 87 insertions(+), 4 deletions(-)\n>create mode 100644 libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/counter_carry.cc\n>\n>diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc\n>index 7a63e868a89..3380b63f355 100644\n>--- a/libstdc++-v3/include/bits/random.tcc\n>+++ b/libstdc++-v3/include/bits/random.tcc\n>@@ -944,8 +944,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>       if constexpr (__n == 4)\n>              {\n>                __type __uh\n>-                 = (static_cast<__type>(_M_x[1]) << __w)\n>-                            | (static_cast<__type>(_M_x[0]) + 1);\n>+                = ((static_cast<__type>(_M_x[1]) << __w)\n>+                           | static_cast<__type>(_M_x[0])) + 1;\n>                __type __lh\n>                  = (static_cast<__type>(_M_x[3]) << __w)\n>                             | static_cast<__type>(_M_x[2]);\n>@@ -964,8 +964,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n>       else\n>              {\n>                __type __num =\n>-                              (static_cast<__type>(_M_x[1]) << __w)\n>-                              | (static_cast<__type>(_M_x[0]) + 1);\n>+                             ((static_cast<__type>(_M_x[1]) << __w)\n>+                             | static_cast<__type>(_M_x[0])) + 1;\n>                _M_x[0] = __num & max();\n>                _M_x[1] = (__num >> __w) & max();\n>              }\n>diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/counter_carry.cc b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/counter_carry.cc\n>new file mode 100644\n>index 00000000000..b1527f6a67b\n>--- /dev/null\n>+++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/counter_carry.cc\n>@@ -0,0 +1,83 @@\n>+// { dg-do run { target c++26 } }\n>+\n>+// N5014 29.5.4.5 Class Template philox_engine\n>+\n>+#include <random>\n>+#include <array>\n>+\n>+#include <testsuite_hooks.h>\n>+\n>+// Helper: set counter, skip one block (n outputs), then compare\n>+// the next block against a reference engine at the expected counter.\n>+template<typename Engine, std::size_t N>\n>+void\n>+verify_carry(const std::array<typename Engine::result_type, N>& current_counter,\n>+                     const std::array<typename Engine::result_type, N>& expected_incremented_counter)\n>+{\n>+  Engine eng_a;\n>+  eng_a.set_counter(current_counter);\n>+  // Skip the block produced from current_counter\n>+  eng_a.discard(N);\n>+\n>+  Engine eng_b;\n>+  eng_b.set_counter(expected_incremented_counter);\n>+\n>+  // Both engines should now produce identical output\n>+  for (std::size_t i = 0; i < N; ++i)\n>+    VERIFY( eng_a() == eng_b() );\n>+}\n>+\n>+\n>+int main()\n>+{\n>+  // philox4x32 (n=4, w=32)\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0, 0, 0, 5},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 0, 0, 6});\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0, 0, 0, 0xFFFFFFFF},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 0, 1, 0});\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0, 0, 1, 0xFFFFFFFF},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 0, 2, 0});\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0, 0, 0xFFFFFFFF, 0xFFFFFFFF},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 1, 0, 0});\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0, 1, 0xFFFFFFFF, 0xFFFFFFFF},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 2, 0, 0});\n>+  verify_carry<std::philox4x32, 4>(std::array<std::philox4x32::result_type, 4>{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},\n>+                                   std::array<std::philox4x32::result_type, 4>{0, 0, 0, 0});\n>+\n>+  // philox4x64 (n=4, w=64)\n>+  constexpr auto philox4x64_max = std::philox4x64::max();\n>+  verify_carry<std::philox4x64, 4>(std::array<std::philox4x64::result_type, 4>{0, 0, 0, philox4x64_max},\n>+                                   std::array<std::philox4x64::result_type, 4>{0, 0, 1, 0});\n>+  verify_carry<std::philox4x64, 4>(std::array<std::philox4x64::result_type, 4>{0, 0, 1, philox4x64_max},\n>+                                   std::array<std::philox4x64::result_type, 4>{0, 0, 2, 0});\n>+  verify_carry<std::philox4x64, 4>(std::array<std::philox4x64::result_type, 4>{0, 0, philox4x64_max, philox4x64_max},\n>+                                   std::array<std::philox4x64::result_type, 4>{0, 1, 0, 0});\n>+  verify_carry<std::philox4x64, 4>(std::array<std::philox4x64::result_type, 4>{0, 1, philox4x64_max, philox4x64_max},\n>+                                   std::array<std::philox4x64::result_type, 4>{0, 2, 0, 0});\n>+  verify_carry<std::philox4x64, 4>(std::array<std::philox4x64::result_type, 4>{philox4x64_max, philox4x64_max, philox4x64_max, philox4x64_max},\n>+                                   std::array<std::philox4x64::result_type, 4>{0, 0, 0, 0});\n>+\n>+  // philox2x32 (n=2, w=32)\n>+  using philox2x32 = std::philox_engine<std::uint_fast32_t,\n>+        32, 2, 10, 0xCD9E8D57, 0x9E3779B9>;\n>+  verify_carry<philox2x32, 2>(std::array<philox2x32::result_type, 2>{0, 5},\n>+                              std::array<philox2x32::result_type, 2>{0, 6});\n>+  verify_carry<philox2x32, 2>(std::array<philox2x32::result_type, 2>{0, 0xFFFFFFFF},\n>+                              std::array<philox2x32::result_type, 2>{1, 0});\n>+  verify_carry<philox2x32, 2>(std::array<philox2x32::result_type, 2>{1, 0xFFFFFFFF},\n>+                              std::array<philox2x32::result_type, 2>{2, 0});\n>+  verify_carry<philox2x32, 2>(std::array<philox2x32::result_type, 2>{0xFFFFFFFF, 0xFFFFFFFF},\n>+                              std::array<philox2x32::result_type, 2>{0, 0});\n>+  // philox2x64 (n=2, w=64)\n>+  using philox2x64 = std::philox_engine<std::uint_fast64_t,\n>+        64, 2, 10, 0xCD9E8D57, 0x9E3779B9>;\n>+  constexpr auto philox2x64_max = philox2x64::max();\n>+  verify_carry<philox2x64, 2>(std::array<philox2x64::result_type, 2>{0, 5},\n>+                              std::array<philox2x64::result_type, 2>{0, 6});\n>+  verify_carry<philox2x64, 2>(std::array<philox2x64::result_type, 2>{0, philox2x64_max},\n>+                              std::array<philox2x64::result_type, 2>{1, 0});\n>+  verify_carry<philox2x64, 2>(std::array<philox2x64::result_type, 2>{1, philox2x64_max},\n>+                              std::array<philox2x64::result_type, 2>{2, 0});\n>+  verify_carry<philox2x64, 2>(std::array<philox2x64::result_type, 2>{philox2x64_max, philox2x64_max},\n>+                              std::array<philox2x64::result_type, 2>{0, 0});\n>+}\n>--\n>2.40.1\n>\n>The changes were tested on x86_64-pc-linux-gnu.\n>\n>Best regards,\n>Elena\n>Intel Deutschland GmbH\n>Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany\n>Tel: +49 89 991 430, www.intel.de\n>Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell\n>Chairperson of the Supervisory Board: Nicole Lau\n>Registered Seat: Munich\n>Commercial Register: Amtsgericht Muenchen HRB 186928","headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=iMIJxDGW;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=iMIJxDGW","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fw78t42cwz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 01:14:05 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 305274BA23D7\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 15:14:03 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 3FAB54BA2E3C\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 15:13:24 +0000 (GMT)","from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-266-e9YTVg-dPzayOX1xTqmd6Q-1; Tue,\n 14 Apr 2026 11:13:19 -0400","from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 0D3E518D6628; Tue, 14 Apr 2026 15:10:05 +0000 (UTC)","from localhost (unknown [10.44.34.88])\n by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 54062180057F; Tue, 14 Apr 2026 15:10:04 +0000 (UTC)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 305274BA23D7","OpenDKIM Filter v2.11.0 sourceware.org 3FAB54BA2E3C"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 3FAB54BA2E3C","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 3FAB54BA2E3C","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776179604; cv=none;\n b=cs3KxGNriuXsgxEMdIQSiVft3LsAaUDGLXby7XhNGRQ2FZhXEOPywIX31TXtq3xcuJTyjK0vV6qlPJQTf4b63AGjOoKacJ4wsKTYSzlNeTK6IAKnboLumeNNBhZvG50VHJV5am18+LwlgnTC5PO0GtCV3t4jkzGaNjV6q9JTMF4=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776179604; c=relaxed/simple;\n bh=4SgczIt2gsmbHGCVL5uZZ/6MF13fLTc3kARha4ng7H0=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=dBeUf1WLfZ7yOC1//c+9EGG0AK1PRDwJmM4xySDQ6+x1MSAIICJzw4o954jUGaP4TLDCV4i4RMZ44axOKDo/pNtHx17cvoUc/cCMbTYkFLH1+Nf6bWk7xHWWGLlH8dVJeALjJpB99I/pqQDHX6g6ChfCXpQ9RV4vjoNLaZdpctk=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776179603;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=1fNAICeOR5UHNKNQjR3ZC/8R4g/qNS2c0+NgF523fZg=;\n b=iMIJxDGW+TE6ynQzd/Jzeg6CBwTr3ftjiIpp0ELMLwgW2laP7+CsOKHrYE/NS7ehSRT58V\n 7/urnVFt8tsdptKNIUEhiZ+VcSGnwuG0ivHu6zTjW+0qZlEavzSbX5IUpbulSoHXDXcGRc\n GnACdgLitucEZyYeBGLTpd+rWzsp6JQ=","X-MC-Unique":"e9YTVg-dPzayOX1xTqmd6Q-1","X-Mimecast-MFC-AGG-ID":"e9YTVg-dPzayOX1xTqmd6Q_1776179598","Date":"Tue, 14 Apr 2026 16:10:03 +0100","From":"Jonathan Wakely <jwakely@redhat.com>","To":"\"Tyuleneva, Elena\" <elena.tyuleneva@intel.com>","Cc":"\"gcc-patches@gcc.gnu.org\" <gcc-patches@gcc.gnu.org>,\n \"Arutyunyan, Ruslan\" <ruslan.arutyunyan@intel.com>,\n \"Dyakov, Pavel\" <pavel.dyakov@intel.com>, libstdc++@gcc.gnu.org","Subject":"Re: [PATCH] libstdc++: Fix philox_engine counter increment carry","Message-ID":"<ad5YyzOtG2XV6r2j@zen.kayari.org>","References":"\n <DM4PR11MB82266EB089C712C94377C906EF252@DM4PR11MB8226.namprd11.prod.outlook.com>","MIME-Version":"1.0","In-Reply-To":"\n <DM4PR11MB82266EB089C712C94377C906EF252@DM4PR11MB8226.namprd11.prod.outlook.com>","X-Clacks-Overhead":"GNU Terry Pratchett","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.93","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"8zYNTQAyHa4A3B6Tl0VGq_X5l47m7y2BwxENzLIMB9c_1776179598","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Disposition":"inline","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"}}]