1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2005-2006 Dan Marsden
4
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>
10
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>
17 #include <boost/fusion/sequence/intrinsic/at.hpp>
18
19 #include <boost/type_traits/remove_reference.hpp>
20
21 #include <algorithm>
22 #include <numeric>
23 #include <functional>
24 #include <iostream>
25 #include <cmath>
26 #include <limits>
27
28 #ifdef _MSC_VER
29 // inline aggressively
30 # pragma inline_recursion(on) // turn on inline recursion
31 # pragma inline_depth(255) // max inline depth
32 #endif
33
34 int const REPEAT_COUNT = 10;
35
36 double const duration = 0.5;
37
38 namespace
39 {
40 struct poly_add
41 {
42 template<typename Sig>
43 struct result;
44
45 template<typename Lhs, typename Rhs>
46 struct result<poly_add(Lhs, Rhs)>
47 : boost::remove_reference<Lhs>
48 {};
49
50 template<typename Lhs, typename Rhs>
operator ()__anonf9589a9f0111::poly_add51 Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
52 {
53 return lhs + rhs;
54 }
55 };
56
57 struct poly_mult
58 {
59 template<typename Sig>
60 struct result;
61
62 template<typename Lhs, typename Rhs>
63 struct result<poly_mult(Lhs, Rhs)>
64 : boost::remove_reference<Lhs>
65 {};
66
67 template<typename Lhs, typename Rhs>
operator ()__anonf9589a9f0111::poly_mult68 Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
69 {
70 return lhs * rhs;
71 }
72 };
73
74 template<int N>
time_for_std_inner_product(int & j)75 double time_for_std_inner_product(int& j)
76 {
77 boost::timer tim;
78 int i = 0;
79 long long iter = 65536;
80 long long counter, repeats;
81 double result = (std::numeric_limits<double>::max)();
82 double runtime = 0;
83 double run;
84 boost::array<int, N> arr1;
85 boost::array<int, N> arr2;
86 std::generate(arr1.begin(), arr1.end(), rand);
87 std::generate(arr2.begin(), arr2.end(), rand);
88 do
89 {
90 tim.restart();
91 for(counter = 0; counter < iter; ++counter)
92 {
93 i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
94 static_cast<void>(i);
95 }
96 runtime = tim.elapsed();
97 iter *= 2;
98 } while(runtime < duration);
99 iter /= 2;
100
101 // repeat test and report least value for consistency:
102 for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
103 {
104 tim.restart();
105 for(counter = 0; counter < iter; ++counter)
106 {
107 i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
108 j += i;
109 }
110 run = tim.elapsed();
111 result = (std::min)(run, result);
112 }
113 std::cout << i << std::endl;
114 return result / iter;
115 }
116
117 template<int N>
time_for_fusion_inner_product(int & j)118 double time_for_fusion_inner_product(int& j)
119 {
120 boost::timer tim;
121 int i = 0;
122 long long iter = 65536;
123 long long counter, repeats;
124 double result = (std::numeric_limits<double>::max)();
125 double runtime = 0;
126 double run;
127 boost::array<int, N> arr1;
128 boost::array<int, N> arr2;
129 std::generate(arr1.begin(), arr1.end(), rand);
130 std::generate(arr2.begin(), arr2.end(), rand);
131 do
132 {
133 tim.restart();
134 for(counter = 0; counter < iter; ++counter)
135 {
136 i = boost::fusion::accumulate(
137 boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
138 static_cast<void>(i);
139 }
140 runtime = tim.elapsed();
141 iter *= 2;
142 } while(runtime < duration);
143 iter /= 2;
144
145 // repeat test and report least value for consistency:
146 for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
147 {
148 tim.restart();
149 for(counter = 0; counter < iter; ++counter)
150 {
151 i = boost::fusion::accumulate(
152 boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
153 j += i;
154 }
155 run = tim.elapsed();
156 result = (std::min)(run, result);
157 }
158 std::cout << i << std::endl;
159 return result / iter;
160 }
161 }
162
main()163 int main()
164 {
165 int total = 0;
166 int res;
167
168 std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl;
169 total += res;
170 std::cout << "short inner_product fusion test " << time_for_fusion_inner_product<8>(res) << std::endl;
171 total += res;
172
173 std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl;
174 total += res;
175 std::cout << "medium inner_product fusion test " << time_for_fusion_inner_product<64>(res) << std::endl;
176 total += res;
177
178 std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl;
179 total += res;
180 std::cout << "long inner_product fusion test " << time_for_fusion_inner_product<128>(res) << std::endl;
181 total += res;
182
183 return total;
184 }
185