1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
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
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
11 #ifndef BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP
12 #define BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP
14 #include <boost/tuple/tuple.hpp>
15 #include <boost/lexical_cast.hpp>
17 #include <boost/proto/core.hpp>
18 #include <boost/preprocessor/cat.hpp>
19 #include <boost/preprocessor/stringize.hpp>
21 #include <boost/compute/functional/get.hpp>
22 #include <boost/compute/lambda/result_of.hpp>
23 #include <boost/compute/lambda/placeholder.hpp>
29 namespace mpl = boost::mpl;
30 namespace proto = boost::proto;
32 // wraps a unary boolean function
33 #define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(name) \
35 struct BOOST_PP_CAT(name, _func) \
37 template<class Expr, class Args> \
38 struct lambda_result \
43 template<class Context, class Arg> \
44 static void apply(Context &ctx, const Arg &arg) \
46 ctx.stream << #name << "("; \
47 proto::eval(arg, ctx); \
53 inline typename proto::result_of::make_expr< \
54 proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \
56 name(const Arg &arg) \
58 return proto::make_expr<proto::tag::function>( \
59 BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \
63 // wraps a unary function who's return type is the same as the argument type
64 #define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(name) \
66 struct BOOST_PP_CAT(name, _func) \
68 template<class Expr, class Args> \
69 struct lambda_result \
71 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
72 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
75 template<class Context, class Arg> \
76 static void apply(Context &ctx, const Arg &arg) \
78 ctx.stream << #name << "("; \
79 proto::eval(arg, ctx); \
85 inline typename proto::result_of::make_expr< \
86 proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \
88 name(const Arg &arg) \
90 return proto::make_expr<proto::tag::function>( \
91 BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \
95 // wraps a binary function
96 #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(name) \
98 struct BOOST_PP_CAT(name, _func) \
100 template<class Expr, class Args> \
101 struct lambda_result \
103 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
104 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
107 template<class Context, class Arg1, class Arg2> \
108 static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
110 ctx.stream << #name << "("; \
111 proto::eval(arg1, ctx); \
112 ctx.stream << ", "; \
113 proto::eval(arg2, ctx); \
118 template<class Arg1, class Arg2> \
119 inline typename proto::result_of::make_expr< \
120 proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
122 name(const Arg1 &arg1, const Arg2 &arg2) \
124 return proto::make_expr<proto::tag::function>( \
125 BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
129 // wraps a binary function who's result type is the scalar type of the first argument
130 #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(name) \
132 struct BOOST_PP_CAT(name, _func) \
134 template<class Expr, class Args> \
135 struct lambda_result \
137 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
138 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type result_type; \
139 typedef typename ::boost::compute::scalar_type<result_type>::type type; \
142 template<class Context, class Arg1, class Arg2> \
143 static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \
145 ctx.stream << #name << "("; \
146 proto::eval(arg1, ctx); \
147 ctx.stream << ", "; \
148 proto::eval(arg2, ctx); \
153 template<class Arg1, class Arg2> \
154 inline typename proto::result_of::make_expr< \
155 proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \
157 name(const Arg1 &arg1, const Arg2 &arg2) \
159 return proto::make_expr<proto::tag::function>( \
160 BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \
164 // wraps a ternary function
165 #define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(name) \
167 struct BOOST_PP_CAT(name, _func) \
169 template<class Expr, class Args> \
170 struct lambda_result \
172 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \
173 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \
176 template<class Context, class Arg1, class Arg2, class Arg3> \
177 static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
179 ctx.stream << #name << "("; \
180 proto::eval(arg1, ctx); \
181 ctx.stream << ", "; \
182 proto::eval(arg2, ctx); \
183 ctx.stream << ", "; \
184 proto::eval(arg3, ctx); \
189 template<class Arg1, class Arg2, class Arg3> \
190 inline typename proto::result_of::make_expr< \
191 proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \
193 name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \
195 return proto::make_expr<proto::tag::function>( \
196 BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \
201 BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all)
202 BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any)
203 BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf)
204 BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan)
205 BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite)
207 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(abs)
208 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos)
209 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acos)
210 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin)
211 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asin)
212 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan)
213 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atan)
214 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt)
215 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt)
216 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp)
217 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp2)
218 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp10)
219 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log)
220 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log2)
221 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log10)
222 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round)
223 BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(length)
225 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross)
226 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pow)
227 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pown)
228 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(powr)
230 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot)
231 BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance)
233 BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp)
234 BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma)
235 BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad)
236 BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(smoothstep)
238 } // end lambda namespace
239 } // end compute namespace
240 } // end boost namespace
242 #endif // BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP