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 TestLambda
12 #include <boost/test/unit_test.hpp>
13 
14 #include <boost/tuple/tuple_io.hpp>
15 #include <boost/tuple/tuple_comparison.hpp>
16 
17 #include <boost/compute/function.hpp>
18 #include <boost/compute/lambda.hpp>
19 #include <boost/compute/algorithm/copy_n.hpp>
20 #include <boost/compute/algorithm/for_each.hpp>
21 #include <boost/compute/algorithm/transform.hpp>
22 #include <boost/compute/container/vector.hpp>
23 #include <boost/compute/functional/bind.hpp>
24 #include <boost/compute/iterator/zip_iterator.hpp>
25 #include <boost/compute/types/pair.hpp>
26 #include <boost/compute/types/tuple.hpp>
27 
28 #include "check_macros.hpp"
29 #include "quirks.hpp"
30 #include "context_setup.hpp"
31 
32 namespace bc = boost::compute;
33 namespace compute = boost::compute;
34 
BOOST_AUTO_TEST_CASE(squared_plus_one)35 BOOST_AUTO_TEST_CASE(squared_plus_one)
36 {
37     bc::vector<int> vector(context);
38     vector.push_back(1, queue);
39     vector.push_back(2, queue);
40     vector.push_back(3, queue);
41     vector.push_back(4, queue);
42     vector.push_back(5, queue);
43 
44     // multiply each value by itself and add one
45     bc::transform(vector.begin(),
46                   vector.end(),
47                   vector.begin(),
48                   (bc::_1 * bc::_1) + 1,
49                   queue);
50     CHECK_RANGE_EQUAL(int, 5, vector, (2, 5, 10, 17, 26));
51 }
52 
BOOST_AUTO_TEST_CASE(abs_int)53 BOOST_AUTO_TEST_CASE(abs_int)
54 {
55     bc::vector<int> vector(context);
56     vector.push_back(-1, queue);
57     vector.push_back(-2, queue);
58     vector.push_back(3, queue);
59     vector.push_back(-4, queue);
60     vector.push_back(5, queue);
61 
62     bc::transform(vector.begin(),
63                   vector.end(),
64                   vector.begin(),
65                   abs(bc::_1),
66                   queue);
67     CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 3, 4, 5));
68 }
69 
70 template<class Result, class Expr>
check_lambda_result(const Expr &)71 void check_lambda_result(const Expr &)
72 {
73     BOOST_STATIC_ASSERT((
74         boost::is_same<
75             typename ::boost::compute::lambda::result_of<Expr>::type,
76             Result
77         >::value
78     ));
79 }
80 
81 template<class Result, class Expr, class Arg1>
check_lambda_result(const Expr &,const Arg1 &)82 void check_lambda_result(const Expr &, const Arg1 &)
83 {
84     BOOST_STATIC_ASSERT((
85         boost::is_same<
86             typename ::boost::compute::lambda::result_of<
87                 Expr,
88                 typename boost::tuple<Arg1>
89             >::type,
90             Result
91         >::value
92     ));
93 }
94 
95 template<class Result, class Expr, class Arg1, class Arg2>
check_lambda_result(const Expr &,const Arg1 &,const Arg2 &)96 void check_lambda_result(const Expr &, const Arg1 &, const Arg2 &)
97 {
98     BOOST_STATIC_ASSERT((
99         boost::is_same<
100             typename ::boost::compute::lambda::result_of<
101                 Expr,
102                 typename boost::tuple<Arg1, Arg2>
103             >::type,
104             Result
105         >::value
106     ));
107 }
108 
109 template<class Result, class Expr, class Arg1, class Arg2, class Arg3>
check_lambda_result(const Expr &,const Arg1 &,const Arg2 &,const Arg3 &)110 void check_lambda_result(const Expr &, const Arg1 &, const Arg2 &, const Arg3 &)
111 {
112     BOOST_STATIC_ASSERT((
113         boost::is_same<
114             typename ::boost::compute::lambda::result_of<
115                 Expr,
116                 typename boost::tuple<Arg1, Arg2, Arg3>
117             >::type,
118             Result
119         >::value
120     ));
121 }
122 
BOOST_AUTO_TEST_CASE(result_of)123 BOOST_AUTO_TEST_CASE(result_of)
124 {
125     using ::boost::compute::lambda::_1;
126     using ::boost::compute::lambda::_2;
127     using ::boost::compute::lambda::_3;
128 
129     namespace proto = ::boost::proto;
130 
131     using boost::compute::int_;
132 
133     check_lambda_result<int_>(proto::lit(1));
134     check_lambda_result<int_>(proto::lit(1) + 2);
135     check_lambda_result<float>(proto::lit(1.2f));
136     check_lambda_result<float>(proto::lit(1) + 1.2f);
137     check_lambda_result<float>(proto::lit(1) / 2 + 1.2f);
138 
139     using boost::compute::float4_;
140     using boost::compute::int4_;
141 
142     check_lambda_result<int_>(_1, int_(1));
143     check_lambda_result<float>(_1, float(1.2f));
144     check_lambda_result<float4_>(_1, float4_(1, 2, 3, 4));
145     check_lambda_result<float4_>(2.0f * _1, float4_(1, 2, 3, 4));
146     check_lambda_result<float4_>(_1 * 2.0f, float4_(1, 2, 3, 4));
147 
148     check_lambda_result<float>(dot(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
149     check_lambda_result<float>(dot(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
150     check_lambda_result<float>(distance(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
151     check_lambda_result<float>(distance(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
152 
153     check_lambda_result<float>(length(_1), float4_(3, 2, 1, 0));
154 
155     check_lambda_result<float4_>(cross(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
156     check_lambda_result<float4_>(cross(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
157 
158     check_lambda_result<float4_>(max(_1, _2), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3));
159     check_lambda_result<float4_>(max(_1, float(1.0f)), float4_(0, 1, 2, 3));
160     check_lambda_result<int4_>(max(_1, int4_(3, 2, 1, 0)), int4_(0, 1, 2, 3));
161     check_lambda_result<int4_>(max(_1, int_(1)), int4_(0, 1, 2, 3));
162     check_lambda_result<float4_>(min(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
163 
164     check_lambda_result<float4_>(step(_1, _2), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3));
165     check_lambda_result<int4_>(step(_1, _2), float(3.0f), int4_(0, 1, 2, 3));
166 
167     check_lambda_result<float4_>(
168         smoothstep(_1, _2, _3),
169         float4_(3, 2, 1, 0), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3)
170     );
171     check_lambda_result<int4_>(
172         smoothstep(_1, _2, _3),
173         float(2.0f), float(3.0f), int4_(0, 1, 2, 3)
174     );
175 
176     check_lambda_result<int4_>(bc::lambda::isinf(_1), float4_(0, 1, 2, 3));
177 
178     check_lambda_result<int>(_1 + 2, int(2));
179     check_lambda_result<float>(_1 + 2, float(2.2f));
180 
181     check_lambda_result<int>(_1 + _2, int(1), int(2));
182     check_lambda_result<float>(_1 + _2, int(1), float(2.2f));
183 
184     check_lambda_result<int>(_1 + _1, int(1));
185     check_lambda_result<float>(_1 * _1, float(1));
186 
187     using boost::compute::lambda::get;
188 
189     check_lambda_result<float>(get<0>(_1), float4_(1, 2, 3, 4));
190     check_lambda_result<bool>(get<0>(_1) < 1.f, float4_(1, 2, 3, 4));
191     check_lambda_result<bool>(_1 < 1.f, float(2));
192 
193     using boost::compute::lambda::make_pair;
194 
195     check_lambda_result<int>(get<0>(make_pair(_1, _2)), int(1), float(1.2f));
196     check_lambda_result<float>(get<1>(make_pair(_1, _2)), int(1), float(1.2f));
197     check_lambda_result<std::pair<int, float> >(make_pair(_1, _2), int(1), float(1.2f));
198 
199     using boost::compute::lambda::make_tuple;
200 
201     check_lambda_result<boost::tuple<int> >(make_tuple(_1), int(1));
202     check_lambda_result<boost::tuple<int, float> >(make_tuple(_1, _2), int(1), float(1.2f));
203     check_lambda_result<boost::tuple<int, int> >(make_tuple(_1, _1), int(1));
204     check_lambda_result<boost::tuple<int, float> >(make_tuple(_1, _2), int(1), float(1.4f));
205     check_lambda_result<boost::tuple<char, int, float> >(
206         make_tuple(_1, _2, _3), char('a'), int(2), float(3.4f)
207     );
208     check_lambda_result<boost::tuple<int, int, int> >(
209         make_tuple(_1, _1, _1), int(1), float(1.4f)
210     );
211     check_lambda_result<boost::tuple<int, float, int, float, int> >(
212         make_tuple(_1, _2, _1, _2, _1), int(1), float(1.4f)
213     );
214 }
215 
BOOST_AUTO_TEST_CASE(make_function_from_lamdba)216 BOOST_AUTO_TEST_CASE(make_function_from_lamdba)
217 {
218     using boost::compute::lambda::_1;
219 
220     int data[] = { 2, 4, 6, 8, 10 };
221     compute::vector<int> vector(data, data + 5, queue);
222 
223     compute::function<int(int)> f = _1 * 2 + 3;
224 
225     compute::transform(
226         vector.begin(), vector.end(), vector.begin(), f, queue
227     );
228     CHECK_RANGE_EQUAL(int, 5, vector, (7, 11, 15, 19, 23));
229 }
230 
BOOST_AUTO_TEST_CASE(make_function_from_binary_lamdba)231 BOOST_AUTO_TEST_CASE(make_function_from_binary_lamdba)
232 {
233     using boost::compute::lambda::_1;
234     using boost::compute::lambda::_2;
235     using boost::compute::lambda::abs;
236 
237     int data1[] = { 2, 4, 6, 8, 10 };
238     int data2[] = { 10, 8, 6, 4, 2 };
239     compute::vector<int> vec1(data1, data1 + 5, queue);
240     compute::vector<int> vec2(data2, data2 + 5, queue);
241     compute::vector<int> result(5, context);
242 
243     compute::function<int(int, int)> f = abs(_1 - _2);
244 
245     compute::transform(
246         vec1.begin(), vec1.end(), vec2.begin(), result.begin(), f, queue
247     );
248     CHECK_RANGE_EQUAL(int, 5, result, (8, 4, 0, 4, 8));
249 }
250 
BOOST_AUTO_TEST_CASE(lambda_binary_function_with_pointer_modf)251 BOOST_AUTO_TEST_CASE(lambda_binary_function_with_pointer_modf)
252 {
253     using boost::compute::lambda::_1;
254     using boost::compute::lambda::_2;
255     using boost::compute::lambda::abs;
256 
257     bc::float_ data1[] = { 2.2f, 4.2f, 6.3f, 8.3f, 10.2f };
258     compute::vector<bc::float_> vec1(data1, data1 + 5, queue);
259     compute::vector<bc::float_> vec2(size_t(5), context);
260     compute::vector<bc::float_> result(5, context);
261 
262     compute::transform(
263         bc::make_transform_iterator(vec1.begin(), _1 + 0.01f),
264         bc::make_transform_iterator(vec1.end(), _1 + 0.01f),
265         vec2.begin(),
266         result.begin(),
267         bc::lambda::modf(_1, _2),
268         queue
269     );
270     CHECK_RANGE_CLOSE(bc::float_, 5, result, (0.21f, 0.21f, 0.31f, 0.31f, 0.21f), 0.01f);
271     CHECK_RANGE_CLOSE(bc::float_, 5, vec2, (2, 4, 6, 8, 10), 0.01f);
272 }
273 
BOOST_AUTO_TEST_CASE(lambda_tenary_function_with_pointer_remquo)274 BOOST_AUTO_TEST_CASE(lambda_tenary_function_with_pointer_remquo)
275 {
276     if(!has_remquo_func(device))
277     {
278         return;
279     }
280 
281     using boost::compute::lambda::_1;
282     using boost::compute::lambda::_2;
283     using boost::compute::lambda::get;
284 
285     bc::float_ data1[] = { 2.2f, 4.2f, 6.3f, 8.3f, 10.2f };
286     bc::float_ data2[] = { 4.4f, 4.2f, 6.3f, 16.6f, 10.2f };
287     compute::vector<bc::float_> vec1(data1, data1 + 5, queue);
288     compute::vector<bc::float_> vec2(data2, data2 + 5, queue);
289     compute::vector<bc::int_> vec3(size_t(5), context);
290     compute::vector<bc::float_> result(5, context);
291 
292     compute::transform(
293         compute::make_zip_iterator(
294             boost::make_tuple(vec1.begin(), vec2.begin(), vec3.begin())
295         ),
296         compute::make_zip_iterator(
297             boost::make_tuple(vec1.end(), vec2.end(), vec3.end())
298         ),
299         result.begin(),
300         bc::lambda::remquo(get<0>(_1), get<1>(_1), get<2>(_1)),
301         queue
302     );
303     CHECK_RANGE_CLOSE(bc::float_, 5, result, (2.2f, 0.0f, 0.0f, 8.3f, 0.0f), 0.01f);
304     CHECK_RANGE_EQUAL(bc::int_, 5, vec3, (0, 1, 1, 0, 1));
305 }
306 
BOOST_AUTO_TEST_CASE(lambda_get_vector)307 BOOST_AUTO_TEST_CASE(lambda_get_vector)
308 {
309     using boost::compute::_1;
310     using boost::compute::int2_;
311     using boost::compute::lambda::get;
312 
313     int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
314     compute::vector<int2_> vector(4, context);
315 
316     compute::copy(
317         reinterpret_cast<int2_ *>(data),
318         reinterpret_cast<int2_ *>(data) + 4,
319         vector.begin(),
320         queue
321     );
322 
323     // extract first component of each vector
324     compute::vector<int> first_component(4, context);
325     compute::transform(
326         vector.begin(),
327         vector.end(),
328         first_component.begin(),
329         get<0>(_1),
330         queue
331     );
332     CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
333 
334     // extract second component of each vector
335     compute::vector<int> second_component(4, context);
336     compute::transform(
337         vector.begin(),
338         vector.end(),
339         first_component.begin(),
340         get<1>(_1),
341         queue
342     );
343     CHECK_RANGE_EQUAL(int, 4, first_component, (2, 4, 6, 8));
344 }
345 
BOOST_AUTO_TEST_CASE(lambda_get_pair)346 BOOST_AUTO_TEST_CASE(lambda_get_pair)
347 {
348     using boost::compute::_1;
349     using boost::compute::lambda::get;
350 
351     compute::vector<std::pair<int, float> > vector(context);
352     vector.push_back(std::make_pair(1, 1.2f), queue);
353     vector.push_back(std::make_pair(3, 3.4f), queue);
354     vector.push_back(std::make_pair(5, 5.6f), queue);
355     vector.push_back(std::make_pair(7, 7.8f), queue);
356 
357     // extract first compoenent of each pair
358     compute::vector<int> first_component(4, context);
359     compute::transform(
360         vector.begin(),
361         vector.end(),
362         first_component.begin(),
363         get<0>(_1),
364         queue
365     );
366     CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
367 
368     // extract second compoenent of each pair
369     compute::vector<float> second_component(4, context);
370     compute::transform(
371         vector.begin(),
372         vector.end(),
373         second_component.begin(),
374         get<1>(_1),
375         queue
376     );
377     CHECK_RANGE_EQUAL(float, 4, second_component, (1.2f, 3.4f, 5.6f, 7.8f));
378 }
379 
BOOST_AUTO_TEST_CASE(lambda_get_tuple)380 BOOST_AUTO_TEST_CASE(lambda_get_tuple)
381 {
382     using boost::compute::_1;
383     using boost::compute::lambda::get;
384 
385     compute::vector<boost::tuple<int, char, float> > vector(context);
386 
387     vector.push_back(boost::make_tuple(1, 'a', 1.2f), queue);
388     vector.push_back(boost::make_tuple(3, 'b', 3.4f), queue);
389     vector.push_back(boost::make_tuple(5, 'c', 5.6f), queue);
390     vector.push_back(boost::make_tuple(7, 'd', 7.8f), queue);
391 
392     // extract first component of each tuple
393     compute::vector<int> first_component(4, context);
394     compute::transform(
395         vector.begin(),
396         vector.end(),
397         first_component.begin(),
398         get<0>(_1),
399         queue
400     );
401     CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
402 
403     // extract second component of each tuple
404     compute::vector<char> second_component(4, context);
405     compute::transform(
406         vector.begin(),
407         vector.end(),
408         second_component.begin(),
409         get<1>(_1),
410         queue
411     );
412     CHECK_RANGE_EQUAL(char, 4, second_component, ('a', 'b', 'c', 'd'));
413 
414     // extract third component of each tuple
415     compute::vector<float> third_component(4, context);
416     compute::transform(
417         vector.begin(),
418         vector.end(),
419         third_component.begin(),
420         get<2>(_1),
421         queue
422     );
423     CHECK_RANGE_EQUAL(float, 4, third_component, (1.2f, 3.4f, 5.6f, 7.8f));
424 }
425 
BOOST_AUTO_TEST_CASE(lambda_get_zip_iterator)426 BOOST_AUTO_TEST_CASE(lambda_get_zip_iterator)
427 {
428     using boost::compute::_1;
429     using boost::compute::lambda::get;
430 
431     float data[] = { 1.2f, 2.3f, 3.4f, 4.5f, 5.6f, 6.7f, 7.8f, 9.0f };
432     compute::vector<float> input(8, context);
433     compute::copy(data, data + 8, input.begin(), queue);
434 
435     compute::vector<float> output(8, context);
436 
437     compute::for_each(
438         compute::make_zip_iterator(
439             boost::make_tuple(input.begin(), output.begin())
440         ),
441         compute::make_zip_iterator(
442             boost::make_tuple(input.end(), output.end())
443         ),
444         get<1>(_1) = get<0>(_1),
445         queue
446     );
447     CHECK_RANGE_EQUAL(float, 8, output,
448         (1.2f, 2.3f, 3.4f, 4.5f, 5.6f, 6.7f, 7.8f, 9.0f)
449     );
450 }
451 
BOOST_AUTO_TEST_CASE(lambda_make_pair)452 BOOST_AUTO_TEST_CASE(lambda_make_pair)
453 {
454     using boost::compute::_1;
455     using boost::compute::_2;
456     using boost::compute::lambda::make_pair;
457 
458     int int_data[] = { 1, 3, 5, 7 };
459     float float_data[] = { 1.2f, 2.3f, 3.4f, 4.5f };
460 
461     compute::vector<int> int_vector(int_data, int_data + 4, queue);
462     compute::vector<float> float_vector(float_data, float_data + 4, queue);
463     compute::vector<std::pair<int, float> > output_vector(4, context);
464 
465     compute::transform(
466         int_vector.begin(),
467         int_vector.end(),
468         float_vector.begin(),
469         output_vector.begin(),
470         make_pair(_1 - 1, 0 - _2),
471         queue
472     );
473 
474     std::vector<std::pair<int, float> > host_vector(4);
475     compute::copy_n(output_vector.begin(), 4, host_vector.begin(), queue);
476     BOOST_CHECK(host_vector[0] == std::make_pair(0, -1.2f));
477     BOOST_CHECK(host_vector[1] == std::make_pair(2, -2.3f));
478     BOOST_CHECK(host_vector[2] == std::make_pair(4, -3.4f));
479     BOOST_CHECK(host_vector[3] == std::make_pair(6, -4.5f));
480 }
481 
BOOST_AUTO_TEST_CASE(lambda_make_tuple)482 BOOST_AUTO_TEST_CASE(lambda_make_tuple)
483 {
484     using boost::compute::_1;
485     using boost::compute::lambda::get;
486     using boost::compute::lambda::make_tuple;
487 
488     std::vector<boost::tuple<int, float> > data;
489     data.push_back(boost::make_tuple(2, 1.2f));
490     data.push_back(boost::make_tuple(4, 2.4f));
491     data.push_back(boost::make_tuple(6, 4.6f));
492     data.push_back(boost::make_tuple(8, 6.8f));
493 
494     compute::vector<boost::tuple<int, float> > input_vector(4, context);
495     compute::copy(data.begin(), data.end(), input_vector.begin(), queue);
496 
497     // reverse the elements in the tuple
498     compute::vector<boost::tuple<float, int> > output_vector(4, context);
499 
500     compute::transform(
501         input_vector.begin(),
502         input_vector.end(),
503         output_vector.begin(),
504         make_tuple(get<1>(_1), get<0>(_1)),
505         queue
506     );
507 
508     std::vector<boost::tuple<float, int> > host_vector(4);
509     compute::copy_n(output_vector.begin(), 4, host_vector.begin(), queue);
510     BOOST_CHECK_EQUAL(host_vector[0], boost::make_tuple(1.2f, 2));
511     BOOST_CHECK_EQUAL(host_vector[1], boost::make_tuple(2.4f, 4));
512     BOOST_CHECK_EQUAL(host_vector[2], boost::make_tuple(4.6f, 6));
513     BOOST_CHECK_EQUAL(host_vector[3], boost::make_tuple(6.8f, 8));
514 
515     // duplicate each element in the tuple
516     compute::vector<boost::tuple<int, int, float, float> > doubled_vector(4, context);
517     compute::transform(
518         input_vector.begin(),
519         input_vector.end(),
520         doubled_vector.begin(),
521         make_tuple(get<0>(_1), get<0>(_1), get<1>(_1), get<1>(_1)),
522         queue
523     );
524 
525     std::vector<boost::tuple<int, int, float, float> > doubled_host_vector(4);
526     compute::copy_n(doubled_vector.begin(), 4, doubled_host_vector.begin(), queue);
527     BOOST_CHECK_EQUAL(doubled_host_vector[0], boost::make_tuple(2, 2, 1.2f, 1.2f));
528     BOOST_CHECK_EQUAL(doubled_host_vector[1], boost::make_tuple(4, 4, 2.4f, 2.4f));
529     BOOST_CHECK_EQUAL(doubled_host_vector[2], boost::make_tuple(6, 6, 4.6f, 4.6f));
530     BOOST_CHECK_EQUAL(doubled_host_vector[3], boost::make_tuple(8, 8, 6.8f, 6.8f));
531 }
532 
BOOST_AUTO_TEST_CASE(bind_lambda_function)533 BOOST_AUTO_TEST_CASE(bind_lambda_function)
534 {
535     using compute::placeholders::_1;
536     namespace lambda = compute::lambda;
537 
538     int data[] = { 1, 2, 3, 4 };
539     compute::vector<int> vector(data, data + 4, queue);
540 
541     compute::transform(
542         vector.begin(), vector.end(), vector.begin(),
543         compute::bind(lambda::_1 * lambda::_2, _1, 2),
544         queue
545     );
546     CHECK_RANGE_EQUAL(int, 4, vector, (2, 4, 6, 8));
547 }
548 
BOOST_AUTO_TEST_CASE(lambda_function_with_uint_args)549 BOOST_AUTO_TEST_CASE(lambda_function_with_uint_args)
550 {
551   compute::uint_ host_data[] = { 1, 3, 5, 7, 9 };
552   compute::vector<compute::uint_> device_vector(host_data, host_data + 5, queue);
553 
554   using boost::compute::lambda::clamp;
555   using compute::lambda::_1;
556 
557   compute::transform(
558     device_vector.begin(), device_vector.end(),
559     device_vector.begin(),
560     clamp(_1, compute::uint_(4), compute::uint_(6)),
561     queue
562   );
563   CHECK_RANGE_EQUAL(compute::uint_, 5, device_vector, (4, 4, 5, 6, 6));
564 }
565 
BOOST_AUTO_TEST_CASE(lambda_function_with_short_args)566 BOOST_AUTO_TEST_CASE(lambda_function_with_short_args)
567 {
568   compute::short_ host_data[] = { 1, 3, 5, 7, 9 };
569   compute::vector<compute::short_> device_vector(host_data, host_data + 5, queue);
570 
571   using boost::compute::lambda::clamp;
572   using compute::lambda::_1;
573 
574   compute::transform(
575     device_vector.begin(), device_vector.end(),
576     device_vector.begin(),
577     clamp(_1, compute::short_(4), compute::short_(6)),
578     queue
579   );
580   CHECK_RANGE_EQUAL(compute::short_, 5, device_vector, (4, 4, 5, 6, 6));
581 }
582 
BOOST_AUTO_TEST_CASE(lambda_function_with_uchar_args)583 BOOST_AUTO_TEST_CASE(lambda_function_with_uchar_args)
584 {
585   compute::uchar_ host_data[] = { 1, 3, 5, 7, 9 };
586   compute::vector<compute::uchar_> device_vector(host_data, host_data + 5, queue);
587 
588   using boost::compute::lambda::clamp;
589   using compute::lambda::_1;
590 
591   compute::transform(
592     device_vector.begin(), device_vector.end(),
593     device_vector.begin(),
594     clamp(_1, compute::uchar_(4), compute::uchar_(6)),
595     queue
596   );
597   CHECK_RANGE_EQUAL(compute::uchar_, 5, device_vector, (4, 4, 5, 6, 6));
598 }
599 
BOOST_AUTO_TEST_CASE(lambda_function_with_char_args)600 BOOST_AUTO_TEST_CASE(lambda_function_with_char_args)
601 {
602   compute::char_ host_data[] = { 1, 3, 5, 7, 9 };
603   compute::vector<compute::char_> device_vector(host_data, host_data + 5, queue);
604 
605   using boost::compute::lambda::clamp;
606   using compute::lambda::_1;
607 
608   compute::transform(
609     device_vector.begin(), device_vector.end(),
610     device_vector.begin(),
611     clamp(_1, compute::char_(4), compute::char_(6)),
612     queue
613   );
614   CHECK_RANGE_EQUAL(compute::char_, 5, device_vector, (4, 4, 5, 6, 6));
615 }
616 
617 BOOST_AUTO_TEST_SUITE_END()
618