• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 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 #ifndef BOOST_COMPUTE_LAMBDA_GET_HPP
12 #define BOOST_COMPUTE_LAMBDA_GET_HPP
13 
14 #include <boost/preprocessor/repetition.hpp>
15 
16 #include <boost/compute/config.hpp>
17 #include <boost/compute/functional/get.hpp>
18 #include <boost/compute/lambda/placeholder.hpp>
19 
20 namespace boost {
21 namespace compute {
22 namespace lambda {
23 namespace detail {
24 
25 // function wrapper for get<N>() in lambda expressions
26 template<size_t N>
27 struct get_func
28 {
29     template<class Expr, class Args>
30     struct lambda_result
31     {
32         typedef typename proto::result_of::child_c<Expr, 1>::type Arg;
33         typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type T;
34         typedef typename ::boost::compute::detail::get_result_type<N, T>::type type;
35     };
36 
37     template<class Context, class Arg>
38     struct make_get_result_type
39     {
40         typedef typename boost::remove_cv<
41             typename boost::compute::lambda::result_of<
42                 Arg, typename Context::args_tuple
43             >::type
44         >::type type;
45     };
46 
47     // returns the suffix string for get<N>() in lambda expressions
48     // (e.g. ".x" for get<0>() with float4)
49     template<class T>
50     struct make_get_suffix
51     {
valueboost::compute::lambda::detail::get_func::make_get_suffix52         static std::string value()
53         {
54             BOOST_STATIC_ASSERT(N < 16);
55 
56             std::stringstream stream;
57 
58             if(N < 10){
59                 stream << ".s" << uint_(N);
60             }
61             else if(N < 16){
62                 stream << ".s" << char('a' + (N - 10));
63             }
64 
65             return stream.str();
66         }
67     };
68 
69     // get<N>() specialization for std::pair<T1, T2>
70     template<class T1, class T2>
71     struct make_get_suffix<std::pair<T1, T2> >
72     {
valueboost::compute::lambda::detail::get_func::make_get_suffix73         static std::string value()
74         {
75             BOOST_STATIC_ASSERT(N < 2);
76 
77             if(N == 0){
78                 return ".first";
79             }
80             else {
81                 return ".second";
82             }
83         };
84     };
85 
86     // get<N>() specialization for boost::tuple<T...>
87     #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \
88     template<BOOST_PP_ENUM_PARAMS(n, class T)> \
89     struct make_get_suffix<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
90     { \
91         static std::string value() \
92         { \
93             BOOST_STATIC_ASSERT(N < n); \
94             return ".v" + boost::lexical_cast<std::string>(N); \
95         } \
96     };
97 
98     BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX, ~)
99 
100     #undef BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX
101 
102     template<class Context, class Arg>
dispatch_apply_terminalboost::compute::lambda::detail::get_func103     static void dispatch_apply_terminal(Context &ctx, const Arg &arg)
104     {
105         typedef typename make_get_result_type<Context, Arg>::type T;
106 
107         proto::eval(arg, ctx);
108         ctx.stream << make_get_suffix<T>::value();
109     }
110 
111     template<class Context, int I>
dispatch_apply_terminalboost::compute::lambda::detail::get_func112     static void dispatch_apply_terminal(Context &ctx, placeholder<I>)
113     {
114         ctx.stream << ::boost::compute::get<N>()(::boost::get<I>(ctx.args));
115     }
116 
117     template<class Context, class Arg>
dispatch_applyboost::compute::lambda::detail::get_func118     static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal)
119     {
120         dispatch_apply_terminal(ctx, proto::value(arg));
121     }
122 
123     template<class Context, class Arg>
applyboost::compute::lambda::detail::get_func124     static void apply(Context &ctx, const Arg &arg)
125     {
126         dispatch_apply(ctx, arg, typename proto::tag_of<Arg>::type());
127     }
128 };
129 
130 } // end detail namespace
131 
132 // get<N>()
133 template<size_t N, class Arg>
134 inline typename proto::result_of::make_expr<
135     proto::tag::function, detail::get_func<N>, const Arg&
136 >::type const
get(const Arg & arg)137 get(const Arg &arg)
138 {
139     return proto::make_expr<proto::tag::function>(
140         detail::get_func<N>(), ::boost::ref(arg)
141     );
142 }
143 
144 } // end lambda namespace
145 } // end compute namespace
146 } // end boost namespace
147 
148 #endif // BOOST_COMPUTE_LAMBDA_GET_HPP
149