• 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 TestClosure
12 #include <boost/test/unit_test.hpp>
13 
14 #include <boost/compute/system.hpp>
15 #include <boost/compute/closure.hpp>
16 #include <boost/compute/function.hpp>
17 #include <boost/compute/algorithm/copy.hpp>
18 #include <boost/compute/algorithm/transform.hpp>
19 #include <boost/compute/algorithm/transform_reduce.hpp>
20 #include <boost/compute/container/array.hpp>
21 #include <boost/compute/container/vector.hpp>
22 #include <boost/compute/iterator/counting_iterator.hpp>
23 
24 #include "check_macros.hpp"
25 #include "context_setup.hpp"
26 
27 namespace compute = boost::compute;
28 
BOOST_AUTO_TEST_CASE(add_two)29 BOOST_AUTO_TEST_CASE(add_two)
30 {
31     int two = 2;
32     BOOST_COMPUTE_CLOSURE(int, add_two, (int x), (two),
33     {
34         return x + two;
35     });
36 
37     int data[] = { 1, 2, 3, 4 };
38     compute::vector<int> vector(data, data + 4, queue);
39 
40     compute::transform(
41         vector.begin(), vector.end(), vector.begin(), add_two, queue
42     );
43     CHECK_RANGE_EQUAL(int, 4, vector, (3, 4, 5, 6));
44 }
45 
BOOST_AUTO_TEST_CASE(add_two_and_pi)46 BOOST_AUTO_TEST_CASE(add_two_and_pi)
47 {
48     int two = 2;
49     float pi = 3.14f;
50     BOOST_COMPUTE_CLOSURE(float, add_two_and_pi, (float x), (two, pi),
51     {
52         return x + two + pi;
53     });
54 
55     float data[] = { 1.9f, 2.2f, 3.4f, 4.7f };
56     compute::vector<float> vector(data, data + 4, queue);
57 
58     compute::transform(
59         vector.begin(), vector.end(), vector.begin(), add_two_and_pi, queue
60     );
61 
62     std::vector<float> results(4);
63     compute::copy(vector.begin(), vector.end(), results.begin(), queue);
64     BOOST_CHECK_CLOSE(results[0], 7.04f, 1e-6);
65     BOOST_CHECK_CLOSE(results[1], 7.34f, 1e-6);
66     BOOST_CHECK_CLOSE(results[2], 8.54f, 1e-6);
67     BOOST_CHECK_CLOSE(results[3], 9.84f, 1e-6);
68 }
69 
BOOST_AUTO_TEST_CASE(add_y)70 BOOST_AUTO_TEST_CASE(add_y)
71 {
72     // setup input and output vectors
73     int data[] = { 1, 2, 3, 4 };
74     compute::vector<int> input(data, data + 4, queue);
75     compute::vector<int> output(4, context);
76 
77     // make closure which adds 'y' to each value
78     int y = 2;
79     BOOST_COMPUTE_CLOSURE(int, add_y, (int x), (y),
80     {
81         return x + y;
82     });
83 
84     compute::transform(
85         input.begin(), input.end(), output.begin(), add_y, queue
86     );
87     CHECK_RANGE_EQUAL(int, 4, output, (3, 4, 5, 6));
88 
89     // change y and run again
90     y = 4;
91 
92     compute::transform(
93         input.begin(), input.end(), output.begin(), add_y, queue
94     );
95     CHECK_RANGE_EQUAL(int, 4, output, (5, 6, 7, 8));
96 }
97 
BOOST_AUTO_TEST_CASE(scale_add_vec)98 BOOST_AUTO_TEST_CASE(scale_add_vec)
99 {
100     const int N = 10;
101     float s = 4.5;
102     compute::vector<float> a(N, context);
103     compute::vector<float> b(N, context);
104     a.assign(N, 1.0f, queue);
105     b.assign(N, 2.0f, queue);
106 
107     BOOST_COMPUTE_CLOSURE(float, scaleAddVec, (float b, float a), (s),
108     {
109         return b * s + a;
110     });
111     compute::transform(b.begin(), b.end(), a.begin(), b.begin(), scaleAddVec, queue);
112 }
113 
BOOST_AUTO_TEST_CASE(capture_vector)114 BOOST_AUTO_TEST_CASE(capture_vector)
115 {
116     int data[] = { 6, 7, 8, 9 };
117     compute::vector<int> vec(data, data + 4, queue);
118 
119     BOOST_COMPUTE_CLOSURE(int, get_vec, (int i), (vec),
120     {
121         return vec[i];
122     });
123 
124     // run using a counting iterator to copy from vec to output
125     compute::vector<int> output(4, context);
126     compute::transform(
127         compute::make_counting_iterator(0),
128         compute::make_counting_iterator(4),
129         output.begin(),
130         get_vec,
131         queue
132     );
133     CHECK_RANGE_EQUAL(int, 4, output, (6, 7, 8, 9));
134 
135     // fill vec with 4's and run again
136     compute::fill(vec.begin(), vec.end(), 4, queue);
137     compute::transform(
138         compute::make_counting_iterator(0),
139         compute::make_counting_iterator(4),
140         output.begin(),
141         get_vec,
142         queue
143     );
144     CHECK_RANGE_EQUAL(int, 4, output, (4, 4, 4, 4));
145 }
146 
BOOST_AUTO_TEST_CASE(capture_array)147 BOOST_AUTO_TEST_CASE(capture_array)
148 {
149     int data[] = { 1, 2, 3, 4 };
150     compute::array<int, 4> array(context);
151     compute::copy(data, data + 4, array.begin(), queue);
152 
153     BOOST_COMPUTE_CLOSURE(int, negative_array_value, (int i), (array),
154     {
155         return -array[i];
156     });
157 
158     compute::vector<int> output(4, context);
159     compute::transform(
160         compute::make_counting_iterator(0),
161         compute::make_counting_iterator(4),
162         output.begin(),
163         negative_array_value,
164         queue
165     );
166     CHECK_RANGE_EQUAL(int, 4, output, (-1, -2, -3, -4));
167 }
168 
BOOST_AUTO_TEST_CASE(triangle_area)169 BOOST_AUTO_TEST_CASE(triangle_area)
170 {
171     using compute::uint4_;
172     using compute::float4_;
173 
174     compute::vector<uint4_> triangle_indices(context);
175     compute::vector<float4_> triangle_vertices(context);
176 
177     triangle_vertices.push_back(float4_(0, 0, 0, 1), queue);
178     triangle_vertices.push_back(float4_(1, 1, 0, 1), queue);
179     triangle_vertices.push_back(float4_(1, 0, 0, 1), queue);
180     triangle_vertices.push_back(float4_(2, 0, 0, 1), queue);
181 
182     triangle_indices.push_back(uint4_(0, 1, 2, 0), queue);
183     triangle_indices.push_back(uint4_(2, 1, 3, 0), queue);
184 
185     queue.finish();
186 
187     BOOST_COMPUTE_CLOSURE(float, triangle_area, (const uint4_ i), (triangle_vertices),
188     {
189         // load triangle vertices
190         const float4 a = triangle_vertices[i.x];
191         const float4 b = triangle_vertices[i.y];
192         const float4 c = triangle_vertices[i.z];
193 
194         // return area of triangle
195         return length(cross(b-a, c-a)) / 2;
196     });
197 
198     // compute area of each triangle
199     compute::vector<float> triangle_areas(triangle_indices.size(), context);
200 
201     compute::transform(
202         triangle_indices.begin(),
203         triangle_indices.end(),
204         triangle_areas.begin(),
205         triangle_area,
206         queue
207     );
208 
209     // compute total area of all triangles
210     float total_area = 0;
211 
212     compute::transform_reduce(
213         triangle_indices.begin(),
214         triangle_indices.end(),
215         &total_area,
216         triangle_area,
217         compute::plus<float>(),
218         queue
219     );
220     BOOST_CHECK_CLOSE(total_area, 1.f, 1e-6);
221 }
222 
223 BOOST_AUTO_TEST_SUITE_END()
224