1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2005-2006 Dan Marsden
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #include <boost/array.hpp>
9 #include <boost/timer.hpp>
11 #include <boost/fusion/algorithm/iteration/accumulate.hpp>
12 #include <boost/fusion/algorithm/transformation/transform.hpp>
13 #include <boost/fusion/container/vector.hpp>
14 #include <boost/fusion/algorithm/transformation/zip.hpp>
15 #include <boost/fusion/sequence/intrinsic/at.hpp>
16 #include <boost/fusion/adapted/array.hpp>
18 #include <boost/type_traits/remove_reference.hpp>
28 // inline aggressively
29 # pragma inline_recursion(on) // turn on inline recursion
30 # pragma inline_depth(255) // max inline depth
33 int const REPEAT_COUNT
= 10;
35 double const duration
= 0.5;
40 double time_for_std_accumulate(int& j
)
44 long long iter
= 65536;
45 long long counter
, repeats
;
46 double result
= (std::numeric_limits
<double>::max
)();
49 boost::array
<int, N
> arr
;
50 std::generate(arr
.begin(), arr
.end(), rand
);
54 for(counter
= 0; counter
< iter
; ++counter
)
56 i
= std::accumulate(arr
.begin(), arr
.end(), 0);
59 runtime
= tim
.elapsed();
61 } while(runtime
< duration
);
64 // repeat test and report least value for consistency:
65 for(repeats
= 0; repeats
< REPEAT_COUNT
; ++repeats
)
68 for(counter
= 0; counter
< iter
; ++counter
)
70 i
= std::accumulate(arr
.begin(), arr
.end(), 0);
74 result
= (std::min
)(run
, result
);
76 std::cout
<< i
<< std::endl
;
82 template<typename Sig
>
85 template<typename Lhs
, typename Rhs
>
86 struct result
<poly_add(Lhs
,Rhs
)>
87 : boost::remove_reference
<Lhs
>
90 template<typename Lhs
, typename Rhs
>
91 Lhs
operator()(const Lhs
& lhs
, const Rhs
& rhs
) const
99 template<typename Sig
>
102 template<typename Lhs
, typename Rhs
>
103 struct result
<poly_mult(Lhs
, Rhs
)>
104 : boost::remove_reference
<Lhs
>
107 template<typename Lhs
, typename Rhs
>
108 Lhs
operator()(const Lhs
& lhs
, const Rhs
& rhs
) const
115 double time_for_fusion_accumulate(int& j
)
119 long long iter
= 65536;
120 long long counter
, repeats
;
121 double result
= (std::numeric_limits
<double>::max
)();
124 boost::array
<int, N
> arr
;
125 std::generate(arr
.begin(), arr
.end(), rand
);
129 for(counter
= 0; counter
< iter
; ++counter
)
131 i
= boost::fusion::accumulate(arr
, 0, poly_add());
132 static_cast<void>(i
);
134 runtime
= tim
.elapsed();
136 } while(runtime
< duration
);
139 std::cout
<< iter
<< " iterations" << std::endl
;
141 // repeat test and report least value for consistency:
142 for(repeats
= 0; repeats
< REPEAT_COUNT
; ++repeats
)
145 for(counter
= 0; counter
< iter
; ++counter
)
147 i
= boost::fusion::accumulate(arr
, 0, poly_add());
151 result
= (std::min
)(run
, result
);
155 std::cout
<< i
<< std::endl
;
156 return result
/ iter
;
161 double time_for_std_inner_product(int& j
)
165 long long iter
= 65536;
166 long long counter
, repeats
;
167 double result
= (std::numeric_limits
<double>::max
)();
170 boost::array
<int, N
> arr1
;
171 boost::array
<int, N
> arr2
;
172 std::generate(arr1
.begin(), arr1
.end(), rand
);
173 std::generate(arr2
.begin(), arr2
.end(), rand
);
177 for(counter
= 0; counter
< iter
; ++counter
)
179 i
= std::inner_product(arr1
.begin(), arr1
.end(), arr2
.begin(), 0);
180 static_cast<void>(i
);
182 runtime
= tim
.elapsed();
184 } while(runtime
< duration
);
187 // repeat test and report least value for consistency:
188 for(repeats
= 0; repeats
< REPEAT_COUNT
; ++repeats
)
191 for(counter
= 0; counter
< iter
; ++counter
)
193 i
= std::inner_product(arr1
.begin(), arr1
.end(), arr2
.begin(), 0);
197 result
= (std::min
)(run
, result
);
199 std::cout
<< i
<< std::endl
;
200 return result
/ iter
;
204 double time_for_fusion_inner_product(int& j
)
208 long long iter
= 65536;
209 long long counter
, repeats
;
210 double result
= (std::numeric_limits
<double>::max
)();
213 boost::array
<int, N
> arr1
;
214 boost::array
<int, N
> arr2
;
215 std::generate(arr1
.begin(), arr1
.end(), rand
);
216 std::generate(arr2
.begin(), arr2
.end(), rand
);
220 for(counter
= 0; counter
< iter
; ++counter
)
222 i
= boost::fusion::accumulate(
223 boost::fusion::transform(arr1
, arr2
, poly_mult()), 0, poly_add());
224 static_cast<void>(i
);
226 runtime
= tim
.elapsed();
228 } while(runtime
< duration
);
231 // repeat test and report least value for consistency:
232 for(repeats
= 0; repeats
< REPEAT_COUNT
; ++repeats
)
235 for(counter
= 0; counter
< iter
; ++counter
)
237 i
= boost::fusion::accumulate(
238 boost::fusion::transform(arr1
, arr2
, poly_mult()), 0, poly_add());
242 result
= (std::min
)(run
, result
);
244 std::cout
<< i
<< std::endl
;
245 return result
/ iter
;
250 template<typename Lhs
, typename Rhs
>
256 template<typename Lhs
, typename Rhs
>
257 typename result
<Lhs
,Rhs
>::type
258 operator()(const Lhs
& lhs
, const Rhs
& rhs
) const
260 return lhs
+ boost::fusion::at_c
<0>(rhs
) * boost::fusion::at_c
<1>(rhs
);
265 double time_for_fusion_inner_product2(int& j
)
269 long long iter
= 65536;
270 long long counter
, repeats
;
271 double result
= (std::numeric_limits
<double>::max
)();
274 boost::array
<int, N
> arr1
;
275 boost::array
<int, N
> arr2
;
276 std::generate(arr1
.begin(), arr1
.end(), rand
);
277 std::generate(arr2
.begin(), arr2
.end(), rand
);
281 for(counter
= 0; counter
< iter
; ++counter
)
283 i
= boost::fusion::accumulate(
284 boost::fusion::zip(arr1
, arr2
), 0, poly_combine());
285 static_cast<void>(i
);
287 runtime
= tim
.elapsed();
289 } while(runtime
< duration
);
292 std::cout
<< iter
<< " iterations" << std::endl
;
294 // repeat test and report least value for consistency:
295 for(repeats
= 0; repeats
< REPEAT_COUNT
; ++repeats
)
298 for(counter
= 0; counter
< iter
; ++counter
)
300 i
= boost::fusion::accumulate(
301 boost::fusion::zip(arr1
, arr2
), 0, poly_combine());
305 result
= (std::min
)(run
, result
);
307 std::cout
<< i
<< std::endl
;
308 return result
/ iter
;
317 std::cout
<< "short accumulate std test " << time_for_std_accumulate
<8>(res
) << std::endl
;
319 std::cout
<< "short accumulate fusion test " << time_for_fusion_accumulate
<8>(res
) << std::endl
;
322 std::cout
<< "medium accumulate std test " << time_for_std_accumulate
<64>(res
) << std::endl
;
324 std::cout
<< "medium accumulate fusion test " << time_for_fusion_accumulate
<64>(res
) << std::endl
;
327 std::cout
<< "long accumulate std test " << time_for_std_accumulate
<128>(res
) << std::endl
;
329 std::cout
<< "long accumulate fusion test " << time_for_fusion_accumulate
<128>(res
) << std::endl
;
333 std::cout
<< "short inner_product std test " << time_for_std_inner_product
<8>(res
) << std::endl
;
335 std::cout
<< "short inner_product fusion test " << time_for_fusion_inner_product
<8>(res
) << std::endl
;
337 std::cout
<< "short inner_product fusion 2 test " << time_for_fusion_inner_product2
<8>(res
) << std::endl
;
340 std::cout
<< "medium inner_product std test " << time_for_std_inner_product
<64>(res
) << std::endl
;
342 std::cout
<< "medium inner_product fusion test " << time_for_fusion_inner_product
<64>(res
) << std::endl
;
344 std::cout
<< "medium inner_product fusion 2 test " << time_for_fusion_inner_product2
<64>(res
) << std::endl
;
348 std::cout
<< "long inner_product std test " << time_for_std_inner_product
<128>(res
) << std::endl
;
350 std::cout
<< "long inner_product fusion test " << time_for_fusion_inner_product
<128>(res
) << std::endl
;
352 std::cout
<< "long inner_product fusion 2 test " << time_for_fusion_inner_product2
<128>(res
) << std::endl
;