[PATCH] libstdc++: Generate result_type bits of precision in piecewise distributions.

Jonathan Wakely jwakely@redhat.com
Thu Jul 16 10:04:38 GMT 2026


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?

>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.

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)));

>+#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.

>+	    _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)

>+#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?


> 	  _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

> 	}
>       __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)

>-          }
>+	  }
>+	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
>
>



More information about the Libstdc++ mailing list