1*e7154709SEric Fiselier //===----------------------------------------------------------------------===// 2*e7154709SEric Fiselier // 3*e7154709SEric Fiselier // The LLVM Compiler Infrastructure 4*e7154709SEric Fiselier // 5*e7154709SEric Fiselier // This file is dual licensed under the MIT and the University of Illinois Open 6*e7154709SEric Fiselier // Source Licenses. See LICENSE.TXT for details. 7*e7154709SEric Fiselier // 8*e7154709SEric Fiselier //===----------------------------------------------------------------------===// 9*e7154709SEric Fiselier 10*e7154709SEric Fiselier // UNSUPPORTED: c++98, c++03, c++11, c++14 11*e7154709SEric Fiselier 12*e7154709SEric Fiselier // <algorithm> 13*e7154709SEric Fiselier 14*e7154709SEric Fiselier // template <class PopulationIterator, class SampleIterator, class Distance, 15*e7154709SEric Fiselier // class UniformRandomNumberGenerator> 16*e7154709SEric Fiselier // SampleIterator sample(PopulationIterator first, PopulationIterator last, 17*e7154709SEric Fiselier // SampleIterator out, Distance n, 18*e7154709SEric Fiselier // UniformRandomNumberGenerator &&g); 19*e7154709SEric Fiselier 20*e7154709SEric Fiselier #include <algorithm> 21*e7154709SEric Fiselier #include <random> 22*e7154709SEric Fiselier #include <cassert> 23*e7154709SEric Fiselier 24*e7154709SEric Fiselier #include "test_iterators.h" 25*e7154709SEric Fiselier 26*e7154709SEric Fiselier struct ReservoirSampleExpectations { 27*e7154709SEric Fiselier enum { os = 4 }; 28*e7154709SEric Fiselier static int oa1[os]; 29*e7154709SEric Fiselier static int oa2[os]; 30*e7154709SEric Fiselier }; 31*e7154709SEric Fiselier 32*e7154709SEric Fiselier int ReservoirSampleExpectations::oa1[] = {10, 5, 9, 4}; 33*e7154709SEric Fiselier int ReservoirSampleExpectations::oa2[] = {5, 2, 10, 4}; 34*e7154709SEric Fiselier 35*e7154709SEric Fiselier struct SelectionSampleExpectations { 36*e7154709SEric Fiselier enum { os = 4 }; 37*e7154709SEric Fiselier static int oa1[os]; 38*e7154709SEric Fiselier static int oa2[os]; 39*e7154709SEric Fiselier }; 40*e7154709SEric Fiselier 41*e7154709SEric Fiselier int SelectionSampleExpectations::oa1[] = {1, 4, 6, 7}; 42*e7154709SEric Fiselier int SelectionSampleExpectations::oa2[] = {1, 2, 6, 8}; 43*e7154709SEric Fiselier 44*e7154709SEric Fiselier template <class IteratorCategory> struct TestExpectations 45*e7154709SEric Fiselier : public SelectionSampleExpectations {}; 46*e7154709SEric Fiselier 47*e7154709SEric Fiselier template <> 48*e7154709SEric Fiselier struct TestExpectations<std::input_iterator_tag> 49*e7154709SEric Fiselier : public ReservoirSampleExpectations {}; 50*e7154709SEric Fiselier 51*e7154709SEric Fiselier template <template<class...> class PopulationIteratorType, class PopulationItem, 52*e7154709SEric Fiselier template<class...> class SampleIteratorType, class SampleItem> 53*e7154709SEric Fiselier void test() { 54*e7154709SEric Fiselier typedef PopulationIteratorType<PopulationItem *> PopulationIterator; 55*e7154709SEric Fiselier typedef SampleIteratorType<SampleItem *> SampleIterator; 56*e7154709SEric Fiselier PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 57*e7154709SEric Fiselier const unsigned is = sizeof(ia) / sizeof(ia[0]); 58*e7154709SEric Fiselier typedef TestExpectations<typename std::iterator_traits< 59*e7154709SEric Fiselier PopulationIterator>::iterator_category> Expectations; 60*e7154709SEric Fiselier const unsigned os = Expectations::os; 61*e7154709SEric Fiselier SampleItem oa[os]; 62*e7154709SEric Fiselier const int *oa1 = Expectations::oa1; 63*e7154709SEric Fiselier const int *oa2 = Expectations::oa2; 64*e7154709SEric Fiselier std::minstd_rand g; 65*e7154709SEric Fiselier SampleIterator end; 66*e7154709SEric Fiselier end = std::sample(PopulationIterator(ia), 67*e7154709SEric Fiselier PopulationIterator(ia + is), 68*e7154709SEric Fiselier SampleIterator(oa), os, g); 69*e7154709SEric Fiselier assert(end.base() - oa == std::min(os, is)); 70*e7154709SEric Fiselier assert(std::equal(oa, oa + os, oa1)); 71*e7154709SEric Fiselier end = std::sample(PopulationIterator(ia), 72*e7154709SEric Fiselier PopulationIterator(ia + is), 73*e7154709SEric Fiselier SampleIterator(oa), os, std::move(g)); 74*e7154709SEric Fiselier assert(end.base() - oa == std::min(os, is)); 75*e7154709SEric Fiselier assert(std::equal(oa, oa + os, oa2)); 76*e7154709SEric Fiselier } 77*e7154709SEric Fiselier 78*e7154709SEric Fiselier template <template<class...> class PopulationIteratorType, class PopulationItem, 79*e7154709SEric Fiselier template<class...> class SampleIteratorType, class SampleItem> 80*e7154709SEric Fiselier void test_empty_population() { 81*e7154709SEric Fiselier typedef PopulationIteratorType<PopulationItem *> PopulationIterator; 82*e7154709SEric Fiselier typedef SampleIteratorType<SampleItem *> SampleIterator; 83*e7154709SEric Fiselier PopulationItem ia[] = {42}; 84*e7154709SEric Fiselier const unsigned os = 4; 85*e7154709SEric Fiselier SampleItem oa[os]; 86*e7154709SEric Fiselier std::minstd_rand g; 87*e7154709SEric Fiselier SampleIterator end = 88*e7154709SEric Fiselier std::sample(PopulationIterator(ia), PopulationIterator(ia), 89*e7154709SEric Fiselier SampleIterator(oa), os, g); 90*e7154709SEric Fiselier assert(end.base() == oa); 91*e7154709SEric Fiselier } 92*e7154709SEric Fiselier 93*e7154709SEric Fiselier template <template<class...> class PopulationIteratorType, class PopulationItem, 94*e7154709SEric Fiselier template<class...> class SampleIteratorType, class SampleItem> 95*e7154709SEric Fiselier void test_empty_sample() { 96*e7154709SEric Fiselier typedef PopulationIteratorType<PopulationItem *> PopulationIterator; 97*e7154709SEric Fiselier typedef SampleIteratorType<SampleItem *> SampleIterator; 98*e7154709SEric Fiselier PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 99*e7154709SEric Fiselier const unsigned is = sizeof(ia) / sizeof(ia[0]); 100*e7154709SEric Fiselier SampleItem oa[1]; 101*e7154709SEric Fiselier std::minstd_rand g; 102*e7154709SEric Fiselier SampleIterator end = 103*e7154709SEric Fiselier std::sample(PopulationIterator(ia), PopulationIterator(ia + is), 104*e7154709SEric Fiselier SampleIterator(oa), 0, g); 105*e7154709SEric Fiselier assert(end.base() == oa); 106*e7154709SEric Fiselier } 107*e7154709SEric Fiselier 108*e7154709SEric Fiselier template <template<class...> class PopulationIteratorType, class PopulationItem, 109*e7154709SEric Fiselier template<class...> class SampleIteratorType, class SampleItem> 110*e7154709SEric Fiselier void test_small_population() { 111*e7154709SEric Fiselier // The population size is less than the sample size. 112*e7154709SEric Fiselier typedef PopulationIteratorType<PopulationItem *> PopulationIterator; 113*e7154709SEric Fiselier typedef SampleIteratorType<SampleItem *> SampleIterator; 114*e7154709SEric Fiselier PopulationItem ia[] = {1, 2, 3, 4, 5}; 115*e7154709SEric Fiselier const unsigned is = sizeof(ia) / sizeof(ia[0]); 116*e7154709SEric Fiselier const unsigned os = 8; 117*e7154709SEric Fiselier SampleItem oa[os]; 118*e7154709SEric Fiselier const SampleItem oa1[] = {1, 2, 3, 4, 5}; 119*e7154709SEric Fiselier std::minstd_rand g; 120*e7154709SEric Fiselier SampleIterator end; 121*e7154709SEric Fiselier end = std::sample(PopulationIterator(ia), 122*e7154709SEric Fiselier PopulationIterator(ia + is), 123*e7154709SEric Fiselier SampleIterator(oa), os, g); 124*e7154709SEric Fiselier assert(end.base() - oa == std::min(os, is)); 125*e7154709SEric Fiselier assert(std::equal(oa, end.base(), oa1)); 126*e7154709SEric Fiselier } 127*e7154709SEric Fiselier 128*e7154709SEric Fiselier int main() { 129*e7154709SEric Fiselier test<input_iterator, int, random_access_iterator, int>(); 130*e7154709SEric Fiselier test<forward_iterator, int, output_iterator, int>(); 131*e7154709SEric Fiselier test<forward_iterator, int, random_access_iterator, int>(); 132*e7154709SEric Fiselier 133*e7154709SEric Fiselier test<input_iterator, int, random_access_iterator, double>(); 134*e7154709SEric Fiselier test<forward_iterator, int, output_iterator, double>(); 135*e7154709SEric Fiselier test<forward_iterator, int, random_access_iterator, double>(); 136*e7154709SEric Fiselier 137*e7154709SEric Fiselier test_empty_population<input_iterator, int, random_access_iterator, int>(); 138*e7154709SEric Fiselier test_empty_population<forward_iterator, int, output_iterator, int>(); 139*e7154709SEric Fiselier test_empty_population<forward_iterator, int, random_access_iterator, int>(); 140*e7154709SEric Fiselier 141*e7154709SEric Fiselier test_empty_sample<input_iterator, int, random_access_iterator, int>(); 142*e7154709SEric Fiselier test_empty_sample<forward_iterator, int, output_iterator, int>(); 143*e7154709SEric Fiselier test_empty_sample<forward_iterator, int, random_access_iterator, int>(); 144*e7154709SEric Fiselier 145*e7154709SEric Fiselier test_small_population<input_iterator, int, random_access_iterator, int>(); 146*e7154709SEric Fiselier test_small_population<forward_iterator, int, output_iterator, int>(); 147*e7154709SEric Fiselier test_small_population<forward_iterator, int, random_access_iterator, int>(); 148*e7154709SEric Fiselier } 149