On Fri, May 29, 2026 at 5:44 PM Tomasz Kaminski <[email protected]> wrote:
> > > On Fri, May 29, 2026 at 4:53 PM Jonathan Wakely <[email protected]> > 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 >> > >> > >> >>
