test_pdqsort.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Boost Sort library test_pdqsort.cpp file ----------------------------//
  2. // Copyright Orson Peters 2017. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org/libs/sort for library home page.
  7. #include <vector>
  8. #include <string>
  9. #include <random>
  10. #include <boost/sort/pdqsort/pdqsort.hpp>
  11. // Include unit test framework
  12. #include <boost/test/included/test_exec_monitor.hpp>
  13. #include <boost/test/test_tools.hpp>
  14. // Gives a vector containing strings with the same order.
  15. std::string u32_to_str(uint32_t n) {
  16. std::string r;
  17. for (int i = 0; i < 32; ++i) {
  18. r = char('0' + (n & 1)) + r;
  19. n >>= 1;
  20. }
  21. return r;
  22. }
  23. std::vector<std::string> vec_u32_to_str(const std::vector<uint32_t>& v) {
  24. std::vector<std::string> r; r.reserve(v.size());
  25. for (size_t i = 0; i < v.size(); ++i) {
  26. r.push_back(u32_to_str(v[i]));
  27. }
  28. return r;
  29. }
  30. // Distributions.
  31. std::vector<uint32_t> shuffled(size_t size, std::mt19937_64& rng) {
  32. std::vector<uint32_t> v; v.reserve(size);
  33. for (uint32_t i = 0; i < size; ++i) v.push_back(i);
  34. std::shuffle(v.begin(), v.end(), rng);
  35. return v;
  36. }
  37. std::vector<uint32_t> shuffled_16_values(size_t size, std::mt19937_64& rng) {
  38. std::vector<uint32_t> v; v.reserve(size);
  39. for (uint32_t i = 0; i < size; ++i) v.push_back(i % 16);
  40. std::shuffle(v.begin(), v.end(), rng);
  41. return v;
  42. }
  43. std::vector<uint32_t> all_equal(size_t size, std::mt19937_64& rng) {
  44. std::vector<uint32_t> v; v.reserve(size);
  45. for (uint32_t i = 0; i < size; ++i) v.push_back(0);
  46. return v;
  47. }
  48. std::vector<uint32_t> ascending(size_t size, std::mt19937_64& rng) {
  49. std::vector<uint32_t> v; v.reserve(size);
  50. for (uint32_t i = 0; i < size; ++i) v.push_back(i);
  51. return v;
  52. }
  53. std::vector<uint32_t> descending(size_t size, std::mt19937_64& rng) {
  54. std::vector<uint32_t> v; v.reserve(size);
  55. for (uint32_t i = size - 1; ; --i) {
  56. v.push_back(i);
  57. if (i == 0) break;
  58. }
  59. return v;
  60. }
  61. std::vector<uint32_t> pipe_organ(size_t size, std::mt19937_64& rng) {
  62. std::vector<uint32_t> v; v.reserve(size);
  63. for (uint32_t i = 0; i < size/2; ++i) v.push_back(i);
  64. for (uint32_t i = size/2; i < size; ++i) v.push_back(size - i);
  65. return v;
  66. }
  67. std::vector<uint32_t> push_front(size_t size, std::mt19937_64& rng) {
  68. std::vector<uint32_t> v; v.reserve(size);
  69. for (uint32_t i = 1; i < size; ++i) v.push_back(i);
  70. v.push_back(0);
  71. return v;
  72. }
  73. std::vector<uint32_t> push_middle(size_t size, std::mt19937_64& rng) {
  74. std::vector<uint32_t> v; v.reserve(size);
  75. for (uint32_t i = 0; i < size; ++i) {
  76. if (i != size/2) v.push_back(i);
  77. }
  78. v.push_back(size/2);
  79. return v;
  80. }
  81. // Tests.
  82. typedef std::vector<uint32_t> (*DistrF)(size_t, std::mt19937_64&);
  83. void execute_test(DistrF distr, std::string distr_name, int repeats) {
  84. // In C++14 we'd just use std::less<>().
  85. std::less<uint32_t> u32less;
  86. std::greater<uint32_t> u32greater;
  87. std::less<std::string> sless;
  88. std::greater<std::string> sgreater;
  89. for (size_t sz = 1; sz <= 1000; sz *= 10) {
  90. // Consistent but pseudorandom tests.
  91. std::mt19937_64 rng; rng.seed(0);
  92. for (int i = 0; i < repeats; ++i) {
  93. std::vector<uint32_t> u32l = distr(sz, rng);
  94. std::vector<uint32_t> u32g = u32l;
  95. std::vector<std::string> sl = vec_u32_to_str(u32l);
  96. std::vector<std::string> sg = sl;
  97. boost::sort::pdqsort(u32l.begin(), u32l.end(), u32less);
  98. boost::sort::pdqsort(u32g.begin(), u32g.end(), u32greater);
  99. boost::sort::pdqsort(sl.begin(), sl.end(), sless);
  100. boost::sort::pdqsort(sg.begin(), sg.end(), sgreater);
  101. BOOST_CHECK_MESSAGE(
  102. std::is_sorted(u32l.begin(), u32l.end(), u32less),
  103. "pdqsort<uint32_t, std::less> " + distr_name + " failed with size " + std::to_string(sz)
  104. );
  105. BOOST_CHECK_MESSAGE(
  106. std::is_sorted(u32g.begin(), u32g.end(), u32greater),
  107. "pdqsort<uint32_t, std::greater> " + distr_name + " failed with size " + std::to_string(sz)
  108. );
  109. BOOST_CHECK_MESSAGE(
  110. std::is_sorted(sl.begin(), sl.end(), sless),
  111. "pdqsort<std::string, std::less> " + distr_name + " failed with size " + std::to_string(sz)
  112. );
  113. BOOST_CHECK_MESSAGE(
  114. std::is_sorted(sg.begin(), sg.end(), sgreater),
  115. "pdqsort<std::string, std::greater> " + distr_name + " failed with size " + std::to_string(sz)
  116. );
  117. }
  118. }
  119. }
  120. // test main
  121. int test_main(int argc, char** argv) {
  122. // No unused warning.
  123. (void) argc; (void) argv;
  124. execute_test(shuffled, "shuffled", 100);
  125. execute_test(shuffled_16_values, "shuffled_16_values", 100);
  126. execute_test(all_equal, "all_equal", 1);
  127. execute_test(ascending, "ascending", 1);
  128. execute_test(descending, "descending", 1);
  129. execute_test(pipe_organ, "pipe_organ", 1);
  130. execute_test(push_front, "push_front", 1);
  131. execute_test(push_middle, "push_middle", 1);
  132. return 0;
  133. }