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

Tomasz Kaminski tkaminsk@gcc.gnu.org
Tue Jul 14 09:19:48 GMT 2026


https://gcc.gnu.org/g:eae197924c7ecfe7073914e141941f582cc32828

commit r17-2391-geae197924c7ecfe7073914e141941f582cc32828
Author: Tomasz Kamiński <tkaminsk@redhat.com>
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 <jwakely@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

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"
+


More information about the Libstdc++-cvs mailing list