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