Constant View: A proposal for a std::as_const
helper function template
P0007R1
diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
index c6b84409f68..ae8dfa9529b 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
@@ -181,6 +181,17 @@ Feature-testing recommendations for C++.
__cpp_lib_boyer_moore_searcher >= 201603
+
+ Library Fundamentals V1 TS Components: Sampling
+
+
+ P0220R1
+
+
+ 7
+ __cpp_lib_sample >= 201603
+
+
Constant View: A proposal for a std::as_const
helper function template
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index ea0b56ca43f..0538a79a351 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -5615,6 +5615,86 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__gnu_cxx::__ops::__iter_comp_iter(__comp));
}
+#if __cplusplus >= 201402L
+ /// Reservoir sampling algorithm.
+ template
+ _RandomAccessIterator
+ __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag,
+ _RandomAccessIterator __out, random_access_iterator_tag,
+ _Size __n, _UniformRandomBitGenerator&& __g)
+ {
+ using __distrib_type = uniform_int_distribution<_Size>;
+ using __param_type = typename __distrib_type::param_type;
+ __distrib_type __d{};
+ _Size __sample_sz = 0;
+ while (__first != __last && __sample_sz != __n)
+ {
+ __out[__sample_sz++] = *__first;
+ ++__first;
+ }
+ for (auto __pop_sz = __sample_sz; __first != __last;
+ ++__first, (void) ++__pop_sz)
+ {
+ const auto __k = __d(__g, __param_type{0, __pop_sz});
+ if (__k < __n)
+ __out[__k] = *__first;
+ }
+ return __out + __sample_sz;
+ }
+
+ /// Selection sampling algorithm.
+ template
+ _OutputIterator
+ __sample(_ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag,
+ _OutputIterator __out, _Cat,
+ _Size __n, _UniformRandomBitGenerator&& __g)
+ {
+ using __distrib_type = uniform_int_distribution<_Size>;
+ using __param_type = typename __distrib_type::param_type;
+ __distrib_type __d{};
+ _Size __unsampled_sz = std::distance(__first, __last);
+ for (__n = std::min(__n, __unsampled_sz); __n != 0; ++__first)
+ if (__d(__g, __param_type{0, --__unsampled_sz}) < __n)
+ {
+ *__out++ = *__first;
+ --__n;
+ }
+ return __out;
+ }
+
+#if __cplusplus > 201402L
+#define __cpp_lib_sample 201603
+ /// Take a random sample from a population.
+ template
+ _SampleIterator
+ sample(_PopulationIterator __first, _PopulationIterator __last,
+ _SampleIterator __out, _Distance __n,
+ _UniformRandomBitGenerator&& __g)
+ {
+ using __pop_cat = typename
+ std::iterator_traits<_PopulationIterator>::iterator_category;
+ using __samp_cat = typename
+ std::iterator_traits<_SampleIterator>::iterator_category;
+
+ static_assert(
+ __or_,
+ is_convertible<__samp_cat, random_access_iterator_tag>>::value,
+ "output range must use a RandomAccessIterator when input range"
+ " does not meet the ForwardIterator requirements");
+
+ static_assert(is_integral<_Distance>::value,
+ "sample size must be an integer type");
+
+ return std::__sample(__first, __last, __pop_cat{}, __out, __samp_cat{},
+ __n, std::forward<_UniformRandomBitGenerator>(__g));
+ }
+#endif // C++17
+#endif // C++14
+
_GLIBCXX_END_NAMESPACE_ALGO
} // namespace std
diff --git a/libstdc++-v3/include/experimental/algorithm b/libstdc++-v3/include/experimental/algorithm
index 0ba6311e952..eb18dde198e 100644
--- a/libstdc++-v3/include/experimental/algorithm
+++ b/libstdc++-v3/include/experimental/algorithm
@@ -36,7 +36,6 @@
#else
#include
-#include
#include
namespace std _GLIBCXX_VISIBILITY(default)
@@ -55,52 +54,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __cpp_lib_experimental_sample 201402
- /// Reservoir sampling algorithm.
- template
- _RandomAccessIterator
- __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag,
- _RandomAccessIterator __out, random_access_iterator_tag,
- _Size __n, _UniformRandomNumberGenerator&& __g)
- {
- using __distrib_type = std::uniform_int_distribution<_Size>;
- using __param_type = typename __distrib_type::param_type;
- __distrib_type __d{};
- _Size __sample_sz = 0;
- while (__first != __last && __sample_sz != __n)
- __out[__sample_sz++] = *__first++;
- for (auto __pop_sz = __sample_sz; __first != __last;
- ++__first, ++__pop_sz)
- {
- const auto __k = __d(__g, __param_type{0, __pop_sz});
- if (__k < __n)
- __out[__k] = *__first;
- }
- return __out + __sample_sz;
- }
-
- /// Selection sampling algorithm.
- template
- _OutputIterator
- __sample(_ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag,
- _OutputIterator __out, _Cat,
- _Size __n, _UniformRandomNumberGenerator&& __g)
- {
- using __distrib_type = std::uniform_int_distribution<_Size>;
- using __param_type = typename __distrib_type::param_type;
- __distrib_type __d{};
- _Size __unsampled_sz = std::distance(__first, __last);
- for (__n = std::min(__n, __unsampled_sz); __n != 0; ++__first)
- if (__d(__g, __param_type{0, --__unsampled_sz}) < __n)
- {
- *__out++ = *__first;
- --__n;
- }
- return __out;
- }
-
/// Take a random sample from a population.
template
@@ -123,9 +76,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_integral<_Distance>::value,
"sample size must be an integer type");
- return std::experimental::__sample(
- __first, __last, __pop_cat{}, __out, __samp_cat{},
- __n, std::forward<_UniformRandomNumberGenerator>(__g));
+ return std::__sample(__first, __last, __pop_cat{}, __out, __samp_cat{},
+ __n,
+ std::forward<_UniformRandomNumberGenerator>(__g));
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/25_algorithms/sample/1.cc b/libstdc++-v3/testsuite/25_algorithms/sample/1.cc
new file mode 100644
index 00000000000..10376e2add5
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/sample/1.cc
@@ -0,0 +1,110 @@
+// Copyright (C) 2014-2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// .
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include
+#include
+#include
+#include
+
+std::mt19937 rng;
+
+using std::sample;
+using __gnu_test::test_container;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+void
+test01()
+{
+ const int in[] = { 1, 2 };
+ test_container pop(in);
+ const int sample_size = 10;
+ int samp[sample_size] = { };
+
+ // population smaller than desired sample size
+ auto it = sample(pop.begin(), pop.end(), samp, sample_size, rng);
+ VERIFY( it == samp + std::distance(pop.begin(), pop.end()) );
+ const auto sum = std::accumulate(pop.begin(), pop.end(), 0);
+ VERIFY( std::accumulate(samp, samp + sample_size, 0) == sum );
+}
+
+void
+test02()
+{
+ const int in[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ test_container pop(in);
+ const int sample_size = 10;
+ int samp[sample_size] = { };
+
+ auto it = sample(pop.begin(), pop.end(), samp, sample_size, rng);
+ VERIFY( it == samp + sample_size );
+
+ // verify no duplicates
+ std::sort(samp, it);
+ auto it2 = std::unique(samp, it);
+ VERIFY( it2 == it );
+}
+
+void
+test03()
+{
+ const int in[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ test_container pop(in);
+ const int sample_size = 5;
+ int samp[sample_size] = { };
+
+ // input iterator for population
+ auto it = sample(pop.begin(), pop.end(), samp, sample_size, rng);
+ VERIFY( it == samp + sample_size );
+
+ // verify no duplicates
+ std::sort(samp, it);
+ auto it2 = std::unique(samp, it);
+ VERIFY( it2 == it );
+}
+
+void
+test04()
+{
+ const int in[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ test_container pop(in);
+ const int sample_size = 5;
+ int out[sample_size];
+ test_container samp(out);
+
+ // forward iterator for population and output iterator for result
+ auto res = sample(pop.begin(), pop.end(), samp.begin(), sample_size, rng);
+
+ // verify no duplicates
+ std::sort(std::begin(out), std::end(out));
+ auto it = std::unique(std::begin(out), std::end(out));
+ VERIFY( it == std::end(out) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}