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 TestReduce
12 #include <boost/test/unit_test.hpp>
13
14 #include <boost/compute/lambda.hpp>
15 #include <boost/compute/system.hpp>
16 #include <boost/compute/functional.hpp>
17 #include <boost/compute/algorithm/reduce.hpp>
18 #include <boost/compute/container/vector.hpp>
19 #include <boost/compute/iterator/constant_iterator.hpp>
20 #include <boost/compute/iterator/counting_iterator.hpp>
21 #include <boost/compute/iterator/transform_iterator.hpp>
22 #include <boost/compute/types/complex.hpp>
23
24 #include "check_macros.hpp"
25 #include "context_setup.hpp"
26
27 namespace compute = boost::compute;
28
BOOST_AUTO_TEST_CASE(reduce_int)29 BOOST_AUTO_TEST_CASE(reduce_int)
30 {
31 int data[] = { 1, 5, 9, 13, 17 };
32 compute::vector<int> vector(data, data + 5, queue);
33 int sum;
34 compute::reduce(vector.begin(), vector.end(), &sum, compute::plus<int>(), queue);
35 BOOST_CHECK_EQUAL(sum, 45);
36
37 int product;
38 compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<int>(), queue);
39 BOOST_CHECK_EQUAL(product, 9945);
40 }
41
BOOST_AUTO_TEST_CASE(reduce_empty_vector)42 BOOST_AUTO_TEST_CASE(reduce_empty_vector)
43 {
44 compute::vector<short> vector(context);
45
46 short sum = 0;
47 compute::reduce(vector.begin(), vector.end(), &sum, queue);
48 BOOST_CHECK_EQUAL(sum, short(0));
49 }
50
BOOST_AUTO_TEST_CASE(reduce_doctest)51 BOOST_AUTO_TEST_CASE(reduce_doctest)
52 {
53 int data[] = { 1, 2, 3, 4 };
54 boost::compute::vector<int> vec(data, data + 4, queue);
55
56 //! [sum_int]
57 int sum = 0;
58 boost::compute::reduce(vec.begin(), vec.end(), &sum, queue);
59 //! [sum_int]
60
61 BOOST_CHECK_EQUAL(sum, 10);
62 }
63
BOOST_AUTO_TEST_CASE(reduce_twos)64 BOOST_AUTO_TEST_CASE(reduce_twos)
65 {
66 using compute::uint_;
67
68 compute::vector<uint_> vector(8, context);
69 compute::fill(vector.begin(), vector.end(), uint_(2), queue);
70
71 uint_ sum;
72 compute::reduce(vector.begin(), vector.end(), &sum, compute::plus<uint_>(), queue);
73 BOOST_CHECK_EQUAL(sum, uint_(16));
74
75 uint_ product;
76 compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<uint_>(), queue);
77 BOOST_CHECK_EQUAL(product, uint_(256));
78 }
79
BOOST_AUTO_TEST_CASE(reduce_on_device)80 BOOST_AUTO_TEST_CASE(reduce_on_device)
81 {
82 int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
83 compute::vector<int> input(data, data + 8, queue);
84 compute::vector<int> result(2, context);
85 compute::reduce(input.begin(), input.begin() + 4, result.begin(), queue);
86 compute::reduce(input.begin() + 4, input.end(), result.end() - 1, queue);
87 CHECK_RANGE_EQUAL(int, 2, result, (10, 26));
88 }
89
BOOST_AUTO_TEST_CASE(reduce_int_min_max)90 BOOST_AUTO_TEST_CASE(reduce_int_min_max)
91 {
92 int data[] = { 11, 5, 92, 13, 42 };
93 compute::vector<int> vector(data, data + 5, queue);
94 int min_value;
95 compute::reduce(
96 vector.begin(),
97 vector.end(),
98 &min_value,
99 compute::min<int>(),
100 queue
101 );
102 BOOST_CHECK_EQUAL(min_value, 5);
103
104 int max_value;
105 compute::reduce(
106 vector.begin(),
107 vector.end(),
108 &max_value,
109 compute::max<int>(),
110 queue
111 );
112 BOOST_CHECK_EQUAL(max_value, 92);
113 }
114
BOOST_AUTO_TEST_CASE(reduce_int2)115 BOOST_AUTO_TEST_CASE(reduce_int2)
116 {
117 std::vector<compute::int2_> data;
118 for(int i = 0; i < 6; i++){
119 compute::int2_ value;
120 value[0] = i + 1;
121 value[1] = 2 * i + 1;
122 data.push_back(value);
123 }
124
125 compute::vector<compute::int2_> vector(data.begin(), data.end(), queue);
126
127 compute::int2_ sum;
128 compute::reduce(
129 vector.begin(),
130 vector.end(),
131 &sum,
132 queue
133 );
134 BOOST_CHECK_EQUAL(sum, compute::int2_(21, 36));
135 }
136
BOOST_AUTO_TEST_CASE(reduce_pinned_vector)137 BOOST_AUTO_TEST_CASE(reduce_pinned_vector)
138 {
139 int data[] = { 2, 5, 8, 11, 15 };
140 std::vector<int> vector(data, data + 5);
141
142 compute::buffer buffer(context,
143 vector.size() * sizeof(int),
144 compute::buffer::read_only | compute::buffer::use_host_ptr,
145 &vector[0]);
146
147 int sum;
148 compute::reduce(
149 compute::make_buffer_iterator<int>(buffer, 0),
150 compute::make_buffer_iterator<int>(buffer, 5),
151 &sum,
152 compute::plus<int>()
153 );
154 BOOST_CHECK_EQUAL(sum, 41);
155 }
156
BOOST_AUTO_TEST_CASE(reduce_constant_iterator)157 BOOST_AUTO_TEST_CASE(reduce_constant_iterator)
158 {
159 int result;
160 compute::reduce(
161 compute::make_constant_iterator(1, 0),
162 compute::make_constant_iterator(1, 5),
163 &result,
164 queue
165 );
166 BOOST_CHECK_EQUAL(result, 5);
167
168 compute::reduce(
169 compute::make_constant_iterator(3, 0),
170 compute::make_constant_iterator(3, 5),
171 &result,
172 queue
173 );
174 BOOST_CHECK_EQUAL(result, 15);
175
176 compute::reduce(
177 compute::make_constant_iterator(2, 0),
178 compute::make_constant_iterator(2, 5),
179 &result,
180 compute::multiplies<int>(),
181 queue
182 );
183 BOOST_CHECK_EQUAL(result, 32);
184 }
185
BOOST_AUTO_TEST_CASE(reduce_counting_iterator)186 BOOST_AUTO_TEST_CASE(reduce_counting_iterator)
187 {
188 int result;
189 compute::reduce(
190 compute::make_counting_iterator(1),
191 compute::make_counting_iterator(10),
192 &result,
193 queue
194 );
195 BOOST_CHECK_EQUAL(result, 45);
196
197 compute::reduce(
198 compute::make_counting_iterator(1),
199 compute::make_counting_iterator(5),
200 &result,
201 compute::multiplies<int>(),
202 queue
203 );
204 BOOST_CHECK_EQUAL(result, 24);
205 }
206
BOOST_AUTO_TEST_CASE(reduce_transform_iterator)207 BOOST_AUTO_TEST_CASE(reduce_transform_iterator)
208 {
209 using ::boost::compute::_1;
210
211 int data[] = { 1, 3, 5, 7, 9 };
212 compute::vector<int> vector(data, data + 5, queue);
213
214 int sum;
215 compute::reduce(
216 compute::make_transform_iterator(vector.begin(), _1 + 1),
217 compute::make_transform_iterator(vector.end(), _1 + 1),
218 &sum,
219 queue
220 );
221 BOOST_CHECK_EQUAL(sum, 30);
222
223 compute::reduce(
224 compute::make_transform_iterator(vector.begin(), _1 > 4),
225 compute::make_transform_iterator(vector.end(), _1 > 4),
226 &sum,
227 compute::plus<int>(),
228 queue
229 );
230 BOOST_CHECK_EQUAL(sum, 3);
231
232 compute::reduce(
233 compute::make_transform_iterator(vector.begin(), _1 * _1),
234 compute::make_transform_iterator(vector.end(), _1 * _1),
235 &sum,
236 queue
237 );
238 BOOST_CHECK_EQUAL(sum, 165);
239 }
240
BOOST_AUTO_TEST_CASE(reduce_complex)241 BOOST_AUTO_TEST_CASE(reduce_complex)
242 {
243 std::vector<std::complex<float> > data;
244 data.push_back(std::complex<float>(1, 2));
245 data.push_back(std::complex<float>(2, 4));
246 data.push_back(std::complex<float>(3, 6));
247 data.push_back(std::complex<float>(4, 8));
248
249 compute::vector<std::complex<float> > vector(data.size(), context);
250 compute::copy(data.begin(), data.end(), vector.begin(), queue);
251
252 std::complex<float> result;
253 compute::reduce(
254 vector.begin(), vector.end(), &result, queue
255 );
256 BOOST_CHECK(result == std::complex<float>(10, 20));
257
258 compute::reduce(
259 vector.begin(), vector.end(), &result, compute::plus<std::complex<float> >(), queue
260 );
261 BOOST_CHECK(result == std::complex<float>(10, 20));
262
263 compute::reduce(
264 vector.begin(), vector.end(), &result, compute::multiplies<std::complex<float> >(), queue
265 );
266 BOOST_CHECK(result == std::complex<float>(-168, -576));
267 }
268
BOOST_AUTO_TEST_CASE(reduce_uchar_to_float)269 BOOST_AUTO_TEST_CASE(reduce_uchar_to_float)
270 {
271 compute::vector<compute::uchar_> data(context);
272 data.push_back(250, queue);
273 data.push_back(250, queue);
274 float sum = 0;
275 compute::reduce(data.begin(), data.end(), &sum, compute::plus<float>(), queue);
276 BOOST_CHECK_EQUAL(sum, 500);
277 }
278
279 // Test case for https://github.com/boostorg/compute/issues/746
BOOST_AUTO_TEST_CASE(buffer_reference_count_test)280 BOOST_AUTO_TEST_CASE(buffer_reference_count_test)
281 {
282 using compute::uint_;
283
284 compute::vector<uint_> vector(8, context);
285 const compute::buffer& b = vector.get_buffer();
286 uint_ rc1 = b.get_info<CL_MEM_REFERENCE_COUNT>();
287 {
288 compute::fill(vector.begin(), vector.end(), uint_(2), queue);
289
290 uint_ product;
291 compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<uint_>(), queue);
292 BOOST_CHECK_EQUAL(product, uint_(256));
293 }
294 uint_ rc2 = b.get_info<CL_MEM_REFERENCE_COUNT>();
295 BOOST_CHECK_EQUAL(rc1, rc2);
296 }
297
298 BOOST_AUTO_TEST_SUITE_END()
299