1*732e2681SEvgeniy Stepanov// -*- C++ -*-
2*732e2681SEvgeniy Stepanov//===-------------------------- algorithm ---------------------------------===//
3*732e2681SEvgeniy Stepanov//
4*732e2681SEvgeniy Stepanov//                     The LLVM Compiler Infrastructure
5*732e2681SEvgeniy Stepanov//
6*732e2681SEvgeniy Stepanov// This file is dual licensed under the MIT and the University of Illinois Open
7*732e2681SEvgeniy Stepanov// Source Licenses. See LICENSE.TXT for details.
8*732e2681SEvgeniy Stepanov//
9*732e2681SEvgeniy Stepanov//===----------------------------------------------------------------------===//
10*732e2681SEvgeniy Stepanov
11*732e2681SEvgeniy Stepanov#ifndef _LIBCPP_EXPERIMENTAL_ALGORITHM
12*732e2681SEvgeniy Stepanov#define _LIBCPP_EXPERIMENTAL_ALGORITHM
13*732e2681SEvgeniy Stepanov
14*732e2681SEvgeniy Stepanov/*
15*732e2681SEvgeniy Stepanov   experimental/algorithm synopsis
16*732e2681SEvgeniy Stepanov
17*732e2681SEvgeniy Stepanov#include <algorithm>
18*732e2681SEvgeniy Stepanov
19*732e2681SEvgeniy Stepanovnamespace std {
20*732e2681SEvgeniy Stepanovnamespace experimental {
21*732e2681SEvgeniy Stepanovinline namespace fundamentals_v1 {
22*732e2681SEvgeniy Stepanov
23*732e2681SEvgeniy Stepanovtemplate <class ForwardIterator, class Searcher>
24*732e2681SEvgeniy StepanovForwardIterator search(ForwardIterator first, ForwardIterator last,
25*732e2681SEvgeniy Stepanov                       const Searcher &searcher);
26*732e2681SEvgeniy Stepanovtemplate <class PopulationIterator, class SampleIterator, class Distance,
27*732e2681SEvgeniy Stepanov          class UniformRandomNumberGenerator>
28*732e2681SEvgeniy StepanovSampleIterator sample(PopulationIterator first, PopulationIterator last,
29*732e2681SEvgeniy Stepanov                      SampleIterator out, Distance n,
30*732e2681SEvgeniy Stepanov                      UniformRandomNumberGenerator &&g);
31*732e2681SEvgeniy Stepanov
32*732e2681SEvgeniy Stepanov} // namespace fundamentals_v1
33*732e2681SEvgeniy Stepanov} // namespace experimental
34*732e2681SEvgeniy Stepanov} // namespace std
35*732e2681SEvgeniy Stepanov
36*732e2681SEvgeniy Stepanov*/
37*732e2681SEvgeniy Stepanov
38*732e2681SEvgeniy Stepanov#include <experimental/__config>
39*732e2681SEvgeniy Stepanov#include <algorithm>
40*732e2681SEvgeniy Stepanov#include <type_traits>
41*732e2681SEvgeniy Stepanov
42*732e2681SEvgeniy Stepanov#include <__undef_min_max>
43*732e2681SEvgeniy Stepanov
44*732e2681SEvgeniy Stepanov#include <__debug>
45*732e2681SEvgeniy Stepanov
46*732e2681SEvgeniy Stepanov#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
47*732e2681SEvgeniy Stepanov#pragma GCC system_header
48*732e2681SEvgeniy Stepanov#endif
49*732e2681SEvgeniy Stepanov
50*732e2681SEvgeniy Stepanov_LIBCPP_BEGIN_NAMESPACE_LFTS
51*732e2681SEvgeniy Stepanov
52*732e2681SEvgeniy Stepanov
53*732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
54*732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
55*732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
56*732e2681SEvgeniy Stepanov_SampleIterator __sample(_PopulationIterator __first,
57*732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
58*732e2681SEvgeniy Stepanov                         _Distance __n,
59*732e2681SEvgeniy Stepanov                         _UniformRandomNumberGenerator &&__g,
60*732e2681SEvgeniy Stepanov                         input_iterator_tag) {
61*732e2681SEvgeniy Stepanov
62*732e2681SEvgeniy Stepanov  _Distance __k = 0;
63*732e2681SEvgeniy Stepanov  for (; __first != __last && __k < __n; ++__first, (void)++__k)
64*732e2681SEvgeniy Stepanov    __out[__k] = *__first;
65*732e2681SEvgeniy Stepanov  _Distance __sz = __k;
66*732e2681SEvgeniy Stepanov  for (; __first != __last; ++__first, (void)++__k) {
67*732e2681SEvgeniy Stepanov    _Distance __r = _VSTD::uniform_int_distribution<_Distance>(0, __k)(__g);
68*732e2681SEvgeniy Stepanov    if (__r < __sz)
69*732e2681SEvgeniy Stepanov      __out[__r] = *__first;
70*732e2681SEvgeniy Stepanov  }
71*732e2681SEvgeniy Stepanov  return __out + _VSTD::min(__n, __k);
72*732e2681SEvgeniy Stepanov}
73*732e2681SEvgeniy Stepanov
74*732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
75*732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
76*732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
77*732e2681SEvgeniy Stepanov_SampleIterator __sample(_PopulationIterator __first,
78*732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
79*732e2681SEvgeniy Stepanov                         _Distance __n,
80*732e2681SEvgeniy Stepanov                         _UniformRandomNumberGenerator &&__g,
81*732e2681SEvgeniy Stepanov                         forward_iterator_tag) {
82*732e2681SEvgeniy Stepanov  _Distance __unsampled_sz = _VSTD::distance(__first, __last);
83*732e2681SEvgeniy Stepanov  for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) {
84*732e2681SEvgeniy Stepanov    _Distance __r =
85*732e2681SEvgeniy Stepanov        _VSTD::uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g);
86*732e2681SEvgeniy Stepanov    if (__r < __n) {
87*732e2681SEvgeniy Stepanov      *__out++ = *__first;
88*732e2681SEvgeniy Stepanov      --__n;
89*732e2681SEvgeniy Stepanov    }
90*732e2681SEvgeniy Stepanov  }
91*732e2681SEvgeniy Stepanov  return __out;
92*732e2681SEvgeniy Stepanov}
93*732e2681SEvgeniy Stepanov
94*732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
95*732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
96*732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
97*732e2681SEvgeniy Stepanov_SampleIterator sample(_PopulationIterator __first,
98*732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
99*732e2681SEvgeniy Stepanov                         _Distance __n, _UniformRandomNumberGenerator &&__g) {
100*732e2681SEvgeniy Stepanov  typedef typename iterator_traits<_PopulationIterator>::iterator_category
101*732e2681SEvgeniy Stepanov        _PopCategory;
102*732e2681SEvgeniy Stepanov  typedef typename iterator_traits<_PopulationIterator>::difference_type
103*732e2681SEvgeniy Stepanov        _Difference;
104*732e2681SEvgeniy Stepanov  typedef typename common_type<_Distance, _Difference>::type _CommonType;
105*732e2681SEvgeniy Stepanov  _LIBCPP_ASSERT(__n >= 0, "N must be a positive number.");
106*732e2681SEvgeniy Stepanov  return _VSTD_LFTS::__sample(
107*732e2681SEvgeniy Stepanov      __first, __last, __out, _CommonType(__n),
108*732e2681SEvgeniy Stepanov      _VSTD::forward<_UniformRandomNumberGenerator>(__g),
109*732e2681SEvgeniy Stepanov      _PopCategory());
110*732e2681SEvgeniy Stepanov}
111*732e2681SEvgeniy Stepanov
112*732e2681SEvgeniy Stepanov_LIBCPP_END_NAMESPACE_LFTS
113*732e2681SEvgeniy Stepanov
114*732e2681SEvgeniy Stepanov#endif /* _LIBCPP_EXPERIMENTAL_ALGORITHM */
115