https://gcc.gnu.org/g:7bed7d9276c11bef5a9a214e20c985af713f1532

commit r17-509-g7bed7d9276c11bef5a9a214e20c985af713f1532
Author: Tomasz Kamiński <[email protected]>
Date:   Wed May 13 17:05:05 2026 +0200

    libstdc++: Fix reserve of size_t(-1) elements in 
piecewise_constant_distribution. [PR113761]
    
    The piecewise_constant_distribution constructor from std::initializer_list 
il,
    unconditionally reserve _M_den for il.size()-1 elements. In case when the 
il.size()
    was zero, this led to unsigned overflow, and attempt to allocate size_t(-1)
    elements.
    
    This patch addresses above, by refactoring the constructors of param_type 
for
    both piecewise_constant_distribution and piecewise_linear_distribution, to
    exit early (and do not populate internal vectors) if number of intervals 
range is
    smaller than two. For the constructor accepting pair of iterators, this is 
done
    by checking result of __detail::__load_first2, that extracts up to two 
elements,
    and returns false, if less than two is found.
    
    Furthermore, we if the number of intervals is equal to two (for iterator 
__bbegin
    is at __bend after __load_first2), we store densities value on stack, and 
call
    newly introduced an _M_initialize2 helper, that does not populate internal 
vector
    if __ints and __dens values correspond to default configuration.
    
    With both of above changes, we no longer populate _M_int and _M_den with 
default
    values, and corresponding code that clears them in _M_initialize is not 
necessary.
    This avoids any unnecessary memory allocators.
    
    For constructor accepting two iterators, we reserve required space in 
_M_int vector,
    if the iterators are forward (or model sized_sentinel in C++20). The _M_den
    initialization is performed afterwards, so _M_int size is already determined
    (even for input iterators) and it can be used for call to reserve.
    
    Finally, the _M_initialize members are renamed to _M_configure, so the new
    implementation that skips the check, is not used by TU compiler will other
    that would invoke it with empty vector, and thus retrigger the issue.
    
            PR libstdc++/113761
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/random.h
            (piecewise_constant_distribution::param_type::_M_initialize)
            (piecewise_linear_distribution::param_type::_M_initialize): Remove.
            (piecewise_constant_distribution::param_type::_M_configure)
            (piecewise_linear_distribution::param_type::_M_configure): Define.
            (piecewise_constant_distribution::param_type::_M_initialize2)
            (piecewise_linear_distribution::param_type::_M_initialize2): 
Declare.
            * include/bits/random.tcc (__detail::__load_first2): Define.
            (piecewise_constant_distribution::param_type::_M_initialize)
            (piecewise_linear_distribution::param_type::_M_initialize):
            Rename to...
            (piecewise_constant_distribution::param_type::_M_configure)
            (piecewise_linear_distribution::param_type::_M_configure):
            Renamed implementation of _M_initialize, that removes checks for
            default values.
            (piecewise_constant_distribution::param_type::_M_initialize2)
            (piecewise_linear_distribution::param_type::_M_initialize2): Define.
            (piecewise_constant_distribution::param_type::param_type)
            (piecewise_linear_distribution::param_type::param_type):
            Exit early for less that two intervals. Use _M_initialize2 to handle
            two intervals case. Reserve _M_int for iterators case.
            * 
testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc:
            Test input and forward iterators, in addition to random_access ones.
            * 
testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc:
            Likewise.
            * 
testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc:
            New test.
            * 
testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc:
            New test.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 libstdc++-v3/include/bits/random.h                 |  10 +-
 libstdc++-v3/include/bits/random.tcc               | 224 ++++++++++++++++-----
 .../cons/fallback.cc                               | 108 ++++++++++
 .../piecewise_constant_distribution/cons/range.cc  |  17 +-
 .../piecewise_linear_distribution/cons/fallback.cc | 127 ++++++++++++
 .../piecewise_linear_distribution/cons/range.cc    |  17 +-
 6 files changed, 439 insertions(+), 64 deletions(-)

diff --git a/libstdc++-v3/include/bits/random.h 
b/libstdc++-v3/include/bits/random.h
index 3fda69c4399a..5d037465d3cf 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -6466,7 +6466,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       private:
        void
-       _M_initialize();
+       _M_configure();
+
+       void
+       _M_initialize2(const _RealType* __ints, _RealType __den);
 
        std::vector<_RealType> _M_int;
        std::vector<double> _M_den;
@@ -6746,7 +6749,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       private:
        void
