test_sort.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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 TestSort
  11. #include <boost/test/unit_test.hpp>
  12. #include <boost/compute/system.hpp>
  13. #include <boost/compute/algorithm/sort.hpp>
  14. #include <boost/compute/algorithm/is_sorted.hpp>
  15. #include <boost/compute/container/vector.hpp>
  16. #include <boost/compute/types/struct.hpp>
  17. struct Particle
  18. {
  19. Particle(): x(0.f), y(0.f) { }
  20. Particle(float _x, float _y): x(_x), y(_y) { }
  21. float x;
  22. float y;
  23. };
  24. // adapt struct for OpenCL
  25. BOOST_COMPUTE_ADAPT_STRUCT(Particle, Particle, (x, y))
  26. #include "check_macros.hpp"
  27. #include "context_setup.hpp"
  28. namespace bc = boost::compute;
  29. // test trivial sorting of zero and one element vectors
  30. BOOST_AUTO_TEST_CASE(sort_int_0_and_1)
  31. {
  32. boost::compute::vector<int> vec(context);
  33. BOOST_CHECK_EQUAL(vec.size(), size_t(0));
  34. BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
  35. boost::compute::sort(vec.begin(), vec.end(), queue);
  36. vec.push_back(11, queue);
  37. BOOST_CHECK_EQUAL(vec.size(), size_t(1));
  38. BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
  39. boost::compute::sort(vec.begin(), vec.end(), queue);
  40. }
  41. // test sorting of two element int vectors
  42. BOOST_AUTO_TEST_CASE(sort_int_2)
  43. {
  44. int data[] = { 4, 2 };
  45. boost::compute::vector<int> vec(data, data + 2, queue);
  46. // check that vec is unsorted
  47. BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == false);
  48. // sort vec
  49. boost::compute::sort(vec.begin(), vec.end(), queue);
  50. // check that vec is sorted
  51. BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
  52. // sort already sorted vec and ensure it is still sorted
  53. boost::compute::sort(vec.begin(), vec.end());
  54. BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
  55. }
  56. BOOST_AUTO_TEST_CASE(sort_float_3)
  57. {
  58. float data[] = { 2.3f, 0.1f, 1.2f };
  59. boost::compute::vector<float> vec(data, data + 3, queue);
  60. boost::compute::sort(vec.begin(), vec.end(), queue);
  61. CHECK_RANGE_EQUAL(float, 3, vec, (0.1f, 1.2f, 2.3f));
  62. }
  63. BOOST_AUTO_TEST_CASE(sort_char_vector)
  64. {
  65. using boost::compute::char_;
  66. char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
  67. boost::compute::vector<char_> vector(data, data + 8, queue);
  68. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  69. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  70. boost::compute::sort(vector.begin(), vector.end(), queue);
  71. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  72. CHECK_RANGE_EQUAL(char_, 8, vector, ('\0', '$', '0', '7', 'B', 'F', 'a', 'c'));
  73. }
  74. BOOST_AUTO_TEST_CASE(sort_uchar_vector)
  75. {
  76. using boost::compute::uchar_;
  77. uchar_ data[] = { 0x12, 0x00, 0xFF, 0xB4, 0x80, 0x32, 0x64, 0xA2 };
  78. boost::compute::vector<uchar_> vector(data, data + 8, queue);
  79. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  80. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  81. boost::compute::sort(vector.begin(), vector.end(), queue);
  82. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  83. CHECK_RANGE_EQUAL(uchar_, 8, vector, (0x00, 0x12, 0x32, 0x64, 0x80, 0xA2, 0xB4, 0xFF));
  84. }
  85. BOOST_AUTO_TEST_CASE(sort_short_vector)
  86. {
  87. using boost::compute::short_;
  88. short_ data[] = { -4, 152, -94, 963, 31002, -456, 0, -2113 };
  89. boost::compute::vector<short_> vector(data, data + 8, queue);
  90. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  91. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  92. boost::compute::sort(vector.begin(), vector.end(), queue);
  93. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  94. CHECK_RANGE_EQUAL(short_, 8, vector, (-2113, -456, -94, -4, 0, 152, 963, 31002));
  95. }
  96. BOOST_AUTO_TEST_CASE(sort_ushort_vector)
  97. {
  98. using boost::compute::ushort_;
  99. ushort_ data[] = { 4, 152, 94, 963, 63202, 34560, 0, 2113 };
  100. boost::compute::vector<ushort_> vector(data, data + 8, queue);
  101. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  102. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  103. boost::compute::sort(vector.begin(), vector.end(), queue);
  104. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  105. CHECK_RANGE_EQUAL(ushort_, 8, vector, (0, 4, 94, 152, 963, 2113, 34560, 63202));
  106. }
  107. BOOST_AUTO_TEST_CASE(sort_int_vector)
  108. {
  109. int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
  110. boost::compute::vector<int> vector(data, data + 8, queue);
  111. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  112. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  113. boost::compute::sort(vector.begin(), vector.end(), queue);
  114. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  115. CHECK_RANGE_EQUAL(int, 8, vector, (-5000, -456, -4, 0, 152, 963, 1112, 75321));
  116. }
  117. BOOST_AUTO_TEST_CASE(sort_uint_vector)
  118. {
  119. using boost::compute::uint_;
  120. uint_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
  121. boost::compute::vector<uint_> vector(data, data + 8, queue);
  122. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  123. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  124. boost::compute::sort(vector.begin(), vector.end(), queue);
  125. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  126. CHECK_RANGE_EQUAL(uint_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
  127. }
  128. BOOST_AUTO_TEST_CASE(sort_long_vector)
  129. {
  130. using boost::compute::long_;
  131. long_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
  132. boost::compute::vector<long_> vector(data, data + 8, queue);
  133. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  134. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  135. boost::compute::sort(vector.begin(), vector.end(), queue);
  136. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  137. CHECK_RANGE_EQUAL(long_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
  138. }
  139. BOOST_AUTO_TEST_CASE(sort_ulong_vector)
  140. {
  141. using boost::compute::ulong_;
  142. ulong_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
  143. boost::compute::vector<ulong_> vector(data, data + 8, queue);
  144. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  145. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  146. boost::compute::sort(vector.begin(), vector.end(), queue);
  147. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  148. CHECK_RANGE_EQUAL(ulong_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
  149. }
  150. BOOST_AUTO_TEST_CASE(sort_float_vector)
  151. {
  152. float data[] = { -6023.0f, 152.5f, -63.0f, 1234567.0f, 11.2f,
  153. -5000.1f, 0.0f, 14.0f, -8.25f, -0.0f };
  154. boost::compute::vector<float> vector(data, data + 10, queue);
  155. BOOST_CHECK_EQUAL(vector.size(), size_t(10));
  156. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  157. boost::compute::sort(vector.begin(), vector.end(), queue);
  158. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  159. CHECK_RANGE_EQUAL(
  160. float, 10, vector,
  161. (-6023.0f, -5000.1f, -63.0f, -8.25f, -0.0f, 0.0f, 11.2f, 14.0f, 152.5f, 1234567.0f)
  162. );
  163. }
  164. BOOST_AUTO_TEST_CASE(sort_double_vector)
  165. {
  166. if(!device.supports_extension("cl_khr_fp64")){
  167. std::cout << "skipping test: device does not support double" << std::endl;
  168. return;
  169. }
  170. double data[] = { -6023.0, 152.5, -63.0, 1234567.0, 11.2,
  171. -5000.1, 0.0, 14.0, -8.25, -0.0 };
  172. boost::compute::vector<double> vector(data, data + 10, queue);
  173. BOOST_CHECK_EQUAL(vector.size(), size_t(10));
  174. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
  175. boost::compute::sort(vector.begin(), vector.end(), queue);
  176. BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
  177. CHECK_RANGE_EQUAL(
  178. double, 10, vector,
  179. (-6023.0, -5000.1, -63.0, -8.25, -0.0, 0.0, 11.2, 14.0, 152.5, 1234567.0)
  180. );
  181. }
  182. BOOST_AUTO_TEST_CASE(reverse_sort_int_vector)
  183. {
  184. int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
  185. boost::compute::vector<int> vector(data, data + 8, queue);
  186. BOOST_CHECK_EQUAL(vector.size(), size_t(8));
  187. boost::compute::sort(vector.begin(), vector.end(),
  188. boost::compute::greater<int>(), queue);
  189. CHECK_RANGE_EQUAL(int, 8, vector, (75321, 1112, 963, 152, 0, -4, -456, -5000));
  190. }
  191. BOOST_AUTO_TEST_CASE(sort_vectors_by_length)
  192. {
  193. using boost::compute::float2_;
  194. using boost::compute::lambda::_1;
  195. using boost::compute::lambda::_2;
  196. float data[] = { 1.0f, 0.2f,
  197. 1.3f, 1.0f,
  198. 6.7f, 0.0f,
  199. 5.2f, 3.4f,
  200. 1.4f, 1.4f };
  201. // create vector on device containing vectors
  202. boost::compute::vector<float2_> vector(
  203. reinterpret_cast<float2_ *>(data),
  204. reinterpret_cast<float2_ *>(data) + 5,
  205. queue
  206. );
  207. // sort vectors by length
  208. boost::compute::sort(
  209. vector.begin(),
  210. vector.end(),
  211. length(_1) < length(_2),
  212. queue
  213. );
  214. // copy sorted values back to host
  215. boost::compute::copy(
  216. vector.begin(),
  217. vector.end(),
  218. reinterpret_cast<float2_ *>(data),
  219. queue
  220. );
  221. // check values
  222. BOOST_CHECK_EQUAL(data[0], 1.0f);
  223. BOOST_CHECK_EQUAL(data[1], 0.2f);
  224. BOOST_CHECK_EQUAL(data[2], 1.3f);
  225. BOOST_CHECK_EQUAL(data[3], 1.0f);
  226. BOOST_CHECK_EQUAL(data[4], 1.4f);
  227. BOOST_CHECK_EQUAL(data[5], 1.4f);
  228. BOOST_CHECK_EQUAL(data[6], 5.2f);
  229. BOOST_CHECK_EQUAL(data[7], 3.4f);
  230. BOOST_CHECK_EQUAL(data[8], 6.7f);
  231. BOOST_CHECK_EQUAL(data[9], 0.0f);
  232. }
  233. BOOST_AUTO_TEST_CASE(sort_host_vector)
  234. {
  235. int data[] = { 5, 2, 3, 6, 7, 4, 0, 1 };
  236. std::vector<int> vector(data, data + 8);
  237. boost::compute::sort(vector.begin(), vector.end(), queue);
  238. CHECK_RANGE_EQUAL(int, 8, vector, (0, 1, 2, 3, 4, 5, 6, 7));
  239. }
  240. BOOST_AUTO_TEST_CASE(sort_custom_struct)
  241. {
  242. // function to compare particles by their x-coordinate
  243. BOOST_COMPUTE_FUNCTION(bool, sort_by_x, (Particle a, Particle b),
  244. {
  245. return a.x < b.x;
  246. });
  247. std::vector<Particle> particles;
  248. particles.push_back(Particle(0.1f, 0.f));
  249. particles.push_back(Particle(-0.4f, 0.f));
  250. particles.push_back(Particle(10.0f, 0.f));
  251. particles.push_back(Particle(0.001f, 0.f));
  252. boost::compute::vector<Particle> vector(4, context);
  253. boost::compute::copy(particles.begin(), particles.end(), vector.begin(), queue);
  254. BOOST_CHECK_EQUAL(vector.size(), size_t(4));
  255. BOOST_CHECK(
  256. boost::compute::is_sorted(vector.begin(), vector.end(),
  257. sort_by_x, queue) == false
  258. );
  259. boost::compute::sort(vector.begin(), vector.end(), sort_by_x, queue);
  260. BOOST_CHECK(
  261. boost::compute::is_sorted(vector.begin(), vector.end(),
  262. sort_by_x, queue) == true
  263. );
  264. boost::compute::copy(vector.begin(), vector.end(), particles.begin(), queue);
  265. BOOST_CHECK_CLOSE(particles[0].x, -0.4f, 0.1);
  266. BOOST_CHECK_CLOSE(particles[1].x, 0.001f, 0.1);
  267. BOOST_CHECK_CLOSE(particles[2].x, 0.1f, 0.1);
  268. BOOST_CHECK_CLOSE(particles[3].x, 10.0f, 0.1);
  269. }
  270. BOOST_AUTO_TEST_CASE(sort_int2)
  271. {
  272. using bc::int2_;
  273. BOOST_COMPUTE_FUNCTION(bool, sort_int2, (int2_ a, int2_ b),
  274. {
  275. return a.x < b.x;
  276. });
  277. const size_t size = 100;
  278. std::vector<int2_> host(size, int2_(0, 0));
  279. host[0] = int2_(100.f, 0.f);
  280. host[size/4] = int2_(20.f, 0.f);
  281. host[(size*3)/4] = int2_(9.f, 0.f);
  282. host[size-3] = int2_(-10.0f, 0.f);
  283. host[size/2+1] = int2_(-10.0f, -1.f);
  284. boost::compute::vector<int2_> vector(size, context);
  285. boost::compute::copy(host.begin(), host.end(), vector.begin(), queue);
  286. BOOST_CHECK_EQUAL(vector.size(), size);
  287. BOOST_CHECK(
  288. boost::compute::is_sorted(vector.begin(), vector.end(),
  289. sort_int2, queue) == false
  290. );
  291. boost::compute::sort(vector.begin(), vector.end(), sort_int2, queue);
  292. BOOST_CHECK(
  293. boost::compute::is_sorted(vector.begin(), vector.end(),
  294. sort_int2, queue) == true
  295. );
  296. boost::compute::copy(vector.begin(), vector.end(), host.begin(), queue);
  297. BOOST_CHECK_CLOSE(host[0][0], -10.f, 0.1);
  298. BOOST_CHECK_CLOSE(host[1][0], -10.f, 0.1);
  299. BOOST_CHECK_CLOSE(host[(size - 3)][0], 9.f, 0.1);
  300. BOOST_CHECK_CLOSE(host[(size - 2)][0], 20.f, 0.1);
  301. BOOST_CHECK_CLOSE(host[(size - 1)][0], 100.f, 0.1);
  302. BOOST_CHECK_NE(host[0], host[1]);
  303. }
  304. BOOST_AUTO_TEST_SUITE_END()