float_sort_test.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Boost Sort library float_sort_test.cpp file -----------------------------//
  2. // Copyright Steven Ross 2014. 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 <boost/sort/spreadsort/spreadsort.hpp>
  8. // Include unit test framework
  9. #include <boost/test/included/test_exec_monitor.hpp>
  10. #include <boost/test/test_tools.hpp>
  11. #include <vector>
  12. using namespace std;
  13. using namespace boost::sort::spreadsort;
  14. //Casting to an integer before bitshifting
  15. struct rightshift {
  16. int operator()(const float &x, const unsigned offset) const {
  17. return float_mem_cast<float, int>(x) >> offset;
  18. }
  19. };
  20. struct rightshift_64 {
  21. boost::int64_t operator()(const double &x, const boost::uint64_t offset) const
  22. {
  23. return float_mem_cast<double, boost::int64_t>(x) >> offset;
  24. }
  25. };
  26. boost::int32_t
  27. rand_32(bool sign = true) {
  28. boost::int32_t result = rand() | (rand()<< 16);
  29. if (rand() % 2)
  30. result |= 1 << 15;
  31. //Adding the sign bit
  32. if (sign && (rand() % 2))
  33. result *= -1;
  34. return result;
  35. }
  36. static const unsigned input_count = 1000000;
  37. // Helper class to run tests across all float_sort interface variants.
  38. template<class FloatType, class RightShift>
  39. void test_vector(vector<FloatType> base_vec, RightShift shifter) {
  40. vector<FloatType> sorted_vec = base_vec;
  41. vector<FloatType> test_vec = base_vec;
  42. std::sort(sorted_vec.begin(), sorted_vec.end());
  43. //Testing boost::sort::spreadsort version
  44. test_vec = base_vec;
  45. boost::sort::spreadsort::spreadsort(test_vec.begin(), test_vec.end());
  46. BOOST_CHECK(test_vec == sorted_vec);
  47. //One functor
  48. test_vec = base_vec;
  49. float_sort(test_vec.begin(), test_vec.end(), shifter);
  50. BOOST_CHECK(test_vec == sorted_vec);
  51. //Both functors
  52. test_vec = base_vec;
  53. float_sort(test_vec.begin(), test_vec.end(), shifter, less<FloatType>());
  54. BOOST_CHECK(test_vec == sorted_vec);
  55. }
  56. void float_test()
  57. {
  58. // Prepare inputs
  59. vector<float> base_vec;
  60. //Generating semirandom numbers that will work for basic testing
  61. for (unsigned u = 0; u < input_count; ++u) {
  62. float val = float(rand_32());
  63. //As std::sort gives arbitrary results for NaNs and 0.0 vs. -0.0, treat all
  64. //those as just 0.0 for testing
  65. if (!(val < 0.0) && !(0.0 < val))
  66. base_vec.push_back(0.0);
  67. else
  68. base_vec.push_back(val);
  69. }
  70. test_vector(base_vec, rightshift());
  71. // Trying both positive and negative sorted and reverse sorted data.
  72. base_vec.clear();
  73. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(-i);
  74. test_vector(base_vec, rightshift());
  75. base_vec.clear();
  76. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(i - input_count);
  77. test_vector(base_vec, rightshift());
  78. base_vec.clear();
  79. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(input_count - i);
  80. test_vector(base_vec, rightshift());
  81. base_vec.clear();
  82. for (size_t i = 0; i < input_count; ++i) base_vec.push_back(i);
  83. test_vector(base_vec, rightshift());
  84. base_vec.clear();
  85. for (size_t i = 0; i < input_count; ++i) base_vec.push_back(i);
  86. for (size_t i = 0; i < input_count; i += 2) base_vec[i] *= -1;
  87. test_vector(base_vec, rightshift());
  88. }
  89. void double_test() {
  90. vector<double> base_vec;
  91. for (unsigned u = 0; u < input_count; ++u) {
  92. double val = double
  93. ((((boost::int64_t)rand_32()) << ((8 * sizeof(int)) -1)) + rand_32(false));
  94. //As std::sort gives arbitrary results for NaNs and 0.0 vs. -0.0,
  95. //treat all those as just 0.0 for testing
  96. if (!(val < 0.0) && !(0.0 < val))
  97. base_vec.push_back(0.0);
  98. else
  99. base_vec.push_back(val);
  100. }
  101. test_vector(base_vec, rightshift_64());
  102. // Trying both positive and negative sorted and reverse sorted data.
  103. base_vec.clear();
  104. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(-i);
  105. test_vector(base_vec, rightshift_64());
  106. base_vec.clear();
  107. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(i - input_count);
  108. test_vector(base_vec, rightshift_64());
  109. base_vec.clear();
  110. for (int i = 0; i < (int)input_count; ++i) base_vec.push_back(input_count - i);
  111. test_vector(base_vec, rightshift_64());
  112. base_vec.clear();
  113. for (size_t i = 0; i < input_count; ++i) base_vec.push_back(i);
  114. test_vector(base_vec, rightshift_64());
  115. base_vec.clear();
  116. for (size_t i = 0; i < input_count; ++i) base_vec.push_back(i);
  117. for (size_t i = 0; i < input_count; i += 2) base_vec[i] *= -1;
  118. test_vector(base_vec, rightshift_64());
  119. }
  120. // Verify that 0 and 1 elements work correctly.
  121. void corner_test() {
  122. vector<float> test_vec;
  123. boost::sort::spreadsort::spreadsort(test_vec.begin(), test_vec.end());
  124. const float test_value = -0.0;
  125. test_vec.push_back(test_value);
  126. boost::sort::spreadsort::spreadsort(test_vec.begin(), test_vec.end());
  127. BOOST_CHECK(test_vec.size() == 1);
  128. BOOST_CHECK(test_vec[0] == test_value);
  129. }
  130. // test main
  131. int test_main( int, char*[] )
  132. {
  133. srand(1);
  134. float_test();
  135. double_test();
  136. corner_test();
  137. return 0;
  138. }