* doc/xml/manual/status_cxx2017.xml: Add std::sample status.
* doc/html/*: Regenerate.
* include/experimental/algorithm (__sample): Move to bits/stl_algo.h
and into namespace std.
* include/bits/stl_algo.h (__sample): Define here. Fix invalid use
of input iterator. Defend against overloaded comma operator.
(sample): Define for C++17.
* testsuite/25_algorithms/sample/1.cc: New test.
From-SVN: r241062
2016-10-12 Jonathan Wakely <jwakely@redhat.com>
+ * doc/xml/manual/status_cxx2017.xml: Add std::sample status.
+ * doc/html/*: Regenerate.
+ * include/experimental/algorithm (__sample): Move to bits/stl_algo.h
+ and into namespace std.
+ * include/bits/stl_algo.h (__sample): Define here. Fix invalid use
+ of input iterator. Defend against overloaded comma operator.
+ (sample): Define for C++17.
+ * testsuite/25_algorithms/sample/1.cc: New test.
+
* testsuite/util/testsuite_common_types.h
(bitwise_assignment_operators): Use direct-initialization for C++11
and later, to avoid CopyConstructible requirement.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2441" target="_top">2441</a>:
<span class="emphasis"><em>Exact-width atomic typedefs should be provided</em></span>
</span></dt><dd><p>Define the typedefs.
+ </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2442" target="_top">2442</a>:
+ <span class="emphasis"><em><code class="code">call_once()</code> shouldn't <code class="code">DECAY_COPY()</code></em></span>
+ </span></dt><dd><p>Remove indirection through call wrapper that made copies
+ of arguments and forward arguments straight to <code class="code">std::invoke</code>.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2454" target="_top">2454</a>:
<span class="emphasis"><em>Add <code class="code">raw_storage_iterator::base()</code> member
</em></span>
<span class="emphasis"><em><code class="code">allocator_traits::max_size()</code> default behavior is incorrect
</em></span>
</span></dt><dd><p>Divide by the object type.
+ </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2484" target="_top">2484</a>:
+ <span class="emphasis"><em><code class="code">rethrow_if_nested()</code> is doubly unimplementable
+ </em></span>
+ </span></dt><dd><p>Avoid using <code class="code">dynamic_cast</code> when it would be
+ ill-formed.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2583" target="_top">2583</a>:
<span class="emphasis"><em>There is no way to supply an allocator for <code class="code"> basic_string(str, pos)</code>
</em></span>
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0220r1.html" target="_top">
P0220R1
</a>
- </td><td align="center"> 7 </td><td align="left"> <code class="code">__cpp_lib_boyer_moore_searcher >= 201603</code> </td></tr><tr><td align="left"> Constant View: A proposal for a <code class="code">std::as_const</code> helper function template </td><td align="left">
+ </td><td align="center"> 7 </td><td align="left"> <code class="code">__cpp_lib_boyer_moore_searcher >= 201603</code> </td></tr><tr><td align="left"> Library Fundamentals V1 TS Components: Sampling </td><td align="left">
+ <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0220r1.html" target="_top">
+ P0220R1
+ </a>
+ </td><td align="center"> 7 </td><td align="left"> <code class="code">__cpp_lib_sample >= 201603</code> </td></tr><tr><td align="left"> Constant View: A proposal for a <code class="code">std::as_const</code> helper function template </td><td align="left">
<a class="link" href="" target="_top">
P0007R1
</a>
<entry> <code>__cpp_lib_boyer_moore_searcher >= 201603</code> </entry>
</row>
+ <row>
+ <entry> Library Fundamentals V1 TS Components: Sampling </entry>
+ <entry>
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0220r1.html">
+ P0220R1
+ </link>
+ </entry>
+ <entry align="center"> 7 </entry>
+ <entry> <code>__cpp_lib_sample >= 201603</code> </entry>
+ </row>
+
<row>
<entry> Constant View: A proposal for a <code>std::as_const</code> helper function template </entry>
<entry>
__gnu_cxx::__ops::__iter_comp_iter(__comp));
}
+#if __cplusplus >= 201402L
+ /// Reservoir sampling algorithm.
+ template<typename _InputIterator, typename _RandomAccessIterator,
+ typename _Size, typename _UniformRandomBitGenerator>
+ _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<typename _ForwardIterator, typename _OutputIterator, typename _Cat,
+ typename _Size, typename _UniformRandomBitGenerator>
+ _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<typename _PopulationIterator, typename _SampleIterator,
+ typename _Distance, typename _UniformRandomBitGenerator>
+ _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<__pop_cat, forward_iterator_tag>,
+ 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
#else
#include <algorithm>
-#include <random>
#include <experimental/bits/lfts_config.h>
namespace std _GLIBCXX_VISIBILITY(default)
#define __cpp_lib_experimental_sample 201402
- /// Reservoir sampling algorithm.
- template<typename _InputIterator, typename _RandomAccessIterator,
- typename _Size, typename _UniformRandomNumberGenerator>
- _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<typename _ForwardIterator, typename _OutputIterator, typename _Cat,
- typename _Size, typename _UniformRandomNumberGenerator>
- _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<typename _PopulationIterator, typename _SampleIterator,
typename _Distance, typename _UniformRandomNumberGenerator>
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
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++1z } }
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+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<const int, random_access_iterator_wrapper> 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<const int, random_access_iterator_wrapper> 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<const int, input_iterator_wrapper> 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<const int, forward_iterator_wrapper> pop(in);
+ const int sample_size = 5;
+ int out[sample_size];
+ test_container<int, output_iterator_wrapper> 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();
+}