test_transform.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 TestTransform
  11. #include <boost/test/unit_test.hpp>
  12. #include <boost/compute/lambda.hpp>
  13. #include <boost/compute/system.hpp>
  14. #include <boost/compute/function.hpp>
  15. #include <boost/compute/functional.hpp>
  16. #include <boost/compute/algorithm/transform.hpp>
  17. #include <boost/compute/container/vector.hpp>
  18. #include <boost/compute/iterator/counting_iterator.hpp>
  19. #include <boost/compute/functional/field.hpp>
  20. #include "check_macros.hpp"
  21. #include "context_setup.hpp"
  22. namespace bc = boost::compute;
  23. namespace compute = boost::compute;
  24. BOOST_AUTO_TEST_CASE(transform_int_abs)
  25. {
  26. int data[] = { 1, -2, -3, -4, 5 };
  27. bc::vector<int> vector(data, data + 5, queue);
  28. CHECK_RANGE_EQUAL(int, 5, vector, (1, -2, -3, -4, 5));
  29. bc::transform(vector.begin(),
  30. vector.end(),
  31. vector.begin(),
  32. bc::abs<int>(),
  33. queue);
  34. CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 3, 4, 5));
  35. }
  36. BOOST_AUTO_TEST_CASE(transform_float_sqrt)
  37. {
  38. float data[] = { 1.0f, 4.0f, 9.0f, 16.0f };
  39. bc::vector<float> vector(data, data + 4, queue);
  40. CHECK_RANGE_EQUAL(float, 4, vector, (1.0f, 4.0f, 9.0f, 16.0f));
  41. bc::transform(vector.begin(),
  42. vector.end(),
  43. vector.begin(),
  44. bc::sqrt<float>(),
  45. queue);
  46. queue.finish();
  47. BOOST_CHECK_CLOSE(float(vector[0]), 1.0f, 1e-4f);
  48. BOOST_CHECK_CLOSE(float(vector[1]), 2.0f, 1e-4f);
  49. BOOST_CHECK_CLOSE(float(vector[2]), 3.0f, 1e-4f);
  50. BOOST_CHECK_CLOSE(float(vector[3]), 4.0f, 1e-4f);
  51. }
  52. BOOST_AUTO_TEST_CASE(transform_float_clamp)
  53. {
  54. float data[] = { 10.f, 20.f, 30.f, 40.f, 50.f };
  55. bc::vector<float> vector(data, data + 5, queue);
  56. CHECK_RANGE_EQUAL(float, 5, vector, (10.0f, 20.0f, 30.0f, 40.0f, 50.0f));
  57. bc::transform(vector.begin(),
  58. vector.end(),
  59. vector.begin(),
  60. clamp(bc::_1, 15.f, 45.f),
  61. queue);
  62. CHECK_RANGE_EQUAL(float, 5, vector, (15.0f, 20.0f, 30.0f, 40.0f, 45.0f));
  63. }
  64. BOOST_AUTO_TEST_CASE(transform_add_int)
  65. {
  66. int data1[] = { 1, 2, 3, 4 };
  67. bc::vector<int> input1(data1, data1 + 4, queue);
  68. int data2[] = { 10, 20, 30, 40 };
  69. bc::vector<int> input2(data2, data2 + 4, queue);
  70. bc::vector<int> output(4, context);
  71. bc::transform(input1.begin(),
  72. input1.end(),
  73. input2.begin(),
  74. output.begin(),
  75. bc::plus<int>(),
  76. queue);
  77. CHECK_RANGE_EQUAL(int, 4, output, (11, 22, 33, 44));
  78. bc::transform(input1.begin(),
  79. input1.end(),
  80. input2.begin(),
  81. output.begin(),
  82. bc::multiplies<int>(),
  83. queue);
  84. CHECK_RANGE_EQUAL(int, 4, output, (10, 40, 90, 160));
  85. }
  86. BOOST_AUTO_TEST_CASE(transform_pow4)
  87. {
  88. float data[] = { 1.0f, 2.0f, 3.0f, 4.0f };
  89. bc::vector<float> vector(data, data + 4, queue);
  90. CHECK_RANGE_EQUAL(float, 4, vector, (1.0f, 2.0f, 3.0f, 4.0f));
  91. bc::vector<float> result(4, context);
  92. bc::transform(vector.begin(),
  93. vector.end(),
  94. result.begin(),
  95. pown(bc::_1, 4),
  96. queue);
  97. queue.finish();
  98. BOOST_CHECK_CLOSE(float(result[0]), 1.0f, 1e-4f);
  99. BOOST_CHECK_CLOSE(float(result[1]), 16.0f, 1e-4f);
  100. BOOST_CHECK_CLOSE(float(result[2]), 81.0f, 1e-4f);
  101. BOOST_CHECK_CLOSE(float(result[3]), 256.0f, 1e-4f);
  102. }
  103. BOOST_AUTO_TEST_CASE(transform_custom_function)
  104. {
  105. float data[] = { 9.0f, 7.0f, 5.0f, 3.0f };
  106. bc::vector<float> vector(data, data + 4, queue);
  107. BOOST_COMPUTE_FUNCTION(float, pow3add4, (float x),
  108. {
  109. return pow(x, 3.0f) + 4.0f;
  110. });
  111. bc::vector<float> result(4, context);
  112. bc::transform(vector.begin(),
  113. vector.end(),
  114. result.begin(),
  115. pow3add4,
  116. queue);
  117. queue.finish();
  118. BOOST_CHECK_CLOSE(float(result[0]), 733.0f, 1e-4f);
  119. BOOST_CHECK_CLOSE(float(result[1]), 347.0f, 1e-4f);
  120. BOOST_CHECK_CLOSE(float(result[2]), 129.0f, 1e-4f);
  121. BOOST_CHECK_CLOSE(float(result[3]), 31.0f, 1e-4f);
  122. }
  123. BOOST_AUTO_TEST_CASE(extract_vector_component)
  124. {
  125. using bc::int2_;
  126. int data[] = { 1, 2,
  127. 3, 4,
  128. 5, 6,
  129. 7, 8 };
  130. bc::vector<int2_> vector(
  131. reinterpret_cast<int2_ *>(data),
  132. reinterpret_cast<int2_ *>(data) + 4,
  133. queue
  134. );
  135. CHECK_RANGE_EQUAL(
  136. int2_, 4, vector,
  137. (int2_(1, 2), int2_(3, 4), int2_(5, 6), int2_(7, 8))
  138. );
  139. bc::vector<int> x_components(4, context);
  140. bc::transform(vector.begin(),
  141. vector.end(),
  142. x_components.begin(),
  143. bc::get<0>(),
  144. queue);
  145. CHECK_RANGE_EQUAL(int, 4, x_components, (1, 3, 5, 7));
  146. bc::vector<int> y_components(4, context);
  147. bc::transform(vector.begin(),
  148. vector.end(),
  149. y_components.begin(),
  150. bc::get<1>(),
  151. queue);
  152. CHECK_RANGE_EQUAL(int, 4, y_components, (2, 4, 6, 8));
  153. }
  154. BOOST_AUTO_TEST_CASE(transform_pinned_vector)
  155. {
  156. int data[] = { 2, -3, 4, -5, 6, -7 };
  157. std::vector<int> vector(data, data + 6);
  158. bc::buffer buffer(context,
  159. vector.size() * sizeof(int),
  160. bc::buffer::read_write | bc::buffer::use_host_ptr,
  161. &vector[0]);
  162. bc::transform(bc::make_buffer_iterator<int>(buffer, 0),
  163. bc::make_buffer_iterator<int>(buffer, 6),
  164. bc::make_buffer_iterator<int>(buffer, 0),
  165. bc::abs<int>(),
  166. queue);
  167. void *ptr = queue.enqueue_map_buffer(buffer,
  168. bc::command_queue::map_read,
  169. 0,
  170. buffer.size());
  171. BOOST_VERIFY(ptr == &vector[0]);
  172. BOOST_CHECK_EQUAL(vector[0], 2);
  173. BOOST_CHECK_EQUAL(vector[1], 3);
  174. BOOST_CHECK_EQUAL(vector[2], 4);
  175. BOOST_CHECK_EQUAL(vector[3], 5);
  176. BOOST_CHECK_EQUAL(vector[4], 6);
  177. BOOST_CHECK_EQUAL(vector[5], 7);
  178. queue.enqueue_unmap_buffer(buffer, ptr);
  179. }
  180. BOOST_AUTO_TEST_CASE(transform_popcount)
  181. {
  182. using boost::compute::uint_;
  183. uint_ data[] = { 0, 1, 2, 3, 4, 45, 127, 5000, 789, 15963 };
  184. bc::vector<uint_> input(data, data + 10, queue);
  185. bc::vector<uint_> output(input.size(), context);
  186. bc::transform(
  187. input.begin(),
  188. input.end(),
  189. output.begin(),
  190. bc::popcount<uint_>(),
  191. queue
  192. );
  193. CHECK_RANGE_EQUAL(uint_, 10, output, (0, 1, 1, 2, 1, 4, 7, 5, 5, 10));
  194. }
  195. // generates the first 25 fibonacci numbers in parallel using the
  196. // rounding-based fibonacci formula
  197. BOOST_AUTO_TEST_CASE(generate_fibonacci_sequence)
  198. {
  199. using boost::compute::uint_;
  200. boost::compute::vector<uint_> sequence(25, context);
  201. BOOST_COMPUTE_FUNCTION(uint_, nth_fibonacci, (const uint_ n),
  202. {
  203. const float golden_ratio = (1.f + sqrt(5.f)) / 2.f;
  204. return floor(pown(golden_ratio, n) / sqrt(5.f) + 0.5f);
  205. });
  206. boost::compute::transform(
  207. boost::compute::make_counting_iterator(uint_(0)),
  208. boost::compute::make_counting_iterator(uint_(sequence.size())),
  209. sequence.begin(),
  210. nth_fibonacci,
  211. queue
  212. );
  213. CHECK_RANGE_EQUAL(
  214. uint_, 25, sequence,
  215. (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610,
  216. 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368)
  217. );
  218. }
  219. BOOST_AUTO_TEST_CASE(field)
  220. {
  221. using compute::uint2_;
  222. using compute::uint4_;
  223. using compute::field;
  224. unsigned int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  225. compute::vector<uint4_> input(
  226. reinterpret_cast<uint4_ *>(data),
  227. reinterpret_cast<uint4_ *>(data) + 2,
  228. queue
  229. );
  230. compute::vector<uint2_> output(input.size(), context);
  231. compute::transform(
  232. input.begin(),
  233. input.end(),
  234. output.begin(),
  235. compute::field<uint2_>("xz"),
  236. queue
  237. );
  238. queue.finish();
  239. BOOST_CHECK_EQUAL(uint2_(output[0]), uint2_(1, 3));
  240. BOOST_CHECK_EQUAL(uint2_(output[1]), uint2_(5, 7));
  241. }
  242. BOOST_AUTO_TEST_CASE(transform_abs_doctest)
  243. {
  244. //! [transform_abs]
  245. int data[] = { -1, -2, -3, -4 };
  246. boost::compute::vector<int> vec(data, data + 4, queue);
  247. using boost::compute::abs;
  248. // calculate the absolute value for each element in-place
  249. boost::compute::transform(
  250. vec.begin(), vec.end(), vec.begin(), abs<int>(), queue
  251. );
  252. // vec == { 1, 2, 3, 4 }
  253. //! [transform_abs]
  254. CHECK_RANGE_EQUAL(int, 4, vec, (1, 2, 3, 4));
  255. }
  256. BOOST_AUTO_TEST_CASE(abs_if_odd)
  257. {
  258. // return absolute value only for odd values
  259. BOOST_COMPUTE_FUNCTION(int, abs_if_odd, (int x),
  260. {
  261. if(x & 1){
  262. return abs(x);
  263. }
  264. else {
  265. return x;
  266. }
  267. });
  268. int data[] = { -2, -3, -4, -5, -6, -7, -8, -9 };
  269. compute::vector<int> vector(data, data + 8, queue);
  270. compute::transform(
  271. vector.begin(), vector.end(), vector.begin(), abs_if_odd, queue
  272. );
  273. CHECK_RANGE_EQUAL(int, 8, vector, (-2, +3, -4, +5, -6, +7, -8, +9));
  274. }
  275. BOOST_AUTO_TEST_SUITE_END()