243 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			243 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //---------------------------------------------------------------------------// | ||
|  | // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com> | ||
|  | // | ||
|  | // Distributed under the Boost Software License, Version 1.0 | ||
|  | // See accompanying file LICENSE_1_0.txt or copy at | ||
|  | // http://www.boost.org/LICENSE_1_0.txt | ||
|  | // | ||
|  | // See http://boostorg.github.com/compute for more information. | ||
|  | //---------------------------------------------------------------------------// | ||
|  | 
 | ||
|  | #ifndef BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP | ||
|  | #define BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP | ||
|  | 
 | ||
|  | #include <boost/tuple/tuple.hpp> | ||
|  | #include <boost/lexical_cast.hpp> | ||
|  | 
 | ||
|  | #include <boost/proto/core.hpp> | ||
|  | #include <boost/preprocessor/cat.hpp> | ||
|  | #include <boost/preprocessor/stringize.hpp> | ||
|  | 
 | ||
|  | #include <boost/compute/functional/get.hpp> | ||
|  | #include <boost/compute/lambda/result_of.hpp> | ||
|  | #include <boost/compute/lambda/placeholder.hpp> | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace compute { | ||
|  | namespace lambda { | ||
|  | 
 | ||
|  | namespace mpl = boost::mpl; | ||
|  | namespace proto = boost::proto; | ||
|  | 
 | ||
|  | // wraps a unary boolean function | ||
|  | #define BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(name) \ | ||
|  |     namespace detail { \ | ||
|  |         struct BOOST_PP_CAT(name, _func) \ | ||
|  |         { \ | ||
|  |             template<class Expr, class Args> \ | ||
|  |             struct lambda_result \ | ||
|  |             { \ | ||
|  |                 typedef int type; \ | ||
|  |             }; \ | ||
|  |             \ | ||
|  |             template<class Context, class Arg> \ | ||
|  |             static void apply(Context &ctx, const Arg &arg) \ | ||
|  |             { \ | ||
|  |                 ctx.stream << #name << "("; \ | ||
|  |                 proto::eval(arg, ctx); \ | ||
|  |                 ctx.stream << ")"; \ | ||
|  |             } \ | ||
|  |         }; \ | ||
|  |     } \ | ||
|  |     template<class Arg> \ | ||
|  |     inline typename proto::result_of::make_expr< \ | ||
|  |         proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \ | ||
|  |     >::type const \ | ||
|  |     name(const Arg &arg) \ | ||
|  |     { \ | ||
|  |         return proto::make_expr<proto::tag::function>( \ | ||
|  |             BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \ | ||
|  |         ); \ | ||
|  |     } | ||
|  | 
 | ||
|  | // wraps a unary function who's return type is the same as the argument type | ||
|  | #define BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(name) \ | ||
|  |     namespace detail { \ | ||
|  |         struct BOOST_PP_CAT(name, _func) \ | ||
|  |         { \ | ||
|  |             template<class Expr, class Args> \ | ||
|  |             struct lambda_result \ | ||
|  |             { \ | ||
|  |                 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ | ||
|  |                 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \ | ||
|  |             }; \ | ||
|  |             \ | ||
|  |             template<class Context, class Arg> \ | ||
|  |             static void apply(Context &ctx, const Arg &arg) \ | ||
|  |             { \ | ||
|  |                 ctx.stream << #name << "("; \ | ||
|  |                 proto::eval(arg, ctx); \ | ||
|  |                 ctx.stream << ")"; \ | ||
|  |             } \ | ||
|  |         }; \ | ||
|  |     } \ | ||
|  |     template<class Arg> \ | ||
|  |     inline typename proto::result_of::make_expr< \ | ||
|  |         proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg& \ | ||
|  |     >::type const \ | ||
|  |     name(const Arg &arg) \ | ||
|  |     { \ | ||
|  |         return proto::make_expr<proto::tag::function>( \ | ||
|  |             BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg) \ | ||
|  |         ); \ | ||
|  |     } | ||
|  | 
 | ||
|  | // wraps a binary function | ||
|  | #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(name) \ | ||
|  |     namespace detail { \ | ||
|  |         struct BOOST_PP_CAT(name, _func) \ | ||
|  |         { \ | ||
|  |             template<class Expr, class Args> \ | ||
|  |             struct lambda_result \ | ||
|  |             { \ | ||
|  |                 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ | ||
|  |                 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \ | ||
|  |             }; \ | ||
|  |             \ | ||
|  |             template<class Context, class Arg1, class Arg2> \ | ||
|  |             static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \ | ||
|  |             { \ | ||
|  |                 ctx.stream << #name << "("; \ | ||
|  |                 proto::eval(arg1, ctx); \ | ||
|  |                 ctx.stream << ", "; \ | ||
|  |                 proto::eval(arg2, ctx); \ | ||
|  |                 ctx.stream << ")"; \ | ||
|  |             } \ | ||
|  |         }; \ | ||
|  |     } \ | ||
|  |     template<class Arg1, class Arg2> \ | ||
|  |     inline typename proto::result_of::make_expr< \ | ||
|  |         proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \ | ||
|  |     >::type const \ | ||
|  |     name(const Arg1 &arg1, const Arg2 &arg2) \ | ||
|  |     { \ | ||
|  |         return proto::make_expr<proto::tag::function>( \ | ||
|  |             BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \ | ||
|  |         ); \ | ||
|  |     } | ||
|  | 
 | ||
