• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 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 TestFunctionalBind
12 #include <boost/test/unit_test.hpp>
13 
14 #include <iostream>
15 
16 #include <boost/compute/function.hpp>
17 #include <boost/compute/algorithm/copy_n.hpp>
18 #include <boost/compute/algorithm/count_if.hpp>
19 #include <boost/compute/algorithm/find_if.hpp>
20 #include <boost/compute/algorithm/transform.hpp>
21 #include <boost/compute/container/vector.hpp>
22 #include <boost/compute/functional/bind.hpp>
23 #include <boost/compute/functional/common.hpp>
24 #include <boost/compute/functional/operator.hpp>
25 #include <boost/compute/types/struct.hpp>
26 
27 // simple test struct
28 struct data_struct
29 {
30     int int_value;
31     float float_value;
32 };
33 
34 BOOST_COMPUTE_ADAPT_STRUCT(data_struct, data_struct, (int_value, float_value))
35 
36 #include "quirks.hpp"
37 #include "check_macros.hpp"
38 #include "context_setup.hpp"
39 
40 namespace compute = boost::compute;
41 
42 using compute::placeholders::_1;
43 using compute::placeholders::_2;
44 
BOOST_AUTO_TEST_CASE(transform_plus_two)45 BOOST_AUTO_TEST_CASE(transform_plus_two)
46 {
47     int data[] = { 1, 2, 3, 4 };
48     compute::vector<int> vector(4, context);
49     compute::copy_n(data, 4, vector.begin(), queue);
50 
51     compute::transform(
52         vector.begin(), vector.end(), vector.begin(),
53         compute::bind(compute::plus<int>(), _1, 2),
54         queue
55     );
56 
57     CHECK_RANGE_EQUAL(int, 4, vector, (3, 4, 5, 6));
58 }
59 
BOOST_AUTO_TEST_CASE(transform_pow_two)60 BOOST_AUTO_TEST_CASE(transform_pow_two)
61 {
62     float data[] = { 2, 3, 4, 5 };
63     compute::vector<float> vector(4, context);
64     compute::copy_n(data, 4, vector.begin(), queue);
65 
66     compute::transform(
67         vector.begin(), vector.end(), vector.begin(),
68         compute::bind(compute::pow<float>(), 2.0f, _1),
69         queue
70     );
71 
72     compute::copy(vector.begin(), vector.end(), data, queue);
73     BOOST_CHECK_CLOSE(data[0], 4.0f, 1e-4);
74     BOOST_CHECK_CLOSE(data[1], 8.0f, 1e-4);
75     BOOST_CHECK_CLOSE(data[2], 16.0f, 1e-4);
76     BOOST_CHECK_CLOSE(data[3], 32.0f, 1e-4);
77 }
78 
BOOST_AUTO_TEST_CASE(find_if_equal)79 BOOST_AUTO_TEST_CASE(find_if_equal)
80 {
81     int data[] = { 1, 2, 3, 4 };
82     compute::vector<int> vector(4, context);
83     compute::copy_n(data, 4, vector.begin(), queue);
84 
85     BOOST_CHECK(
86         compute::find_if(
87             vector.begin(), vector.end(),
88             compute::bind(compute::equal_to<int>(), _1, 3),
89             queue
90         ) == vector.begin() + 2
91     );
92 }
93 
BOOST_AUTO_TEST_CASE(compare_less_than)94 BOOST_AUTO_TEST_CASE(compare_less_than)
95 {
96     int data[] = { 1, 2, 3, 4 };
97     compute::vector<int> vector(data, data + 4, queue);
98 
99     int count = boost::compute::count_if(
100         vector.begin(), vector.end(),
101         compute::bind(compute::less<int>(), _1, int(3)),
102         queue
103     );
104     BOOST_CHECK_EQUAL(count, 2);
105 
106     count = boost::compute::count_if(
107         vector.begin(), vector.end(),
108         compute::bind(compute::less<int>(), int(3), _1),
109         queue
110     );
111     BOOST_CHECK_EQUAL(count, 1);
112 }
113 
BOOST_AUTO_TEST_CASE(subtract_ranges)114 BOOST_AUTO_TEST_CASE(subtract_ranges)
115 {
116     int data1[] = { 1, 2, 3, 4 };
117     int data2[] = { 4, 3, 2, 1 };
118 
119     compute::vector<int> vector1(data1, data1 + 4, queue);
120     compute::vector<int> vector2(data2, data2 + 4, queue);
121 
122     compute::vector<int> result(4, context);
123 
124     compute::transform(
125         vector1.begin(),
126         vector1.end(),
127         vector2.begin(),
128         result.begin(),
129         compute::bind(compute::minus<int>(), _1, _2),
130         queue
131     );
132     CHECK_RANGE_EQUAL(int, 4, result, (-3, -1, 1, 3));
133 
134     compute::transform(
135         vector1.begin(),
136         vector1.end(),
137         vector2.begin(),
138         result.begin(),
139         compute::bind(compute::minus<int>(), _2, _1),
140         queue
141     );
142     CHECK_RANGE_EQUAL(int, 4, result, (3, 1, -1, -3));
143 
144     compute::transform(
145         vector1.begin(),
146         vector1.end(),
147         vector2.begin(),
148         result.begin(),
149         compute::bind(compute::minus<int>(), 5, _1),
150         queue
151     );
152     CHECK_RANGE_EQUAL(int, 4, result, (4, 3, 2, 1));
153 
154     compute::transform(
155         vector1.begin(),
156         vector1.end(),
157         vector2.begin(),
158         result.begin(),
159         compute::bind(compute::minus<int>(), 5, _2),
160         queue
161     );
162     CHECK_RANGE_EQUAL(int, 4, result, (1, 2, 3, 4));
163 }
164 
BOOST_AUTO_TEST_CASE(clamp_values)165 BOOST_AUTO_TEST_CASE(clamp_values)
166 {
167     int data[] = { 1, 2, 3, 4 };
168     compute::vector<int> vector(data, data + 4, queue);
169 
170     compute::transform(
171         vector.begin(), vector.end(), vector.begin(),
172         compute::bind(compute::clamp<int>(), _1, 2, 3),
173         queue
174     );
175     CHECK_RANGE_EQUAL(int, 4, vector, (2, 2, 3, 3));
176 }
177 
BOOST_AUTO_TEST_CASE(bind_custom_function)178 BOOST_AUTO_TEST_CASE(bind_custom_function)
179 {
180     int data[] = { 1, 2, 3, 4 };
181     compute::vector<int> vector(data, data + 4, queue);
182 
183     BOOST_COMPUTE_FUNCTION(int, x_if_odd_else_y, (int x, int y),
184     {
185         if(x & 1)
186             return x;
187         else
188             return y;
189     });
190 
191     compute::transform(
192         vector.begin(), vector.end(), vector.begin(),
193         compute::bind(x_if_odd_else_y, _1, 9),
194         queue
195     );
196     CHECK_RANGE_EQUAL(int, 4, vector, (1, 9, 3, 9));
197 
198     compute::copy(
199         data, data + 4, vector.begin(), queue
200     );
201 
202     compute::transform(
203         vector.begin(), vector.end(), vector.begin(),
204         compute::bind(x_if_odd_else_y, 2, _1),
205         queue
206     );
207     CHECK_RANGE_EQUAL(int, 4, vector, (1, 2, 3, 4));
208 }
209 
BOOST_AUTO_TEST_CASE(bind_struct)210 BOOST_AUTO_TEST_CASE(bind_struct)
211 {
212     if(bug_in_struct_assignment(device)){
213         std::cerr << "skipping bind_struct test" << std::endl;
214         return;
215     }
216 
217     BOOST_COMPUTE_FUNCTION(int, add_struct_value, (int x, data_struct s),
218     {
219         return s.int_value + x;
220     });
221 
222     data_struct data;
223     data.int_value = 3;
224     data.float_value = 4.56f;
225 
226     int input[] = { 1, 2, 3, 4 };
227     compute::vector<int> vec(input, input + 4, queue);
228 
229     compute::transform(
230         vec.begin(), vec.end(), vec.begin(),
231         compute::bind(add_struct_value, _1, data),
232         queue
233     );
234     CHECK_RANGE_EQUAL(int, 4, vec, (4, 5, 6, 7));
235 }
236 
237 BOOST_AUTO_TEST_SUITE_END()
238