https://gcc.gnu.org/g:eae197924c7ecfe7073914e141941f582cc32828
commit r17-2391-geae197924c7ecfe7073914e141941f582cc32828 Author: Tomasz Kamiński <[email protected]> Date: Tue May 26 15:43:00 2026 +0200 libstdc++: Change piecewise distribution densities to return vector<result_type> [PR82749] 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. 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. To preserve current behavior, the operators>> load densities as values of _StorageType. Finally, we introduce _GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS, that revers above changes, restoring old behavior for all floating point types. Additionally for the users 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. PR libstdc++/82749 libstdc++-v3/ChangeLog: * doc/xml/manual/using.xml (_GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS): Add entry. (_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) [!_GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS]: 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, additional change return type and mark as always_inline if _GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS is not defined. (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. * testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_fallback.cc: Run accessors.cc with _GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS. * testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_fallback.cc: Likewise. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/doc/html/manual/using_macros.html | 19 +++ libstdc++-v3/doc/xml/manual/using.xml | 29 +++++ libstdc++-v3/include/bits/random.h | 145 +++++++++++++++------ libstdc++-v3/include/bits/random.tcc | 8 +- .../operators/accessors.cc | 83 ++++++++++++ .../operators/accessors_exact.cc | 5 + .../operators/accessors_fallback.cc | 5 + .../operators/accessors.cc | 85 ++++++++++++ .../operators/accessors_exact.cc | 5 + .../operators/accessors_fallback.cc | 5 + 10 files changed, 350 insertions(+), 39 deletions(-) diff --git a/libstdc++-v3/doc/html/manual/using_macros.html b/libstdc++-v3/doc/html/manual/using_macros.html index f1d8492fb9ef..10cf46436796 100644 --- a/libstdc++-v3/doc/html/manual/using_macros.html +++ b/libstdc++-v3/doc/html/manual/using_macros.html @@ -156,4 +156,23 @@ <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_OLD_PIECEWISE_DISTRIBUTIONS</code></span></dt><dd><p> + Undefined by default. + When defined, the behavior of specializations of + <code class="code">piecewise_constant_distribution</code> and + <code class="code">piecewise_linear_distribution</code> + 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>) in GCC 17. + </p></dd><dt><span class="term"><code class="code">_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></span></dt><dd><p> + Undefined by default. ABI-changing. + When defined, specializations of + <code class="code">piecewise_constant_distribution</code> and + <code class="code">piecewise_linear_distribution</code> with a + <code class="code">result_type</code> of either <code class="code">float</code> or + <code class="code">long double</code> will manage their internal state using + <code class="code">result_type</code> values (instead of <code class="code">double</code>). + This is required for standard conformance, but is incompatible with + the default implementation of those class templates. </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 e2e75e8fe28c..a34b8ff484a0 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1379,6 +1379,35 @@ 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_OLD_PIECEWISE_DISTRIBUTIONS</code></term> + <listitem> + <para> + Undefined by default. + When defined, the behavior of specializations of + <code>piecewise_constant_distribution</code> and + <code>piecewise_linear_distribution</code> + is restored to their state prior the implementation + of <link xmlns:xlink="http://www.w3.org/1999/xlink" + 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>) in GCC 17. + </para> + </listitem></varlistentry> + <varlistentry><term><code>_GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></term> + <listitem> + <para> + Undefined by default. ABI-changing. + When defined, specializations of + <code>piecewise_constant_distribution</code> and + <code>piecewise_linear_distribution</code> with a + <code>result_type</code> of either <code>float</code> or + <code>long double</code> will manage their internal state using + <code>result_type</code> values (instead of <code>double</code>). + This is required for standard conformance, but is incompatible with + the default implementation of those class templates. + </para> + </listitem></varlistentry> </variablelist> </section> diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index fd7b8b4fb202..c219930cc29f 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -6409,6 +6409,43 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { return !(__d1 == __d2); } #endif + namespace __detail + { +#if defined(_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS) + template<typename _Tp> + using __piecewise_distributions_storage_t = double; +#elif defined(_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 + 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. * @@ -6431,6 +6468,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; @@ -6461,7 +6501,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()) @@ -6474,9 +6514,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return _M_int; } +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS std::vector<double> densities() const { return _M_den.empty() ? std::vector<double>(1, 1.0) : _M_den; } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1439. Return from densities() functions? + [[__gnu__::__abi_tag__("__rt")]] + std::vector<result_type> + densities() const + { +#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 + return std::vector<_RealType>(_M_den.begin(), _M_den.end()); +#pragma GCC diagnostic pop + } +#endif friend bool operator==(const param_type& __p1, const param_type& __p2) @@ -6496,8 +6555,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>& @@ -6544,28 +6603,23 @@ _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. */ +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS std::vector<double> densities() const - { - return _M_param._M_den.empty() - ? std::vector<double>(1, 1.0) : _M_param._M_den; - } + { return _M_param.densities(); } +#else + [[__gnu__::__always_inline__]] + std::vector<result_type> + densities() const + { return _M_param.densities(); } +#endif /** * @brief Returns the parameter set of the distribution. @@ -6719,6 +6773,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; @@ -6749,7 +6806,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()) @@ -6762,9 +6819,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return _M_int; } +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS std::vector<double> densities() const { return _M_den.empty() ? std::vector<double>(2, 1.0) : _M_den; } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1439. Return from densities() functions? + [[__gnu__::__abi_tag__("__rt")]] + std::vector<result_type> + densities() const + { +#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 + return std::vector<_RealType>(_M_den.begin(), _M_den.end()); +#pragma GCC diagnostic pop + } +#endif friend bool operator==(const param_type& __p1, const param_type& __p2) @@ -6784,9 +6860,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>& @@ -6833,29 +6909,24 @@ _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. */ +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS std::vector<double> densities() const - { - return _M_param._M_den.empty() - ? std::vector<double>(2, 1.0) : _M_param._M_den; - } + { return _M_param.densities(); } +#else + [[__gnu__::__always_inline__]] + std::vector<result_type> + densities() const + { return _M_param.densities(); } +#endif /** * @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 a8fab79961d7..12c891fbbafd 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 000000000000..db4193847e3e --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc @@ -0,0 +1,83 @@ +// { 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) ); + +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS + const std::vector<double>& density = u.densities(); +#else + const std::vector<RealType>& density = u.densities(); +#endif + + 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) ); + +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS + const std::vector<double>& density = u.densities(); +#else + const std::vector<RealType>& density = u.densities(); +#endif + + 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 000000000000..469ed3fac469 --- /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_constant_distribution/operators/accessors_fallback.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_fallback.cc new file mode 100644 index 000000000000..1f7269a879cd --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors_fallback.cc @@ -0,0 +1,5 @@ +// { dg-options "-D_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS" } +// { 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 000000000000..0a13e0fd9e21 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc @@ -0,0 +1,85 @@ +// { 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) ); + +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS + const std::vector<double>& density = u.densities(); +#else + const std::vector<RealType>& density = u.densities(); +#endif + + 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) ); + +#ifdef _GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS + const std::vector<double>& density = u.densities(); +#else + const std::vector<RealType>& density = u.densities(); +#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)) ); +} + +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 000000000000..469ed3fac469 --- /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" + diff --git a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_fallback.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_fallback.cc new file mode 100644 index 000000000000..1f7269a879cd --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_fallback.cc @@ -0,0 +1,5 @@ +// { dg-options "-D_GLIBCXX_USE_OLD_PIECEWISE_DISTRIBUTIONS" } +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } +#include "accessors.cc" +
