[PATCH v2] libstdc++: Change piecewise distribution densities to return vector<result_type> [PR82749]

Jonathan Wakely jwakely@redhat.com
Mon Jul 13 17:23:40 GMT 2026


On Mon, 01 Jun 2026 at 09:21 +0200, Tomasz Kamiński wrote:
>This implements the interface changes from
>LWG1439, "Return from densities() functions?".
>
>Due the ABI concerns, we cannot change the the element_type of member
>(_M_den, _M_cp, and _M_m) vectors, and we convert the _M_den values
>to result_type when function is invoked. However, as the usage of
>distributions with types other than float, double, and long double
>is either undefined (pre C++26) or implementaiton-defined (post C++26),
>this limitation de-fact applies to float, and long double (if it's
>different size than double).
>
>To handle above we introduce the __piecewise_distributions_storage<_Tp>
>struct, whose type nested typedef points to double in above two cases,
>and _Tp otherwise. The _StorageType is defined in terms of
>__piecewise_distributions_storage_t alias to above, and is then used
>in defintion of _M_den, _M_cp, and _M_m members. In consequence for
>extended floating point types (__float128, std::float16, ...) for which
>ABI can be changed, we store densitiees (and other values) as result_type.
>
>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

The grammar seems garbled here, "the behaviour specializations of foo
and bar their behavior to the state prior to the implementation of
..."

Also, two different spellings of "behaviour". The manual pages usually
use the American spelling, "behavior" (there are a few places that
were probably written by me and use the British spelling).

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

Period at the end of the sentence.

>       </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")]]

I've been trying to think of a tag name that is a bit more
self-documenting that "rt" but I don't have a better suggestion.

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

Can this be simply return {_M_den.begin(), _M_den.end()} ?
That will convert from _StorageType to _RealType.

>+	    }
>+#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
>
>



More information about the Libstdc++ mailing list