summaryrefslogtreecommitdiff
path: root/boost/compute/lambda/get.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/compute/lambda/get.hpp')
-rw-r--r--boost/compute/lambda/get.hpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/boost/compute/lambda/get.hpp b/boost/compute/lambda/get.hpp
new file mode 100644
index 0000000000..547c208e95
--- /dev/null
+++ b/boost/compute/lambda/get.hpp
@@ -0,0 +1,148 @@
+//---------------------------------------------------------------------------//
+// 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