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 TestZipIterator
12 #include <boost/test/unit_test.hpp>
13
14 #include <boost/type_traits.hpp>
15 #include <boost/static_assert.hpp>
16 #include <boost/tuple/tuple_io.hpp>
17 #include <boost/tuple/tuple_comparison.hpp>
18
19 #include <boost/compute/functional.hpp>
20 #include <boost/compute/algorithm/copy.hpp>
21 #include <boost/compute/algorithm/transform.hpp>
22 #include <boost/compute/container/vector.hpp>
23 #include <boost/compute/iterator/constant_iterator.hpp>
24 #include <boost/compute/iterator/zip_iterator.hpp>
25 #include <boost/compute/types/tuple.hpp>
26
27 #include "check_macros.hpp"
28 #include "context_setup.hpp"
29
30 namespace compute = boost::compute;
31
BOOST_AUTO_TEST_CASE(value_type)32 BOOST_AUTO_TEST_CASE(value_type)
33 {
34 BOOST_STATIC_ASSERT((
35 boost::is_same<
36 boost::compute::zip_iterator<
37 boost::tuple<
38 boost::compute::buffer_iterator<float>,
39 boost::compute::buffer_iterator<int>
40 >
41 >::value_type,
42 boost::tuple<float, int>
43 >::value
44 ));
45 }
46
BOOST_AUTO_TEST_CASE(distance)47 BOOST_AUTO_TEST_CASE(distance)
48 {
49 boost::compute::vector<char> char_vector(5, context);
50 boost::compute::vector<int> int_vector(5, context);
51
52 BOOST_CHECK_EQUAL(
53 std::distance(
54 boost::compute::make_zip_iterator(
55 boost::make_tuple(
56 char_vector.begin(),
57 int_vector.begin()
58 )
59 ),
60 boost::compute::make_zip_iterator(
61 boost::make_tuple(
62 char_vector.end(),
63 int_vector.end()
64 )
65 )
66 ),
67 ptrdiff_t(5)
68 );
69
70 BOOST_CHECK_EQUAL(
71 std::distance(
72 boost::compute::make_zip_iterator(
73 boost::make_tuple(
74 char_vector.begin(),
75 int_vector.begin()
76 )
77 ) + 1,
78 boost::compute::make_zip_iterator(
79 boost::make_tuple(
80 char_vector.end(),
81 int_vector.end()
82 )
83 ) - 1
84 ),
85 ptrdiff_t(3)
86 );
87
88 BOOST_CHECK_EQUAL(
89 std::distance(
90 boost::compute::make_zip_iterator(
91 boost::make_tuple(
92 char_vector.begin() + 2,
93 int_vector.begin() + 2
94 )
95 ),
96 boost::compute::make_zip_iterator(
97 boost::make_tuple(
98 char_vector.end() - 1,
99 int_vector.end() - 1
100 )
101 )
102 ),
103 ptrdiff_t(2)
104 );
105 }
106
BOOST_AUTO_TEST_CASE(copy)107 BOOST_AUTO_TEST_CASE(copy)
108 {
109 // create three separate vectors of three different types
110 char char_data[] = { 'x', 'y', 'z' };
111 boost::compute::vector<char> char_vector(char_data, char_data + 3, queue);
112
113 int int_data[] = { 4, 7, 9 };
114 boost::compute::vector<int> int_vector(int_data, int_data + 3, queue);
115
116 float float_data[] = { 3.2f, 4.5f, 7.6f };
117 boost::compute::vector<float> float_vector(float_data, float_data + 3, queue);
118
119 // zip all three vectors into a single tuple vector
120 boost::compute::vector<boost::tuple<char, int, float> > tuple_vector(3, context);
121
122 boost::compute::copy(
123 boost::compute::make_zip_iterator(
124 boost::make_tuple(
125 char_vector.begin(),
126 int_vector.begin(),
127 float_vector.begin()
128 )
129 ),
130 boost::compute::make_zip_iterator(
131 boost::make_tuple(
132 char_vector.end(),
133 int_vector.end(),
134 float_vector.end()
135 )
136 ),
137 tuple_vector.begin(),
138 queue
139 );
140
141 // copy tuple vector to host
142 std::vector<boost::tuple<char, int, float> > host_vector(3);
143
144 boost::compute::copy(
145 tuple_vector.begin(),
146 tuple_vector.end(),
147 host_vector.begin(),
148 queue
149 );
150
151 // check tuple values
152 BOOST_CHECK_EQUAL(host_vector[0], boost::make_tuple('x', 4, 3.2f));
153 BOOST_CHECK_EQUAL(host_vector[1], boost::make_tuple('y', 7, 4.5f));
154 BOOST_CHECK_EQUAL(host_vector[2], boost::make_tuple('z', 9, 7.6f));
155 }
156
BOOST_AUTO_TEST_CASE(zip_iterator_get)157 BOOST_AUTO_TEST_CASE(zip_iterator_get)
158 {
159 int data1[] = { 0, 2, 4, 6, 8 };
160 int data2[] = { 1, 3, 5, 7, 9 };
161
162 compute::vector<int> input1(data1, data1 + 5, queue);
163 compute::vector<int> input2(data2, data2 + 5, queue);
164 compute::vector<int> output(5, context);
165
166 // extract first component from (input1)
167 compute::transform(
168 compute::make_zip_iterator(
169 boost::make_tuple(input1.begin())
170 ),
171 compute::make_zip_iterator(
172 boost::make_tuple(input1.end())
173 ),
174 output.begin(),
175 compute::get<0>(),
176 queue
177 );
178 CHECK_RANGE_EQUAL(int, 5, output, (0, 2, 4, 6, 8));
179
180 // extract first component from (input2, input1)
181 compute::transform(
182 compute::make_zip_iterator(
183 boost::make_tuple(input2.begin(), input1.begin())
184 ),
185 compute::make_zip_iterator(
186 boost::make_tuple(input2.end(), input1.end())
187 ),
188 output.begin(),
189 compute::get<0>(),
190 queue
191 );
192 CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 7, 9));
193
194 // extract second component from (input1, input2, input1)
195 compute::transform(
196 compute::make_zip_iterator(
197 boost::make_tuple(input1.begin(), input2.begin(), input1.begin())
198 ),
199 compute::make_zip_iterator(
200 boost::make_tuple(input1.end(), input2.end(), input1.end())
201 ),
202 output.begin(),
203 compute::get<1>(),
204 queue
205 );
206 CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 7, 9));
207 }
208
BOOST_AUTO_TEST_CASE(zip_constant_iterator)209 BOOST_AUTO_TEST_CASE(zip_constant_iterator)
210 {
211 compute::vector<int> result(4, context);
212
213 compute::transform(
214 compute::make_zip_iterator(
215 boost::make_tuple(
216 compute::make_constant_iterator(7)
217 )
218 ),
219 compute::make_zip_iterator(
220 boost::make_tuple(
221 compute::make_constant_iterator(7, result.size())
222 )
223 ),
224 result.begin(),
225 compute::get<0>(),
226 queue
227 );
228
229 CHECK_RANGE_EQUAL(int, 4, result, (7, 7, 7, 7));
230 }
231
232 BOOST_AUTO_TEST_SUITE_END()
233