test_function.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 TestFunction
  11. #include <boost/test/unit_test.hpp>
  12. #include <iostream>
  13. #include <boost/compute/system.hpp>
  14. #include <boost/compute/function.hpp>
  15. #include <boost/compute/algorithm/accumulate.hpp>
  16. #include <boost/compute/algorithm/copy.hpp>
  17. #include <boost/compute/algorithm/generate.hpp>
  18. #include <boost/compute/algorithm/sort.hpp>
  19. #include <boost/compute/algorithm/transform.hpp>
  20. #include <boost/compute/container/vector.hpp>
  21. #include <boost/compute/iterator/zip_iterator.hpp>
  22. #include <boost/compute/types/pair.hpp>
  23. #include "check_macros.hpp"
  24. #include "context_setup.hpp"
  25. namespace compute = boost::compute;
  26. BOOST_AUTO_TEST_CASE(add_three)
  27. {
  28. BOOST_COMPUTE_FUNCTION(int, add_three, (int x),
  29. {
  30. return x + 3;
  31. });
  32. int data[] = { 1, 2, 3, 4 };
  33. compute::vector<int> vector(data, data + 4, queue);
  34. compute::transform(
  35. vector.begin(), vector.end(), vector.begin(), add_three, queue
  36. );
  37. CHECK_RANGE_EQUAL(int, 4, vector, (4, 5, 6, 7));
  38. }
  39. BOOST_AUTO_TEST_CASE(sum_odd_values)
  40. {
  41. BOOST_COMPUTE_FUNCTION(int, add_odd_value, (int sum, int value),
  42. {
  43. if(value & 1){
  44. return sum + value;
  45. }
  46. else {
  47. return sum + 0;
  48. }
  49. });
  50. int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  51. compute::vector<int> vector(data, data + 8, queue);
  52. int result = compute::accumulate(
  53. vector.begin(), vector.end(), 0, add_odd_value, queue
  54. );
  55. BOOST_CHECK_EQUAL(result, 16);
  56. }
  57. BOOST_AUTO_TEST_CASE(sort_pairs)
  58. {
  59. if(device.vendor() == "NVIDIA" && device.platform().name() == "Apple"){
  60. // FIXME: this test currently segfaults on NVIDIA GPUs on Apple
  61. std::cerr << "skipping sort_pairs test on NVIDIA GPU on Apple platform" << std::endl;
  62. return;
  63. }
  64. std::vector<std::pair<int, float> > data;
  65. data.push_back(std::make_pair(1, 2.3f));
  66. data.push_back(std::make_pair(0, 4.2f));
  67. data.push_back(std::make_pair(2, 1.0f));
  68. compute::vector<std::pair<int, float> > vector(data.begin(), data.end(), queue);
  69. // sort by first component
  70. BOOST_COMPUTE_FUNCTION(bool, compare_first, (std::pair<int, float> a, std::pair<int, float> b),
  71. {
  72. return a.first < b.first;
  73. });
  74. compute::sort(vector.begin(), vector.end(), compare_first, queue);
  75. compute::copy(vector.begin(), vector.end(), data.begin(), queue);
  76. BOOST_CHECK(data[0] == std::make_pair(0, 4.2f));
  77. BOOST_CHECK(data[1] == std::make_pair(1, 2.3f));
  78. BOOST_CHECK(data[2] == std::make_pair(2, 1.0f));
  79. // sort by second component
  80. BOOST_COMPUTE_FUNCTION(bool, compare_second, (std::pair<int, float> a, std::pair<int, float> b),
  81. {
  82. return a.second < b.second;
  83. });
  84. compute::sort(vector.begin(), vector.end(), compare_second, queue);
  85. compute::copy(vector.begin(), vector.end(), data.begin(), queue);
  86. BOOST_CHECK(data[0] == std::make_pair(2, 1.0f));
  87. BOOST_CHECK(data[1] == std::make_pair(1, 2.3f));
  88. BOOST_CHECK(data[2] == std::make_pair(0, 4.2f));
  89. }
  90. BOOST_AUTO_TEST_CASE(transform_zip_iterator)
  91. {
  92. float float_data[] = { 1.f, 2.f, 3.f, 4.f };
  93. compute::vector<float> input_floats(float_data, float_data + 4, queue);
  94. int int_data[] = { 2, 4, 6, 8 };
  95. compute::vector<int> input_ints(int_data, int_data + 4, queue);
  96. compute::vector<float> results(4, context);
  97. BOOST_COMPUTE_FUNCTION(float, tuple_pown, (boost::tuple<float, int> x),
  98. {
  99. return pown(boost_tuple_get(x, 0), boost_tuple_get(x, 1));
  100. });
  101. compute::transform(
  102. compute::make_zip_iterator(
  103. boost::make_tuple(input_floats.begin(), input_ints.begin())
  104. ),
  105. compute::make_zip_iterator(
  106. boost::make_tuple(input_floats.end(), input_ints.end())
  107. ),
  108. results.begin(),
  109. tuple_pown,
  110. queue
  111. );
  112. float results_data[4];
  113. compute::copy(results.begin(), results.end(), results_data, queue);
  114. BOOST_CHECK_CLOSE(results_data[0], 1.f, 1e-4);
  115. BOOST_CHECK_CLOSE(results_data[1], 16.f, 1e-4);
  116. BOOST_CHECK_CLOSE(results_data[2], 729.f, 1e-4);
  117. BOOST_CHECK_CLOSE(results_data[3], 65536.f, 1e-4);
  118. }
  119. static BOOST_COMPUTE_FUNCTION(int, static_function, (int x),
  120. {
  121. return x + 5;
  122. });
  123. BOOST_AUTO_TEST_CASE(test_static_function)
  124. {
  125. int data[] = { 1, 2, 3, 4};
  126. compute::vector<int> vec(data, data + 4, queue);
  127. compute::transform(
  128. vec.begin(), vec.end(), vec.begin(), static_function, queue
  129. );
  130. CHECK_RANGE_EQUAL(int, 4, vec, (6, 7, 8, 9));
  131. }
  132. template<class T>
  133. inline compute::function<T(T)> make_negate_function()
  134. {
  135. BOOST_COMPUTE_FUNCTION(T, negate, (const T x),
  136. {
  137. return -x;
  138. });
  139. return negate;
  140. }
  141. BOOST_AUTO_TEST_CASE(test_templated_function)
  142. {
  143. int int_data[] = { 1, 2, 3, 4 };
  144. compute::vector<int> int_vec(int_data, int_data + 4, queue);
  145. compute::function<int(int)> negate_int = make_negate_function<int>();
  146. compute::transform(
  147. int_vec.begin(), int_vec.end(), int_vec.begin(), negate_int, queue
  148. );
  149. CHECK_RANGE_EQUAL(int, 4, int_vec, (-1, -2, -3, -4));
  150. float float_data[] = { 1.1f, 2.2f, 3.3f, 4.4f };
  151. compute::vector<float> float_vec(float_data, float_data + 4, queue);
  152. compute::function<float(float)> negate_float = make_negate_function<float>();
  153. compute::transform(
  154. float_vec.begin(), float_vec.end(), float_vec.begin(), negate_float, queue
  155. );
  156. CHECK_RANGE_EQUAL(float, 4, float_vec, (-1.1f, -2.2f, -3.3f, -4.4f));
  157. }
  158. BOOST_AUTO_TEST_CASE(define)
  159. {
  160. BOOST_COMPUTE_FUNCTION(int, return_number, (),
  161. {
  162. return NUMBER;
  163. });
  164. return_number.define("NUMBER", "4");
  165. compute::vector<int> vec(1, context);
  166. compute::generate(vec.begin(), vec.end(), return_number, queue);
  167. CHECK_RANGE_EQUAL(int, 1, vec, (4));
  168. return_number.define("NUMBER", "2");
  169. compute::generate(vec.begin(), vec.end(), return_number, queue);
  170. CHECK_RANGE_EQUAL(int, 1, vec, (2));
  171. }
  172. BOOST_AUTO_TEST_SUITE_END()