-       _M_initialize();
+       _M_configure();
+
+       void
+       _M_initialize2(const _RealType* __ints, const _RealType* __dens);
 
        std::vector<_RealType> _M_int;
        std::vector<double> _M_den;
diff --git a/libstdc++-v3/include/bits/random.tcc 
b/libstdc++-v3/include/bits/random.tcc
index 4475e365c2d7..80b51d099fad 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -2945,18 +2945,8 @@ namespace __detail
   template<typename _RealType>
     void
     piecewise_constant_distribution<_RealType>::param_type::
-    _M_initialize()
+    _M_configure()
     {
-      if (_M_int.size() < 2
-         || (_M_int.size() == 2
-             && _M_int[0] == _RealType(0)
-             && _M_int[1] == _RealType(1)))
-       {
-         _M_int.clear();
-         _M_den.clear();
-         return;
-       }
-
       const double __sum = std::accumulate(_M_den.begin(),
                                           _M_den.end(), 0.0);
       __glibcxx_assert(__sum > 0);
@@ -2975,6 +2965,46 @@ namespace __detail
        _M_den[__k] /= _M_int[__k + 1] - _M_int[__k];
     }
 
+  template<typename _RealType>
+    void
+    piecewise_constant_distribution<_RealType>::param_type::
+    _M_initialize2(const _RealType* __ints, _RealType __den)
+    {
+      if (__ints[0] == _RealType(0) && __ints[1] == _RealType(1))
+       return;
+
+      _M_int.reserve(2);
+      _M_int.push_back(__ints[0]);
+      _M_int.push_back(__ints[1]);
+
+      _M_den.reserve(1);
+      _M_den.push_back(__den);
+      _M_configure();
+    }
+
+namespace __detail
+{
+  template<typename _InputIterator, typename _RealType>
+    bool
+    __load_first2(_InputIterator& __first, _InputIterator __last,
+                 _RealType* __out)
+    {
+      if (__first == __last)
+       return false;
+
+      *__out = *__first;
+      ++__first;
+      if (__first == __last)
+       return false;
+
+      ++__out;
+      *__out = *__first;
+      ++__first;
+      return true;
+    }
+} // namespace __detail
+
+
   template<typename _RealType>
     template<typename _InputIteratorB, typename _InputIteratorW>
       piecewise_constant_distribution<_RealType>::param_type::
@@ -2983,21 +3013,39 @@ namespace __detail
                 _InputIteratorW __wbegin)
       : _M_int(), _M_den(), _M_cp()
       {
-       if (__bbegin != __bend)
-         {
-           for (;;)
-             {
-               _M_int.push_back(*__bbegin);
-               ++__bbegin;
-               if (__bbegin == __bend)
-                 break;
+       _RealType __ints[2];
+       if (!__detail::__load_first2(__bbegin, __bend, __ints))
+         return;
 
-               _M_den.push_back(*__wbegin);
-               ++__wbegin;
-             }
+       if (__bbegin == __bend)
+         {
+           _M_initialize2(__ints, *__wbegin);
+           return;
          }
 
-       _M_initialize();
+#if __glibcxx_concepts // C++ >= C++20
+       if constexpr (sized_sentinel_for<_InputIteratorB, _InputIteratorB>
+                       || forward_iterator<_InputIteratorB>)
+         _M_int.reserve(2 + size_t(ranges::distance(__bbegin, __bend)));
+#else
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+       if constexpr (is_convertible<__iter_category_t<_InputIteratorB>,
+                                    forward_iterator_tag>::value)
+         _M_int.reserve(2 + size_t(std::distance(__bbegin, __bend)));
+#pragma GCC diagnostic pop
+#endif
+
+       _M_int.push_back(__ints[0]);
+       _M_int.push_back(__ints[1]);
+       for (; __bbegin != __bend; ++__bbegin)
+         _M_int.push_back(*__bbegin);
+
+       _M_den.reserve(_M_int.size() - 1);
+       for (size_t __k = 0; __k < _M_int.size() - 1; (void)++__k, ++__wbegin)
+         _M_den.push_back(*__wbegin);
+
+       _M_configure();
       }
 
   template<typename _RealType>
@@ -3006,15 +3054,23 @@ namespace __detail
       param_type(initializer_list<_RealType> __bl, _Func __fw)
       : _M_int(), _M_den(), _M_cp()
       {
-       _M_int.reserve(__bl.size());
-       for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter)
-         _M_int.push_back(*__biter);
+       if (__bl.size() < 2)
+         return;
 
+       if (__bl.size() == 2)
+         {
+           const _RealType *__ints = __bl.begin();
+           _RealType __den = __fw(0.5 * (__ints[1] + __ints[0]));
+           _M_initialize2(__ints, __den);
+           return;
+         }
+
+       _M_int = __bl;
        _M_den.reserve(_M_int.size() - 1);
        for (size_t __k = 0; __k < _M_int.size() - 1; ++__k)
          _M_den.push_back(__fw(0.5 * (_M_int[__k + 1] + _M_int[__k])));
 
-       _M_initialize();
+       _M_configure();
       }
 
   template<typename _RealType>
