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.
libstdc++ PR/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.
---
v2 adds also _GLIBCXX_USE_OLD_PICEWISE_DISTRIBUTIONS, that
reverts the changes. I plan to use it for all changes made
to this distributions in GCC-17.
Additionally
* updates and add PR link to commit description
* add accessorrs_fallback.cc tests
* use result_type in return consistently on new path
Resated *piecewise* test. Testing on x86_64-linux.
OK for trunk?
.../doc/html/manual/using_macros.html | 19 +++
libstdc++-v3/doc/xml/manual/using.xml | 29 ++++
libstdc++-v3/include/bits/random.h | 154 +++++++++++++-----
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, 359 insertions(+), 39 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_constant_distribution/operators/accessors_fallback.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
create mode 100644
libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_fallback.cc
diff --git a/libstdc++-v3/doc/html/manual/using_macros.html
b/libstdc++-v3/doc/html/manual/using_macros.html
index f1d8492fb9e..4be2ab576dc 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_PICEWISE_DISTRIBUTIONS</code></span></dt><dd><p>
+ Undefined by default.
+ When defined, the behaviour specializations of
+ <code class="code">piecewise_constant_distribution</code> and
+ <code class="code">piecewise_linear_distribution</code> for
+ their behavior to the 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 e2e75e8fe28..1759eb5a214 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_PICEWISE_DISTRIBUTIONS</code></term>
+ <listitem>
+ <para>
+ Undefined by default.
+ When defined, the behaviour specializations of
+ <code>piecewise_constant_distribution</code> and
+ <code>piecewise_linear_distribution</code> for
+ their behavior to the 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 a0592a00763..6b82d1120b7 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
+ 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,34 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
return _M_int;
}
+#ifdef _GLIBCXX_USE_OLD_PICEWISE_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
+ {
+ std::vector<_RealType> __res;
+ __res.reserve(_M_den.size());
+ for (_RealType __v : _M_den)
+ __res.push_back(__v);
+ return __res;
+ }
+#pragma GCC diagnostic pop
+ }
+#endif
friend bool
operator==(const param_type& __p1, const param_type& __p2)
@@ -6472,8 +6534,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 +6582,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_PICEWISE_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.
@@ -6695,6 +6752,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 +6785,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 +6798,34 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
return _M_int;
}
+#ifdef _GLIBCXX_USE_OLD_PICEWISE_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
+ {
+ std::vector<_RealType> __res;
+ __res.reserve(_M_den.size());
+ for (_RealType __v : _M_den)
+ __res.push_back(__v);
+ return __res;
+ }
+#pragma GCC diagnostic pop
+ }
+#endif
friend bool
operator==(const param_type& __p1, const param_type& __p2)
@@ -6760,9 +6845,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 +6894,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_PICEWISE_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 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..219d1949040
--- /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_PICEWISE_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_PICEWISE_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 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_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 00000000000..3e2fbf03430
--- /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_PICEWISE_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 00000000000..d3855ee0291
--- /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_PICEWISE_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_PICEWISE_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 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"
+
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 00000000000..3e2fbf03430
--- /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_PICEWISE_DISTRIBUTIONS" }
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+#include "accessors.cc"
+
--
2.54.0