1732e2681SEvgeniy Stepanov// -*- C++ -*-
2732e2681SEvgeniy Stepanov//===-------------------------- algorithm ---------------------------------===//
3732e2681SEvgeniy Stepanov//
4732e2681SEvgeniy Stepanov//                     The LLVM Compiler Infrastructure
5732e2681SEvgeniy Stepanov//
6732e2681SEvgeniy Stepanov// This file is dual licensed under the MIT and the University of Illinois Open
7732e2681SEvgeniy Stepanov// Source Licenses. See LICENSE.TXT for details.
8732e2681SEvgeniy Stepanov//
9732e2681SEvgeniy Stepanov//===----------------------------------------------------------------------===//
10732e2681SEvgeniy Stepanov
11732e2681SEvgeniy Stepanov#ifndef _LIBCPP_EXPERIMENTAL_ALGORITHM
12732e2681SEvgeniy Stepanov#define _LIBCPP_EXPERIMENTAL_ALGORITHM
13732e2681SEvgeniy Stepanov
14732e2681SEvgeniy Stepanov/*
15732e2681SEvgeniy Stepanov   experimental/algorithm synopsis
16732e2681SEvgeniy Stepanov
17732e2681SEvgeniy Stepanov#include <algorithm>
18732e2681SEvgeniy Stepanov
19732e2681SEvgeniy Stepanovnamespace std {
20732e2681SEvgeniy Stepanovnamespace experimental {
21732e2681SEvgeniy Stepanovinline namespace fundamentals_v1 {
22732e2681SEvgeniy Stepanov
23732e2681SEvgeniy Stepanovtemplate <class ForwardIterator, class Searcher>
24732e2681SEvgeniy StepanovForwardIterator search(ForwardIterator first, ForwardIterator last,
25732e2681SEvgeniy Stepanov                       const Searcher &searcher);
26732e2681SEvgeniy Stepanovtemplate <class PopulationIterator, class SampleIterator, class Distance,
27732e2681SEvgeniy Stepanov          class UniformRandomNumberGenerator>
28732e2681SEvgeniy StepanovSampleIterator sample(PopulationIterator first, PopulationIterator last,
29732e2681SEvgeniy Stepanov                      SampleIterator out, Distance n,
30732e2681SEvgeniy Stepanov                      UniformRandomNumberGenerator &&g);
31732e2681SEvgeniy Stepanov
32732e2681SEvgeniy Stepanov} // namespace fundamentals_v1
33732e2681SEvgeniy Stepanov} // namespace experimental
34732e2681SEvgeniy Stepanov} // namespace std
35732e2681SEvgeniy Stepanov
36732e2681SEvgeniy Stepanov*/
37732e2681SEvgeniy Stepanov
38732e2681SEvgeniy Stepanov#include <experimental/__config>
39732e2681SEvgeniy Stepanov#include <algorithm>
40732e2681SEvgeniy Stepanov#include <type_traits>
41732e2681SEvgeniy Stepanov
42732e2681SEvgeniy Stepanov#include <__undef_min_max>
43732e2681SEvgeniy Stepanov
44732e2681SEvgeniy Stepanov#include <__debug>
45732e2681SEvgeniy Stepanov
46732e2681SEvgeniy Stepanov#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
47732e2681SEvgeniy Stepanov#pragma GCC system_header
48732e2681SEvgeniy Stepanov#endif
49732e2681SEvgeniy Stepanov
50732e2681SEvgeniy Stepanov_LIBCPP_BEGIN_NAMESPACE_LFTS
51732e2681SEvgeniy Stepanov
52732e2681SEvgeniy Stepanov
5381416e49SMarshall Clowtemplate <class _ForwardIterator, class _Searcher>
5481416e49SMarshall Clow_LIBCPP_INLINE_VISIBILITY
5581416e49SMarshall Clow_ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher &__s)
56*28cc4ddeSMarshall Clow{ return __s(__f, __l).first; }
5781416e49SMarshall Clow
5881416e49SMarshall Clow
59732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
60732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
61732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
62732e2681SEvgeniy Stepanov_SampleIterator __sample(_PopulationIterator __first,
63732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
64732e2681SEvgeniy Stepanov                         _Distance __n,
65732e2681SEvgeniy Stepanov                         _UniformRandomNumberGenerator &&__g,
66732e2681SEvgeniy Stepanov                         input_iterator_tag) {
67732e2681SEvgeniy Stepanov
68732e2681SEvgeniy Stepanov  _Distance __k = 0;
69732e2681SEvgeniy Stepanov  for (; __first != __last && __k < __n; ++__first, (void)++__k)
70732e2681SEvgeniy Stepanov    __out[__k] = *__first;
71732e2681SEvgeniy Stepanov  _Distance __sz = __k;
72732e2681SEvgeniy Stepanov  for (; __first != __last; ++__first, (void)++__k) {
73732e2681SEvgeniy Stepanov    _Distance __r = _VSTD::uniform_int_distribution<_Distance>(0, __k)(__g);
74732e2681SEvgeniy Stepanov    if (__r < __sz)
75732e2681SEvgeniy Stepanov      __out[__r] = *__first;
76732e2681SEvgeniy Stepanov  }
77732e2681SEvgeniy Stepanov  return __out + _VSTD::min(__n, __k);
78732e2681SEvgeniy Stepanov}
79732e2681SEvgeniy Stepanov
80732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
81732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
82732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
83732e2681SEvgeniy Stepanov_SampleIterator __sample(_PopulationIterator __first,
84732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
85732e2681SEvgeniy Stepanov                         _Distance __n,
86732e2681SEvgeniy Stepanov                         _UniformRandomNumberGenerator &&__g,
87732e2681SEvgeniy Stepanov                         forward_iterator_tag) {
88732e2681SEvgeniy Stepanov  _Distance __unsampled_sz = _VSTD::distance(__first, __last);
89732e2681SEvgeniy Stepanov  for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) {
90732e2681SEvgeniy Stepanov    _Distance __r =
91732e2681SEvgeniy Stepanov        _VSTD::uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g);
92732e2681SEvgeniy Stepanov    if (__r < __n) {
93732e2681SEvgeniy Stepanov      *__out++ = *__first;
94732e2681SEvgeniy Stepanov      --__n;
95732e2681SEvgeniy Stepanov    }
96732e2681SEvgeniy Stepanov  }
97732e2681SEvgeniy Stepanov  return __out;
98732e2681SEvgeniy Stepanov}
99732e2681SEvgeniy Stepanov
100732e2681SEvgeniy Stepanovtemplate <class _PopulationIterator, class _SampleIterator, class _Distance,
101732e2681SEvgeniy Stepanov          class _UniformRandomNumberGenerator>
102732e2681SEvgeniy Stepanov_LIBCPP_INLINE_VISIBILITY
103732e2681SEvgeniy Stepanov_SampleIterator sample(_PopulationIterator __first,
104732e2681SEvgeniy Stepanov                         _PopulationIterator __last, _SampleIterator __out,
105732e2681SEvgeniy Stepanov                         _Distance __n, _UniformRandomNumberGenerator &&__g) {
106732e2681SEvgeniy Stepanov  typedef typename iterator_traits<_PopulationIterator>::iterator_category
107732e2681SEvgeniy Stepanov        _PopCategory;
108732e2681SEvgeniy Stepanov  typedef typename iterator_traits<_PopulationIterator>::difference_type
109732e2681SEvgeniy Stepanov        _Difference;
110732e2681SEvgeniy Stepanov  typedef typename common_type<_Distance, _Difference>::type _CommonType;
111732e2681SEvgeniy Stepanov  _LIBCPP_ASSERT(__n >= 0, "N must be a positive number.");
112732e2681SEvgeniy Stepanov  return _VSTD_LFTS::__sample(
113732e2681SEvgeniy Stepanov      __first, __last, __out, _CommonType(__n),
114732e2681SEvgeniy Stepanov      _VSTD::forward<_UniformRandomNumberGenerator>(__g),
115732e2681SEvgeniy Stepanov      _PopCategory());
116732e2681SEvgeniy Stepanov}
117732e2681SEvgeniy Stepanov
118732e2681SEvgeniy Stepanov_LIBCPP_END_NAMESPACE_LFTS
119732e2681SEvgeniy Stepanov
120732e2681SEvgeniy Stepanov#endif /* _LIBCPP_EXPERIMENTAL_ALGORITHM */
121