[PATCH v2] libstdc++: Change piecewise distribution densities to return vector<result_type>.
Tomasz Kaminski
tkaminsk@redhat.com
Fri May 29 16:52:23 GMT 2026
On Fri, May 29, 2026 at 5:44 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>
> On Fri, May 29, 2026 at 4:53 PM Jonathan Wakely <jwakely@redhat.com>
> wrote:
>
>> On Wed, 27 May 2026 at 08:42 +0200, Tomasz Kamiński wrote:
>> >This implements the interface changes from
>> >LWG1439, "Return from densities() functions?".
>> >
>> >Due the ABI concerns, we cannot change the the element_type of member
>> >(_M_den, _M_cp, and _M_m) vectors, and we convert the _M_den values
>> >to result_type when function is invoked. However, as the usage of
>> >distributions with types other than float, double, and long double
>> >is either undefined (pre C++26) or implementaiton-defined (post C++26),
>> >this limitation de-fact applies to float, and long double (if it's
>> >different size than double).
>> >
>> >To handle above we introduce the __piecewise_distributions_storage<_Tp>
>> >struct, whose type nested typedef points to double in above two cases,
>> >and _Tp otherwise. The _StorageType is defined in terms of
>> >__piecewise_distributions_storage_t alias to above, and is then used
>> >in defintion of _M_den, _M_cp, and _M_m members. In consequence for
>> >extended floating point types (__float128, std::float16, ...) for which
>> >ABI can be changed, we store densitiees (and other values) as
>> result_type.
>> >
>> >For user that can accept above ABI change, we introduce a macro
>> >_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES, that result in
>> >__piecewise_distributions_storage_t being unconditionally defined
>> >as _Tp, and thus adjust internal storage also for float and long double.
>> >
>> >To avoid symbol conflicts, the param_type::densities member functions
>> >are marked with "__rt" ABI tag. The corresponding members of the
>> >distributions are modified to invoke param_type method, and marked
>> >as always_inline. For consistency intervals methods are adjusted same
>> >way.
>> >
>> >Finally, to preserve current behavior, the operators>> load densities
>> >as values of _StorageType.
>> >
>> >libstdc++-v3/ChangeLog:
>> >
>> > * doc/xml/manual/using.xml
>> > (_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES): Add entry.
>> > * doc/html/manual/using_macros.html: Regenerate.
>> > * include/bits/random.h
>> > (__detail::__piecewise_distributions_storage)
>> > (__detail::__piecewise_distributions_storage_t)
>> > (piecewise_constant_distribution::_StorageType)
>> > (piecewise_linear_distribution::_StorageType): Define.
>> > (piecewise_constant_distribution::param_type::_M_den)
>> > (piecewise_constant_distribution::param_type::_M_cp)
>> > (piecewise_linear_distribution::param_type::_M_den)
>> > (piecewise_linear_distribution::param_type::_M_cp)
>> > (piecewise_linear_distribution::param_type::_M_m): Use
>> _StorageType
>> > as element type.
>> > (piecewise_constant_distribution::param_type::densities)
>> > (piecewise_linear_distribution::param_type::densities): Change
>> > return type to vector<result_type>, mark with "__rt" ABI tag,
>> > and adjust implementation.
>> > (piecewise_constant_distribution::param_type::intervals)
>> > (piecewise_linear_distribution::param_type::intervals): Use
>> > result_type alias in return type.
>> > (piecewise_constant_distribution::densities)
>> > (piecewise_linear_distribution::densities): Delegate to param_type
>> > method, and mark as always_inline.
>> > (piecewise_constant_distribution::intervals)
>> > (piecewise_linear_distribution::intervals): Delegate to param_type
>> > method and use result_type alias in return type.
>> > * include/bits/random.tcc
>> > (operator<<(basic_ostream&, const
>> piecewise_constant_distribution&))
>> > (operator<<(basic_ostream&, const
>> piecewise_linear_distribution&)):
>> > Parse vector of _StorageType for densities, to preserve behavior.
>> > *
>> testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc:
>> > New test.
>> > *
>> testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc:
>> > New test.
>> > *
>> testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_exact.cc:
>> > Run accessors.cc with
>> _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES.
>> > *
>> testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc:
>> > Likewise.
>> >---
>> >v2:
>> > - removes unused _StorageType alias from operator<<
>> > - introduces __piecewise_distributions_storage_t alias,
>> > and changes commit description
>> >(Sending due changes to commit description).
>> >
>> >Tested on x86_64-linux. OK for trunk?
>> >
>> > .../doc/html/manual/using_macros.html | 11 ++
>> > libstdc++-v3/doc/xml/manual/using.xml | 17 +++
>> > libstdc++-v3/include/bits/random.h | 142 ++++++++++++------
>> > libstdc++-v3/include/bits/random.tcc | 8 +-
>> > .../operators/accessors.cc | 73 +++++++++
>> > .../operators/accessors_exact.cc | 5 +
>> > .../operators/accessors.cc | 75 +++++++++
>> > .../operators/accessors_exact.cc | 5 +
>> > 8 files changed, 291 insertions(+), 45 deletions(-)
>> > create mode 100644
>> libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
>> > create mode 100644
>> libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_exact.cc
>> > create mode 100644
>> libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
>> > create mode 100644
>> libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc
>> >
>> >diff --git a/libstdc++-v3/doc/html/manual/using_macros.html
>> b/libstdc++-v3/doc/html/manual/using_macros.html
>> >index f1d8492fb9e..ea32f065bea 100644
>> >--- a/libstdc++-v3/doc/html/manual/using_macros.html
>> >+++ b/libstdc++-v3/doc/html/manual/using_macros.html
>> >@@ -156,4 +156,15 @@
>> > <code class="option">-fexec-charset=UTF-8</code> so might give
>> incorrect results
>> > if called from a source file that uses a non-Unicode encoding,
>> > especially for format strings using non-ASCII fill characters.
>> >+ </p></dd><dt><span class="term"><code
>> class="code">_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></span></dt><dd><p>
>> >+ Undefined by default. When defined specializations of
>> >+ <code class="code">piecewise_constant_distribution</code> and
>> >+ <code class="code">piecewise_linear_distribution</code> for <code
>> class="code">float</code> or
>> >+ <code class="code">long double</code> <code
>> class="code">result_type</code>, stores value of
>> >+ densities (and other state) as <code
>> class="code">result_type</code> (instead of
>> >+ <code class="code">double</code>). This complete the resolution
>> of library issue
>> >+ <a class="link" href="https://cplusplus.github.io/LWG/issue1439"
>> target="_top">
>> >+ 1449. Return from densities() functions?</a>, however makes their
>> >+ representation ABI incompatible with one used by translation units
>> >+ compiled without this flag, including older GCC releases.
>> > </p></dd></dl></div></div><div class="navfooter"><hr /><table
>> width="100%" summary="Navigation footer"><tr><td width="40%"
>> align="left"><a accesskey="p" href="using_headers.html">Prev</a> </td><td
>> width="20%" align="center"><a accesskey="u"
>> href="using.html">Up</a></td><td width="40%" align="right"> <a
>> accesskey="n" href="using_dual_abi.html">Next</a></td></tr><tr><td
>> width="40%" align="left" valign="top">Headers </td><td width="20%"
>> align="center"><a accesskey="h" href="../index.html">Home</a></td><td
>> width="40%" align="right" valign="top"> Dual
>> ABI</td></tr></table></div></body></html>
>> >\ No newline at end of file
>> >diff --git a/libstdc++-v3/doc/xml/manual/using.xml
>> b/libstdc++-v3/doc/xml/manual/using.xml
>> >index e2e75e8fe28..d71dd13703b 100644
>> >--- a/libstdc++-v3/doc/xml/manual/using.xml
>> >+++ b/libstdc++-v3/doc/xml/manual/using.xml
>> >@@ -1379,6 +1379,23 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2
>> hello.cc -o test.exe
>> > especially for format strings using non-ASCII fill characters.
>> > </para>
>> > </listitem></varlistentry>
>> >+
>> <varlistentry><term><code>_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></term>
>> >+ <listitem>
>> >+ <para>
>> >+ Undefined by default. When defined specializations of
>> >+ <code>piecewise_constant_distribution</code> and
>> >+ <code>piecewise_linear_distribution</code> for <code>float</code>
>> or
>> >+ <code>long double</code> <code>result_type</code>, stores value of
>> >+ densities (and other state) as <code>result_type</code> (instead
>> of
>> >+ <code>double</code>). This complete the resolution of library
>> issue
>> >+ <link xmlns:xlink="http://www.w3.org/1999/xlink"
>> >+ xlink:href="https://cplusplus.github.io/LWG/issue1439">
>> >+ 1449. Return from densities() functions?</link>, however makes
>> their
>> >+ representation ABI incompatible with one used by translation units
>> >+ compiled without this flag, including older GCC releases.
>> >+ </para>
>>
>> Let's rephrase this as follows (and include the magic phrase
>> "ABI-changing" which that page defines and uses for macros which
>> affect the ABI:
>>
>> Undefined by default. ABI-changing.
>> When defined, specializations of piecewise_constant_distribution and
>> piecewise_linear_distribution with a result_type of either float or
>> long double will manage their internal state using result_type values
>> (instead of double). This is required for standard conformance, but is
>> incompatible with the default implementation of those class templates.
>>
>>
>> >+ </listitem></varlistentry>
>> >+
>> > </variablelist>
>> >
>> > </section>
>> >diff --git a/libstdc++-v3/include/bits/random.h
>> b/libstdc++-v3/include/bits/random.h
>> >index a0592a00763..6016a56dc21 100644
>> >--- a/libstdc++-v3/include/bits/random.h
>> >+++ b/libstdc++-v3/include/bits/random.h
>> >@@ -6385,6 +6385,40 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > { return !(__d1 == __d2); }
>> > #endif
>> >
>> >+ namespace __detail
>> >+ {
>> >+#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
>> >+ template<typename _Tp>
>> >+ using __piecewise_distributions_storage_t = _Tp;
>> >+#else
>> >+ template<typename _Tp>
>> >+ struct __piecewise_distributions_storage
>> >+ { using type = _Tp; };
>> >+
>> >+ template<>
>> >+ struct __piecewise_distributions_storage<float>
>> >+ { using type = double; };
>> >+
>> >+# ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
>>
>> Is this necessary?
>>
>> Users should only instantiate the <random> distributions with float,
>> double, or long double. In any given translation unit, they should
>> only refer to piecewise_linear_distribution<long double> and not
>> piecewise_linear_distribution</* the other kind of long double */>.
>>
>> I suppose it's possible that they need to explicitly refer to
>> piecewise_linear_distribution<__ibm128> for a class data member to
>> ensure it has a stable definition in all TUs.
>>
>> >+ template<>
>> >+ struct __piecewise_distributions_storage<__ibm128>
>> >+ { using type = double; };
>> >+
>> >+ template<>
>> >+ struct __piecewise_distributions_storage<__ieee128>
>> >+ { using type = double; };
>> >+# elif __LDBL_MANT_DIG__ != __DBL_MANT_DIG__
>> >+ template<>
>> >+ struct __piecewise_distributions_storage<long double>
>> >+ { using type = double; };
>> >+# endif
>> >+
>> >+ template<typename _Tp>
>> >+ using __piecewise_distributions_storage_t
>> >+ = typename __piecewise_distributions_storage<_Tp>::type;
>> >+#endif // _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
>> >+ }
>> >+
>> > /**
>> > * @brief A piecewise_constant_distribution random number
>> distribution.
>> > *
>> >@@ -6407,6 +6441,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > static_assert(std::is_floating_point<_RealType>::value,
>> > "result_type must be a floating point type");
>> >
>> >+ using _StorageType
>> >+ = __detail::__piecewise_distributions_storage_t<_RealType>;
>> >+
>> > public:
>> > /** The type of the range of the distribution. */
>> > typedef _RealType result_type;
>> >@@ -6437,7 +6474,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > param_type(const param_type&) = default;
>> > param_type& operator=(const param_type&) = default;
>> >
>> >- std::vector<_RealType>
>> >+ std::vector<result_type>
>> > intervals() const
>> > {
>> > if (_M_int.empty())
>> >@@ -6450,9 +6487,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > return _M_int;
>> > }
>> >
>> >- std::vector<double>
>> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
>> >+ // 1439. Return from densities() functions?
>> >+ [[__gnu__::__abi_tag__("__rt")]]
>> >+ std::vector<result_type>
>>
>> I wonder if the _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES macro
>> should also control this, or a different macro. So that users who
>> don't want the new return type can select the old one.
>>
>> Curently we have a macro to change the _M_den and _M_cp members, but
>> no way to control the return type here. The abi_tag and always_inline
>> attributes makes them distinct functions, but it would still be a
>> source-breaking change for any code doing:
>>
>> std::piecewise_constant_distribution<float> dist;
>> vector<double> d = dist.densities();
>>
>> Maybe that's OK?
>>
> That's what PR was about. Note that this macro does not revert the change,
> Specifically, it does not affect floating-point types other than float or
> long double.
> It pushes further by including ABI changes in addition to API changes.
>
> If we want to revert the interface change, we should create a separate
> macro,
> to revert interface change.
>
As discussed:
We have other changes that will affect the result of the
picewise_distributions
(like asking for result_type from iterator), and I will add above into
single
_USE_OLD_PIECWISE_DISTR_IMPL switch, that will revert all the changes.
>
>
>
>>
>> > densities() const
>> >- { return _M_den.empty() ? std::vector<double>(1, 1.0) : _M_den; }
>> >+ {
>> >+#pragma GCC diagnostic push
>> >+#pragma GCC diagnostic ignored "-Wc++17-extensions"
>> >+ if (_M_den.empty())
>> >+ return std::vector<_RealType>(1, _RealType(1));
>> >+ else if constexpr (is_same<_RealType, _StorageType>::value)
>> >+ return _M_den;
>> >+ else
>> >+ {
>> >+ std::vector<_RealType> __res;
>> >+ __res.reserve(_M_den.size());
>> >+ for (_RealType __v : _M_den)
>> >+ __res.push_back(__v);
>> >+ return __res;
>> >+ }
>> >+#pragma GCC diagnostic pop
>> >+ }
>> >
>> > friend bool
>> > operator==(const param_type& __p1, const param_type& __p2)
>> >@@ -6472,8 +6528,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > _M_initialize2(const _RealType* __ints, _RealType __den);
>> >
>> > std::vector<_RealType> _M_int;
>> >- std::vector<double> _M_den;
>> >- std::vector<double> _M_cp;
>> >+ std::vector<_StorageType> _M_den;
>> >+ std::vector<_StorageType> _M_cp;
>> >
>> > template<typename _RealType1, typename _CharT, typename _Traits>
>> > friend std::basic_ostream<_CharT, _Traits>&
>> >@@ -6520,28 +6576,17 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > /**
>> > * @brief Returns a vector of the intervals.
>> > */
>> >- std::vector<_RealType>
>> >+ std::vector<result_type>
>> > intervals() const
>> >- {
>> >- if (_M_param._M_int.empty())
>> >- {
>> >- std::vector<_RealType> __tmp(2);
>> >- __tmp[1] = _RealType(1);
>> >- return __tmp;
>> >- }
>> >- else
>> >- return _M_param._M_int;
>> >- }
>> >+ { return _M_param.intervals(); }
>> >
>> > /**
>> > * @brief Returns a vector of the probability densities.
>> > */
>> >- std::vector<double>
>> >+ [[__gnu__::__always_inline__]]
>> >+ std::vector<_RealType>
>>
>> You've changed vector<_RealType> to vector<result_type> elsewhere,
>> should this be vector<result_type> too?
>>
>> > densities() const
>> >- {
>> >- return _M_param._M_den.empty()
>> >- ? std::vector<double>(1, 1.0) : _M_param._M_den;
>> >- }
>> >+ { return _M_param.densities(); }
>> >
>> > /**
>> > * @brief Returns the parameter set of the distribution.
>> >@@ -6695,6 +6740,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > static_assert(std::is_floating_point<_RealType>::value,
>> > "result_type must be a floating point type");
>> >
>> >+ using _StorageType
>> >+ = __detail::__piecewise_distributions_storage_t<_RealType>;
>> >+
>> > public:
>> > /** The type of the range of the distribution. */
>> > typedef _RealType result_type;
>> >@@ -6725,7 +6773,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > param_type(const param_type&) = default;
>> > param_type& operator=(const param_type&) = default;
>> >
>> >- std::vector<_RealType>
>> >+ std::vector<result_type>
>> > intervals() const
>> > {
>> > if (_M_int.empty())
>> >@@ -6738,9 +6786,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > return _M_int;
>> > }
>> >
>> >- std::vector<double>
>> >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
>> >+ // 1439. Return from densities() functions?
>> >+ [[__gnu__::__abi_tag__("__rt")]]
>> >+ std::vector<result_type>
>> > densities() const
>> >- { return _M_den.empty() ? std::vector<double>(2, 1.0) : _M_den; }
>> >+ {
>> >+#pragma GCC diagnostic push
>> >+#pragma GCC diagnostic ignored "-Wc++17-extensions"
>> >+ if (_M_den.empty())
>> >+ return std::vector<_RealType>(2, _RealType(1));
>> >+ else if constexpr (is_same<_RealType, _StorageType>::value)
>> >+ return _M_den;
>> >+ else
>> >+ {
>> >+ std::vector<_RealType> __res;
>> >+ __res.reserve(_M_den.size());
>> >+ for (_RealType __v : _M_den)
>> >+ __res.push_back(__v);
>> >+ return __res;
>> >+ }
>> >+#pragma GCC diagnostic pop
>> >+ }
>> >
>> > friend bool
>> > operator==(const param_type& __p1, const param_type& __p2)
>> >@@ -6760,9 +6827,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > _M_initialize2(const _RealType* __ints, const _RealType* __dens);
>> >
>> > std::vector<_RealType> _M_int;
>> >- std::vector<double> _M_den;
>> >- std::vector<double> _M_cp;
>> >- std::vector<double> _M_m;
>> >+ std::vector<_StorageType> _M_den;
>> >+ std::vector<_StorageType> _M_cp;
>> >+ std::vector<_StorageType> _M_m;
>> >
>> > template<typename _RealType1, typename _CharT, typename _Traits>
>> > friend std::basic_ostream<_CharT, _Traits>&
>> >@@ -6809,29 +6876,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>> > /**
>> > * @brief Return the intervals of the distribution.
>> > */
>> >- std::vector<_RealType>
>> >+ std::vector<result_type>
>> > intervals() const
>> >- {
>> >- if (_M_param._M_int.empty())
>> >- {
>> >- std::vector<_RealType> __tmp(2);
>> >- __tmp[1] = _RealType(1);
>> >- return __tmp;
>> >- }
>> >- else
>> >- return _M_param._M_int;
>> >- }
>> >+ { return _M_param.intervals(); }
>> >
>> > /**
>> > * @brief Return a vector of the probability densities of the
>> > * distribution.
>> > */
>> >- std::vector<double>
>> >+ [[__gnu__::__always_inline__]]
>> >+ std::vector<result_type>
>> > densities() const
>> >- {
>> >- return _M_param._M_den.empty()
>> >- ? std::vector<double>(2, 1.0) : _M_param._M_den;
>> >- }
>> >+ { return _M_param.densities(); }
>> >
>> > /**
>> > * @brief Returns the parameter set of the distribution.
>> >diff --git a/libstdc++-v3/include/bits/random.tcc
>> b/libstdc++-v3/include/bits/random.tcc
>> >index e581f912764..6c88d68d3e4 100644
>> >--- a/libstdc++-v3/include/bits/random.tcc
>> >+++ b/libstdc++-v3/include/bits/random.tcc
>> >@@ -3199,6 +3199,8 @@ namespace __detail
>> > piecewise_constant_distribution<_RealType>& __x)
>> > {
>> > using __ios_base = typename basic_istream<_CharT,
>> _Traits>::ios_base;
>> >+ using _StorageType
>> >+ = typename
>> piecewise_constant_distribution<_RealType>::_StorageType;
>> >
>> > const typename __ios_base::fmtflags __flags = __is.flags();
>> > __is.flags(__ios_base::dec | __ios_base::skipws);
>> >@@ -3209,7 +3211,7 @@ namespace __detail
>> > std::vector<_RealType> __int_vec;
>> > if (__detail::__extract_params(__is, __int_vec, __n + 1))
>> > {
>> >- std::vector<double> __den_vec;
>> >+ std::vector<_StorageType> __den_vec;
>> > if (__detail::__extract_params(__is, __den_vec, __n))
>> > {
>> > __x.param({ __int_vec.begin(), __int_vec.end(),
>> >@@ -3466,6 +3468,8 @@ namespace __detail
>> > piecewise_linear_distribution<_RealType>& __x)
>> > {
>> > using __ios_base = typename basic_istream<_CharT,
>> _Traits>::ios_base;
>> >+ using _StorageType
>> >+ = typename piecewise_linear_distribution<_RealType>::_StorageType;
>> >
>> > const typename __ios_base::fmtflags __flags = __is.flags();
>> > __is.flags(__ios_base::dec | __ios_base::skipws);
>> >@@ -3476,7 +3480,7 @@ namespace __detail
>> > vector<_RealType> __int_vec;
>> > if (__detail::__extract_params(__is, __int_vec, __n + 1))
>> > {
>> >- vector<double> __den_vec;
>> >+ vector<_StorageType> __den_vec;
>> > if (__detail::__extract_params(__is, __den_vec, __n + 1))
>> > {
>> > __x.param({ __int_vec.begin(), __int_vec.end(),
>> >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
>> >new file mode 100644
>> >index 00000000000..6d466d83cd5
>> >--- /dev/null
>> >+++
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
>> >@@ -0,0 +1,73 @@
>> >+// { dg-do run { target c++11 } }
>> >+// { dg-require-cstdint "" }
>> >+
>> >+#include <random>
>> >+#include <testsuite_hooks.h>
>> >+
>> >+template<typename RealType>
>> >+void
>> >+test_exact()
>> >+{
>> >+ RealType x[6] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
>> >+ RealType wt[5] = {0.5, 1.0, 3.5, 2.5, 0.5};
>> >+
>> >+ std::piecewise_constant_distribution<RealType>
>> >+ u(std::begin(x), std::end(x), wt);
>> >+
>> >+ const std::vector<RealType>& interval = u.intervals();
>> >+ VERIFY( interval.size() == 6 );
>> >+ VERIFY( interval[0] == RealType(0.0) );
>> >+ VERIFY( interval[5] == RealType(5.0) );
>> >+
>> >+ const std::vector<RealType>& density = u.densities();
>> >+ VERIFY( density.size() == 5 );
>> >+ VERIFY( density[0] == RealType(0.5 / 8.0) );
>> >+ VERIFY( density[1] == RealType(1.0 / 8.0) );
>> >+ VERIFY( density[2] == RealType(3.5 / 8.0) );
>> >+ VERIFY( density[3] == RealType(2.5 / 8.0) );
>> >+ VERIFY( density[4] == RealType(0.5 / 8.0) );
>> >+}
>> >+
>> >+template<typename RealType>
>> >+void
>> >+test_precision_depended()
>> >+{
>> >+ constexpr bool preserved
>> >+#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
>> >+ = true;
>> >+#else
>> >+ = sizeof(RealType) <= 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::piecewise_constant_distribution<RealType>
>> >+ u(std::begin(x), std::end(x), wt);
>> >+
>> >+ const std::vector<RealType>& interval = u.intervals();
>> >+ VERIFY( interval.size() == 3 );
>> >+ VERIFY( interval[0] == RealType(0.0) );
>> >+ VERIFY( interval[2] == RealType(1.0) );
>> >+
>> >+ const std::vector<RealType>& density = u.densities();
>> >+ VERIFY( density.size() == 2 );
>> >+ VERIFY( density[0] == (preserved ? wt[0] : RealType(1)) );
>> >+ VERIFY( density[1] == (preserved ? wt[1] : RealType(1)) );
>> >+}
>> >+
>> >+int main()
>> >+{
>> >+ using namespace __gnu_test;
>> >+ test_exact<float>();
>> >+ test_exact<double>();
>> >+ test_exact<long double>();
>> >+
>> >+ test_precision_depended<float>();
>> >+ test_precision_depended<double>();
>> >+ test_precision_depended<long double>();
>> >+
>> >+ return 0;
>> >+}
>> >diff --git
>> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_exact.cc
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_exact.cc
>> >new file mode 100644
>> >index 00000000000..469ed3fac46
>> >--- /dev/null
>> >+++
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_exact.cc
>> >@@ -0,0 +1,5 @@
>> >+// { dg-options "-D_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES" }
>> >+// { dg-do run { target c++11 } }
>> >+// { dg-require-cstdint "" }
>> >+#include "accessors.cc"
>> >+
>> >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
>> >new file mode 100644
>> >index 00000000000..23d10696fdb
>> >--- /dev/null
>> >+++
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
>> >@@ -0,0 +1,75 @@
>> >+// { dg-do run { target c++11 } }
>> >+// { dg-require-cstdint "" }
>> >+
>> >+#include <random>
>> >+#include <testsuite_hooks.h>
>> >+
>> >+template<typename RealType>
>> >+void
>> >+test_exact()
>> >+{
>> >+ RealType x[6] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
>> >+ RealType wt[6] = {0.0, 1.0, 1.0, 6.0, -1.0, 2.0};
>> >+
>> >+ std::piecewise_linear_distribution<RealType>
>> >+ u(std::begin(x), std::end(x), wt);
>> >+
>> >+ const std::vector<RealType>& interval = u.intervals();
>> >+ VERIFY( interval.size() == 6 );
>> >+ VERIFY( interval[0] == RealType(0.0) );
>> >+ VERIFY( interval[5] == RealType(5.0) );
>> >+
>> >+ const std::vector<RealType>& density = u.densities();
>> >+ VERIFY( density.size() == 6 );
>> >+ VERIFY( density[0] == RealType(0.0 / 8.0) );
>> >+ VERIFY( density[1] == RealType(1.0 / 8.0) );
>> >+ VERIFY( density[2] == RealType(1.0 / 8.0) );
>> >+ VERIFY( density[3] == RealType(6.0 / 8.0) );
>> >+ VERIFY( density[4] == RealType(-1.0 / 8.0) );
>> >+ VERIFY( density[5] == RealType(2.0 / 8.0) );
>> >+}
>> >+
>> >+template<typename RealType>
>> >+void
>> >+test_precision_depended()
>> >+{
>> >+ constexpr bool preserved
>> >+#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
>> >+ = true;
>> >+#else
>> >+ = sizeof(RealType) <= 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::piecewise_linear_distribution<RealType>
>> >+ u(std::begin(x), std::end(x), wt);
>> >+
>> >+ const std::vector<RealType>& interval = u.intervals();
>> >+ VERIFY( interval.size() == 3 );
>> >+ VERIFY( interval[0] == RealType(0.0) );
>> >+ VERIFY( interval[2] == RealType(1.0) );
>> >+
>> >+ const std::vector<RealType>& density = u.densities();
>> >+ 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)) );
>> >+}
>> >+
>> >+int main()
>> >+{
>> >+ using namespace __gnu_test;
>> >+ test_exact<float>();
>> >+ test_exact<double>();
>> >+ test_exact<long double>();
>> >+
>> >+ test_precision_depended<float>();
>> >+ test_precision_depended<double>();
>> >+ test_precision_depended<long double>();
>> >+
>> >+ return 0;
>> >+}
>> >diff --git
>> a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc
>> >new file mode 100644
>> >index 00000000000..469ed3fac46
>> >--- /dev/null
>> >+++
>> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc
>> >@@ -0,0 +1,5 @@
>> >+// { dg-options "-D_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES" }
>> >+// { dg-do run { target c++11 } }
>> >+// { dg-require-cstdint "" }
>> >+#include "accessors.cc"
>> >+
>> >--
>> >2.54.0
>> >
>> >
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260529/e04e4bbd/attachment-0001.htm>
More information about the Libstdc++
mailing list