|  | // wraps a binary function who's result type is the scalar type of the first argument | ||
|  | #define BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(name) \ | ||
|  |     namespace detail { \ | ||
|  |         struct BOOST_PP_CAT(name, _func) \ | ||
|  |         { \ | ||
|  |             template<class Expr, class Args> \ | ||
|  |             struct lambda_result \ | ||
|  |             { \ | ||
|  |                 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ | ||
|  |                 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type result_type; \ | ||
|  |                 typedef typename ::boost::compute::scalar_type<result_type>::type type; \ | ||
|  |             }; \ | ||
|  |             \ | ||
|  |             template<class Context, class Arg1, class Arg2> \ | ||
|  |             static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2) \ | ||
|  |             { \ | ||
|  |                 ctx.stream << #name << "("; \ | ||
|  |                 proto::eval(arg1, ctx); \ | ||
|  |                 ctx.stream << ", "; \ | ||
|  |                 proto::eval(arg2, ctx); \ | ||
|  |                 ctx.stream << ")"; \ | ||
|  |             } \ | ||
|  |         }; \ | ||
|  |     } \ | ||
|  |     template<class Arg1, class Arg2> \ | ||
|  |     inline typename proto::result_of::make_expr< \ | ||
|  |         proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2& \ | ||
|  |     >::type const \ | ||
|  |     name(const Arg1 &arg1, const Arg2 &arg2) \ | ||
|  |     { \ | ||
|  |         return proto::make_expr<proto::tag::function>( \ | ||
|  |             BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2) \ | ||
|  |         ); \ | ||
|  |     } | ||
|  | 
 | ||
|  | // wraps a ternary function | ||
|  | #define BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(name) \ | ||
|  |     namespace detail { \ | ||
|  |         struct BOOST_PP_CAT(name, _func) \ | ||
|  |         { \ | ||
|  |             template<class Expr, class Args> \ | ||
|  |             struct lambda_result \ | ||
|  |             { \ | ||
|  |                 typedef typename proto::result_of::child_c<Expr, 1>::type Arg1; \ | ||
|  |                 typedef typename ::boost::compute::lambda::result_of<Arg1, Args>::type type; \ | ||
|  |             }; \ | ||
|  |             \ | ||
|  |             template<class Context, class Arg1, class Arg2, class Arg3> \ | ||
|  |             static void apply(Context &ctx, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ | ||
|  |             { \ | ||
|  |                 ctx.stream << #name << "("; \ | ||
|  |                 proto::eval(arg1, ctx); \ | ||
|  |                 ctx.stream << ", "; \ | ||
|  |                 proto::eval(arg2, ctx); \ | ||
|  |                 ctx.stream << ", "; \ | ||
|  |                 proto::eval(arg3, ctx); \ | ||
|  |                 ctx.stream << ")"; \ | ||
|  |             } \ | ||
|  |         }; \ | ||
|  |     } \ | ||
|  |     template<class Arg1, class Arg2, class Arg3> \ | ||
|  |     inline typename proto::result_of::make_expr< \ | ||
|  |         proto::tag::function, BOOST_PP_CAT(detail::name, _func), const Arg1&, const Arg2&, const Arg3& \ | ||
|  |     >::type const \ | ||
|  |     name(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) \ | ||
|  |     { \ | ||
|  |         return proto::make_expr<proto::tag::function>( \ | ||
|  |             BOOST_PP_CAT(detail::name, _func)(), ::boost::ref(arg1), ::boost::ref(arg2), ::boost::ref(arg3) \ | ||
|  |         ); \ | ||
|  |     } | ||
|  | 
 | ||
|  | 
 | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(all) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(any) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isinf) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isnan) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BOOLEAN_UNARY_FUNCTION(isfinite) | ||
|  | 
 | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(abs) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(cos) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(acos) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sin) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(asin) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(tan) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(atan) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(sqrt) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(rsqrt) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp2) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(exp10) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log2) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(log10) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(round) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_UNARY_FUNCTION_T(length) | ||
|  | 
 | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(cross) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pow) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(pown) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION(powr) | ||
|  | 
 | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(dot) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_BINARY_FUNCTION_ST(distance) | ||
|  | 
 | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(clamp) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(fma) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(mad) | ||
|  | BOOST_COMPUTE_LAMBDA_WRAP_TERNARY_FUNCTION(smoothstep) | ||
|  | 
 | ||
|  | } // end lambda namespace | ||
|  | } // end compute namespace | ||
|  | } // end boost namespace | ||
|  | 
 | ||
|  | #endif // BOOST_COMPUTE_LAMBDA_FUNCTIONAL_HPP |