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:
