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 TestAccumulate
12 #include <boost/test/unit_test.hpp>
13
14 #include <numeric>
15
16 #include <boost/compute/command_queue.hpp>
17 #include <boost/compute/algorithm/accumulate.hpp>
18 #include <boost/compute/algorithm/iota.hpp>
19 #include <boost/compute/container/mapped_view.hpp>
20 #include <boost/compute/container/vector.hpp>
21 #include <boost/compute/iterator/counting_iterator.hpp>
22
23 #include "context_setup.hpp"
24
BOOST_AUTO_TEST_CASE(sum_int)25 BOOST_AUTO_TEST_CASE(sum_int)
26 {
27 int data[] = { 2, 4, 6, 8 };
28 boost::compute::vector<int> vector(data, data + 4, queue);
29 BOOST_CHECK_EQUAL(
30 boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
31 20
32 );
33
34 BOOST_CHECK_EQUAL(
35 boost::compute::accumulate(vector.begin(), vector.end(), -10, queue),
36 10
37 );
38
39 BOOST_CHECK_EQUAL(
40 boost::compute::accumulate(vector.begin(), vector.end(), 5, queue),
41 25
42 );
43 }
44
BOOST_AUTO_TEST_CASE(product_int)45 BOOST_AUTO_TEST_CASE(product_int)
46 {
47 int data[] = { 2, 4, 6, 8 };
48 boost::compute::vector<int> vector(data, data + 4, queue);
49 BOOST_CHECK_EQUAL(
50 boost::compute::accumulate(
51 vector.begin(), vector.end(), 1, boost::compute::multiplies<int>(),
52 queue),
53 384
54 );
55
56 BOOST_CHECK_EQUAL(
57 boost::compute::accumulate(
58 vector.begin(), vector.end(), -1, boost::compute::multiplies<int>(),
59 queue),
60 -384
61 );
62
63 BOOST_CHECK_EQUAL(
64 boost::compute::accumulate(
65 vector.begin(), vector.end(), 2, boost::compute::multiplies<int>(),
66 queue),
67 768
68 );
69 }
70
BOOST_AUTO_TEST_CASE(quotient_int)71 BOOST_AUTO_TEST_CASE(quotient_int)
72 {
73 int data[] = { 2, 8, 16 };
74 boost::compute::vector<int> vector(data, data + 3, queue);
75 BOOST_CHECK_EQUAL(
76 boost::compute::accumulate(
77 vector.begin(),
78 vector.end(),
79 1024,
80 boost::compute::divides<int>(),
81 queue
82 ),
83 4
84 );
85 }
86
BOOST_AUTO_TEST_CASE(sum_counting_iterator)87 BOOST_AUTO_TEST_CASE(sum_counting_iterator)
88 {
89 // sum 0 -> 9
90 BOOST_CHECK_EQUAL(
91 boost::compute::accumulate(
92 boost::compute::make_counting_iterator(0),
93 boost::compute::make_counting_iterator(10),
94 0,
95 boost::compute::plus<int>(),
96 queue
97 ),
98 45
99 );
100
101 // sum 0 -> 9 + 7
102 BOOST_CHECK_EQUAL(
103 boost::compute::accumulate(
104 boost::compute::make_counting_iterator(0),
105 boost::compute::make_counting_iterator(10),
106 7,
107 boost::compute::plus<int>(),
108 queue
109 ),
110 52
111 );
112
113 // sum 15 -> 24
114 BOOST_CHECK_EQUAL(
115 boost::compute::accumulate(
116 boost::compute::make_counting_iterator(15),
117 boost::compute::make_counting_iterator(25),
118 0,
119 boost::compute::plus<int>(),
120 queue
121 ),
122 195
123 );
124
125 // sum -5 -> 10
126 BOOST_CHECK_EQUAL(
127 boost::compute::accumulate(
128 boost::compute::make_counting_iterator(-5),
129 boost::compute::make_counting_iterator(10),
130 0,
131 boost::compute::plus<int>(),
132 queue
133 ),
134 30
135 );
136
137 // sum -5 -> 10 - 2
138 BOOST_CHECK_EQUAL(
139 boost::compute::accumulate(
140 boost::compute::make_counting_iterator(-5),
141 boost::compute::make_counting_iterator(10),
142 -2,
143 boost::compute::plus<int>(),
144 queue
145 ),
146 28
147 );
148 }
149
BOOST_AUTO_TEST_CASE(sum_iota)150 BOOST_AUTO_TEST_CASE(sum_iota)
151 {
152 // size 0
153 boost::compute::vector<int> vector(0, context);
154
155 BOOST_CHECK_EQUAL(
156 boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
157 0
158 );
159
160 BOOST_CHECK_EQUAL(
161 boost::compute::accumulate(vector.begin(), vector.end(), 4, queue),
162 4
163 );
164
165 // size 50
166 vector.resize(50);
167 boost::compute::iota(vector.begin(), vector.end(), 0, queue);
168
169 BOOST_CHECK_EQUAL(
170 boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
171 1225
172 );
173
174 BOOST_CHECK_EQUAL(
175 boost::compute::accumulate(vector.begin(), vector.end(), 11, queue),
176 1236
177 );
178
179 // size 1000
180 vector.resize(1000);
181 boost::compute::iota(vector.begin(), vector.end(), 0, queue);
182
183 BOOST_CHECK_EQUAL(
184 boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
185 499500
186 );
187
188 BOOST_CHECK_EQUAL(
189 boost::compute::accumulate(vector.begin(), vector.end(), -45, queue),
190 499455
191 );
192
193 // size 1025
194 vector.resize(1025);
195 boost::compute::iota(vector.begin(), vector.end(), 0, queue);
196
197 BOOST_CHECK_EQUAL(
198 boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
199 524800
200 );
201
202 BOOST_CHECK_EQUAL(
203 boost::compute::accumulate(vector.begin(), vector.end(), 2, queue),
204 524802
205 );
206 }
207
BOOST_AUTO_TEST_CASE(min_and_max)208 BOOST_AUTO_TEST_CASE(min_and_max)
209 {
210 using boost::compute::int2_;
211
212 int data[] = { 5, 3, 1, 6, 4, 2 };
213 boost::compute::vector<int> vector(data, data + 6, queue);
214
215 BOOST_COMPUTE_FUNCTION(int2_, min_and_max, (int2_ accumulator, const int value),
216 {
217 return (int2)((min)(accumulator.x, value), (max)(accumulator.y, value));
218 });
219
220 int2_ result = boost::compute::accumulate(
221 vector.begin(), vector.end(), int2_(100, -100), min_and_max, queue
222 );
223 BOOST_CHECK_EQUAL(result[0], 1);
224 BOOST_CHECK_EQUAL(result[1], 6);
225 }
226
BOOST_AUTO_TEST_CASE(min_max)227 BOOST_AUTO_TEST_CASE(min_max)
228 {
229 float data[] = { 1.2f, 5.5f, 0.1f, 9.6f, 4.2f, 6.7f, 9.0f, 3.4f };
230 boost::compute::vector<float> vec(data, data + 8, queue);
231
232 using ::boost::compute::min;
233 using ::boost::compute::max;
234
235 float min_value = boost::compute::accumulate(
236 vec.begin(), vec.end(), (std::numeric_limits<float>::max)(), min<float>(), queue
237 );
238 BOOST_CHECK_EQUAL(min_value, 0.1f);
239
240 float max_value = boost::compute::accumulate(
241 vec.begin(), vec.end(), (std::numeric_limits<float>::min)(), max<float>(), queue
242 );
243 BOOST_CHECK_EQUAL(max_value, 9.6f);
244
245 // find min with init less than any value in the array
246 min_value = boost::compute::accumulate(
247 vec.begin(), vec.end(), -1.f, min<float>(), queue
248 );
249 BOOST_CHECK_EQUAL(min_value, -1.f);
250
251 // find max with init greater than any value in the array
252 max_value = boost::compute::accumulate(
253 vec.begin(), vec.end(), 10.f, max<float>(), queue
254 );
255 BOOST_CHECK_EQUAL(max_value, 10.f);
256 }
257
258 template<class T>
ensure_std_accumulate_equality(const std::vector<T> & data,boost::compute::command_queue & queue)259 void ensure_std_accumulate_equality(const std::vector<T> &data,
260 boost::compute::command_queue &queue)
261 {
262 boost::compute::mapped_view<T> view(&data[0], data.size(), queue.get_context());
263
264 BOOST_CHECK_EQUAL(
265 std::accumulate(data.begin(), data.end(), 0),
266 boost::compute::accumulate(view.begin(), view.end(), 0, queue)
267 );
268 }
269
BOOST_AUTO_TEST_CASE(std_accumulate_equality)270 BOOST_AUTO_TEST_CASE(std_accumulate_equality)
271 {
272 // test accumulate() with int
273 int data1[] = { 1, 2, 3, 4 };
274 std::vector<int> vec1(data1, data1 + 4);
275 ensure_std_accumulate_equality(vec1, queue);
276
277 vec1.resize(10000);
278 std::fill(vec1.begin(), vec1.end(), 2);
279 ensure_std_accumulate_equality(vec1, queue);
280
281 // test accumulate() with float
282 float data2[] = { 1.2f, 2.3f, 4.5f, 6.7f, 8.9f };
283 std::vector<float> vec2(data2, data2 + 5);
284 ensure_std_accumulate_equality(vec2, queue);
285
286 vec2.resize(10000);
287 std::fill(vec2.begin(), vec2.end(), 1.01f);
288 ensure_std_accumulate_equality(vec2, queue);
289
290 // test accumulate() with double
291 if(device.supports_extension("cl_khr_fp64")){
292 double data3[] = { 1.2, 2.3, 4.5, 6.7, 8.9 };
293 std::vector<double> vec3(data3, data3 + 5);
294 ensure_std_accumulate_equality(vec3, queue);
295
296 vec3.resize(10000);
297 std::fill(vec3.begin(), vec3.end(), 2.02);
298 ensure_std_accumulate_equality(vec3, queue);
299 }
300 }
301
302 BOOST_AUTO_TEST_SUITE_END()
303