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