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.
>
> >+    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?
>
That's what PR was about. Note that this macro does not revert the change,
Specifically, it does not affect floating-point types other than float or
long double.
It pushes further by including ABI changes in addition to API changes.

If we want to revert the interface change, we should create a separate
macro,
to revert interface change.


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