On Fri, May 29, 2026 at 4:53 PM Jonathan Wakely <[email protected]> wrote:

> On Wed, 27 May 2026 at 08:42 +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.
> >
> >For user that can 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.
> >
> >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.
> >
> >Finally, to preserve current behavior, the operators>> load densities
> >as values of _StorageType.
> >
> >libstdc++-v3/ChangeLog:
> >
> >       * doc/xml/manual/using.xml
> >       (_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): 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, and mark as always_inline.
> >       (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.
> >---
> >v2:
> > - removes unused _StorageType alias from operator<<
> > - introduces __piecewise_distributions_storage_t alias,
> >   and changes commit description
> >(Sending due changes to commit description).
> >
> >Tested on x86_64-linux. OK for trunk?
> >
> > .../doc/html/manual/using_macros.html         |  11 ++
> > libstdc++-v3/doc/xml/manual/using.xml         |  17 +++
> > libstdc++-v3/include/bits/random.h            | 142 ++++++++++++------
> > libstdc++-v3/include/bits/random.tcc          |   8 +-
> > .../operators/accessors.cc                    |  73 +++++++++
> > .../operators/accessors_exact.cc              |   5 +
> > .../operators/accessors.cc                    |  75 +++++++++
> > .../operators/accessors_exact.cc              |   5 +
> > 8 files changed, 291 insertions(+), 45 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_linear_distribution/operators/accessors.cc
> > create mode 100644
> libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors_exact.cc
> >
> >diff --git a/libstdc++-v3/doc/html/manual/using_macros.html
> b/libstdc++-v3/doc/html/manual/using_macros.html
> >index f1d8492fb9e..ea32f065bea 100644
> >--- a/libstdc++-v3/doc/html/manual/using_macros.html
> >+++ b/libstdc++-v3/doc/html/manual/using_macros.html
> >@@ -156,4 +156,15 @@
> >       <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_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></span></dt><dd><p>
> >+      Undefined by default. When defined specializations of
> >+      <code class="code">piecewise_constant_distribution</code> and
> >+      <code class="code">piecewise_linear_distribution</code> for <code
> class="code">float</code> or
> >+      <code class="code">long double</code> <code
> class="code">result_type</code>, stores value of
> >+      densities (and other state) as <code
> class="code">result_type</code> (instead of
> >+      <code class="code">double</code>). This complete the resolution of
> library issue
> >+      <a class="link" href="https://cplusplus.github.io/LWG/issue1439";
> target="_top">
> >+      1449. Return from densities() functions?</a>, however makes their
> >+      representation ABI incompatible with one used by translation units
> >+      compiled without this flag, including older GCC releases.
> >       </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..d71dd13703b 100644
> >--- a/libstdc++-v3/doc/xml/manual/using.xml
> >+++ b/libstdc++-v3/doc/xml/manual/using.xml
> >@@ -1379,6 +1379,23 @@ 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_RESULT_TYPE_FOR_PIECEWISE_DENSITIES</code></term>
> >+    <listitem>
> >+      <para>
> >+      Undefined by default. When defined specializations of
> >+      <code>piecewise_constant_distribution</code> and
> >+      <code>piecewise_linear_distribution</code> for <code>float</code>
> or
> >+      <code>long double</code> <code>result_type</code>, stores value of
> >+      densities (and other state) as <code>result_type</code> (instead of
> >+      <code>double</code>). This complete the resolution of library issue
> >+      <link xmlns:xlink="http://www.w3.org/1999/xlink";
> >+      xlink:href="https://cplusplus.github.io/LWG/issue1439";>
> >+      1449. Return from densities() functions?</link>, however makes
> their
> >+      representation ABI incompatible with one used by translation units
> >+      compiled without this flag, including older GCC releases.
> >+      </para>
>
> Let's rephrase this as follows (and include the magic phrase
> "ABI-changing" which that page defines and uses for macros which
> affect the ABI:
>
> Undefined by default. ABI-changing.
> When defined, specializations of piecewise_constant_distribution and
> piecewise_linear_distribution with a result_type of either float or
> long double will manage their internal state using result_type values
> (instead of double). This is required for standard conformance, but is
> incompatible with the default implementation of those class templates.
>
>
> >+    </listitem></varlistentry>
> >+
> >     </variablelist>
> >
> >   </section>
> >diff --git a/libstdc++-v3/include/bits/random.h
> b/libstdc++-v3/include/bits/random.h
> >index a0592a00763..6016a56dc21 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
>
> Is this necessary?
>
> Users should only instantiate the <random> distributions with float,
> double, or long double. In any given translation unit, they should
> only refer to piecewise_linear_distribution<long double> and not
> piecewise_linear_distribution</* the other kind of long double */>.
>
> I suppose it's possible that they need to explicitly refer to
> piecewise_linear_distribution<__ibm128> for a class data member to
> ensure it has a stable definition in all TUs.
>
I was thinking about the internal uses in the library, where some
template being explicitly instantiated with __ibm128 or __int128
(like format does) will trigger instantiation of piecewise_distributions.
With the above, I do not need to concern myself with searching for such
situation, however unlikely it may be.


>
> >+    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,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> >           return _M_int;
> >       }
> >
> >-      std::vector<double>
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 1439. Return from densities() functions?
> >+      [[__gnu__::__abi_tag__("__rt")]]
> >+      std::vector<result_type>
>
> I wonder if the _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES macro
> should also control this, or a different macro. So that users who
> don't want the new return type can select the old one.
>
> Curently we have a macro to change the _M_den and _M_cp members, but
> no way to control the return type here. The abi_tag and always_inline
> attributes makes them distinct functions, but it would still be a
> source-breaking change for any code doing:
>
>    std::piecewise_constant_distribution<float> dist;
>    vector<double> d = dist.densities();
>
> Maybe that's OK?
>
> >       densities() const
> >-      { return _M_den.empty() ? std::vector<double>(1, 1.0) : _M_den; }
> >+      {
> >+#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
> >+      }
> >
> >       friend bool
> >       operator==(const param_type& __p1, const param_type& __p2)
> >@@ -6472,8 +6528,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 +6576,17 @@ _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.
> >        */
> >-      std::vector<double>
> >+      [[__gnu__::__always_inline__]]
> >+      std::vector<_RealType>
>
> You've changed vector<_RealType> to vector<result_type> elsewhere,
> should this be vector<result_type> too?
>
> >       densities() const
> >-      {
> >-      return _M_param._M_den.empty()
> >-        ? std::vector<double>(1, 1.0) : _M_param._M_den;
> >-      }
> >+      { return _M_param.densities(); }
> >
> >       /**
> >        * @brief Returns the parameter set of the distribution.
> >@@ -6695,6 +6740,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 +6773,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 +6786,28 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
> >           return _M_int;
> >       }
> >
> >-      std::vector<double>
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 1439. Return from densities() functions?
> >+      [[__gnu__::__abi_tag__("__rt")]]
> >+      std::vector<result_type>
> >       densities() const
> >-      { return _M_den.empty() ? std::vector<double>(2, 1.0) : _M_den; }
> >+      {
> >+#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
> >+      }
> >
> >       friend bool
> >       operator==(const param_type& __p1, const param_type& __p2)
> >@@ -6760,9 +6827,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 +6876,18 @@ _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.
> >        */
> >-      std::vector<double>
> >+      [[__gnu__::__always_inline__]]
> >+      std::vector<result_type>
> >       densities() const
> >-      {
> >-      return _M_param._M_den.empty()
> >-        ? std::vector<double>(2, 1.0) : _M_param._M_den;
> >-      }
> >+      { return _M_param.densities(); }
> >
> >       /**
> >        * @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..6d466d83cd5
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/operators/accessors.cc
> >@@ -0,0 +1,73 @@
> >+// { 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) );
> >+
> >+  const std::vector<RealType>& density = u.densities();
> >+  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) );
> >+
> >+  const std::vector<RealType>& density = u.densities();
> >+  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_linear_distribution/operators/accessors.cc
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> >new file mode 100644
> >index 00000000000..23d10696fdb
> >--- /dev/null
> >+++
> b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/operators/accessors.cc
> >@@ -0,0 +1,75 @@
> >+// { 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) );
> >+
> >+  const std::vector<RealType>& density = u.densities();
> >+  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) );
> >+
> >+  const std::vector<RealType>& density = u.densities();
> >+  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"
> >+
> >--
> >2.54.0
> >
> >
>
>

Reply via email to