[PATCH] libstdc++: Generate result_type bits of precision in piecewise distributions.
Tomasz Kaminski
tkaminsk@redhat.com
Thu Jul 16 10:23:19 GMT 2026
On Thu, Jul 16, 2026 at 12:04 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> On Thu, 09 Jul 2026 at 15:41 +0200, Tomasz Kamiński wrote:
> >The piecewise distributions previously always generated an double value
>
> "a double"
>
> >out of provided generator, regardless of the result_type (template
> >parameter). This patch address above, by generating value of _RealType
> >by default.
> >
> >Furthermore, this patch addresses LWG4052, "Bogus requirements for
> >piecewise_linear_distribution" issue, by converting the inputs
> >(from iterators, or provided weights functor) to RealType, instead
> >of double. See input_type test included in this patch.
> >
> >For consistency the internal computations are now performed in RealType,
> >instead of double. This reduces the precision if the float it used,
>
> "if float is used,"
>
> >however due the ABI compatibility, the double is still used for storage,
>
> "double is still used" (without "the")
>
> >unless _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES is defined (see
> >test_precision_depended in accessors.cc) test.
> >
> >The above change leads to user-observable changes in the behavior or
>
> "the behaviour of"
>
> >distributions, both in produced outputs and number of calls to provided
> >generator performed per each element (see test_engine_calls in
> accessors.cc).
> >The pre-GCC17 behavior of distributions can be restored by defining
> >_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS (this also revers r17-xxxxxx
>
> "reverts"
>
> Should this mention both r17-2392-g86a93aaef14c15 and
> r17-2391-geae197924c7ecf or just one of them?
>
Both of them.
>
> >TODO update when merged). This is achieved by introduction of _CompType
> >that is either defined as double or _RealType.
> >
> >To reduce the code duplication the __generate_one functions are introduced
> >for both distributions. They are used both by the operator() and
> >__generate_impl. The linear __generate_impl is now consistent with
> constant
> >version, and simply assigns the result of generator invocation for default
> >configuration.
> >
> >Finally, this made result of stream operator for float/double param_type
> >of piecewise_linear_distribution consistent for 32bits/64bits. The
> >float specialization for constant distribution still produces different
> >result, however the calculated values are consistent when printed
> >as hexfloat.
> >
> >libstdc++-v3/ChangeLog:
> >
> > * doc/html/manual/using_macros.html: Regenrate.
> > * doc/xml/manual/using.xml
> > (_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS): Mention LWG4052.
> > * include/bits/random.h
> > (piecewise_constant_distribution::_CompType)
> > (piecewise_linear_distribution::_CompType): Define.
> > (piecewise_constant_distribution::__generate_one)
> > (piecewise_linear_distribution::__generate_one): Declare.
> > (piecewise_constant_distribution::_M_initialize2)
> > (piecewise_linear_distribution::__M_initialize2): Adjust
> > densities parameter to _CompType.
> > * include/bits/random.tcc (std::__normalize): Perform
> > computation in the type of factor parameter.
> > (piecewise_constant_distribution::_M_configure)
> > (piecewise_linear_distribution::_M_configure): Use _CompType.
> > (piecewise_constant_distribution::param_type::param_type)
> > (piecewise_constant_distribution::param_type::param_type):
> > Cast the inputs to the _CompType. Use _RealTyp e as input
> > weight functor.
> > (piecewise_constant_distribution::__generate_one)
> > (piecewise_linear_distribution::__generate_one): Extract
> > from operator() and use _CompType.
> > (piecewise_constant_distribution::operator())
> > (piecewise_constant_distribution::__generate_impl).
> > (piecewise_linear_distribution::operator()): Use __generate_one.
> > (piecewise_linear_distribution::__generate_impl): Optimize
> > _M_cp.empty() case and user __generate_one otherwise.
> > *
> testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc:
> > (test_precision_depended): Expand test to cover all constructors,
> > and inputs different from distribution result type.
> > (test_engine_calls): New tests.
> > *
> testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc:
> > Likewise.
> > *
> testsuite/26_numerics/random/piecewise_constant_distribution/operators/serialize2.cc:
> > Update values to accommodate the change in precision for float.
> > Remove trailing whitespaces.
> > *
> testsuite/26_numerics/random/piecewise_linear_distribution/operators/serialize2.cc:
> > Likewise, and enable float/double test for i686.
> > *
> testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type.cc:
> > New test.
> > *
> testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type_fallback_neg.cc:
> > New test.
> > *
> testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type.cc:
> > New test.
> > *
> testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type_fallback_neg.cc:
> > New test.
> >---
> >This depends on my previous two in-flight patches in the area:
> >* https://gcc.gnu.org/pipermail/libstdc++/2026-May/066674.html
> >* https://gcc.gnu.org/pipermail/libstdc++/2026-June/066750.html
> >
> >Tested on x86_64-linux locally. *piecewise* test also passed with
> >all standard modes, -m32, debug and assertions.
> >OK for trunk?
> >
> > .../doc/html/manual/using_macros.html | 5 +-
> > libstdc++-v3/doc/xml/manual/using.xml | 6 +-
> > libstdc++-v3/include/bits/random.h | 24 ++-
> > libstdc++-v3/include/bits/random.tcc | 198 +++++++++++-------
> > .../cons/input_type.cc | 52 +++++
> > .../cons/input_type_fallback_neg.cc | 55 +++++
> > .../operators/accessors.cc | 90 ++++++--
> > .../operators/serialize2.cc | 10 +-
> > .../cons/input_type.cc | 52 +++++
> > .../cons/input_type_fallback_neg.cc | 55 +++++
> > .../operators/accessors.cc | 95 +++++++--
> > .../operators/serialize2.cc | 15 +-
> > 12 files changed, 520 insertions(+), 137 deletions(-)
> > create mode 100644
> libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type.cc
> > create mode 100644
> libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type_fallback_neg.cc
> > create mode 100644
> libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type.cc
> > create mode 100644
> libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type_fallback_neg.cc
> >
> >diff --git a/libstdc++-v3/doc/html/manual/using_macros.html
> b/libstdc++-v3/doc/html/manual/using_macros.html
> >index 2f54bf259fd..29a1e1567d1 100644
> >--- a/libstdc++-v3/doc/html/manual/using_macros.html
> >+++ b/libstdc++-v3/doc/html/manual/using_macros.html
> >@@ -164,8 +164,9 @@
> > their behavior to the 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>), and <a class="link" href="
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125548" target="_top">
> >- PR125548</a>) in GCC-17.
> >+ LWG1439</a>), <a class="link" href="
> https://cplusplus.github.io/LWG/lwg-defects.html#4052" target="_top">
> >+ LWG4052</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 1d4b32de30c..2a3ae1ca52f 100644
> >--- a/libstdc++-v3/doc/xml/manual/using.xml
> >+++ b/libstdc++-v3/doc/xml/manual/using.xml
> >@@ -1391,9 +1391,11 @@ 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>), and <link xmlns:xlink="
> http://www.w3.org/1999/xlink"
> >+ LWG1439</link>), <link xmlns:xlink="http://www.w3.org/1999/xlink"
> >+ xlink:href="https://cplusplus.github.io/LWG/lwg-defects.html#4052
> ">
> >+ LWG4052</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.
> >+ 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.h
> b/libstdc++-v3/include/bits/random.h
> >index 6fefa9e1c44..b5a7630935c 100644
> >--- a/libstdc++-v3/include/bits/random.h
> >+++ b/libstdc++-v3/include/bits/random.h
> >@@ -6470,6 +6470,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> >
> > using _StorageType
> > = __detail::__piecewise_distributions_storage_t<_RealType>;
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ using _CompType = double;
> >+#else
> >+ using _CompType = _RealType;
> >+#endif
> >
> > public:
> > /** The type of the range of the distribution. */
> >@@ -6558,7 +6563,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> > _M_configure();
> >
> > void
> >- _M_initialize2(const _RealType* __ints, _RealType __den);
> >+ _M_initialize2(const _RealType* __ints, _CompType __den);
> >
> > std::vector<_RealType> _M_int;
> > std::vector<_StorageType> _M_den;
> >@@ -6739,6 +6744,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> > std::piecewise_constant_distribution<_RealType1>& __x);
> >
> > private:
> >+ template<typename _AdaptedUniformRandomNumberGenerator>
> >+ result_type
> >+ __generate_one(_AdaptedUniformRandomNumberGenerator& __aurng,
> >+ const param_type& __param);
> >+
> > template<typename _ForwardIterator,
> > typename _UniformRandomNumberGenerator>
> > void
> >@@ -6781,6 +6791,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> >
> > using _StorageType
> > = __detail::__piecewise_distributions_storage_t<_RealType>;
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ using _CompType = double;
>
> Would _CalcType be a better name, making it clear that it's the type
> used for calculations? "comp" could mean comparison or computation.
>
Yes, that much better. I didn't realize that Comp was used.
>
> The existing wording in the standard (and my proposed resolution for
> LWG4052) uses the word "calculated" too, e.g. "the remaining n
> parameters are calculated as: ..."
>
> >+#else
> >+ using _CompType = _RealType;
> >+#endif
> >
> > public:
> > /** The type of the range of the distribution. */
> >@@ -6869,7 +6884,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> > _M_configure();
> >
> > void
> >- _M_initialize2(const _RealType* __ints, const _RealType* __dens);
> >+ _M_initialize2(const _RealType* __ints, const _CompType* __dens);
> >
> > std::vector<_RealType> _M_int;
> > std::vector<_StorageType> _M_den;
> >@@ -7052,6 +7067,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> > std::piecewise_linear_distribution<_RealType1>& __x);
> >
> > private:
> >+ template<typename _AdaptedUniformRandomNumberGenerator>
> >+ result_type
> >+ __generate_one(_AdaptedUniformRandomNumberGenerator& __aurng,
> >+ const param_type& __param);
> >+
> > template<typename _ForwardIterator,
> > typename _UniformRandomNumberGenerator>
> > void
> >diff --git a/libstdc++-v3/include/bits/random.tcc
> b/libstdc++-v3/include/bits/random.tcc
> >index bf402876eb2..070879b89f7 100644
> >--- a/libstdc++-v3/include/bits/random.tcc
> >+++ b/libstdc++-v3/include/bits/random.tcc
> >@@ -78,13 +78,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > }
> >
> > template<typename _InputIterator, typename _OutputIterator,
> >- typename _Tp>
> >+ typename _RealType>
> > _OutputIterator
> > __normalize(_InputIterator __first, _InputIterator __last,
> >- _OutputIterator __result, const _Tp& __factor)
> >+ _OutputIterator __result, const _RealType& __factor)
> > {
> > for (; __first != __last; ++__first, (void) ++__result)
> >- *__result = *__first / __factor;
> >+ *__result = _RealType(_RealType(*__first) / __factor);
> > return __result;
> > }
> >
> >@@ -2947,28 +2947,30 @@ namespace __detail
> > piecewise_constant_distribution<_RealType>::param_type::
> > _M_configure()
> > {
> >- const double __sum = std::accumulate(_M_den.begin(),
> >- _M_den.end(), 0.0);
> >+ const _CompType __sum = std::accumulate(_M_den.begin(),
> _M_den.end(),
> >+ _CompType(0));
> > __glibcxx_assert(__sum > 0);
> >
> > __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(),
> > __sum);
> >
> >+ _CompType __psum(0);
> > _M_cp.reserve(_M_den.size());
> >- std::partial_sum(_M_den.begin(), _M_den.end(),
> >- std::back_inserter(_M_cp));
> >+ for (_CompType __den : _M_den)
> >+ _M_cp.push_back(__psum += __den);
> >
> > // Make sure the last cumulative probability is one.
> >- _M_cp[_M_cp.size() - 1] = 1.0;
> >+ _M_cp[_M_cp.size() - 1] = _CompType(1);
> >
> > for (size_t __k = 0; __k < _M_den.size(); ++__k)
> >- _M_den[__k] /= _M_int[__k + 1] - _M_int[__k];
> >+ _M_den[__k] = _CompType(_CompType(_M_den[__k])
> >+ / (_M_int[__k + 1] - _M_int[__k]));
> > }
> >
> > template<typename _RealType>
> > void
> > piecewise_constant_distribution<_RealType>::param_type::
> >- _M_initialize2(const _RealType* __ints, _RealType __den)
> >+ _M_initialize2(const _RealType* __ints, _CompType __den)
> > {
> > if (__ints[0] == _RealType(0) && __ints[1] == _RealType(1))
> > return;
> >@@ -3041,9 +3043,11 @@ namespace __detail
> > for (; __bbegin != __bend; ++__bbegin)
> > _M_int.push_back(*__bbegin);
> >
> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+ // 4052. Bogus requirements for piecewise_linear_distribution
> > _M_den.reserve(_M_int.size() - 1);
> > for (size_t __k = 0; __k < _M_int.size() - 1; (void)++__k,
> ++__wbegin)
> >- _M_den.push_back(*__wbegin);
> >+ _M_den.push_back(_CompType(*__wbegin));
> >
> > _M_configure();
> > }
> >@@ -3057,10 +3061,21 @@ namespace __detail
> > if (__bl.size() < 2)
> > return;
> >
> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+ // 4052. Bogus requirements for piecewise_linear_distribution
> >+ auto __cfw = [&__fw](_RealType __n, _RealType __p)
> >+ {
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ return __fw(0.5 * (__n + __p));
> >+#else
> >+ return _RealType(__fw(_RealType(0.5 * (__n + __p))));
>
> Should this be _RealType(0.5), to that we don't perform calculations
> using double precision. On a small microcontroller using softfp a user
> generating random float values might not want to use double precision
> internally for any calculations.
>
> So return _RealType(__fw(_RealType(0.5) * (__n + __p)));
>
Yes, that makes sense, I will adjust it.
>
> >+#endif
> >+ };
> >+
> > if (__bl.size() == 2)
> > {
> > const _RealType *__ints = __bl.begin();
> >- _RealType __den = __fw(0.5 * (__ints[1] + __ints[0]));
>
> Hmm, this wasn't even being consistent about using 'double' as the
> type for internal calculations. If the __ints sequence contains
> _RealType values and _RealType is long double, this would have passed
> a long double to __fw.
>
Yes, but this was recently introduced in GCC-17, and I realized that after
that patch. However, it could not be easilly addressed without the CalcType,
so I left it that way, assuming I would fix it with a more holistic fix.
>
> >+ _CompType __den = __cfw(__ints[1], __ints[0]);
> > _M_initialize2(__ints, __den);
> > return;
> > }
> >@@ -3068,7 +3083,7 @@ namespace __detail
> > _M_int = __bl;
> > _M_den.reserve(_M_int.size() - 1);
> > for (size_t __k = 0; __k < _M_int.size() - 1; ++__k)
> >- _M_den.push_back(__fw(0.5 * (_M_int[__k + 1] + _M_int[__k])));
> >+ _M_den.push_back(__cfw(_M_int[__k + 1], _M_int[__k]));
> >
> > _M_configure();
> > }
> >@@ -3081,10 +3096,19 @@ namespace __detail
> > {
> > const size_t __n = __nw == 0 ? 1 : __nw;
> > const _RealType __delta = (__xmax - __xmin) / __n;
> >+ auto __cfw = [&__fw, __delta](_RealType __v)
> >+ {
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ return __fw(__v + 0.5 * __delta);
> >+#else
> >+ return _RealType(__fw(_RealType(__v + 0.5 * __delta)));
>
> This should be _RealType(0.5)
>
Will do that.
>
> >+#endif
> >+ };
> >+
> > if (__n == 1)
> > {
> > _RealType __ints[2] = { __xmin, __xmin + __delta };
> >- _RealType __den = __fw(__xmin + 0.5 * __delta);
> >+ _CompType __den = __cfw(__xmin);
> > _M_initialize2(__ints, __den);
> > return;
> > }
> >@@ -3095,11 +3119,26 @@ namespace __detail
> >
> > _M_den.reserve(__n);
> > for (size_t __k = 0; __k < __nw; ++__k)
> >- _M_den.push_back(__fw(_M_int[__k] + 0.5 * __delta));
> >+ _M_den.push_back(__cfw(_M_int[__k]));
> >
> > _M_configure();
> > }
> >
> >+ template<typename _RealType>
> >+ template<typename _AdaptedUniformRandomNumberGenerator>
> >+ typename piecewise_constant_distribution<_RealType>::result_type
> >+ piecewise_constant_distribution<_RealType>::
> >+ __generate_one(_AdaptedUniformRandomNumberGenerator& __aurng,
> >+ const param_type& __param)
> >+ {
> >+ const _CompType __p = __aurng();
> >+ auto __pos = std::lower_bound(__param._M_cp.begin(),
> >+ __param._M_cp.end(), __p);
> >+ const size_t __i = __pos - __param._M_cp.begin();
> >+ const _CompType __pref = __i > 0 ? __param._M_cp[__i - 1] :
> _CompType(0);
> >+ return __param._M_int[__i] + (__p - __pref) /
> _CompType(__param._M_den[__i]);
> >+ }
> >+
> > template<typename _RealType>
> > template<typename _UniformRandomNumberGenerator>
> > typename piecewise_constant_distribution<_RealType>::result_type
> >@@ -3107,20 +3146,13 @@ namespace __detail
> > operator()(_UniformRandomNumberGenerator& __urng,
> > const param_type& __param)
> > {
> >- __detail::_Adaptor<_UniformRandomNumberGenerator, double>
> >+ __detail::_Adaptor<_UniformRandomNumberGenerator, _CompType>
> > __aurng(__urng);
> >
> >- const double __p = __aurng();
> > if (__param._M_cp.empty())
> >- return __p;
> >-
> >- auto __pos = std::lower_bound(__param._M_cp.begin(),
> >- __param._M_cp.end(), __p);
> >- const size_t __i = __pos - __param._M_cp.begin();
> >+ return __aurng();
> >
> >- const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0;
> >-
> >- return __param._M_int[__i] + (__p - __pref) / __param._M_den[__i];
> >+ return __generate_one(__aurng, __param);
> > }
> >
> > template<typename _RealType>
> >@@ -3133,29 +3165,15 @@ namespace __detail
> > const param_type& __param)
> > {
> >
> __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
> >- __detail::_Adaptor<_UniformRandomNumberGenerator, double>
> >+ __detail::_Adaptor<_UniformRandomNumberGenerator, _CompType>
> > __aurng(__urng);
> >
> > if (__param._M_cp.empty())
> >- {
> >- while (__f != __t)
> >- *__f++ = __aurng();
> >- return;
> >- }
> >-
> >- while (__f != __t)
> >- {
> >- const double __p = __aurng();
> >-
> >- auto __pos = std::lower_bound(__param._M_cp.begin(),
> >- __param._M_cp.end(), __p);
> >- const size_t __i = __pos - __param._M_cp.begin();
> >-
> >- const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0;
> >-
> >- *__f++ = (__param._M_int[__i]
> >- + (__p - __pref) / __param._M_den[__i]);
> >- }
> >+ while (__f != __t)
> >+ *__f++ = __aurng();
> >+ else
> >+ while (__f != __t)
> >+ *__f++ = __generate_one(__urng, __param);
> > }
> >
> > template<typename _RealType, typename _CharT, typename _Traits>
> >@@ -3230,15 +3248,17 @@ namespace __detail
> > piecewise_linear_distribution<_RealType>::param_type::
> > _M_configure()
> > {
> >- double __sum = 0.0;
> >+ _CompType __sum = 0.0;
> > _M_cp.reserve(_M_int.size() - 1);
> > _M_m.reserve(_M_int.size() - 1);
> > for (size_t __k = 0; __k < _M_int.size() - 1; ++__k)
> > {
> > const _RealType __delta = _M_int[__k + 1] - _M_int[__k];
> >- __sum += 0.5 * (_M_den[__k + 1] + _M_den[__k]) * __delta;
> >+ __sum
> >+ += 0.5 * (_CompType(_M_den[__k + 1]) + _CompType(_M_den[__k]))
> * __delta;
>
> _CompType(0.5) (or maybe _CalcType(0.5))
>
> Does it matter that __delta is _RealType and not converted to
> _CompType here?
>
Yes, note that this was already _RealType on trunk, so if _RealType was
long double,
the result of 0.5 * (_M_den[__k + 1] + _M_den[__k]) * __delta was already
long double.
If I would convert it to _CompType then setting
_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
will not produce exactly the same result, as above computation will no
longer promote
to long double.
Yes, so it is very important that type of __delta is not changed to
_CompType.
>
>
> > _M_cp.push_back(__sum);
> >- _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta);
> >+ _M_m.push_back(
> >+ (_CompType(_M_den[__k + 1]) - _CompType(_M_den[__k])) /
> __delta);
>
> Same question about __delta
>
Same answer.
>
> > }
> > __glibcxx_assert(__sum > 0);
> >
> >@@ -3251,13 +3271,13 @@ namespace __detail
> > __detail::__normalize(_M_m.begin(), _M_m.end(), _M_m.begin(),
> __sum);
> >
> > // Make sure the last cumulative probablility is one.
> >- _M_cp[_M_cp.size() - 1] = 1.0;
> >+ _M_cp[_M_cp.size() - 1] = _CompType(1);
> > }
> >
> > template<typename _RealType>
> > void
> > piecewise_linear_distribution<_RealType>::param_type::
> >- _M_initialize2(const _RealType* __ints, const _RealType* __dens)
> >+ _M_initialize2(const _RealType* __ints, const _CompType* __dens)
> > {
> > if (__ints[0] == _RealType(0)
> > && __ints[1] == _RealType(1)
> >@@ -3288,7 +3308,7 @@ namespace __detail
> >
> > if (__bbegin == __bend)
> > {
> >- _RealType __dens[2];
> >+ _CompType __dens[2];
> > __dens[0] = *__wbegin;
> > ++__wbegin;
> > __dens[1] = *__wbegin;
> >@@ -3314,9 +3334,11 @@ namespace __detail
> > for (; __bbegin != __bend; ++__bbegin)
> > _M_int.push_back(*__bbegin);
> >
> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+ // 4052. Bogus requirements for piecewise_linear_distribution
> > _M_den.reserve(_M_int.size());
> > for (size_t __i = 0; __i < _M_int.size(); (void)++__i, ++__wbegin)
> >- _M_den.push_back(*__wbegin);
> >+ _M_den.push_back(_CompType(*__wbegin));
> >
> > _M_configure();
> > }
> >@@ -3333,7 +3355,7 @@ namespace __detail
> > if (__bl.size() == 2)
> > {
> > const _RealType *__ints = __bl.begin();
> >- _RealType __den[2];
> >+ _CompType __den[2];
> > __den[0] = __fw(__ints[0]);
> > __den[1] = __fw(__ints[1]);
> > _M_initialize2(__ints, __den);
> >@@ -3343,7 +3365,7 @@ namespace __detail
> > _M_int = __bl;
> > _M_den.reserve(__bl.size());
> > for (_RealType __b : __bl)
> >- _M_den.push_back(__fw(__b));
> >+ _M_den.push_back(_CompType(__fw(__b)));
> > _M_configure();
> > }
> >
> >@@ -3356,18 +3378,20 @@ 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);
> >+ return __fw(__v + __delta);
> > #else
> >- return __fw(__v);
> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+ // 4052. Bogus requirements for piecewise_linear_distribution
> >+ return _RealType(__fw(__v));
> > #endif
> >- };
> >+ };
> >
> > if (__n == 1)
> > {
> > _RealType __ints[2] = { __xmin, __xmin + __delta };
> >- _RealType __dens[2];
> >+ _CompType __dens[2];
> > __dens[0] = __cfw(__ints[0]);
> > __dens[1] = __cfw(__ints[1]);
> > _M_initialize2(__ints, __dens);
> >@@ -3386,39 +3410,49 @@ namespace __detail
> > }
> >
> > template<typename _RealType>
> >- template<typename _UniformRandomNumberGenerator>
> >+ template<typename _AdaptedUniformRandomNumberGenerator>
> > typename piecewise_linear_distribution<_RealType>::result_type
> > piecewise_linear_distribution<_RealType>::
> >- operator()(_UniformRandomNumberGenerator& __urng,
> >- const param_type& __param)
> >+ __generate_one(_AdaptedUniformRandomNumberGenerator& __aurng,
> >+ const param_type& __param)
> > {
> >- __detail::_Adaptor<_UniformRandomNumberGenerator, double>
> >- __aurng(__urng);
> >-
> >- const double __p = __aurng();
> >- if (__param._M_cp.empty())
> >- return __p;
> >-
> >+ const _CompType __p = __aurng();
> > auto __pos = std::lower_bound(__param._M_cp.begin(),
> > __param._M_cp.end(), __p);
> > const size_t __i = __pos - __param._M_cp.begin();
> >
> >- const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0;
> >+ const _CompType __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0;
> >
> >- const double __a = 0.5 * __param._M_m[__i];
> >- const double __b = __param._M_den[__i];
> >- const double __cm = __p - __pref;
> >+ const _CompType __a = 0.5 * __param._M_m[__i];
>
> _CompType(0.5)
>
> >+ const _CompType __b = __param._M_den[__i];
> >+ const _CompType __cm = __p - __pref;
> >
> > _RealType __x = __param._M_int[__i];
> > if (__a == 0)
> > __x += __cm / __b;
> > else
> > {
> >- const double __d = __b * __b + 4.0 * __a * __cm;
> >+ const _CompType __d = __b * __b + 4.0 * __a * __cm;
> > __x += 0.5 * (std::sqrt(__d) - __b) / __a;
>
> _CompType(0.5)
>
Yes, this change also is sav when the old behavior from being restored,
at the cast does not change the type of literal.
>
> >- }
> >+ }
> >+ return __x;
> >+ }
> >+
> >
> >- return __x;
> >+ template<typename _RealType>
> >+ template<typename _UniformRandomNumberGenerator>
> >+ typename piecewise_linear_distribution<_RealType>::result_type
> >+ piecewise_linear_distribution<_RealType>::
> >+ operator()(_UniformRandomNumberGenerator& __urng,
> >+ const param_type& __param)
> >+ {
> >+ __detail::_Adaptor<_UniformRandomNumberGenerator, _CompType>
> >+ __aurng(__urng);
> >+
> >+ if (__param._M_cp.empty())
> >+ return __aurng();
> >+
> >+ return __generate_one(__aurng, __param);
> > }
> >
> > template<typename _RealType>
> >@@ -3431,9 +3465,15 @@ namespace __detail
> > const param_type& __param)
> > {
> >
> __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
> >- // We could duplicate everything from operator()...
> >- while (__f != __t)
> >- *__f++ = this->operator()(__urng, __param);
> >+ __detail::_Adaptor<_UniformRandomNumberGenerator, _CompType>
> >+ __aurng(__urng);
> >+
> >+ if (__param._M_cp.empty())
> >+ while (__f != __t)
> >+ *__f++ = __aurng();
> >+ else
> >+ while (__f != __t)
> >+ *__f++ = __generate_one(__urng, __param);
> > }
> >
> > template<typename _RealType, typename _CharT, typename _Traits>
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type.cc
> >new file mode 100644
> >index 00000000000..ebd548eb5c4
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type.cc
> >@@ -0,0 +1,52 @@
> >+// { dg-do compile { target c++11 } }
> >+// { dg-require-cstdint "" }
> >+
> >+#include <random>
> >+
> >+template<typename RealType>
> >+struct OnlyConv
> >+{
> >+ long double v;
> >+
> >+ template<typename DestType>
> >+ operator DestType() const
> >+ {
> >+ static_assert(std::is_same<DestType, RealType>::value);
> >+ return v;
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+struct OnlyCall
> >+{
> >+ template<typename SourceType>
> >+ OnlyConv<RealType> operator()(SourceType src)
> >+ {
> >+ static_assert(std::is_same<SourceType, RealType>::value);
> >+ return OnlyConv<RealType>{src};
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+void
> >+test()
> >+{
> >+ std::initializer_list<RealType> invs{0, 1, 2};
> >+ OnlyConv<RealType> weights[2]{1, 2};
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_iter(invs.begin(), invs.end(), weights);
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_init_list(invs, OnlyCall<RealType>());
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_count(2, 0, 2, OnlyCall<RealType>());
> >+}
> >+
> >+int main()
> >+{
> >+ test<float>();
> >+ test<double>();
> >+ test<long double>();
> >+}
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type_fallback_neg.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type_fallback_neg.cc
> >new file mode 100644
> >index 00000000000..6fb04ef7655
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/input_type_fallback_neg.cc
> >@@ -0,0 +1,55 @@
> >+// { dg-options "-D_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS" }
> >+// { dg-do compile { target c++11 } }
> >+// { dg-require-cstdint "" }
> >+
> >+#include <random>
> >+
> >+template<typename RealType>
> >+struct OnlyConv
> >+{
> >+ long double v;
> >+
> >+ template<typename DestType>
> >+ operator DestType() const
> >+ {
> >+ static_assert(std::is_same<DestType, RealType>::value);
> >+ return v;
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+struct OnlyCall
> >+{
> >+ template<typename SourceType>
> >+ OnlyConv<RealType> operator()(SourceType src)
> >+ {
> >+ static_assert(std::is_same<SourceType, RealType>::value);
> >+ return OnlyConv<RealType>{src};
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+void
> >+test()
> >+{
> >+ std::initializer_list<RealType> invs{0, 1, 2};
> >+ OnlyConv<RealType> weights[2]{1, 2};
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_iter(invs.begin(), invs.end(), weights);
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_init_list(invs, OnlyCall<RealType>());
> >+
> >+ std::piecewise_constant_distribution<RealType>
> >+ from_count(2, 0, 2, OnlyCall<RealType>());
> >+}
> >+
> >+int main()
> >+{
> >+ test<float>(); // { dg-error "here" }
> >+ test<double>();
> >+ test<long double>(); // { dg-error "here" }
> >+}
> >+
> >+// { dg-prune-output "static assertion failed" }
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
> >index db4193847e3..15fb6821749 100644
> >---
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
> >@@ -33,39 +33,84 @@ test_exact()
> > VERIFY( density[4] == RealType(0.5 / 8.0) );
> > }
> >
> >-template<typename RealType>
> >+template<typename InputType, typename DistType = InputType>
> > void
> > test_precision_depended()
> > {
> > constexpr bool preserved
> >-#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> >- = true;
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ = sizeof(InputType) <= sizeof(double);
> >+#elifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> >+ = sizeof(InputType) <= sizeof(DistType);
> > #else
> >- = sizeof(RealType) <= sizeof(double);
> >+ // input is converted to DistType and stored in double
> >+ = (sizeof(InputType) <= sizeof(DistType))
> >+ && (sizeof(InputType) <= sizeof(double));
> > #endif
> >
> >- RealType x[3]{0.0, 0.5, 1.0};
> >- constexpr RealType step
> >- = std::numeric_limits<RealType>::epsilon();
> >- RealType wt[2]{RealType(1) - step, RealType(1) + step};
> >+ std::initializer_list<DistType> x{0.0, 0.5, 1.0};
> >+ constexpr InputType step
> >+ = std::numeric_limits<InputType>::epsilon();
> >+ InputType wt[2]{InputType(1) - step, InputType(1) + step};
> >
> >- std::piecewise_constant_distribution<RealType>
> >- u(std::begin(x), std::end(x), wt);
> >+ using Distribution = std::piecewise_constant_distribution<DistType>;
> >+ auto validate = [&wt](const Distribution& dist)
> >+ {
> >+ const std::vector<DistType>& interval = dist.intervals();
> >+ VERIFY( interval.size() == 3 );
> >+ VERIFY( interval[0] == DistType(0.0) );
> >+ VERIFY( interval[2] == DistType(1.0) );
> >
> >- const std::vector<RealType>& interval = u.intervals();
> >- VERIFY( interval.size() == 3 );
> >- VERIFY( interval[0] == RealType(0.0) );
> >- VERIFY( interval[2] == RealType(1.0) );
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ const std::vector<double>& density = dist.densities();
> >+#else
> >+ const std::vector<DistType>& density = dist.densities();
> >+#endif
> >+
> >+ VERIFY( density.size() == 2 );
> >+ VERIFY( density[0] == (preserved ? wt[0] : InputType(1)) );
> >+ VERIFY( density[1] == (preserved ? wt[1] : InputType(1)) );
> >+ };
> >+
> >+ Distribution from_iter(x.begin(), x.end(), wt);
> >+ validate(from_iter);
> >
> >+ auto wf = [&wt](DistType v)
> >+ { return wt[int(v / 0.5)]; };
> >+
> >+ Distribution from_init_list(x, wf);
> >+ validate(from_init_list);
> >+
> >+ Distribution from_count(2, InputType(0), InputType(1), wf);
> >+ validate(from_count);
> >+}
> >+
> >+template<typename RealType, typename URBG = std::mt19937>
> >+void
> >+test_engine_calls()
> >+{
> >+ constexpr std::size_t bits = __builtin_popcountg(URBG::max() -
> URBG::min());
> >+ constexpr std::size_t calls
> > #ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >- const std::vector<double>& density = u.densities();
> >+ = (std::numeric_limits<double>::digits + bits - 1) / bits;
> > #else
> >- const std::vector<RealType>& density = u.densities();
> >+ = (std::numeric_limits<RealType>::digits + bits - 1) / bits;
> > #endif
> >
> >- VERIFY( density.size() == 2 );
> >- VERIFY( density[0] == (preserved ? wt[0] : RealType(1)) );
> >- VERIFY( density[1] == (preserved ? wt[1] : RealType(1)) );
> >+ struct wrapper : URBG
> >+ {
> >+ typename URBG::result_type operator()()
> >+ {
> >+ ++num_calls;
> >+ return URBG::operator()();
> >+ }
> >+ std::size_t num_calls = 0;
> >+ };
> >+
> >+ wrapper eng;
> >+ std::piecewise_constant_distribution<RealType> u;
> >+ u(eng);
> >+ VERIFY(eng.num_calls == calls);
> > }
> >
> > int main()
> >@@ -79,5 +124,12 @@ int main()
> > test_precision_depended<double>();
> > test_precision_depended<long double>();
> >
> >+ test_precision_depended<double, float>();
> >+ test_precision_depended<long double, float>();
> >+ test_precision_depended<long double, double>();
> >+
> >+ test_engine_calls<float>();
> >+ test_engine_calls<double>();
> >+ test_engine_calls<long double>();
> > return 0;
> > }
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/serialize2.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/serialize2.cc
> >index 60838d7396b..dae9f4aaf34 100644
> >---
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/serialize2.cc
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/serialize2.cc
> >@@ -38,7 +38,7 @@ test_default()
> > "1 0.00000000000000000e+00 1.00000000000000000e+00
> 1.00000000000000000e+00";
> > VERIFY( res == expected );
> > break;
> >- case 64: // ieee80
> >+ case 64: // ieee80
> > expected =
> > "1 0.000000000000000000000e+00 1.000000000000000000000e+00
> 1.000000000000000000000e+00";
> > VERIFY( res == expected );
> >@@ -74,19 +74,19 @@ test_custom()
> > case 24: // ieee32
> > expected =
> > "3 0.000000000e+00 3.333333433e-01 6.666666865e-01 1.000000000e+00"
> >- " 7.777777281e-01 9.999999702e-01 1.222222322e+00";
> >+ " 7.777777314e-01 1.000000000e+00 1.222222328e+00";
> > VERIFY( res == expected );
> > break;
> > case 53: // ieee64
> > expected =
> > "3 0.00000000000000000e+00 3.33333333333333315e-01
> 6.66666666666666630e-01 1.00000000000000000e+00"
> >- " 7.77777777777777901e-01 1.00000000000000000e+00
> 1.22222222222222210e+00";
> >+ " 7.77777777777777901e-01 1.00000000000000000e+00
> 1.22222222222222210e+00";
> > VERIFY( res == expected );
> > break;
> >- case 64: // ieee80
> >+ case 64: // ieee80
> > expected =
> > "3 0.000000000000000000000e+00 3.333333333333333333424e-01
> 6.666666666666666666847e-01 1.000000000000000000000e+00"
> >- " 7.777777777777779011359e-01 1.000000000000000000000e+00
> 1.222222222222222098864e+00";
> >+ " 7.777777777777779011359e-01 1.000000000000000000000e+00
> 1.222222222222222098864e+00";
> > VERIFY( res == expected );
> > break;
> > default:
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type.cc
> >new file mode 100644
> >index 00000000000..3c5b717e0f2
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type.cc
> >@@ -0,0 +1,52 @@
> >+// { dg-do compile { target c++11 } }
> >+// { dg-require-cstdint "" }
> >+
> >+#include <random>
> >+
> >+template<typename RealType>
> >+struct OnlyConv
> >+{
> >+ long double v;
> >+
> >+ template<typename DestType>
> >+ operator DestType() const
> >+ {
> >+ static_assert(std::is_same<DestType, RealType>::value);
> >+ return v;
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+struct OnlyCall
> >+{
> >+ template<typename SourceType>
> >+ OnlyConv<RealType> operator()(SourceType src)
> >+ {
> >+ static_assert(std::is_same<SourceType, RealType>::value);
> >+ return OnlyConv<RealType>{src};
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+void
> >+test()
> >+{
> >+ std::initializer_list<RealType> invs{0, 1, 2};
> >+ OnlyConv<RealType> weights[3]{1, 2, 3};
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_iter(invs.begin(), invs.end(), weights);
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_init_list(invs, OnlyCall<RealType>());
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_count(2, 0, 2, OnlyCall<RealType>());
> >+}
> >+
> >+int main()
> >+{
> >+ test<float>();
> >+ test<double>();
> >+ test<long double>();
> >+}
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type_fallback_neg.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type_fallback_neg.cc
> >new file mode 100644
> >index 00000000000..48ae22b87bb
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/input_type_fallback_neg.cc
> >@@ -0,0 +1,55 @@
> >+// { dg-options "-D_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS" }
> >+// { dg-do compile { target c++11 } }
> >+// { dg-require-cstdint "" }
> >+
> >+#include <random>
> >+
> >+template<typename RealType>
> >+struct OnlyConv
> >+{
> >+ long double v;
> >+
> >+ template<typename DestType>
> >+ operator DestType() const
> >+ {
> >+ static_assert(std::is_same<DestType, RealType>::value);
> >+ return v;
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+struct OnlyCall
> >+{
> >+ template<typename SourceType>
> >+ OnlyConv<RealType> operator()(SourceType src)
> >+ {
> >+ static_assert(std::is_same<SourceType, RealType>::value);
> >+ return OnlyConv<RealType>{src};
> >+ }
> >+};
> >+
> >+template<typename RealType>
> >+void
> >+test()
> >+{
> >+ std::initializer_list<RealType> invs{0, 1, 2};
> >+ OnlyConv<RealType> weights[3]{1, 2, 3};
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_iter(invs.begin(), invs.end(), weights);
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_init_list(invs, OnlyCall<RealType>());
> >+
> >+ std::piecewise_linear_distribution<RealType>
> >+ from_count(2, 0, 2, OnlyCall<RealType>());
> >+}
> >+
> >+int main()
> >+{
> >+ test<float>(); // { dg-error "here" }
> >+ test<double>();
> >+ test<long double>(); // { dg-error "here" }
> >+}
> >+
> >+// { dg-prune-output "static assertion failed" }
> >diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> >index 0a13e0fd9e2..5da22fc1011 100644
> >---
> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> >@@ -34,40 +34,88 @@ test_exact()
> > VERIFY( density[5] == RealType(2.0 / 8.0) );
> > }
> >
> >-template<typename RealType>
> >+template<typename InputType, typename DistType = InputType>
> > void
> > test_precision_depended()
> > {
> > constexpr bool preserved
> >-#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> >- = true;
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ = sizeof(InputType) <= sizeof(double);
> >+#elifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> >+ = sizeof(InputType) <= sizeof(DistType);
> > #else
> >- = sizeof(RealType) <= sizeof(double);
> >+ // input is converted to DistType and stored in double
> >+ = (sizeof(InputType) <= sizeof(DistType))
> >+ && (sizeof(InputType) <= sizeof(double));
> > #endif
> >
> >- RealType x[3]{0.0, 0.5, 1.0};
> >- constexpr RealType step
> >- = std::numeric_limits<RealType>::epsilon() * 2;
> >- RealType wt[3]{RealType(1) - step, RealType(1), RealType(1) + step};
> >+ std::initializer_list<DistType> x{0.0, 0.5, 1.0};
> >+ constexpr InputType step
> >+ = std::numeric_limits<InputType>::epsilon() * 2;
> >+ InputType wt[3]{InputType(1) - step, InputType(1), InputType(1) +
> step};
> >
> >- std::piecewise_linear_distribution<RealType>
> >- u(std::begin(x), std::end(x), wt);
> >+ using Distribution = std::piecewise_linear_distribution<DistType>;
> >+ auto validate = [&wt](const Distribution& dist)
> >+ {
> >+ const std::vector<DistType>& interval = dist.intervals();
> >+ VERIFY( interval.size() == 3 );
> >+ VERIFY( interval[0] == DistType(0.0) );
> >+ VERIFY( interval[2] == DistType(1.0) );
> >
> >- const std::vector<RealType>& interval = u.intervals();
> >- VERIFY( interval.size() == 3 );
> >- VERIFY( interval[0] == RealType(0.0) );
> >- VERIFY( interval[2] == RealType(1.0) );
> >+#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ const std::vector<double>& density = dist.densities();
> >+#else
> >+ const std::vector<DistType>& density = dist.densities();
> >+#endif
> >+
> >+ VERIFY( density.size() == 3 );
> >+ VERIFY( density[0] == (preserved ? wt[0] : InputType(1)) );
> >+ VERIFY( density[1] == InputType(1) );
> >+ VERIFY( density[2] == (preserved ? wt[2] : InputType(1)) );
> >+ };
> >+
> >+ Distribution from_iter(x.begin(), x.end(), wt);
> >+ validate(from_iter);
> >
> >+ auto wf = [&wt](DistType v)
> >+ { return wt[int(v / 0.5)]; };
> >+
> >+ Distribution from_init_list(x, wf);
> >+ validate(from_init_list);
> >+
> >+#ifndef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >+ // PR125548 leads to incorrect densities being used
> >+ Distribution from_count(2, InputType(0), InputType(1), wf);
> >+ validate(from_count);
> >+#endif
> >+}
> >+
> >+template<typename RealType, typename URBG = std::mt19937>
> >+void
> >+test_engine_calls()
> >+{
> >+ constexpr std::size_t bits = __builtin_popcountg(URBG::max() -
> URBG::min());
> >+ constexpr std::size_t calls
> > #ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> >- const std::vector<double>& density = u.densities();
> >+ = (std::numeric_limits<double>::digits + bits - 1) / bits;
> > #else
> >- const std::vector<RealType>& density = u.densities();
> >+ = (std::numeric_limits<RealType>::digits + bits - 1) / bits;
> > #endif
> >
> >- VERIFY( density.size() == 3 );
> >- VERIFY( density[0] == (preserved ? wt[0] : RealType(1)) );
> >- VERIFY( density[1] == RealType(1) );
> >- VERIFY( density[2] == (preserved ? wt[2] : RealType(1)) );
> >+ struct wrapper : URBG
> >+ {
> >+ typename URBG::result_type operator()()
> >+ {
> >+ ++num_calls;
> >+ return URBG::operator()();
> >+ }
> >+ std::size_t num_calls = 0;
> >+ };
> >+
> >+ wrapper eng;
> >+ std::piecewise_linear_distribution<RealType> u;
> >+ u(eng);
> >+ VERIFY(eng.num_calls == calls);
> > }
> >
> > int main()
> >@@ -81,5 +129,12 @@ int main()
> > test_precision_depended<double>();
> > test_precision_depended<long double>();
> >
> >+ test_precision_depended<double, float>();
> >+ test_precision_depended<long double, float>();
> >+ test_precision_depended<long double, double>();
> >+
> >+ test_engine_calls<float>();
> >+ test_engine_calls<double>();
> >+ test_engine_calls<long double>();
> > return 0;
> > }
> >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 21365057f9e..55f0d8c427d 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
> >@@ -24,7 +24,7 @@ test_default()
> >
> > if (!std::numeric_limits<RealType>::is_iec559)
> > return;
> >-
> >+
> > char const* expected = nullptr;
> > switch (std::numeric_limits<RealType>::digits)
> > {
> >@@ -40,7 +40,7 @@ test_default()
> > " 1.00000000000000000e+00 1.00000000000000000e+00";
> > VERIFY( res == expected );
> > break;
> >- case 64: // ieee80
> >+ case 64: // ieee80
> > expected =
> > "1 0.000000000000000000000e+00 1.000000000000000000000e+00"
> > " 1.000000000000000000000e+00 1.000000000000000000000e+00";
> >@@ -63,7 +63,7 @@ test_custom()
> > str << u;
> > std::string res = str.str();
> >
> >- std::piecewise_constant_distribution<RealType> v;
> >+ std::piecewise_linear_distribution<RealType> v;
> > str >> v;
> > // This does not hold currently
> > // VERIFY( u == v );
> >@@ -77,16 +77,16 @@ test_custom()
> > case 24: // ieee32
> > expected =
> > "3 0.000000000e+00 3.333333433e-01 6.666666865e-01 1.000000000e+00"
> >- " 6.666666534e-01 8.888888977e-01 1.111111142e+00 1.333333307e+00";
> >+ " 6.666666865e-01 8.888888955e-01 1.111111164e+00 1.333333373e+00";
> > VERIFY( res == expected );
> > break;
> > case 53: // ieee64
> > expected =
> >- "3 0.00000000000000000e+00 3.33333333333333315e-01
> 6.66666666666666630e-01 1.00000000000000000e+00"
> >+ "3 0.00000000000000000e+00 3.33333333333333315e-01
> 6.66666666666666630e-01 1.00000000000000000e+00"
> > " 6.66666666666666630e-01 8.88888888888888840e-01
> 1.11111111111111094e+00 1.33333333333333326e+00";
> > VERIFY( res == expected );
> > break;
> >- case 64: // ieee80
> >+ case 64: // ieee80
> > expected =
> > "3 0.000000000000000000000e+00 3.333333333333333333424e-01
> 6.666666666666666666847e-01 1.000000000000000000000e+00"
> > " 6.666666666666666296592e-01 8.888888888888888395456e-01
> 1.111111111111111160454e+00 1.333333333333333259318e+00";
> >@@ -103,10 +103,9 @@ int main()
> > test_default<double>();
> > test_default<long double>();
> >
> >-#ifdef __x86_64__
> > test_custom<float>();
> > test_custom<double>();
> >-#endif
> > test_custom<long double>();
> >+
> > return 0;
> > }
> >--
> >2.54.0
> >
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260716/a91705a0/attachment-0001.htm>
More information about the Libstdc++
mailing list