[gcc r17-2392] libstdc++: Fix weight computation for piecewise_linear_distribution(nw, xmin, xmax, fw) constructor

Tomasz Kaminski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <20260714092513.61DB14BA2E22__16838.3778933034$1784021190$gmane$org@sourceware.org>
https://gcc.gnu.org/g:86a93aaef14c1597f531a826f0004c6a86e9fdd4

commit r17-2392-g86a93aaef14c1597f531a826f0004c6a86e9fdd4
Author: Tomasz Kamiński <[email protected]>
Date:   Mon Jun 1 15:31:11 2026 +0200

    libstdc++: Fix weight computation for piecewise_linear_distribution(nw, xmin, xmax, fw) constructor [PR125548]
    
    Compute kth weight using __fw(_M_int[k]) as required by standard,
    instead of __fw(_M_int[k] + __delta), i.e. __fw(_M_int[k + 1]).
    For __nw == 1, this was already corrected by r17-509-g7bed7d9276c11b.
    
    In both cases, previous behavior can be restored by defining
    _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS.
    
            PR libstdc++/125548
    
    libstdc++-v3/ChangeLog:
    
            * doc/html/manual/using_macros.html:
            (_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS): Mention PR125548
            * doc/xml/manual/using.xml: Regenerate
            * include/bits/random.tcc
            (piecewise_linear_distribution::param_type::param_type(size_t, _RealType, ...)):
            Update weight computation.
            * testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc:
            Updated expected values.
            * testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548.cc:
            New test.
            * testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548_fallback.cc:
            Run pr125548.cc with _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 libstdc++-v3/doc/html/manual/using_macros.html     |  3 +-
 libstdc++-v3/doc/xml/manual/using.xml              |  4 ++-
 libstdc++-v3/include/bits/random.tcc               | 15 ++++++++--
 .../piecewise_linear_distribution/cons/pr125548.cc | 33 ++++++++++++++++++++++
 .../cons/pr125548_fallback.cc                      |  5 ++++
 .../operators/serialize2.cc                        |  6 ++--
 6 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/doc/html/manual/using_macros.html b/libstdc++-v3/doc/html/manual/using_macros.html
index 10cf46436796..2e5f4b2e1a11 100644
--- a/libstdc++-v3/doc/html/manual/using_macros.html
+++ b/libstdc++-v3/doc/html/manual/using_macros.html
@@ -164,7 +164,8 @@
 	is restored to their state prior the implementation
 	of <a class="link" href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82749" target="_top">
 	PR82749</a> (<a class="link" href="https://cplusplus.github.io/LWG/lwg-defects.html#1439" target="_top">
-	LWG1439</a>) in GCC 17.
+	LWG1439</a>), and <a class="link" href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125548" target="_top">
+	PR125548</a>) in GCC 17.
       </p></dd><dt><span class="term"><code class="code">_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></span></dt><dd><p>
 	Undefined by default. ABI-changing.
 	When defined, specializations of
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index a34b8ff484a0..027b26b72cf8 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1391,7 +1391,9 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe
 	xlink:href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82749">
 	PR82749</link> (<link xmlns:xlink="http://www.w3.org/1999/xlink"
 	xlink:href="https://cplusplus.github.io/LWG/lwg-defects.html#1439">
-	LWG1439</link>) in GCC 17.
+	LWG1439</link>), and <link xmlns:xlink="http://www.w3.org/1999/xlink"
+	xlink:href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125548">
+	PR125548</link>) in GCC 17.
       </para>
     </listitem></varlistentry>
     <varlistentry><term><code>_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></term>
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 12c891fbbafd..bf402876eb21 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -3355,12 +3355,21 @@ namespace __detail
       {
 	const size_t __n = __nw == 0 ? 1 : __nw;
 	const _RealType __delta = (__xmax - __xmin) / __n;
+	const auto __cfw = [&] (_RealType __v)
+	  {
+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
+	    return __fw(__v + __delta);
+#else
+	    return __fw(__v);
+#endif
+	  };
+
 	if (__n == 1)
 	  {
 	    _RealType __ints[2] = { __xmin, __xmin + __delta };
 	    _RealType __dens[2];
-	    __dens[0] = __fw(__ints[0]);
-	    __dens[1] = __fw(__ints[1]);
+	    __dens[0] = __cfw(__ints[0]);
+	    __dens[1] = __cfw(__ints[1]);
 	    _M_initialize2(__ints, __dens);
 	    return;
 	  }
@@ -3370,7 +3379,7 @@ namespace __detail
 	for (size_t __k = 0; __k <= __nw; ++__k)
 	  {
 	    _M_int.push_back(__xmin + __k * __delta);
-	    _M_den.push_back(__fw(_M_int[__k] + __delta));
+	    _M_den.push_back(__cfw(_M_int[__k]));
 	  }
 
 	_M_configure();
diff --git a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548.cc
new file mode 100644
index 000000000000..2d7ae555eaa7
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548.cc
@@ -0,0 +1,33 @@
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+void 
+test_functor(int n)
+{
+  const double step = 1.0/n;
+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS 
+  double expected = step;
+#else
+  double expected = 0.0;
+#endif
+
+  auto check_val = [&] (double value) mutable {
+    VERIFY( value == expected ); 
+    expected += step;
+    return value;
+  };
+
+  std::piecewise_linear_distribution<> d(n, 0.0, 1.0, check_val);
+}
+
+int
+main()
+{
+  test_functor(1);
+  test_functor(2);
+  test_functor(4);
+  test_functor(8);
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548_fallback.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548_fallback.cc
new file mode 100644
index 000000000000..4b8e66585700
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/pr125548_fallback.cc
@@ -0,0 +1,5 @@
+// { dg-options "-D_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS" }
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+#include "pr125548.cc"
+
diff --git a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc
index e8ab174eb702..21365057f9ef 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc
@@ -77,19 +77,19 @@ test_custom()
   case 24: // ieee32
     expected =
       "3 0.000000000e+00 3.333333433e-01 6.666666865e-01 1.000000000e+00"
-	" 7.272727292e-01 9.090909278e-01 1.090909061e+00 1.272727325e+00";
+	" 6.666666534e-01 8.888888977e-01 1.111111142e+00 1.333333307e+00";
     VERIFY( res == expected );
     break;
   case 53: // ieee64
     expected =
       "3 0.00000000000000000e+00 3.33333333333333315e-01 6.66666666666666630e-01 1.00000000000000000e+00" 
-	" 7.27272727272727182e-01 9.09090909090908950e-01 1.09090909090909083e+00 1.27272727272727249e+00";
+	" 6.66666666666666630e-01 8.88888888888888840e-01 1.11111111111111094e+00 1.33333333333333326e+00";
     VERIFY( res == expected );
     break;
   case 64: // ieee80 
     expected =
       "3 0.000000000000000000000e+00 3.333333333333333333424e-01 6.666666666666666666847e-01 1.000000000000000000000e+00"
-	" 7.272727272727271818908e-01 9.090909090909090606303e-01 1.090909090909090828347e+00 1.272727272727272707087e+00";
+	" 6.666666666666666296592e-01 8.888888888888888395456e-01 1.111111111111111160454e+00 1.333333333333333259318e+00";
     VERIFY( res == expected );
     break;
   default:
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.