On Thu, 16 Jul 2026 at 12:50, Tomasz Kamiński <[email protected]> wrote:
>
> The piecewise distributions previously always generated a double value
> 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 float it used, however
> due the ABI compatibility, double is still used for storage, 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 behaviour or
> 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 reverts r17-2391-geae19
> and r17-2392-g86a93). This is achieved by converting the values to _CalcType
> that is either defined as double or _RealType. This change is not applied
> to interval delta (_M_int[__k + 1] - _M_int[__k]) that used _RealType
> already, to preserve the result of computations involving it.
>
> 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::_CalcType)
>         (piecewise_linear_distribution::_CalcType): 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 _CalcType.
>         * 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 _CalcType.
>         (piecewise_constant_distribution::param_type::param_type)
>         (piecewise_constant_distribution::param_type::param_type):
>         Cast the inputs to the _CalcType. Use _RealTyp e as input

There's a stray space in "_RealTyp e" here.

OK for trunk

>         weight functor.
>         (piecewise_constant_distribution::__generate_one)
>         (piecewise_linear_distribution::__generate_one): Extract
>         from operator() and use _CalcType.
>         (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.
>
> Reviewed-by: Jonathan Wakely <[email protected]>
> Signed-off-by: Tomasz Kamiński <[email protected]>
> ---
> v2:
> - renames _CompType to _CalcType,
> - cast the literals to _CalcType, keepign the calculations in it
> - apply fixup to commit description suggested on review,
>   and add a sentece regarding interval delta not being
>   changed to _CalcType: we also do not cast (_M_int[__k + 1] - _M_int[__k])
>   in constant distribution for same reason,
> - some trailing whitespace fixes
>
> Testing on x86_64-linux. *piecewise* test passed in all standard
> modes, debug and -m32. OK for trunk?
>
>  .../doc/html/manual/using_macros.html         |   3 +-
>  libstdc++-v3/doc/xml/manual/using.xml         |   4 +-
>  libstdc++-v3/include/bits/random.h            |  24 ++-
>  libstdc++-v3/include/bits/random.tcc          | 203 +++++++++++-------
>  .../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, 521 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 2e5f4b2e1a1..0df3a2d3451 100644
> --- a/libstdc++-v3/doc/html/manual/using_macros.html
> +++ b/libstdc++-v3/doc/html/manual/using_macros.html
> @@ -164,7 +164,8 @@
>         is restored to their state prior the implementation
>         of <a class="link" 
> href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82749"; target="_top">
>         PR82749</a> (<a class="link" 
> href="https://cplusplus.github.io/LWG/lwg-defects.html#1439"; target="_top">
> -       LWG1439</a>), and <a class="link" 
> href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125548"; target="_top">
> +       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.
> diff --git a/libstdc++-v3/doc/xml/manual/using.xml 
> b/libstdc++-v3/doc/xml/manual/using.xml
> index 027b26b72cf..da710be408f 100644
> --- a/libstdc++-v3/doc/xml/manual/using.xml
> +++ b/libstdc++-v3/doc/xml/manual/using.xml
> @@ -1391,7 +1391,9 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 
> hello.cc -o test.exe
>         xlink:href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82749";>
>         PR82749</link> (<link xmlns:xlink="http://www.w3.org/1999/xlink";
>         xlink:href="https://cplusplus.github.io/LWG/lwg-defects.html#1439";>
> -       LWG1439</link>), 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.
>        </para>
> diff --git a/libstdc++-v3/include/bits/random.h 
> b/libstdc++-v3/include/bits/random.h
> index c219930cc29..b01b92862cc 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 _CalcType = double;
> +#else
> +      using _CalcType = _RealType;
> +#endif
>
>      public:
>        /** The type of the range of the distribution. */
> @@ -6552,7 +6557,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>         _M_configure();
>
>         void
> -       _M_initialize2(const _RealType* __ints, _RealType __den);
> +       _M_initialize2(const _RealType* __ints, _CalcType __den);
>
>         std::vector<_RealType> _M_int;
>         std::vector<_StorageType> _M_den;
> @@ -6733,6 +6738,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
> @@ -6775,6 +6785,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>
>        using _StorageType
>         = __detail::__piecewise_distributions_storage_t<_RealType>;
> +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS
> +      using _CalcType = double;
> +#else
> +      using _CalcType = _RealType;
> +#endif
>
>      public:
>        /** The type of the range of the distribution. */
> @@ -6857,7 +6872,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>         _M_configure();
>
>         void
> -       _M_initialize2(const _RealType* __ints, const _RealType* __dens);
> +       _M_initialize2(const _RealType* __ints, const _CalcType* __dens);
>
>         std::vector<_RealType> _M_int;
>         std::vector<_StorageType> _M_den;
> @@ -7040,6 +7055,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..aa176db4778 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 _CalcType __sum = std::accumulate(_M_den.begin(), _M_den.end(),
> +                                             _CalcType(0));
>        __glibcxx_assert(__sum > 0);
>
>        __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(),
>                             __sum);
>
> +      _CalcType __psum(0);
>        _M_cp.reserve(_M_den.size());
> -      std::partial_sum(_M_den.begin(), _M_den.end(),
> -                      std::back_inserter(_M_cp));
> +      for (_CalcType __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] = _CalcType(1);
>
>        for (size_t __k = 0; __k < _M_den.size(); ++__k)
> -       _M_den[__k] /= _M_int[__k + 1] - _M_int[__k];
> +       _M_den[__k] = _CalcType(_CalcType(_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, _CalcType __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(_CalcType(*__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)));
> +#endif
> +       };
> +
>         if (__bl.size() == 2)
>           {
>             const _RealType *__ints = __bl.begin();
> -           _RealType __den = __fw(0.5 * (__ints[1] + __ints[0]));
> +           _CalcType __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(__v + _RealType(0.5) * __delta));
> +#endif
> +       };
> +
>         if (__n == 1)
>           {
>             _RealType __ints[2] = { __xmin, __xmin + __delta };
> -           _RealType __den = __fw(__xmin + 0.5 * __delta);
> +           _CalcType __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 _CalcType __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 _CalcType __pref = __i > 0 ? __param._M_cp[__i - 1] : 
> _CalcType(0);
> +       return __param._M_int[__i] + (__p - __pref) / 
> _CalcType(__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, _CalcType>
>           __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();
> -
> -       const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0;
> +         return __aurng();
>
> -       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, _CalcType>
>           __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,34 +3248,37 @@ namespace __detail
>      piecewise_linear_distribution<_RealType>::param_type::
>      _M_configure()
>      {
> -      double __sum = 0.0;
> +      _CalcType __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 += _CalcType(0.5)
> +                  * (_CalcType(_M_den[__k + 1]) + _CalcType(_M_den[__k]))
> +                  * __delta;
>           _M_cp.push_back(__sum);
> -         _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta);
> +         _M_m.push_back(
> +           (_CalcType(_M_den[__k + 1]) - _CalcType(_M_den[__k])) / __delta);
>         }
>        __glibcxx_assert(__sum > 0);
>
>        //  Now normalize the densities...
>        __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(),
>                             __sum);
> -      //  ... and partial sums...
> +      //  ... and partial sums...
>        __detail::__normalize(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), 
> __sum);
>        //  ... and slopes.
>        __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] = _CalcType(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 _CalcType* __dens)
>      {
>        if (__ints[0] == _RealType(0)
>           && __ints[1] == _RealType(1)
> @@ -3288,7 +3309,7 @@ namespace __detail
>
>         if (__bbegin == __bend)
>           {
> -           _RealType __dens[2];
> +           _CalcType __dens[2];
>             __dens[0] = *__wbegin;
>             ++__wbegin;
>             __dens[1] = *__wbegin;
> @@ -3314,9 +3335,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(_CalcType(*__wbegin));
>
>         _M_configure();
>        }
> @@ -3333,7 +3356,7 @@ namespace __detail
>         if (__bl.size() == 2)
>           {
>             const _RealType *__ints = __bl.begin();
> -           _RealType __den[2];
> +           _CalcType __den[2];
>             __den[0] = __fw(__ints[0]);
>             __den[1] = __fw(__ints[1]);
>             _M_initialize2(__ints, __den);
> @@ -3343,7 +3366,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(_CalcType(__fw(__b)));
>         _M_configure();
>        }
>
> @@ -3356,18 +3379,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];
> +           _CalcType __dens[2];
>             __dens[0] = __cfw(__ints[0]);
>             __dens[1] = __cfw(__ints[1]);
>             _M_initialize2(__ints, __dens);
> @@ -3386,39 +3411,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 _CalcType __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 _CalcType __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 _CalcType __a = _CalcType(0.5) * __param._M_m[__i];
> +       const _CalcType __b = __param._M_den[__i];
> +       const _CalcType __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;
> -           __x += 0.5 * (std::sqrt(__d) - __b) / __a;
> -          }
> +           const _CalcType __d = __b * __b + 4.0 * __a * __cm;
> +           __x += _CalcType(0.5) * (std::sqrt(__d) - __b) / __a;
> +         }
> +       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, _CalcType>
> +         __aurng(__urng);
> +
> +       if (__param._M_cp.empty())
> +         return __aurng();
> +
> +       return __generate_one(__aurng, __param);
>        }
>
>    template<typename _RealType>
> @@ -3431,9 +3466,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, _CalcType>
> +         __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.55.0
>

Reply via email to