1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2006-2007 Tobias Schwinger
4
5 Use modification and distribution are subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt).
8 ==============================================================================*/
9
10 #include <boost/fusion/container/list.hpp>
11 #include <boost/fusion/container/vector.hpp>
12 #include <boost/fusion/algorithm/iteration/fold.hpp>
13 #include <boost/fusion/functional/adapter/unfused.hpp>
14 #include <boost/fusion/functional/adapter/fused_function_object.hpp>
15
16 #include <boost/functional/forward_adapter.hpp>
17 #include <boost/functional/lightweight_forward_adapter.hpp>
18
19 #include <boost/utility/result_of.hpp>
20 #include <boost/config.hpp>
21 #include <boost/timer.hpp>
22 #include <algorithm>
23 #include <iostream>
24
25 #ifdef _MSC_VER
26 // inline aggressively
27 # pragma inline_recursion(on) // turn on inline recursion
28 # pragma inline_depth(255) // max inline depth
29 #endif
30
31 int const REPEAT_COUNT = 3;
32
33 double const duration = 0.125;
34
35
36 namespace
37 {
38 struct fused_sum
39 {
40 template <typename Seq>
operator ()__anoneab77e950111::fused_sum41 int operator()(Seq const & seq) const
42 {
43 int state = 0;
44 return boost::fusion::fold(seq, state, sum_op());
45 }
46
47 typedef int result_type;
48
49 private:
50
51 struct sum_op
52 {
53 template <typename T>
operator ()__anoneab77e950111::fused_sum::sum_op54 int operator()(T const & elem, int value) const
55 {
56 return value + sizeof(T) * elem;
57 }
58
59 template <typename T>
operator ()__anoneab77e950111::fused_sum::sum_op60 int operator()(T & elem, int value) const
61 {
62 elem += sizeof(T);
63 return value;
64 }
65
66 typedef int result_type;
67 };
68 };
69
70 struct unfused_sum
71 {
operator ()__anoneab77e950111::unfused_sum72 inline int operator()() const
73 {
74 return 0;
75 }
76 template<typename T0>
operator ()__anoneab77e950111::unfused_sum77 inline int operator()(T0 const & a0) const
78 {
79 return a0;
80 }
81 template<typename T0, typename T1>
operator ()__anoneab77e950111::unfused_sum82 inline int operator()(T0 const & a0, T1 const & a1) const
83 {
84 return a0 + a1;
85 }
86 template<typename T0, typename T1, typename T2>
operator ()__anoneab77e950111::unfused_sum87 inline int operator()(T0 const & a0, T1 const & a1, T2 a2) const
88 {
89 return a0 + a1 + a2;
90 }
91 template<typename T0, typename T1, typename T2, typename T3>
operator ()__anoneab77e950111::unfused_sum92 inline int operator()(T0 const & a0, T1 const & a1, T2 const & a2, T3 const & a3) const
93 {
94 return a0 + a1 + a2 + a3;
95 }
96
97 typedef int result_type;
98 };
99
100 template<typename F>
call_unfused(F const & func,int & j)101 double call_unfused(F const & func, int & j)
102 {
103 boost::timer tim;
104 int i = 0;
105 long long iter = 65536;
106 long long counter, repeats;
107 double result = (std::numeric_limits<double>::max)();
108 double runtime = 0;
109 double run;
110 do
111 {
112 tim.restart();
113 for(counter = 0; counter < iter; ++counter)
114 {
115 i += func();
116 i += func(0);
117 i += func(0,1);
118 i += func(0,1,2);
119 i += func(0,1,2,3);
120 }
121 runtime = tim.elapsed();
122 iter *= 2;
123 } while(runtime < duration);
124 iter /= 2;
125
126 for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
127 {
128 tim.restart();
129 for(counter = 0; counter < iter; ++counter)
130 {
131 i = func(); j += i;
132 i = func(0); j += i;
133 i = func(0,1); j += i;
134 i = func(0,1,2); j += i;
135 i = func(0,1,2,3); j += i;
136 }
137 run = tim.elapsed();
138 result = (std::min)(run, result);
139 }
140 return result / iter;
141 }
142
143 template<typename F>
call_fused_ra(F const & func,int & j)144 double call_fused_ra(F const & func, int & j)
145 {
146 boost::timer tim;
147 int i = 0;
148 long long iter = 65536;
149 long long counter, repeats;
150 double result = (std::numeric_limits<double>::max)();
151 double runtime = 0;
152 double run;
153 do
154 {
155 boost::fusion::vector<> v0;
156 boost::fusion::vector<int> v1(0);
157 boost::fusion::vector<int,int> v2(0,1);
158 boost::fusion::vector<int,int,int> v3(0,1,2);
159 boost::fusion::vector<int,int,int,int> v4(0,1,2,3);
160 tim.restart();
161 for(counter = 0; counter < iter; ++counter)
162 {
163 i += func(v0);
164 i += func(v1);
165 i += func(v2);
166 i += func(v3);
167 i += func(v4);
168 }
169 runtime = tim.elapsed();
170 iter *= 2;
171 } while(runtime < duration);
172 iter /= 2;
173
174 for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
175 {
176 boost::fusion::vector<> v0;
177 boost::fusion::vector<int> v1(0);
178 boost::fusion::vector<int,int> v2(0,1);
179 boost::fusion::vector<int,int,int> v3(0,1,2);
180 boost::fusion::vector<int,int,int,int> v4(0,1,2,3);
181 tim.restart();
182 for(counter = 0; counter < iter; ++counter)
183 {
184 i = func(v0); j += i;
185 i = func(v1); j += i;
186 i = func(v2); j += i;
187 i = func(v3); j += i;
188 i = func(v4); j += i;
189 }
190 run = tim.elapsed();
191 result = (std::min)(run, result);
192 }
193 return result / iter;
194 }
195
196 template<typename F>
call_fused(F const & func,int & j)197 double call_fused(F const & func, int & j)
198 {
199 boost::timer tim;
200 int i = 0;
201 long long iter = 65536;
202 long long counter, repeats;
203 double result = (std::numeric_limits<double>::max)();
204 double runtime = 0;
205 double run;
206 do
207 {
208 boost::fusion::list<> l0;
209 boost::fusion::list<int> l1(0);
210 boost::fusion::list<int,int> l2(0,1);
211 boost::fusion::list<int,int,int> l3(0,1,2);
212 boost::fusion::list<int,int,int,int> l4(0,1,2,3);
213 tim.restart();
214 for(counter = 0; counter < iter; ++counter)
215 {
216 i += func(l0);
217 i += func(l1);
218 i += func(l2);
219 i += func(l3);
220 i += func(l4);
221 }
222 runtime = tim.elapsed();
223 iter *= 2;
224 } while(runtime < duration);
225 iter /= 2;
226
227 for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
228 {
229 boost::fusion::list<> l0;
230 boost::fusion::list<int> l1(0);
231 boost::fusion::list<int,int> l2(0,1);
232 boost::fusion::list<int,int,int> l3(0,1,2);
233 boost::fusion::list<int,int,int,int> l4(0,1,2,3);
234 tim.restart();
235 for(counter = 0; counter < iter; ++counter)
236 {
237 i = func(l0); j += i;
238 i = func(l1); j += i;
239 i = func(l2); j += i;
240 i = func(l3); j += i;
241 i = func(l4); j += i;
242 }
243 run = tim.elapsed();
244 result = (std::min)(run, result);
245 }
246 return result / iter;
247 }
248 }
249
main()250 int main()
251 {
252 int total = 0;
253 int res;
254 typedef fused_sum F;
255 typedef unfused_sum U;
256
257 std::cout << "Compiler: " << BOOST_COMPILER << std::endl;
258 std::cout << std::endl << "Unfused adapters:" << std::endl;
259 {
260 F f;
261 std::cout << "F /* a fused function object */ " << call_fused_ra(f,res) << std::endl;
262 total += res;
263 }
264 {
265 F f;
266 std::cout << "without random access " << call_fused(f,res) << std::endl;
267 total += res;
268 }
269 {
270 boost::lightweight_forward_adapter< boost::fusion::unfused<F> > f;
271 std::cout << "lightweight_forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl;
272 total += res;
273 }
274 {
275 boost::forward_adapter< boost::fusion::unfused<F> > f;
276 std::cout << "forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl;
277 total += res;
278 }
279 std::cout << std::endl << "Fused adapters:" << std::endl;
280 {
281 unfused_sum f;
282 std::cout << "U /* an unfused function object */ " << call_unfused(f,res) << std::endl;
283 total += res;
284 }
285 {
286 boost::fusion::fused_function_object<U> f;
287 std::cout << "fused_function_object<U> " << call_fused_ra(f,res) << std::endl;
288 total += res;
289 }
290 {
291 boost::fusion::fused_function_object<U> f;
292 std::cout << "without random access " << call_fused(f,res) << std::endl;
293 total += res;
294 }
295 {
296 boost::lightweight_forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f;
297 std::cout << "lightweight_forward_adapter< unfused<fused_function_object<U> > >" << call_unfused(f,res) << std::endl;
298 total += res;
299 }
300 {
301 boost::forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f;
302 std::cout << "forward_adapter< unfused<fused_function_object<U> > > " << call_unfused(f,res) << std::endl;
303 total += res;
304 }
305
306 return total;
307 }
308