minmax_element.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. //===----------------------------------------------------------------------===//
  12. //
  13. // The LLVM Compiler Infrastructure
  14. //
  15. // This file is dual licensed under the MIT and the University of Illinois Open
  16. // Source Licenses. See LICENSE.TXT for details.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #include <memory>
  20. #include <numeric>
  21. #include <random>
  22. #include <algorithm>
  23. #include <range/v3/core.hpp>
  24. #include <range/v3/algorithm/minmax_element.hpp>
  25. #include "../array.hpp"
  26. #include "../simple_test.hpp"
  27. #include "../test_utils.hpp"
  28. #include "../test_iterators.hpp"
  29. RANGES_DIAGNOSTIC_IGNORE_GLOBAL_CONSTRUCTORS
  30. namespace
  31. {
  32. std::mt19937 gen;
  33. template<class Iter, class Sent = Iter>
  34. void
  35. test_iter(Iter first, Sent last)
  36. {
  37. ranges::minmax_element_result<Iter> p = ranges::minmax_element(first, last);
  38. if (first != last)
  39. {
  40. for (Iter j = first; j != last; ++j)
  41. {
  42. CHECK(!(*j < *p.min));
  43. CHECK(!(*p.max < *j));
  44. }
  45. }
  46. else
  47. {
  48. CHECK(p.min == last);
  49. CHECK(p.max == last);
  50. }
  51. auto rng = ::MakeTestRange(first, last);
  52. p = ranges::minmax_element(rng);
  53. if (first != last)
  54. {
  55. for (Iter j = first; j != last; ++j)
  56. {
  57. CHECK(!(*j < *p.min));
  58. CHECK(!(*p.max < *j));
  59. }
  60. }
  61. else
  62. {
  63. CHECK(p.min == last);
  64. CHECK(p.max == last);
  65. }
  66. auto res = ranges::minmax_element(std::move(rng));
  67. if (first != last)
  68. {
  69. for (Iter j = first; j != last; ++j)
  70. {
  71. CHECK(is_dangling(res.min));
  72. CHECK(!(*p.max < *j));
  73. }
  74. }
  75. else
  76. {
  77. CHECK(is_dangling(res.min));
  78. CHECK(is_dangling(res.max));
  79. }
  80. }
  81. template<class Iter, class Sent = Iter>
  82. void
  83. test_iter(unsigned N)
  84. {
  85. std::unique_ptr<int[]> a{new int[N]};
  86. std::iota(a.get(), a.get()+N, 0);
  87. std::shuffle(a.get(), a.get()+N, gen);
  88. test_iter(Iter(a.get()), Sent(a.get()+N));
  89. }
  90. template<class Iter, class Sent = Iter>
  91. void
  92. test_iter()
  93. {
  94. test_iter<Iter, Sent>(0);
  95. test_iter<Iter, Sent>(1);
  96. test_iter<Iter, Sent>(2);
  97. test_iter<Iter, Sent>(3);
  98. test_iter<Iter, Sent>(10);
  99. test_iter<Iter, Sent>(1000);
  100. {
  101. const unsigned N = 100;
  102. std::unique_ptr<int[]> a{new int[N]};
  103. std::fill_n(a.get(), N, 5);
  104. std::shuffle(a.get(), a.get()+N, gen);
  105. ranges::minmax_element_result<Iter> p = ranges::minmax_element(Iter(a.get()), Sent(a.get()+N));
  106. CHECK(base(p.min) == a.get());
  107. CHECK(base(p.max) == a.get()+N-1);
  108. }
  109. }
  110. template<class Iter, class Sent = Iter>
  111. void
  112. test_iter_comp(Iter first, Sent last)
  113. {
  114. typedef std::greater<int> Compare;
  115. Compare comp;
  116. ranges::minmax_element_result<Iter> p = ranges::minmax_element(first, last, comp);
  117. if (first != last)
  118. {
  119. for (Iter j = first; j != last; ++j)
  120. {
  121. CHECK(!comp(*j, *p.min));
  122. CHECK(!comp(*p.max, *j));
  123. }
  124. }
  125. else
  126. {
  127. CHECK(p.min == last);
  128. CHECK(p.max == last);
  129. }
  130. auto rng = ::MakeTestRange(first, last);
  131. p = ranges::minmax_element(rng, comp);
  132. if (first != last)
  133. {
  134. for (Iter j = first; j != last; ++j)
  135. {
  136. CHECK(!comp(*j, *p.min));
  137. CHECK(!comp(*p.max, *j));
  138. }
  139. }
  140. else
  141. {
  142. CHECK(p.min == last);
  143. CHECK(p.max == last);
  144. }
  145. auto res = ranges::minmax_element(std::move(rng), comp);
  146. CHECK(is_dangling(res.min));
  147. CHECK(is_dangling(res.max));
  148. }
  149. template<class Iter, class Sent = Iter>
  150. void
  151. test_iter_comp(unsigned N)
  152. {
  153. std::unique_ptr<int[]> a{new int[N]};
  154. std::iota(a.get(), a.get()+N, 0);
  155. std::shuffle(a.get(), a.get()+N, gen);
  156. test_iter_comp(Iter(a.get()), Sent(a.get()+N));
  157. }
  158. template<class Iter, class Sent = Iter>
  159. void
  160. test_iter_comp()
  161. {
  162. test_iter_comp<Iter, Sent>(0);
  163. test_iter_comp<Iter, Sent>(1);
  164. test_iter_comp<Iter, Sent>(2);
  165. test_iter_comp<Iter, Sent>(3);
  166. test_iter_comp<Iter, Sent>(10);
  167. test_iter_comp<Iter, Sent>(1000);
  168. {
  169. const unsigned N = 100;
  170. std::unique_ptr<int[]> a{new int[N]};
  171. std::fill_n(a.get(), N, 5);
  172. std::shuffle(a.get(), a.get()+N, gen);
  173. typedef std::greater<int> Compare;
  174. Compare comp;
  175. ranges::minmax_element_result<Iter> p = ranges::minmax_element(Iter(a.get()), Sent(a.get()+N), comp);
  176. CHECK(base(p.min) == a.get());
  177. CHECK(base(p.max) == a.get()+N-1);
  178. }
  179. }
  180. struct S
  181. {
  182. int i;
  183. };
  184. }
  185. int main()
  186. {
  187. test_iter<ForwardIterator<const int*> >();
  188. test_iter<BidirectionalIterator<const int*> >();
  189. test_iter<RandomAccessIterator<const int*> >();
  190. test_iter<const int*>();
  191. test_iter<ForwardIterator<const int*>, Sentinel<const int*>>();
  192. test_iter<BidirectionalIterator<const int*>, Sentinel<const int*>>();
  193. test_iter<RandomAccessIterator<const int*>, Sentinel<const int*>>();
  194. test_iter<ForwardIterator<const int*> >();
  195. test_iter<BidirectionalIterator<const int*> >();
  196. test_iter<RandomAccessIterator<const int*> >();
  197. test_iter<const int*>();
  198. test_iter<ForwardIterator<const int*>, Sentinel<const int*>>();
  199. test_iter<BidirectionalIterator<const int*>, Sentinel<const int*>>();
  200. test_iter<RandomAccessIterator<const int*>, Sentinel<const int*>>();
  201. test_iter_comp<ForwardIterator<const int*> >();
  202. test_iter_comp<BidirectionalIterator<const int*> >();
  203. test_iter_comp<RandomAccessIterator<const int*> >();
  204. test_iter_comp<const int*>();
  205. test_iter_comp<ForwardIterator<const int*>, Sentinel<const int*>>();
  206. test_iter_comp<BidirectionalIterator<const int*>, Sentinel<const int*>>();
  207. test_iter_comp<RandomAccessIterator<const int*>, Sentinel<const int*>>();
  208. test_iter_comp<ForwardIterator<const int*> >();
  209. test_iter_comp<BidirectionalIterator<const int*> >();
  210. test_iter_comp<RandomAccessIterator<const int*> >();
  211. test_iter_comp<const int*>();
  212. test_iter_comp<ForwardIterator<const int*>, Sentinel<const int*>>();
  213. test_iter_comp<BidirectionalIterator<const int*>, Sentinel<const int*>>();
  214. test_iter_comp<RandomAccessIterator<const int*>, Sentinel<const int*>>();
  215. // Works with projections?
  216. S s[] = {S{1},S{2},S{3},S{4},S{-4},S{5},S{6},S{40},S{7},S{8},S{9}};
  217. ranges::minmax_element_result<S const *> ps = ranges::minmax_element(s, std::less<int>{}, &S::i);
  218. CHECK(ps.min->i == -4);
  219. CHECK(ps.max->i == 40);
  220. {
  221. constexpr auto a = test::array<int, 10>{{1, 2, 3, 4, -4, 5, 6, 40, 8, 9}};
  222. STATIC_CHECK(ranges::minmax_element(a).min == ranges::begin(a) + 4);
  223. STATIC_CHECK(ranges::minmax_element(a).max == ranges::begin(a) + 7);
  224. }
  225. return test_result();
  226. }