sample.pass.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. // UNSUPPORTED: c++98, c++03, c++11, c++14
  10. // <algorithm>
  11. // template <class PopulationIterator, class SampleIterator, class Distance,
  12. // class UniformRandomNumberGenerator>
  13. // SampleIterator sample(PopulationIterator first, PopulationIterator last,
  14. // SampleIterator out, Distance n,
  15. // UniformRandomNumberGenerator &&g);
  16. #include <algorithm>
  17. #include <random>
  18. #include <type_traits>
  19. #include <cassert>
  20. #include <cstddef>
  21. #include "test_iterators.h"
  22. #include "test_macros.h"
  23. struct ReservoirSampleExpectations {
  24. enum { os = 4 };
  25. static int oa1[os];
  26. static int oa2[os];
  27. };
  28. int ReservoirSampleExpectations::oa1[] = {10, 5, 9, 4};
  29. int ReservoirSampleExpectations::oa2[] = {5, 2, 10, 4};
  30. struct SelectionSampleExpectations {
  31. enum { os = 4 };
  32. static int oa1[os];
  33. static int oa2[os];
  34. };
  35. int SelectionSampleExpectations::oa1[] = {1, 4, 6, 7};
  36. int SelectionSampleExpectations::oa2[] = {1, 2, 6, 8};
  37. template <class IteratorCategory> struct TestExpectations
  38. : public SelectionSampleExpectations {};
  39. template <>
  40. struct TestExpectations<std::input_iterator_tag>
  41. : public ReservoirSampleExpectations {};
  42. template <template<class...> class PopulationIteratorType, class PopulationItem,
  43. template<class...> class SampleIteratorType, class SampleItem>
  44. void test() {
  45. typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
  46. typedef SampleIteratorType<SampleItem *> SampleIterator;
  47. PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  48. const unsigned is = sizeof(ia) / sizeof(ia[0]);
  49. typedef TestExpectations<typename std::iterator_traits<
  50. PopulationIterator>::iterator_category> Expectations;
  51. const unsigned os = Expectations::os;
  52. SampleItem oa[os];
  53. const int *oa1 = Expectations::oa1;
  54. ((void)oa1); // Prevent unused warning
  55. const int *oa2 = Expectations::oa2;
  56. ((void)oa2); // Prevent unused warning
  57. std::minstd_rand g;
  58. SampleIterator end;
  59. end = std::sample(PopulationIterator(ia),
  60. PopulationIterator(ia + is),
  61. SampleIterator(oa), os, g);
  62. assert(static_cast<std::size_t>(end.base() - oa) == std::min(os, is));
  63. // sample() is deterministic but non-reproducible;
  64. // its results can vary between implementations.
  65. LIBCPP_ASSERT(std::equal(oa, oa + os, oa1));
  66. end = std::sample(PopulationIterator(ia),
  67. PopulationIterator(ia + is),
  68. SampleIterator(oa), os, std::move(g));
  69. assert(static_cast<std::size_t>(end.base() - oa) == std::min(os, is));
  70. LIBCPP_ASSERT(std::equal(oa, oa + os, oa2));
  71. }
  72. template <template<class...> class PopulationIteratorType, class PopulationItem,
  73. template<class...> class SampleIteratorType, class SampleItem>
  74. void test_empty_population() {
  75. typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
  76. typedef SampleIteratorType<SampleItem *> SampleIterator;
  77. PopulationItem ia[] = {42};
  78. const unsigned os = 4;
  79. SampleItem oa[os];
  80. std::minstd_rand g;
  81. SampleIterator end =
  82. std::sample(PopulationIterator(ia), PopulationIterator(ia),
  83. SampleIterator(oa), os, g);
  84. assert(end.base() == oa);
  85. }
  86. template <template<class...> class PopulationIteratorType, class PopulationItem,
  87. template<class...> class SampleIteratorType, class SampleItem>
  88. void test_empty_sample() {
  89. typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
  90. typedef SampleIteratorType<SampleItem *> SampleIterator;
  91. PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  92. const unsigned is = sizeof(ia) / sizeof(ia[0]);
  93. SampleItem oa[1];
  94. std::minstd_rand g;
  95. SampleIterator end =
  96. std::sample(PopulationIterator(ia), PopulationIterator(ia + is),
  97. SampleIterator(oa), 0, g);
  98. assert(end.base() == oa);
  99. }
  100. template <template<class...> class PopulationIteratorType, class PopulationItem,
  101. template<class...> class SampleIteratorType, class SampleItem>
  102. void test_small_population() {
  103. // The population size is less than the sample size.
  104. typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
  105. typedef SampleIteratorType<SampleItem *> SampleIterator;
  106. PopulationItem ia[] = {1, 2, 3, 4, 5};
  107. const unsigned is = sizeof(ia) / sizeof(ia[0]);
  108. const unsigned os = 8;
  109. SampleItem oa[os];
  110. const SampleItem oa1[] = {1, 2, 3, 4, 5};
  111. std::minstd_rand g;
  112. SampleIterator end;
  113. end = std::sample(PopulationIterator(ia),
  114. PopulationIterator(ia + is),
  115. SampleIterator(oa), os, g);
  116. assert(static_cast<std::size_t>(end.base() - oa) == std::min(os, is));
  117. typedef typename std::iterator_traits<PopulationIterator>::iterator_category PopulationCategory;
  118. if (std::is_base_of<std::forward_iterator_tag, PopulationCategory>::value) {
  119. assert(std::equal(oa, end.base(), oa1));
  120. } else {
  121. assert(std::is_permutation(oa, end.base(), oa1));
  122. }
  123. }
  124. int main() {
  125. test<input_iterator, int, random_access_iterator, int>();
  126. test<forward_iterator, int, output_iterator, int>();
  127. test<forward_iterator, int, random_access_iterator, int>();
  128. test<input_iterator, int, random_access_iterator, double>();
  129. test<forward_iterator, int, output_iterator, double>();
  130. test<forward_iterator, int, random_access_iterator, double>();
  131. test_empty_population<input_iterator, int, random_access_iterator, int>();
  132. test_empty_population<forward_iterator, int, output_iterator, int>();
  133. test_empty_population<forward_iterator, int, random_access_iterator, int>();
  134. test_empty_sample<input_iterator, int, random_access_iterator, int>();
  135. test_empty_sample<forward_iterator, int, output_iterator, int>();
  136. test_empty_sample<forward_iterator, int, random_access_iterator, int>();
  137. test_small_population<input_iterator, int, random_access_iterator, int>();
  138. test_small_population<forward_iterator, int, output_iterator, int>();
  139. test_small_population<forward_iterator, int, random_access_iterator, int>();
  140. }