[gcc r17-2391] libstdc++: Change piecewise distribution densities to return vector<result_type> [PR82749]

Tomasz Kaminski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <20260714091948.5724E4BA540B__14618.6778599926$1784020796$gmane$org@sourceware.org>
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"
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.