nth_element.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright Neil Groves 2009. Use, modification and
  2. // distribution is subject to the Boost Software License, Version
  3. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. //
  7. // For more information, see http://www.boost.org/libs/range/
  8. //
  9. #include <boost/range/algorithm/nth_element.hpp>
  10. #include <boost/test/test_tools.hpp>
  11. #include <boost/test/unit_test.hpp>
  12. #include <boost/assign.hpp>
  13. #include <boost/bind.hpp>
  14. #include <algorithm>
  15. #include <functional>
  16. #include <list>
  17. #include <numeric>
  18. #include <deque>
  19. #include <vector>
  20. namespace boost
  21. {
  22. namespace
  23. {
  24. struct nth_element_policy
  25. {
  26. template<class Container, class Iterator>
  27. void test_nth_element(Container& cont, Iterator mid)
  28. {
  29. const Container old_cont(cont);
  30. boost::nth_element(cont, mid);
  31. // Test the same operation on the container, for the
  32. // case where a temporary is passed as the first
  33. // argument.
  34. Container cont2(old_cont);
  35. const std::size_t index = std::distance(cont.begin(), mid);
  36. Iterator mid2(cont2.begin());
  37. std::advance(mid2, index);
  38. boost::nth_element(boost::make_iterator_range(cont2), mid2);
  39. BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(),
  40. cont2.begin(), cont2.end() );
  41. }
  42. template<class Container, class Iterator>
  43. void reference_nth_element(Container& cont, Iterator mid)
  44. {
  45. std::nth_element(cont.begin(), mid, cont.end());
  46. }
  47. };
  48. template<class BinaryPredicate>
  49. struct nth_element_pred_policy
  50. {
  51. template<class Container, class Iterator>
  52. void test_nth_element(Container& cont, Iterator mid)
  53. {
  54. const Container old_cont(cont);
  55. boost::nth_element(cont, mid, BinaryPredicate());
  56. Container cont2(old_cont);
  57. const std::size_t index = std::distance(cont.begin(), mid);
  58. Iterator mid2(cont2.begin());
  59. std::advance(mid2, index);
  60. boost::nth_element(boost::make_iterator_range(cont2), mid2,
  61. BinaryPredicate());
  62. BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(),
  63. cont2.begin(), cont2.end() );
  64. }
  65. template<class Container, class Iterator>
  66. void reference_nth_element(Container& cont, Iterator mid)
  67. {
  68. std::nth_element(cont.begin(), mid, cont.end(), BinaryPredicate());
  69. }
  70. };
  71. template<class Container, class TestPolicy>
  72. void test_nth_element_tp_impl(Container& cont, TestPolicy policy)
  73. {
  74. Container reference(cont);
  75. Container test(cont);
  76. typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
  77. BOOST_CHECK_EQUAL( reference.size(), test.size() );
  78. if (reference.size() != test.size())
  79. return;
  80. iterator_t reference_mid = reference.begin();
  81. iterator_t test_mid = test.begin();
  82. bool complete = false;
  83. while (!complete)
  84. {
  85. if (reference_mid == reference.end())
  86. complete = true;
  87. policy.test_nth_element(test, test_mid);
  88. policy.reference_nth_element(reference, reference_mid);
  89. BOOST_CHECK_EQUAL_COLLECTIONS(
  90. reference.begin(), reference.end(),
  91. test.begin(), test.end()
  92. );
  93. if (reference_mid != reference.end())
  94. {
  95. ++reference_mid;
  96. ++test_mid;
  97. }
  98. }
  99. }
  100. template<class Container>
  101. void test_nth_element_impl(Container& cont)
  102. {
  103. test_nth_element_tp_impl(cont, nth_element_policy());
  104. }
  105. template<class Container, class BinaryPredicate>
  106. void test_nth_element_impl(Container& cont, BinaryPredicate pred)
  107. {
  108. test_nth_element_tp_impl(cont, nth_element_pred_policy<BinaryPredicate>());
  109. }
  110. template<class Container>
  111. void run_tests(Container& cont)
  112. {
  113. test_nth_element_impl(cont);
  114. test_nth_element_impl(cont, std::less<int>());
  115. test_nth_element_impl(cont, std::greater<int>());
  116. }
  117. template<class Container>
  118. void test_nth_element_impl()
  119. {
  120. using namespace boost::assign;
  121. Container cont;
  122. run_tests(cont);
  123. cont.clear();
  124. cont += 1;
  125. run_tests(cont);
  126. cont.clear();
  127. cont += 1,2,3,4,5,6,7,8,9;
  128. run_tests(cont);
  129. }
  130. void test_nth_element()
  131. {
  132. test_nth_element_impl< std::vector<int> >();
  133. test_nth_element_impl< std::deque<int> >();
  134. }
  135. }
  136. }
  137. boost::unit_test::test_suite*
  138. init_unit_test_suite(int argc, char* argv[])
  139. {
  140. boost::unit_test::test_suite* test
  141. = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.nth_element" );
  142. test->add( BOOST_TEST_CASE( &boost::test_nth_element ) );
  143. return test;
  144. }