1 // loop_time_test.cpp ----------------------------------------------------------------//
2
3 // Copyright Beman Dawes 2013
4
5 // Distributed under the Boost Software License, Version 1.0.
6 // http://www.boost.org/LICENSE_1_0.txt
7
8 //--------------------------------------------------------------------------------------//
9
10 //#define BOOST_ENDIAN_NO_INTRINSICS
11
12 #include <boost/endian/detail/disable_warnings.hpp>
13
14 #include <boost/endian/conversion.hpp>
15 #include <boost/endian/arithmetic.hpp>
16 #include <boost/cstdint.hpp>
17 #include <boost/timer/timer.hpp>
18 #include <iostream>
19 #include <cstdlib>
20 #include <string>
21 #include <boost/detail/lightweight_main.hpp>
22
23 #ifdef _MSC_VER
24 # pragma warning (push)
25 # pragma warning (disable : 4459)
26 #endif
27 #include <boost/lexical_cast.hpp>
28 #ifdef _MSC_VER
29 # pragma warning (pop)
30 #endif
31
32 using namespace boost;
33 using namespace boost::endian;
34
35 using std::cout;
36 using std::endl;
37
38 namespace
39 {
40 typedef boost::timer::nanosecond_type nanosecond_t;
41 std::string command_args;
42 uint64_t n; // number of test cases to run
43 int places = 2; // decimal places for times
44 bool verbose (false);
45 bool time_aligned (true);
46 bool time_unaligned (true);
47 bool time_16(true);
48 bool time_32(true);
49 bool time_64(true);
50
process_command_line(int argc,char * argv[])51 void process_command_line(int argc, char * argv[])
52 {
53 for (int a = 0; a < argc; ++a)
54 {
55 command_args += argv[a];
56 if (a != argc-1)
57 command_args += ' ';
58 }
59
60 // cout << command_args << '\n';;
61
62 if (argc >=2)
63 #ifndef _MSC_VER
64 n = atoll(argv[1]);
65 #else
66 n = _atoi64(argv[1]);
67 #endif
68
69 for (; argc > 2; ++argv, --argc)
70 {
71 if ( *(argv[2]+1) == 'p' )
72 places = atoi( argv[2]+2 );
73 else if (*(argv[2] + 1) == 'v')
74 verbose = true;
75 else if (*(argv[2] + 1) == 'a')
76 time_unaligned = false;
77 else if (*(argv[2] + 1) == 'u')
78 time_aligned = false;
79 else if (*(argv[2] + 1) == '1')
80 time_32 = time_64 = false;
81 else if (*(argv[2] + 1) == '3')
82 time_16 = time_64 = false;
83 else if (*(argv[2] + 1) == '6')
84 time_16 = time_32 = false;
85 else
86 {
87 cout << "Error - unknown option: " << argv[2] << "\n\n";
88 argc = -1;
89 break;
90 }
91 }
92
93 if (argc < 2)
94 {
95 cout << "Usage: loop_time_test n [Options]\n"
96 " The argument n specifies the number of test cases to run\n"
97 " Options:\n"
98 " -v Verbose messages\n"
99 " -p# Decimal places for times; default -p" << places << "\n"
100 " -a Aligned tests only\n"
101 " -u Unaligned tests only\n"
102 " -16 16-bit tests only\n"
103 " -32 32-bit tests only\n"
104 " -64 64-bit tests only\n"
105 ;
106 return std::exit(1);
107 }
108 }
109
with_digit_separator(int64_t x)110 std::string with_digit_separator(int64_t x)
111 {
112 std::string s = boost::lexical_cast<std::string>(x);
113 std::string s2;
114
115 for (std::string::size_type i = 0; i < s.size(); ++i)
116 {
117 if (i && ((s.size()-i) % 3) == 0)
118 s2 += '\'';
119 s2 += s[i];
120 }
121 return s2;
122 }
123
124 //--------------------------------------------------------------------------------------//
125
126 template <class T, class EndianT>
time()127 void time()
128 {
129 T total = 0;
130 {
131 // cout << "*************Endian integer approach...\n";
132 EndianT x(0);
133 boost::timer::cpu_timer t;
134 for (uint64_t i = 0; i < n; ++i)
135 {
136 x += static_cast<T>(i);
137 }
138 t.stop();
139 total += x;
140 cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
141 }
142 {
143 // cout << "***************Endian conversion approach...\n";
144 T x(0);
145 boost::timer::cpu_timer t;
146 native_to_big_inplace(x);
147 for (uint64_t i = 0; i < n; ++i)
148 {
149 x += static_cast<T>(i);
150 }
151 big_to_native_inplace(x);
152 t.stop();
153 native_to_big_inplace(x);
154 if (x != total)
155 throw std::logic_error("integer approach total != conversion approach total");
156 cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
157 }
158 }
159
160
test_big_align_int16()161 void test_big_align_int16()
162 {
163 cout << "<tr><td>16-bit aligned big endian</td>";
164 time<int16_t, big_int16_at>();
165 cout << "</tr>\n";
166 }
167
test_little_align_int16()168 void test_little_align_int16()
169 {
170 cout << "<tr><td>16-bit aligned little endian</td>";
171 time<int16_t, little_int16_at>();
172 cout << "</tr>\n";
173 }
174
test_big_int16()175 void test_big_int16()
176 {
177 cout << "<tr><td>16-bit unaligned big endian</td>";
178 time<int16_t, big_int16_t>();
179 cout << "</tr>\n";
180 }
181
test_little_int16()182 void test_little_int16()
183 {
184 cout << "<tr><td>16-bit unaligned little endian</td>";
185 time<int16_t, little_int16_t>();
186 cout << "</tr>\n";
187 }
188
test_big_align_int32()189 void test_big_align_int32()
190 {
191 cout << "<tr><td>32-bit aligned big endian</td>";
192 time<int32_t, big_int32_at>();
193 cout << "</tr>\n";
194 }
195
test_little_align_int32()196 void test_little_align_int32()
197 {
198 cout << "<tr><td>32-bit aligned little endian</td>";
199 time<int32_t, little_int32_at>();
200 cout << "</tr>\n";
201 }
202
test_big_int32()203 void test_big_int32()
204 {
205 cout << "<tr><td>32-bit unaligned big endian</td>";
206 time<int32_t, big_int32_t>();
207 cout << "</tr>\n";
208 }
209
test_little_int32()210 void test_little_int32()
211 {
212 cout << "<tr><td>32-bit unaligned little endian</td>";
213 time<int32_t, little_int32_t>();
214 cout << "</tr>\n";
215 }
216
test_big_align_int64()217 void test_big_align_int64()
218 {
219 cout << "<tr><td>64-bit aligned big endian</td>";
220 time<int64_t, big_int64_at>();
221 cout << "</tr>\n";
222 }
223
test_little_align_int64()224 void test_little_align_int64()
225 {
226 cout << "<tr><td>64-bit aligned little endian</td>";
227 time<int64_t, little_int64_at>();
228 cout << "</tr>\n";
229 }
230
test_big_int64()231 void test_big_int64()
232 {
233 cout << "<tr><td>64-bit unaligned big endian</td>";
234 time<int64_t, big_int64_t>();
235 cout << "</tr>\n";
236 }
237
test_little_int64()238 void test_little_int64()
239 {
240 cout << "<tr><td>64-bit unaligned little endian</td>";
241 time<int64_t, little_int64_t>();
242 cout << "</tr>\n";
243 }
244
245 } // unnamed namespace
246
247 //--------------------------------------------------------------------------------------//
248
cpp_main(int argc,char * argv[])249 int cpp_main(int argc, char* argv[])
250 {
251 process_command_line(argc, argv);
252
253 cout
254 << "<html>\n<head>\n<title>Endian Loop Time Test</title>\n</head>\n<body>\n"
255 << "<!-- boost-no-inspect -->\n"
256 << "<div align=\"center\"> <center>\n"
257 << "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\""
258 << "style=\"border-collapse: collapse\" bordercolor=\"#111111\">\n"
259 << "<tr><td colspan=\"6\" align=\"center\"><b>"
260 << BOOST_COMPILER << "</b></td></tr>\n"
261 << "<tr><td colspan=\"6\" align=\"center\"><b>"
262 << " Iterations: " << with_digit_separator(n)
263 << ", Intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG
264 << "</b></td></tr>\n"
265 << "<tr><td><b>Test Case</b></td>\n"
266 "<td align=\"center\"><b>Endian<br>arithmetic<br>type</b></td>\n"
267 "<td align=\"center\"><b>Endian<br>conversion<br>function</b></td>\n"
268 "</tr>\n"
269 ;
270
271 if (time_aligned)
272 {
273 if (time_16)
274 {
275 test_big_align_int16();
276 test_little_align_int16();
277 }
278 if (time_32)
279 {
280 test_big_align_int32();
281 test_little_align_int32();
282 }
283 if (time_64)
284 {
285 test_big_align_int64();
286 test_little_align_int64();
287 }
288 }
289
290 if (time_unaligned)
291 {
292 if (time_16)
293 {
294 test_big_int16();
295 test_little_int16();
296 }
297 if (time_32)
298 {
299 test_big_int32();
300 test_little_int32();
301 }
302 if (time_64)
303 {
304 test_big_int64();
305 test_little_int64();
306 }
307 }
308
309 cout << "\n</div> </center>\n"
310 << "\n</table>\n</body>\n</html>\n";
311
312 return 0;
313 }
314
315 #include <boost/endian/detail/disable_warnings_pop.hpp>
316