test_radix_sort_by_key.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2016 Jakub Szuppe <j.szuppe@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #define BOOST_TEST_MODULE TestRadixSortByKey
  11. #include <boost/test/unit_test.hpp>
  12. #include <iostream>
  13. #include <boost/compute/system.hpp>
  14. #include <boost/compute/algorithm/is_sorted.hpp>
  15. #include <boost/compute/algorithm/detail/radix_sort.hpp>
  16. #include <boost/compute/container/vector.hpp>
  17. #include "quirks.hpp"
  18. #include "check_macros.hpp"
  19. #include "context_setup.hpp"
  20. namespace compute = boost::compute;
  21. const bool descending = false;
  22. // radix_sort_by_key should be stable
  23. BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_int)
  24. {
  25. if(is_apple_cpu_device(device)) {
  26. std::cerr
  27. << "skipping all radix_sort_by_key tests due to Apple platform"
  28. << " behavior when local memory is used on a CPU device"
  29. << std::endl;
  30. return;
  31. }
  32. compute::int_ keys_data[] = { 10, 9, 2, 7, 6, -1, 4, 2, 2, 10 };
  33. compute::int_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  34. compute::vector<compute::int_> keys(keys_data, keys_data + 10, queue);
  35. compute::vector<compute::int_> values(values_data, values_data + 10, queue);
  36. BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
  37. compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
  38. BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
  39. CHECK_RANGE_EQUAL(
  40. compute::int_, 10, keys,
  41. (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
  42. // ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
  43. );
  44. CHECK_RANGE_EQUAL(
  45. compute::int_, 10, values,
  46. // (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
  47. ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
  48. );
  49. }
  50. // radix_sort_by_key should be stable
  51. BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_int_desc)
  52. {
  53. if(is_apple_cpu_device(device)) {
  54. return;
  55. }
  56. compute::int_ keys_data[] = { 10, 9, 2, 7, 6, -1, 4, 2, 2, 10 };
  57. compute::int_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  58. compute::vector<compute::int_> keys(keys_data, keys_data + 10, queue);
  59. compute::vector<compute::int_> values(values_data, values_data + 10, queue);
  60. BOOST_CHECK(
  61. !compute::is_sorted(
  62. keys.begin(), keys.end(), compute::greater<compute::int_>(), queue
  63. )
  64. );
  65. compute::detail::radix_sort_by_key(
  66. keys.begin(), keys.end(), values.begin(), descending, queue
  67. );
  68. BOOST_CHECK(
  69. compute::is_sorted(
  70. keys.begin(), keys.end(), compute::greater<compute::int_>(), queue
  71. )
  72. );
  73. CHECK_RANGE_EQUAL(
  74. compute::int_, 10, keys,
  75. (10, 10, 9, 7, 6, 4, 2, 2, 2, -1) // keys
  76. // ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) values
  77. );
  78. CHECK_RANGE_EQUAL(
  79. compute::int_, 10, values,
  80. // (10, 10, 9, 7, 6, 4, 2, 2, 2, -1) // keys
  81. ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) // values
  82. );
  83. }
  84. // radix_sort_by_key should be stable
  85. BOOST_AUTO_TEST_CASE(stable_radix_sort_uint_by_uint)
  86. {
  87. if(is_apple_cpu_device(device)) {
  88. return;
  89. }
  90. compute::uint_ keys_data[] = { 10, 9, 2, 7, 6, 1, 4, 2, 2, 10 };
  91. compute::uint_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  92. compute::vector<compute::uint_> keys(keys_data, keys_data + 10, queue);
  93. compute::vector<compute::uint_> values(values_data, values_data + 10, queue);
  94. BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
  95. compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
  96. BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
  97. CHECK_RANGE_EQUAL(
  98. compute::uint_, 10, keys,
  99. (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
  100. // (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
  101. );
  102. CHECK_RANGE_EQUAL(
  103. compute::uint_, 10, values,
  104. // (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
  105. (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
  106. );
  107. }
  108. // radix_sort_by_key should be stable
  109. BOOST_AUTO_TEST_CASE(stable_radix_sort_uint_by_uint_desc)
  110. {
  111. if(is_apple_cpu_device(device)) {
  112. return;
  113. }
  114. compute::uint_ keys_data[] = { 10, 9, 2, 7, 6, 1, 4, 2, 2, 10 };
  115. compute::uint_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  116. compute::vector<compute::uint_> keys(keys_data, keys_data + 10, queue);
  117. compute::vector<compute::uint_> values(values_data, values_data + 10, queue);
  118. BOOST_CHECK(
  119. !compute::is_sorted(
  120. keys.begin(), keys.end(), compute::greater<compute::uint_>(), queue
  121. )
  122. );
  123. compute::detail::radix_sort_by_key(
  124. keys.begin(), keys.end(), values.begin(), descending, queue
  125. );
  126. BOOST_CHECK(
  127. compute::is_sorted(
  128. keys.begin(), keys.end(), compute::greater<compute::uint_>(), queue
  129. )
  130. );
  131. CHECK_RANGE_EQUAL(
  132. compute::uint_, 10, keys,
  133. (10, 10, 9, 7, 6, 4, 2, 2, 2, 1) // keys
  134. // ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) values
  135. );
  136. CHECK_RANGE_EQUAL(
  137. compute::uint_, 10, values,
  138. // (10, 10, 9, 7, 6, 4, 2, 2, 2, 1) // keys
  139. ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) // values
  140. );
  141. }
  142. // radix_sort_by_key should be stable
  143. BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_float)
  144. {
  145. if(is_apple_cpu_device(device)) {
  146. return;
  147. }
  148. compute::float_ keys_data[] = { 10., 5.5, 10., 7., 5.5};
  149. compute::int_ values_data[] = { 1, 200, -10, 2, 4 };
  150. compute::vector<compute::float_> keys(keys_data, keys_data + 5, queue);
  151. compute::vector<compute::uint_> values(values_data, values_data + 5, queue);
  152. BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
  153. compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
  154. BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
  155. CHECK_RANGE_EQUAL(
  156. compute::float_, 5, keys,
  157. (5.5, 5.5, 7., 10., 10.) // keys
  158. // (200, 4, 2, 1, -10) values
  159. );
  160. CHECK_RANGE_EQUAL(
  161. compute::int_, 5, values,
  162. // (5.5, 5.5, 7., 10., 10.) keys
  163. (200, 4, 2, 1, -10) // values
  164. );
  165. }
  166. // radix_sort_by_key should be stable
  167. BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_float_desc)
  168. {
  169. if(is_apple_cpu_device(device)) {
  170. return;
  171. }
  172. compute::float_ keys_data[] = { 10., 5.5, 10., 7., 5.5};
  173. compute::int_ values_data[] = { 1, 200, -10, 2, 4 };
  174. compute::vector<compute::float_> keys(keys_data, keys_data + 5, queue);
  175. compute::vector<compute::uint_> values(values_data, values_data + 5, queue);
  176. BOOST_CHECK(
  177. !compute::is_sorted(
  178. keys.begin(), keys.end(), compute::greater<compute::float_>(), queue
  179. )
  180. );
  181. compute::detail::radix_sort_by_key(
  182. keys.begin(), keys.end(), values.begin(), descending, queue
  183. );
  184. BOOST_CHECK(
  185. compute::is_sorted(
  186. keys.begin(), keys.end(), compute::greater<compute::float_>(), queue
  187. )
  188. );
  189. CHECK_RANGE_EQUAL(
  190. compute::float_, 5, keys,
  191. (10., 10., 7., 5.5, 5.5) // keys
  192. // ( 1, -10, 2, 200, 4) values
  193. );
  194. CHECK_RANGE_EQUAL(
  195. compute::int_, 5, values,
  196. // (10., 10., 7., 5.5, 5.5) // keys
  197. ( 1, -10, 2, 200, 4) // values
  198. );
  199. }
  200. // radix_sort_by_key should be stable
  201. BOOST_AUTO_TEST_CASE(stable_radix_sort_char_by_int)
  202. {
  203. if(is_apple_cpu_device(device)) {
  204. return;
  205. }
  206. compute::int_ keys_data[] = { 6, 1, 1, 3, 4, 7, 5, 1 };
  207. compute::char_ values_data[] = { 'g', 'c', 'b', 'd', 'e', 'h', 'f', 'a' };
  208. compute::vector<compute::int_> keys(keys_data, keys_data + 8, queue);
  209. compute::vector<compute::char_> values(values_data, values_data + 8, queue);
  210. BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
  211. compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
  212. BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
  213. CHECK_RANGE_EQUAL(
  214. compute::int_, 8, keys,
  215. (1, 1, 1, 3, 4, 5, 6, 7)
  216. );
  217. CHECK_RANGE_EQUAL(
  218. compute::char_, 8, values,
  219. ('c', 'b', 'a', 'd', 'e', 'f', 'g', 'h')
  220. );
  221. }
  222. // radix_sort_by_key should be stable
  223. BOOST_AUTO_TEST_CASE(stable_radix_sort_int2_by_int)
  224. {
  225. if(is_apple_cpu_device(device)) {
  226. return;
  227. }
  228. compute::int_ keys_data[] = { 6, 1, 1, 3, 4, 7, 5, 1 };
  229. compute::int2_ values_data[] = {
  230. compute::int2_(1, 1), // 6
  231. compute::int2_(1, 2), // 1
  232. compute::int2_(1, 3), // 1
  233. compute::int2_(1, 4), // 3
  234. compute::int2_(1, 5), // 4
  235. compute::int2_(1, 6), // 7
  236. compute::int2_(1, 7), // 5
  237. compute::int2_(1, 8) // 1
  238. };
  239. compute::vector<compute::int_> keys(keys_data, keys_data + 8, queue);
  240. compute::vector<compute::int2_> values(values_data, values_data + 8, queue);
  241. BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
  242. compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
  243. BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
  244. CHECK_RANGE_EQUAL(
  245. compute::int_, 8, keys,
  246. (1, 1, 1, 3, 4, 5, 6, 7)
  247. );
  248. CHECK_RANGE_EQUAL(
  249. compute::int2_, 8, values,
  250. (
  251. compute::int2_(1, 2),
  252. compute::int2_(1, 3),
  253. compute::int2_(1, 8),
  254. compute::int2_(1, 4),
  255. compute::int2_(1, 5),
  256. compute::int2_(1, 7),
  257. compute::int2_(1, 1),
  258. compute::int2_(1, 6)
  259. )
  260. );
  261. }
  262. BOOST_AUTO_TEST_SUITE_END()