@@ -3025,6 +3081,13 @@ namespace __detail
       {
        const size_t __n = __nw == 0 ? 1 : __nw;
        const _RealType __delta = (__xmax - __xmin) / __n;
+       if (__n == 1)
+         {
+           _RealType __ints[2] = { __xmin, __xmin + __delta };
+           _RealType __den = __fw(__xmin * 0.5 * __delta);
+           _M_initialize2(__ints, __den);
+           return;
+         }
 
        _M_int.reserve(__n + 1);
        for (size_t __k = 0; __k <= __nw; ++__k)
@@ -3034,7 +3097,7 @@ namespace __detail
        for (size_t __k = 0; __k < __nw; ++__k)
          _M_den.push_back(__fw(_M_int[__k] + 0.5 * __delta));
 
-       _M_initialize();
+       _M_configure();
       }
 
   template<typename _RealType>
@@ -3159,19 +3222,8 @@ namespace __detail
   template<typename _RealType>
     void
     piecewise_linear_distribution<_RealType>::param_type::
-    _M_initialize()
+    _M_configure()
     {
-      if (_M_int.size() < 2
-         || (_M_int.size() == 2
-             && _M_int[0] == _RealType(0)
-             && _M_int[1] == _RealType(1)
-             && _M_den[0] == _M_den[1]))
-       {
-         _M_int.clear();
-         _M_den.clear();
-         return;
-       }
-
       double __sum = 0.0;
       _M_cp.reserve(_M_int.size() - 1);
       _M_m.reserve(_M_int.size() - 1);
@@ -3194,7 +3246,27 @@ namespace __detail
 
       //  Make sure the last cumulative probablility is one.
       _M_cp[_M_cp.size() - 1] = 1.0;
-     }
+    }
+
+  template<typename _RealType>
+    void
+    piecewise_linear_distribution<_RealType>::param_type::
+    _M_initialize2(const _RealType* __ints, const _RealType* __dens)
+    {
+      if (__ints[0] == _RealType(0)
+         && __ints[1] == _RealType(1)
+         && __dens[0] == __dens[1])
+       return;
+
+      _M_int.reserve(2);
+      _M_int.push_back(__ints[0]);
+      _M_int.push_back(__ints[1]);
+
+      _M_den.reserve(2);
+      _M_den.push_back(__dens[0]);
+      _M_den.push_back(__dens[1]);
+      _M_configure();
+    }
 
   template<typename _RealType>
     template<typename _InputIteratorB, typename _InputIteratorW>
@@ -3204,13 +3276,43 @@ namespace __detail
                 _InputIteratorW __wbegin)
       : _M_int(), _M_den(), _M_cp(), _M_m()
       {
-       for (; __bbegin != __bend; ++__bbegin, (void) ++__wbegin)
+       _RealType __ints[2];
+       if (!__detail::__load_first2(__bbegin, __bend, __ints))
+         return;
+
+       if (__bbegin == __bend)
          {
-           _M_int.push_back(*__bbegin);
-           _M_den.push_back(*__wbegin);
+           _RealType __dens[2];
+           __dens[0] = *__wbegin;
+           ++__wbegin;
+           __dens[1] = *__wbegin;
+           _M_initialize2(__ints, __dens);
+           return;
          }
 
-       _M_initialize();
+#if __glibcxx_concepts // C++ >= C++20
+       if constexpr (sized_sentinel_for<_InputIteratorB, _InputIteratorB>
+                       || forward_iterator<_InputIteratorB>)
+         _M_int.reserve(2 + size_t(ranges::distance(__bbegin, __bend)));
+#else
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
+       if constexpr (is_convertible<__iter_category_t<_InputIteratorB>,
+                                    forward_iterator_tag>::value)
+         _M_int.reserve(2 + size_t(std::distance(__bbegin, __bend)));
+#pragma GCC diagnostic pop
+#endif
+
+       _M_int.push_back(__ints[0]);
+       _M_int.push_back(__ints[1]);
+       for (; __bbegin != __bend; ++__bbegin)
+         _M_int.push_back(*__bbegin);
+
+       _M_den.reserve(_M_int.size());
+       for (size_t __i = 0; __i < _M_int.size(); (void)++__i, ++__wbegin)
+         _M_den.push_back(*__wbegin);
+
+       _M_configure();
       }
 
   template<typename _RealType>
