149 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			149 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //---------------------------------------------------------------------------// | ||
|  | // Copyright (c) 2013-2014 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_GET_HPP | ||
|  | #define BOOST_COMPUTE_LAMBDA_GET_HPP | ||
|  | 
 | ||
|  | #include <boost/preprocessor/repetition.hpp> | ||
|  | 
 | ||
|  | #include <boost/compute/config.hpp> | ||
|  | #include <boost/compute/functional/get.hpp> | ||
|  | #include <boost/compute/lambda/placeholder.hpp> | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace compute { | ||
|  | namespace lambda { | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | // function wrapper for get<N>() in lambda expressions | ||
|  | template<size_t N> | ||
|  | struct get_func | ||
|  | { | ||
|  |     template<class Expr, class Args> | ||
|  |     struct lambda_result | ||
|  |     { | ||
|  |         typedef typename proto::result_of::child_c<Expr, 1>::type Arg; | ||
|  |         typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type T; | ||
|  |         typedef typename ::boost::compute::detail::get_result_type<N, T>::type type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template<class Context, class Arg> | ||
|  |     struct make_get_result_type | ||
|  |     { | ||
|  |         typedef typename boost::remove_cv< | ||
|  |             typename boost::compute::lambda::result_of< | ||
|  |                 Arg, typename Context::args_tuple | ||
|  |             >::type | ||
|  |         >::type type; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // returns the suffix string for get<N>() in lambda expressions | ||
|  |     // (e.g. ".x" for get<0>() with float4) | ||
|  |     template<class T> | ||
|  |     struct make_get_suffix | ||
|  |     { | ||
|  |         static std::string value() | ||
|  |         { | ||
|  |             BOOST_STATIC_ASSERT(N < 16); | ||
|  | 
 | ||
|  |             std::stringstream stream; | ||
|  | 
 | ||
|  |             if(N < 10){ | ||
|  |                 stream << ".s" << uint_(N); | ||
|  |             } | ||
|  |             else if(N < 16){ | ||
|  |                 stream << ".s" << char('a' + (N - 10)); | ||
|  |             } | ||
|  | 
 | ||
|  |             return stream.str(); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     // get<N>() specialization for std::pair<T1, T2> | ||
|  |     template<class T1, class T2> | ||
|  |     struct make_get_suffix<std::pair<T1, T2> > | ||
|  |     { | ||
|  |         static std::string value() | ||
|  |         { | ||
|  |             BOOST_STATIC_ASSERT(N < 2); | ||
|  | 
 | ||
|  |             if(N == 0){ | ||
|  |                 return ".first"; | ||
|  |             } | ||
|  |             else { | ||
|  |                 return ".second"; | ||
|  |             } | ||
|  |         }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // get<N>() specialization for boost::tuple<T...> | ||
|  |     #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \ | ||
|  |     template<BOOST_PP_ENUM_PARAMS(n, class T)> \ | ||
|  |     struct make_get_suffix<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \ | ||
|  |     { \ | ||
|  |         static std::string value() \ | ||
|  |         { \ | ||
|  |             BOOST_STATIC_ASSERT(N < n); \ | ||
|  |             return ".v" + boost::lexical_cast<std::string>(N); \ | ||
|  |         } \ | ||
|  |     }; | ||
|  | 
 | ||
|  |     BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX, ~) | ||
|  | 
 | ||
|  |     #undef BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX | ||
|  | 
 | ||
|  |     template<class Context, class Arg> | ||
|  |     static void dispatch_apply_terminal(Context &ctx, const Arg &arg) | ||
|  |     { | ||
|  |         typedef typename make_get_result_type<Context, Arg>::type T; | ||
|  | 
 | ||
|  |         proto::eval(arg, ctx); | ||
|  |         ctx.stream << make_get_suffix<T>::value(); | ||
|  |     } | ||
|  | 
 | ||
|  |     template<class Context, int I> | ||
|  |     static void dispatch_apply_terminal(Context &ctx, placeholder<I>) | ||
|  |     { | ||
|  |         ctx.stream << ::boost::compute::get<N>()(::boost::get<I>(ctx.args)); | ||
|  |     } | ||
|  | 
 | ||
|  |     template<class Context, class Arg> | ||
|  |     static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal) | ||
|  |     { | ||
|  |         dispatch_apply_terminal(ctx, proto::value(arg)); | ||
|  |     } | ||
|  | 
 | ||
|  |     template<class Context, class Arg> | ||
|  |     static void apply(Context &ctx, const Arg &arg) | ||
|  |     { | ||
|  |         dispatch_apply(ctx, arg, typename proto::tag_of<Arg>::type()); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | } // end detail namespace | ||
|  | 
 | ||
|  | // get<N>() | ||
|  | template<size_t N, class Arg> | ||
|  | inline typename proto::result_of::make_expr< | ||
|  |     proto::tag::function, detail::get_func<N>, const Arg& | ||
|  | >::type const | ||
|  | get(const Arg &arg) | ||
|  | { | ||
|  |     return proto::make_expr<proto::tag::function>( | ||
|  |         detail::get_func<N>(), ::boost::ref(arg) | ||
|  |     ); | ||
|  | } | ||
|  | 
 | ||
|  | } // end lambda namespace | ||
|  | } // end compute namespace | ||
|  | } // end boost namespace | ||
|  | 
 | ||
|  | #endif // BOOST_COMPUTE_LAMBDA_GET_HPP |