[PATCH] libstdc++: Fix reserve of size_t(-1) elements in piecewise_constant_distribution. [PR113761]
Tomasz Kamiński
tkaminsk@redhat.com
Thu Apr 30 11:03:26 GMT 2026
The piecewise_constant_distribution constructor from std::initializer_list il,
unconditionally _M_den reserved 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.
Futhremore, 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 popluate 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 uncessary memory allocatos.
Finally, 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_ints size is already
determined (even for input iterators) and it can be used for call to reserve.
PR libstdc++/113761
libstdc++-v3/ChangeLog:
* include/bits/random.h
(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):
Remove 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.
---
Tested on x86_64-linux locally. *piecewise* tests additionally tested
with all standard modes and modules. OK for trunk?
libstdc++-v3/include/bits/random.h | 6 +
libstdc++-v3/include/bits/random.tcc | 208 ++++++++++++++----
.../cons/fallback.cc | 108 +++++++++
.../cons/range.cc | 17 +-
.../cons/fallback.cc | 127 +++++++++++
.../cons/range.cc | 17 +-
6 files changed, 429 insertions(+), 54 deletions(-)
create mode 100644 libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/fallback.cc
create mode 100644 libstdc++-v3/testsuite/26_numerics/random/piecewise_linear_distribution/cons/fallback.cc
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 3fda69c4399..d8125bb0f62 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -6468,6 +6468,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
void
_M_initialize();
+ void
+ _M_initialize2(const _RealType* __ints, _RealType __den);
+
std::vector<_RealType> _M_int;
std::vector<double> _M_den;
std::vector<double> _M_cp;
@@ -6748,6 +6751,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
void
_M_initialize();
+ void
+ _M_initialize2(const _RealType* __ints, const _RealType *__dens);
+
std::vector<_RealType> _M_int;
std::vector<double> _M_den;
std::vector<double> _M_cp;
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 4475e365c2d..8d4e46c5168 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -2947,16 +2947,6 @@ namespace __detail
piecewise_constant_distribution<_RealType>::param_type::
_M_initialize()
{
- 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_initialize();
+ }
+
+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,20 +3013,38 @@ 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;
}
+#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_initialize();
}
@@ -3006,10 +3054,18 @@ 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])));
@@ -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)
@@ -3161,17 +3224,6 @@ namespace __detail
piecewise_linear_distribution<_RealType>::param_type::
_M_initialize()
{
- 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_initialize();
+ }
template<typename _RealType>
template<typename _InputIteratorB, typename _InputIteratorW>
@@ -3204,12 +3276,42 @@ 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;
}
+#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_initialize();
}
@@ -3219,14 +3321,23 @@ 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_int = __bl;
+ _M_den.reserve(__bl.size());
+ for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter)
+ _M_den.push_back(__fw(*__biter));
_M_initialize();
}
@@ -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);
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 00000000000..1917e69972a
--- /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 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 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 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_constant_distribution/cons/range.cc b/libstdc++-v3/testsuite/26_numerics/random/piecewise_constant_distribution/cons/range.cc
index 3714e460391..4bfa20ea3bb 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 00000000000..b2e6ca65123
--- /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 c698e7a66e6..af979fdac42 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;
}
--
2.54.0
More information about the Libstdc++
mailing list