@@ -3219,15 +3321,24 @@ namespace __detail
       param_type(initializer_list<_RealType> __bl, _Func __fw)
       : _M_int(), _M_den(), _M_cp(), _M_m()
       {
-       _M_int.reserve(__bl.size());
-       _M_den.reserve(__bl.size());
-       for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter)
+       if (__bl.size() < 2)
+         return;
+
+       if (__bl.size() == 2)
          {
-           _M_int.push_back(*__biter);
-           _M_den.push_back(__fw(*__biter));
+           const _RealType *__ints = __bl.begin();
+           _RealType __den[2];
+           __den[0] = __fw(__ints[0]);
+           __den[1] = __fw(__ints[1]);
+           _M_initialize2(__ints, __den);
+           return;
          }
 
-       _M_initialize();
+       _M_int = __bl;
+       _M_den.reserve(__bl.size());
+       for (_RealType __b : __bl)
+         _M_den.push_back(__fw(__b));
+       _M_configure();
       }
 
   template<typename _RealType>
@@ -3238,6 +3349,15 @@ namespace __detail
       {
        const size_t __n = __nw == 0 ? 1 : __nw;
        const _RealType __delta = (__xmax - __xmin) / __n;
+       if (__n == 1)
+         {
+           _RealType __ints[2] = { __xmin, __xmin + __delta };
+           _RealType __dens[2];
+           __dens[0] = __fw(__ints[0]);
+           __dens[1] = __fw(__ints[1]);
+           _M_initialize2(__ints, __dens);
+           return;
+         }
 
        _M_int.reserve(__n + 1);
        _M_den.reserve(__n + 1);
@@ -3247,7 +3367,7 @@ namespace __detail
            _M_den.push_back(__fw(_M_int[__k] + __delta));
          }
 
-       _M_initialize();
+       _M_configure();
       }
 
   template<typename _RealType>
diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc
new file mode 100644
index 000000000000..f10f5ca2a786
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc
@@ -0,0 +1,108 @@
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using dist = std::piecewise_linear_distribution<>;
+
+template<typename... Args>
+bool
+is_default(Args&&... args)
+{
+  std::piecewise_constant_distribution<> u(std::forward<Args>(args)...);
+
+  std::vector<double> ints = u.intervals();
+  if (ints.size() != 2 || ints[0] != 0.0 || ints[1] != 1.0)
+    return false;
+
+  std::vector<double> dens = u.densities();
+  if (dens.size() != 1 || dens[0] != 1.0)
+    return false;
+
+  return true;
+}
+
+template<template<typename> class Range>
+void
+test_it_pair()
+{
+  double wt[2];
+  double x[3];
+
+  Range<double> r0(x, x);
+  VERIFY( is_default(r0.begin(), r0.end(), wt) );
+
+  x[0] = 4.2;
+  Range<double> r1a(x, x+1);
+  VERIFY( is_default(r1a.begin(), r1a.end(), wt) );
+
+  x[0] = 0.0;
+  Range<double> r1b(x, x+1);
+  VERIFY( is_default(r1b.begin(), r1b.end(), wt) );
+
+  x[1] = 1.0;
+  wt[0] = 13.0;
+  Range<double> r2a(x, x+2);
+  VERIFY( is_default(r2a.begin(), r2a.end(), wt) );
+
+  wt[0] = 4.2;
+  Range<double> r2b(x, x+2);
+  VERIFY( is_default(r2b.begin(), r2b.end(), wt) );
+
+  x[1] = 0.5;
+  Range<double> r2c(x, x+2);
+  VERIFY( !is_default(r2c.begin(), r2c.end(), wt) );
+
+  x[2] = 1.0;
+  wt[1] = 2.0;
+  Range<double> r3(x, x+3);
+  VERIFY( !is_default(r3.begin(), r3.end(), wt) );
+}
+
+void test_init_list()
+{
+  auto c = [](double x) { return 10; };
+  VERIFY(  is_default(std::initializer_list<double>{}, c) );
+  VERIFY(  is_default(std::initializer_list<double>{4.2}, c) );
+  VERIFY(  is_default(std::initializer_list<double>{0.0, 1.0}, c) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5}, c) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5, 1.0}, c) );
+
+  auto rel = [](double x) { return x + 10; };
+  VERIFY(  is_default(std::initializer_list<double>{}, rel) );
+  VERIFY(  is_default(std::initializer_list<double>{4.2}, rel) );
+  VERIFY(  is_default(std::initializer_list<double>{0.0, 1.0}, rel) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5}, rel) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5, 1.0}, rel) );
+}
+
+void test_xbound()
+{
+  auto c = [](double x) { return 10; };
+  VERIFY(  is_default(0, 0.0, 1.0, c) );
+  VERIFY( !is_default(0, 0.0, 0.5, c) );
+  VERIFY(  is_default(1, 0.0, 1.0, c) );
+  VERIFY( !is_default(1, 0.0, 0.5, c) );
+  VERIFY( !is_default(2, 0.0, 1.0, c) );
+
+  auto rel = [](double x) { return x + 10; };
+  VERIFY(  is_default(0, 0.0, 1.0, rel) );
+  VERIFY( !is_default(0, 0.0, 0.5, rel) );
+  VERIFY(  is_default(1, 0.0, 1.0, rel) );
+  VERIFY( !is_default(1, 0.0, 0.5, rel) );
+  VERIFY( !is_default(2, 0.0, 1.0, rel) );
+}
+
+int main()
+{
+  using namespace __gnu_test;
+  test_it_pair<input_container>();
+  test_it_pair<forward_container>();
+  test_it_pair<random_access_container>();
+
+  test_init_list();
+  test_xbound();
+  return 0;
+}
diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc
index 3714e460391b..4bfa20ea3bbc 100644
--- 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc
@@ -25,13 +25,17 @@
 
 #include <random>
 #include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
 
