main.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //#define NDEBUG 1
  2. #ifndef __cplusplus
  3. #error A C++ compiler is required.
  4. #endif
  5. #include <vector>
  6. #include <queue>
  7. #include <iostream>
  8. #include <stdint.h>
  9. #include <time.h>
  10. #include <algorithm>
  11. #include "priority_deque.hpp"
  12. #include "priority_deque_verify.hpp"
  13. int main();
  14. //! @todo More tests!
  15. #define BENCHMARK
  16. #define VERIFY_HEAP
  17. template <typename pq_t>
  18. void benchmark_priority_queue (unsigned benchmark_elements) {
  19. pq_t pq;
  20. clock_t bench_begin, bench_mid, bench_end;
  21. std::cout << "Benchmark results: ";
  22. // First, fill the queue with most of the elements, to get a better idea of the average case.
  23. for (unsigned n = benchmark_elements / 2; n--;)
  24. pq.push(rand());
  25. // Test how long it takes to fill the rest of the way.
  26. bench_begin = clock();
  27. for (unsigned n = benchmark_elements / 2; n--;)
  28. pq.push(rand());
  29. bench_mid = clock();
  30. std::cout << "Push: " << (bench_mid - bench_begin) << " (" << static_cast<double>(bench_mid - bench_begin) / CLOCKS_PER_SEC << "s)";
  31. // Test time required to remove the same number of elements.
  32. bench_mid = clock();
  33. for (unsigned n = benchmark_elements / 2; n--;)
  34. pq.pop();
  35. bench_end = clock();
  36. std::cout << ", Pop: " << (bench_end - bench_mid) << " (" << static_cast<double>(bench_end - bench_mid) / CLOCKS_PER_SEC << "s)\n";
  37. }
  38. int main() {
  39. std::cout << "__cplusplus = " << __cplusplus << "\n";
  40. #ifndef NDEBUG
  41. std::cout << "Debug mode (asserts active).\n";
  42. #endif
  43. srand(clock());
  44. using boost::container::priority_deque;
  45. using boost::heap::is_interval_heap;
  46. using std::priority_queue;
  47. // Begin tests
  48. {
  49. priority_deque<int> test_deque;
  50. // Sufficient sample size for observing all potential interesting behaviors.
  51. for (int i = 0; i < 256; ++i) {
  52. try {
  53. test_deque.push(i);
  54. if (std::find(test_deque.begin(), test_deque.end(), i) == test_deque.end()) {
  55. std::cerr << "Element lost <push>.\n";
  56. break;
  57. }
  58. if (!is_interval_heap(test_deque.begin(), test_deque.end(), std::less<int>())) {
  59. std::cerr << "Heap corrupted <push>.\n";
  60. break;
  61. }
  62. if (test_deque.maximum() != i)
  63. std::cerr << "Incorrect maximum. i = " << i << "\n";
  64. } catch (...) {
  65. std::cerr << "Exception thrown <push>.\n";
  66. break;
  67. }
  68. }
  69. std::vector<int> test_vector;
  70. for (int i = 0; i < 256; ++i) {
  71. test_vector.push_back(i);
  72. std::random_shuffle(test_vector.begin(), test_vector.end());
  73. try {
  74. test_deque.clear();
  75. test_deque.merge(test_vector);
  76. if (test_deque.size() != test_vector.size())
  77. std::cerr << "Merge changed number of elements.\n";
  78. for (int j = 0; j <= i; ++j) {
  79. if (std::find(test_deque.begin(), test_deque.end(), j) == test_deque.end()) {
  80. std::cerr << "Element removed <merge>.\n";
  81. break;
  82. }
  83. }
  84. if (!is_interval_heap(test_deque.begin(), test_deque.end(), std::less<int>())) {
  85. std::cerr << "Heap corrupted <merge>.\n";
  86. break;
  87. }
  88. } catch (...) {
  89. std::cerr << "Exception thrown <merge>.\n";
  90. break;
  91. }
  92. }
  93. }
  94. // Benchmark performance relative to std::priority_queue.
  95. #ifdef BENCHMARK
  96. {
  97. typedef intmax_t benchmark_type;
  98. const unsigned benchmark_elements = 20000000;
  99. std::cout << "PD: ";
  100. benchmark_priority_queue<priority_deque<benchmark_type> >(benchmark_elements);
  101. std::cout << "PQ: ";
  102. benchmark_priority_queue<priority_queue<benchmark_type> >(benchmark_elements);
  103. }
  104. #endif
  105. #ifdef VERIFY_HEAP
  106. std::cout << "\n\nTesting heap integrity after:\n";
  107. const int element_total = 3001;//8192 * 2000;
  108. priority_deque<uint32_t> pd;
  109. std::cout << "'push' (" << element_total << "x)\n";
  110. for (int n = 1; n <= element_total; ++n) {
  111. pd.push(rand());
  112. if (is_valid_until(pd) != pd.end()) {
  113. std::cout << "Failed push (error in replace_leaf)\n";
  114. break;
  115. }
  116. }
  117. srand(25346);
  118. std::vector<uint32_t> v;
  119. for (int n = 1; n <= 5; ++n)
  120. v.push_back(rand());
  121. for (int n = 1; n <= 1; ++n) {
  122. std::cout << "'merge' (" << v.size() << " elements)\n";
  123. /*for (auto it = v.begin(); it != v.end(); ++it)
  124. std::cout << *it << ", ";
  125. std::cout << "\n";*/
  126. boost::heap::make_interval_heap(v.begin(), v.end(), std::less<uint32_t>());
  127. if (!boost::heap::is_interval_heap(v.begin(), v.end(), std::less<uint32_t>())) {
  128. std::cout << "Failed\n";
  129. for (auto it = v.begin(); it != v.end(); ++it)
  130. std::cout << *it << ", ";
  131. std::cout << "\n";
  132. }
  133. std::random_shuffle(v.begin(), v.end());
  134. v.push_back(rand());
  135. }
  136. /*for (int n = 1; n < 64; ++n) {
  137. std::cout << "'merge' (" << v.size() << " elements)\n";
  138. pd.clear();
  139. pd.merge(v.begin(), v.end());
  140. if (is_valid_until(pd) != pd.end())
  141. std::cout << "Failed merge (error in make_valid)\n";
  142. v.push_back(rand());
  143. }*/
  144. std::cout << "'set' (" << element_total << "x)\n";
  145. for (int t = 0; t < element_total; ++t) {
  146. pd.update(pd.begin() + rand() % pd.size(), rand());
  147. if (is_valid_until(pd) != pd.end()) {
  148. std::cout << "Failed random-access set (error in replace)\n";
  149. break;
  150. }
  151. }
  152. std::cout << "'pop_minimum' (" << pd.size() << "x)\n";
  153. while (!pd.empty()) {
  154. pd.pop_minimum();
  155. if (is_valid_until(pd) != pd.end()) {
  156. std::cout << "Failed pop_minimum (error in replace)\n";
  157. break;
  158. }
  159. }
  160. pd.clear();
  161. std::cout << "'push', 'pop_maximum', 'pop_minimum', 'erase', 'set' (indefinitely)\n";
  162. boost::container::priority_deque<int> test_pd;
  163. for (int n = 0; n < 13; ++n) {
  164. test_pd.push(rand());
  165. if (is_valid_until(pd) != pd.end())
  166. std::cout << "Failed push (error in replace_leaf)\n";
  167. }
  168. int last_rand = -1;
  169. while (true) {
  170. if (test_pd.size() < 3000) {
  171. last_rand = -1;
  172. test_pd.push(rand());
  173. } else {
  174. last_rand = rand() % 8;
  175. switch (last_rand) {
  176. case 0: test_pd.pop_maximum(); break;
  177. case 1: test_pd.pop_minimum(); break;
  178. case 2: test_pd.erase(test_pd.begin() + rand() % test_pd.size()); break;
  179. default: test_pd.update(test_pd.begin() + rand() % test_pd.size(), rand());
  180. }
  181. }
  182. if (is_valid_until(pd) != pd.end()) {
  183. std::cout << "An error has occurred! (code " << last_rand << ").\n";
  184. break;
  185. }
  186. }
  187. #endif
  188. return 0;
  189. }