On Tue, May 26, 2026 at 5:09 PM Tomasz Kamiński <[email protected]> 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>
> alias, whose type nested typedef points to double in above two cases,
> and _Tp otherwise. This alias is used to define _StorageType nested
> type, that 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
> _StorageType being unconditionally defined as _RealType (result_type),
> 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)
>         (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.
> ---
> The commit description is pretty long, but the change are
> are not really. Handling extra define to force usage of
> correct result type was trivial, so I have added it.
>
> Testing on x86_64-linux. All *piecewise* test passed,
> including serializaiton one.
> OK for trunk when all test passes?
>
>  .../doc/html/manual/using_macros.html         |  11 ++
>  libstdc++-v3/doc/xml/manual/using.xml         |  17 +++
>  libstdc++-v3/include/bits/random.h            | 141 ++++++++++++------
>  libstdc++-v3/include/bits/random.tcc          |  10 +-
>  .../operators/accessors.cc                    |  73 +++++++++
>  .../operators/accessors_exact.cc              |   5 +
>  .../operators/accessors.cc                    |  75 ++++++++++
>  .../operators/accessors_exact.cc              |   5 +
>  8 files changed, 292 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>
> +    </listitem></varlistentry>
> +
>      </variablelist>
>
>    </section>
> diff --git a/libstdc++-v3/include/bits/random.h
> b/libstdc++-v3/include/bits/random.h
> index a0592a00763..05cdb44ff95 100644
> --- a/libstdc++-v3/include/bits/random.h
> +++ b/libstdc++-v3/include/bits/random.h
> @@ -6385,6 +6385,33 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      { return !(__d1 == __d2); }
>  #endif
>
> +#ifndef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> +  namespace __detail
> +  {
> +    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
> +  }
> +#endif // _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> +
>    /**
>     * @brief A piecewise_constant_distribution random number distribution.
>     *
> @@ -6406,6 +6433,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      {
>        static_assert(std::is_floating_point<_RealType>::value,
>                     "result_type must be a floating point type");
> +      using _StorageType
> +#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> +       = _RealType;
> +#else
> +       = typename
> __detail::__piecewise_distributions_storage<_RealType>::type;
> +#endif
>
I think it would be better to
introduce  __detail::__piecewise_distributions_storage_t alias
defined as follows, and keep the logic in one place:
   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; };
@@ -6409,8 +6412,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       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
+  }

Done the change above locally:


>      public:
>        /** The type of the range of the distribution. */
> @@ -6437,7 +6470,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 +6483,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>(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 +6524,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 +6572,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>
>        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.
> @@ -6694,6 +6735,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      {
>        static_assert(std::is_floating_point<_RealType>::value,
>                     "result_type must be a floating point type");
> +      using _StorageType
> +#ifdef _GLIBCXX_USE_RESULT_TYPE_FOR_PIECEWISE_DENSITIES
> +       = _RealType;
> +#else
> +       = typename
> __detail::__piecewise_distributions_storage<_RealType>::type;
> +#endif
>
>      public:
>        /** The type of the range of the distribution. */
> @@ -6725,7 +6772,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 +6785,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 +6826,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 +6875,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..f0e2a0d5849 100644
> --- a/libstdc++-v3/include/bits/random.tcc
> +++ b/libstdc++-v3/include/bits/random.tcc
> @@ -3164,6 +3164,8 @@ namespace __detail
>                const piecewise_constant_distribution<_RealType>& __x)
>      {
>        using __ios_base = typename basic_ostream<_CharT,
> _Traits>::ios_base;
> +      using _StorageType
> +       = typename
> piecewise_constant_distribution<_RealType>::_StorageType;
>
>        const typename __ios_base::fmtflags __flags = __os.flags();
>        const _CharT __fill = __os.fill();
> @@ -3199,6 +3201,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 +3213,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 +3470,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 +3482,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