Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / phoenix / example / parallel_for.cpp
1 /*=============================================================================
2     Copyright (c) 2001-2007 Joel de Guzman
3
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7
8 #include <boost/phoenix.hpp>
9
10 struct omp_for_eval
11 {
12     typedef void result_type;
13
14     template <typename Init, typename Cond, typename Step, typename Do, typename Context>
15     result_type
16     operator()(
17         Init const& init
18       , Cond const& cond
19       , Step const& step
20       , Do const& do_
21       , Context & ctx
22     ) const
23     {
24 #pragma omp parallel
25         for(
26             boost::phoenix::eval(init, ctx);
27             boost::phoenix::eval(cond, ctx);
28             boost::phoenix::eval(step, ctx)
29         )
30         {
31             boost::phoenix::eval(do_, ctx);
32         }
33     }
34 };
35
36
37 ////////////////////////////////////////////////////////////////////////////////
38 // Define new custom expression
39 BOOST_PHOENIX_DEFINE_EXPRESSION(
40     (omp_for)
41   , (boost::phoenix::meta_grammar) // Cond
42     (boost::phoenix::meta_grammar) // Init
43     (boost::phoenix::meta_grammar) // Step
44     (boost::phoenix::meta_grammar) // Do
45 )
46
47 namespace boost { namespace phoenix
48 {
49     template <>
50     struct default_actions::when< ::rule::omp_for>
51         : boost::phoenix::call< ::omp_for_eval>
52     {};
53 }}
54
55 template <typename Init, typename Cond, typename Step>
56 struct omp_for_gen
57 {
58     omp_for_gen(Init const& init, Cond const& cond, Step const& step)
59         : init(init), cond(cond), step(step) {}
60     
61     template <typename Do>
62     typename result_of::make_omp_for<Init, Cond, Step, Do>::type const
63     operator[](Do const& do_) const
64     {
65         return make_omp_for(init, cond, step, do_);
66     }
67     
68     Init init;
69     Cond cond;
70     Step step;
71 };
72
73 template <typename Init, typename Cond, typename Step>
74 inline
75 omp_for_gen<Init, Cond, Step> const
76 omp_for(Init const& init, Cond const& cond, Step const& step)
77 {
78     return omp_for_gen<Init, Cond, Step>(init, cond, step);
79 }
80 ////////////////////////////////////////////////////////////////////////////////
81
82
83 ////////////////////////////////////////////////////////////////////////////////
84 // Define new evaluation scheme
85
86 struct parallel_actions
87 {
88     template <typename Rule>
89     struct when
90         : boost::phoenix::default_actions::when<Rule>
91     {};
92 };
93
94 template <>
95 struct parallel_actions::when<boost::phoenix::rule::for_>
96     : boost::phoenix::call<omp_for_eval>
97 {};
98
99 // Doing the same as actor<Expr>::operator
100 template <typename Expr, typename A0, typename A1, typename A2>
101 typename boost::phoenix::result_of::eval<
102     Expr const &
103   , typename boost::phoenix::result_of::make_context<
104         typename boost::phoenix::result_of::make_env<
105             Expr const *
106           , A0 &
107           , A1 &
108           , A2 &
109         >::type
110       , parallel_actions
111     >::type
112 >::type
113 parallel_eval(Expr & expr, A0 & a0, A1 & a1, A2 & a2)
114 {
115     Expr const * this_ = boost::addressof(expr);
116     return
117         boost::phoenix::eval(
118             expr
119           , boost::phoenix::make_context(
120                 boost::phoenix::make_env(this_, a0, a1, a2)
121               , parallel_actions()
122             )
123         );
124 }
125
126 // changing evaluation mechanism on the fly
127 BOOST_PHOENIX_DEFINE_EXPRESSION(
128     (parallel)
129   , (boost::phoenix::meta_grammar)
130 )
131
132 namespace boost { namespace phoenix
133 {
134     template <>
135     struct default_actions::when< ::rule::parallel>
136         : proto::call<
137             evaluator(
138                 proto::_child0
139               , functional::make_context(
140                     _env
141                   , parallel_actions()
142                 )
143               , unused()//mpl::void_()
144             )
145         >
146     {};
147 }}
148
149 template <typename Expr>
150 typename result_of::make_parallel<Expr>::type
151 parallel(Expr const & expr)
152 {
153     return make_parallel(expr);
154 }
155 ////////////////////////////////////////////////////////////////////////////////
156
157
158 #include <vector>
159 #include <iostream>
160
161 int main()
162 {
163     using boost::phoenix::arg_names::_1;
164     using boost::phoenix::arg_names::_2;
165     using boost::phoenix::arg_names::_3;
166     using boost::phoenix::local_names::_a;
167     using boost::phoenix::local_names::_b;
168     using boost::phoenix::local_names::_c;
169     using boost::phoenix::let;
170     using boost::phoenix::bind;
171     using boost::phoenix::lambda;
172     using boost::phoenix::nothing;
173
174     const int NUM = 1;
175
176     {
177         std::vector<int> a(NUM, 1);
178         std::vector<int> b(NUM, 2);
179         std::vector<int> c(NUM, 0);
180
181         (
182             let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
183             [
184                 for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
185                 [
186                     *_c = *_a + *_b
187                 ]
188             ]
189           , std::cout << accumulate(_3, 0) << "\n"
190         )(a, b, c);
191     }
192
193     {
194         std::vector<int> a(NUM, 1);
195         std::vector<int> b(NUM, 2);
196         std::vector<int> c(NUM, 0);
197
198         (
199             let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
200             [
201                 omp_for(nothing, _a != end(_1), (++_a, ++_b, ++_c))
202                 [
203                     *_c = *_a + *_b
204                 ]
205               , std::cout << accumulate(_3, 0) << "\n"
206             ]
207         )(a, b, c);
208     }
209     
210     {
211         std::vector<int> a(NUM, 1);
212         std::vector<int> b(NUM, 2);
213         std::vector<int> c(NUM, 0);
214
215         parallel_eval(
216             let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
217             [
218                 for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
219                 [
220                     *_c = *_a + *_b
221                 ]
222               , std::cout << accumulate(_3, 0) << "\n"
223             ]
224           , a, b, c);
225     }
226     
227     {
228         std::vector<int> a(NUM, 1);
229         std::vector<int> b(NUM, 2);
230         std::vector<int> c(NUM, 0);
231
232         (
233             let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
234             [
235                 parallel(
236                     for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
237                     [
238                         *_c = *_a + *_b
239                     ]
240                 )
241             ]
242           , std::cout << accumulate(_3, 0) << "\n"
243         )(a, b, c);
244     }
245 }