+template<template<typename> class Range>
 void
-test01()
+test_it_pair()
 {
-  std::vector<double> x = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
-  std::vector<double> wt = {0.5, 1.0, 2.5, 1.5, 0.5};
-  std::piecewise_constant_distribution<> u(x.begin(), x.end(), wt.begin());
+  double x[6] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
+  double wt[5] = {0.5, 1.0, 2.5, 1.5, 0.5};
+
+  Range<double> r(x, x+6);
+  std::piecewise_constant_distribution<> u(r.begin(), r.end(), wt);
   std::vector<double> interval = u.intervals();
   std::vector<double> density = u.densities();
   VERIFY( interval.size() == 6 );
@@ -44,6 +48,9 @@ test01()
 
 int main()
 {
-  test01();
+  using namespace __gnu_test;
+  test_it_pair<input_container>();
+  test_it_pair<forward_container>();
+  test_it_pair<random_access_container>();
   return 0;
 }
diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc
new file mode 100644
index 000000000000..b2e6ca651231
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc
@@ -0,0 +1,127 @@
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using dist = std::piecewise_linear_distribution<>;
+
+template<typename... Args>
+bool
+is_default(Args&&... args)
+{
+  std::piecewise_linear_distribution<> u(std::forward<Args>(args)...);
+
+  std::vector<double> ints = u.intervals();
+  if (ints.size() != 2 || ints[0] != 0.0 || ints[1] != 1.0)
+    return false;
+
+  std::vector<double> dens = u.densities();
+  if (dens.size() != 2 || dens[0] != 1.0 || dens[1] != 1.0)
+    return false;
+
+  return true;
+}
+
+template<template<typename> class Range>
+void
+test_it_pair()
+{
+  double wt[3];
+  double x[3];
+
+  Range<double> r0(x, x);
+  VERIFY( is_default(r0.begin(), r0.end(), wt) );
+
+  x[0] = 4.2;
+  Range<double> r1a(x, x+1);
+  VERIFY( is_default(r1a.begin(), r1a.end(), wt) );
+
+  x[0] = 0.0;
+  Range<double> r1b(x, x+1);
+  VERIFY( is_default(r1b.begin(), r1b.end(), wt) );
+
+  x[1] = 1.0;
+  wt[0] = wt[1] = 13.0;
+  Range<double> r2a(x, x+2);
+  VERIFY( is_default(r2a.begin(), r2a.end(), wt) );
+
+  wt[0] = wt[1] = 1.0;
+  Range<double> r2b(x, x+2);
+  VERIFY( is_default(r2b.begin(), r2b.end(), wt) );
+
+  wt[1] = 2.0;
+  Range<double> r2c(x, x+2);
+  VERIFY( !is_default(r2c.begin(), r2c.end(), wt) );
+
+  x[1] = 0.5;
+  wt[0] = wt[1] = 2.0;
+  Range<double> r2d(x, x+2);
+  VERIFY( !is_default(r2d.begin(), r2d.end(), wt) );
+
+  x[2] = 1.0;
+  wt[2] = wt[0];
+  Range<double> r3(x, x+3);
+  VERIFY( !is_default(r3.begin(), r3.end(), wt) );
+}
+
+void test_init_list()
+{
+  auto c1 = [](double x) { return 1.0; };
+  VERIFY(  is_default(std::initializer_list<double>{}, c1) );
+  VERIFY(  is_default(std::initializer_list<double>{4.2}, c1) );
+  VERIFY(  is_default(std::initializer_list<double>{0.0, 1.0}, c1) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5}, c1) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5, 1.0}, c1) );
+
+  auto c2 = [](double x) { return 4.2; };
+  VERIFY(  is_default(std::initializer_list<double>{}, c2) );
+  VERIFY(  is_default(std::initializer_list<double>{4.2}, c2) );
+  VERIFY(  is_default(std::initializer_list<double>{0.0, 1.0}, c2) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5}, c2) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5, 1.0}, c2) );
+
+  auto id = [](double x) { return x; };
+  VERIFY(  is_default(std::initializer_list<double>{}, id) );
+  VERIFY(  is_default(std::initializer_list<double>{4.2}, id) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 1.0}, id) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5}, id) );
+  VERIFY( !is_default(std::initializer_list<double>{0.0, 0.5, 1.0}, id) );
+}
+
+void test_xbound()
+{
+  auto c1 = [](double x) { return 1.0; };
+  VERIFY(  is_default(0, 0.0, 1.0, c1) );
+  VERIFY( !is_default(0, 0.0, 0.5, c1) );
+  VERIFY(  is_default(1, 0.0, 1.0, c1) );
+  VERIFY( !is_default(1, 0.0, 0.5, c1) );
+  VERIFY( !is_default(2, 0.0, 1.0, c1) );
+
+  auto c2 = [](double x) { return 4.2; };
+  VERIFY(  is_default(0, 0.0, 1.0, c2) );
+  VERIFY( !is_default(0, 0.0, 0.5, c2) );
+  VERIFY(  is_default(1, 0.0, 1.0, c2) );
+  VERIFY( !is_default(1, 0.0, 0.5, c2) );
+  VERIFY( !is_default(2, 0.0, 1.0, c2) );
+
+  auto id = [](double x) { return x; };
+  VERIFY( !is_default(0, 0.0, 1.0, id) );
+  VERIFY( !is_default(0, 0.0, 0.5, id) );
+  VERIFY( !is_default(1, 0.0, 1.0, id) );
+  VERIFY( !is_default(1, 0.0, 0.5, id) );
+  VERIFY( !is_default(2, 0.0, 1.0, id) );
+}
+
+int main()
+{
+  using namespace __gnu_test;
+  test_it_pair<input_container>();
+  test_it_pair<forward_container>();
+  test_it_pair<random_access_container>();
+
+  test_init_list();
+  test_xbound();
+  return 0;
+}
diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc
index c698e7a66e6e..af979fdac42a 100644
--- 
a/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/range.cc
@@ -25,13 +25,17 @@
 
 #include <random>
 #include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
 
+template<template<typename> class Range>
 void
-test01()
+test_it_pair()
 {
-  std::vector<double> x = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
-  std::vector<double> wt = {0.0, 1.0, 2.5, 1.5, 3.5, 0.0};
-  std::piecewise_linear_distribution<> u(x.begin(), x.end(), wt.begin());
+  double x[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
+  double wt[] = {0.0, 1.0, 2.5, 1.5, 3.5, 0.0};
+
+  Range<double> r(x, x+6);
+  std::piecewise_linear_distribution<> u(r.begin(), r.end(), wt);
   std::vector<double> interval = u.intervals();
   std::vector<double> density = u.densities();
   VERIFY( interval.size() == 6 );
@@ -44,6 +48,9 @@ test01()
 
 int main()
 {
-  test01();
+  using namespace __gnu_test;
+  test_it_pair<input_container>();
+  test_it_pair<forward_container>();
+  test_it_pair<random_access_container>();
   return 0;
 }

Reply via email to