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

Reply via email to