On Thu, Jul 16, 2026 at 12:04 PM Jonathan Wakely <[email protected]> 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 > > > > > >
