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 >
