1 ///////////////////////////////////////////////////////////////
2 // Copyright 2011-9 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
5
6 #define BOOST_CHRONO_HEADER_ONLY
7
8 #ifdef _MSC_VER
9 #define _SCL_SECURE_NO_WARNINGS
10 #endif
11
12 #if !defined(TEST_MPF) && !defined(TEST_MPZ) && \
13 !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPQ) && !defined(TEST_TOMMATH) && \
14 !defined(TEST_TOMMATH_BOOST_RATIONAL) && !defined(TEST_MPZ_BOOST_RATIONAL) && !defined(TEST_CPP_INT) && \
15 !defined(TEST_CPP_INT_RATIONAL) && !defined(TEST_CPP_BIN_FLOAT)
16 #define TEST_MPF
17 #define TEST_MPZ
18 #define TEST_MPQ
19 #define TEST_MPFR
20 #define TEST_CPP_DEC_FLOAT
21 #define TEST_MPQ
22 #define TEST_TOMMATH
23 #define TEST_CPP_INT
24 #define TEST_CPP_INT_RATIONAL
25 #define TEST_CPP_BIN_FLOAT
26
27 #ifdef _MSC_VER
28 #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
29 #endif
30 #ifdef __GNUC__
31 #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
32 #endif
33
34 #endif
35
36 #include <boost/chrono.hpp>
37 #include <vector>
38 #include <map>
39 #include <string>
40 #include <cstring>
41 #include <cctype>
42 #include <iostream>
43 #include <iomanip>
44 #include <boost/random/mersenne_twister.hpp>
45 #include <boost/random/uniform_int.hpp>
46 #include <boost/multiprecision/number.hpp>
47
48 template <class Clock>
49 struct stopwatch
50 {
51 typedef typename Clock::duration duration;
stopwatchstopwatch52 stopwatch()
53 {
54 m_start = Clock::now();
55 }
elapsedstopwatch56 duration elapsed()
57 {
58 return Clock::now() - m_start;
59 }
resetstopwatch60 void reset()
61 {
62 m_start = Clock::now();
63 }
64
65 private:
66 typename Clock::time_point m_start;
67 };
68
69 extern unsigned bits_wanted; // for integer types
70
71 template <class T, int Type>
72 struct tester
73 {
testertester74 tester()
75 {
76 a.assign(500, 0);
77 for (int i = 0; i < 500; ++i)
78 {
79 b.push_back(generate_random());
80 c.push_back(generate_random());
81 small.push_back(gen());
82 }
83 }
test_addtester84 double test_add()
85 {
86 stopwatch<boost::chrono::high_resolution_clock> w;
87 for (unsigned i = 0; i < 1000; ++i)
88 {
89 for (unsigned j = 0; j < b.size(); ++j)
90 a[j] = b[j] + c[j];
91 }
92 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
93 }
test_subtracttester94 double test_subtract()
95 {
96 stopwatch<boost::chrono::high_resolution_clock> w;
97 for (unsigned i = 0; i < 1000; ++i)
98 {
99 for (unsigned j = 0; j < b.size(); ++j)
100 a[j] = b[j] - c[j];
101 }
102 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
103 }
test_add_inttester104 double test_add_int()
105 {
106 stopwatch<boost::chrono::high_resolution_clock> w;
107 for (unsigned i = 0; i < 1000; ++i)
108 {
109 for (unsigned j = 0; j < b.size(); ++j)
110 a[j] = b[j] + 1;
111 }
112 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
113 }
test_subtract_inttester114 double test_subtract_int()
115 {
116 stopwatch<boost::chrono::high_resolution_clock> w;
117 for (unsigned i = 0; i < 1000; ++i)
118 {
119 for (unsigned j = 0; j < b.size(); ++j)
120 a[j] = b[j] - 1;
121 }
122 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
123 }
test_multiplytester124 double test_multiply()
125 {
126 stopwatch<boost::chrono::high_resolution_clock> w;
127 for (unsigned i = 0; i < 1000; ++i)
128 {
129 for (unsigned k = 0; k < b.size(); ++k)
130 a[k] = b[k] * c[k];
131 }
132 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
133 }
test_multiply_inttester134 double test_multiply_int()
135 {
136 stopwatch<boost::chrono::high_resolution_clock> w;
137 for (unsigned i = 0; i < 1000; ++i)
138 {
139 for (unsigned j = 0; j < b.size(); ++j)
140 a[j] = b[j] * 3;
141 }
142 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
143 }
test_dividetester144 double test_divide()
145 {
146 stopwatch<boost::chrono::high_resolution_clock> w;
147 for (unsigned i = 0; i < 1000; ++i)
148 {
149 for (unsigned j = 0; j < b.size(); ++j)
150 a[j] = b[j] / c[j] + b[j] / small[j];
151 }
152 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
153 }
test_divide_inttester154 double test_divide_int()
155 {
156 stopwatch<boost::chrono::high_resolution_clock> w;
157 for (unsigned i = 0; i < 1000; ++i)
158 {
159 for (unsigned j = 0; j < b.size(); ++j)
160 a[j] = b[j] / 3;
161 }
162 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
163 }
test_strtester164 double test_str(const boost::mpl::false_&)
165 {
166 stopwatch<boost::chrono::high_resolution_clock> w;
167 for (unsigned i = 0; i < b.size(); ++i)
168 a[i] = boost::lexical_cast<T>(boost::lexical_cast<std::string>(b[i]));
169 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
170 }
test_strtester171 double test_str(const boost::mpl::true_&)
172 {
173 stopwatch<boost::chrono::high_resolution_clock> w;
174 for (unsigned i = 0; i < b.size(); ++i)
175 a[i].assign(b[i].str());
176 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
177 }
test_strtester178 double test_str()
179 {
180 return test_str(boost::is_class<T>());
181 }
182 //
183 // The following tests only work for integer types:
184 //
test_modtester185 double test_mod()
186 {
187 stopwatch<boost::chrono::high_resolution_clock> w;
188 for (unsigned i = 0; i < 1000; ++i)
189 {
190 for (unsigned i = 0; i < b.size(); ++i)
191 a[i] = b[i] % c[i] + b[i] % small[i];
192 }
193 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
194 }
test_mod_inttester195 double test_mod_int()
196 {
197 stopwatch<boost::chrono::high_resolution_clock> w;
198 for (unsigned i = 0; i < 1000; ++i)
199 {
200 for (unsigned i = 0; i < b.size(); ++i)
201 a[i] = b[i] % 254;
202 }
203 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
204 }
test_ortester205 double test_or()
206 {
207 stopwatch<boost::chrono::high_resolution_clock> w;
208 for (unsigned i = 0; i < 1000; ++i)
209 {
210 for (unsigned i = 0; i < b.size(); ++i)
211 a[i] = b[i] | c[i];
212 }
213 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
214 }
test_or_inttester215 double test_or_int()
216 {
217 stopwatch<boost::chrono::high_resolution_clock> w;
218 for (unsigned i = 0; i < 1000; ++i)
219 {
220 for (unsigned i = 0; i < b.size(); ++i)
221 a[i] = b[i] | 234;
222 }
223 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
224 }
test_andtester225 double test_and()
226 {
227 stopwatch<boost::chrono::high_resolution_clock> w;
228 for (unsigned i = 0; i < 1000; ++i)
229 {
230 for (unsigned i = 0; i < b.size(); ++i)
231 a[i] = b[i] & c[i];
232 }
233 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
234 }
test_and_inttester235 double test_and_int()
236 {
237 stopwatch<boost::chrono::high_resolution_clock> w;
238 for (unsigned i = 0; i < 1000; ++i)
239 {
240 for (unsigned i = 0; i < b.size(); ++i)
241 a[i] = b[i] & 234;
242 }
243 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
244 }
test_xortester245 double test_xor()
246 {
247 stopwatch<boost::chrono::high_resolution_clock> w;
248 for (unsigned i = 0; i < 1000; ++i)
249 {
250 for (unsigned i = 0; i < b.size(); ++i)
251 a[i] = b[i] ^ c[i];
252 }
253 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
254 }
test_xor_inttester255 double test_xor_int()
256 {
257 stopwatch<boost::chrono::high_resolution_clock> w;
258 for (unsigned i = 0; i < 1000; ++i)
259 {
260 for (unsigned i = 0; i < b.size(); ++i)
261 a[i] = b[i] ^ 234;
262 }
263 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
264 }
test_complementtester265 double test_complement()
266 {
267 stopwatch<boost::chrono::high_resolution_clock> w;
268 for (unsigned i = 0; i < 1000; ++i)
269 {
270 for (unsigned i = 0; i < b.size(); ++i)
271 a[i] = ~b[i];
272 }
273 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
274 }
test_left_shifttester275 double test_left_shift()
276 {
277 int max_shift = std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : bits_wanted;
278 int shift = 0;
279 stopwatch<boost::chrono::high_resolution_clock> w;
280 for (unsigned i = 0; i < 1000; ++i)
281 {
282 for (unsigned i = 0; i < b.size(); ++i)
283 a[i] = b[i] << (shift++ % max_shift);
284 }
285 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
286 }
test_right_shifttester287 double test_right_shift()
288 {
289 int max_shift = 2 + std::numeric_limits<T>::is_bounded ? std::numeric_limits<T>::digits : bits_wanted;
290 int shift = 0;
291 stopwatch<boost::chrono::high_resolution_clock> w;
292 for (unsigned i = 0; i < 1000; ++i)
293 {
294 for (unsigned i = 0; i < b.size(); ++i)
295 a[i] = b[i] >> (shift++) % max_shift;
296 }
297 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
298 }
test_gcdtester299 double test_gcd()
300 {
301 using boost::integer::gcd;
302 stopwatch<boost::chrono::high_resolution_clock> w;
303 for (unsigned i = 0; i < 1000; ++i)
304 {
305 for (unsigned i = 0; i < b.size(); ++i)
306 a[i] = gcd(b[i], c[i]);
307 }
308 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
309 }
test_powmtester310 double test_powm()
311 {
312 stopwatch<boost::chrono::high_resolution_clock> w;
313 for (unsigned i = 0; i < 25; ++i)
314 {
315 for (unsigned i = 0; i < b.size(); ++i)
316 a[i] = powm(b[i], b[i] / 2, c[i]);
317 }
318 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
319 }
test_constructtester320 double test_construct()
321 {
322 std::allocator<T> alloc;
323 T* pt = alloc.allocate(1000);
324 stopwatch<boost::chrono::high_resolution_clock> w;
325 for (unsigned i = 0; i < 1000; ++i)
326 {
327 for (unsigned j = 0; j < 1000; ++j)
328 new (pt + j) T();
329 for (unsigned j = 0; j < 1000; ++j)
330 std::allocator_traits<std::allocator<T> >::destroy(alloc, pt + j);
331 }
332 double result = boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
333 alloc.deallocate(pt, 1000);
334 return result;
335 }
test_construct_unsignedtester336 double test_construct_unsigned()
337 {
338 std::allocator<T> alloc;
339 T* pt = alloc.allocate(1000);
340 stopwatch<boost::chrono::high_resolution_clock> w;
341 for (unsigned i = 0; i < 1000; ++i)
342 {
343 for (unsigned j = 0; j < 1000; ++j)
344 new (pt + j) T(j);
345 for (unsigned j = 0; j < 1000; ++j)
346 std::allocator_traits<std::allocator<T> >::destroy(alloc, pt + j);
347 }
348 double result = boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
349 alloc.deallocate(pt, 1000);
350 return result;
351 }
test_construct_unsigned_lltester352 double test_construct_unsigned_ll()
353 {
354 std::allocator<T> alloc;
355 T* pt = alloc.allocate(1000);
356 stopwatch<boost::chrono::high_resolution_clock> w;
357 for (unsigned i = 0; i < 1000; ++i)
358 {
359 for (unsigned long long j = 0; j < 1000; ++j)
360 new (pt + j) T(j);
361 for (unsigned j = 0; j < 1000; ++j)
362 std::allocator_traits<std::allocator<T> >::destroy(alloc, pt + j);
363 }
364 double result = boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
365 alloc.deallocate(pt, 1000);
366 return result;
367 }
368
369 //
370 // Hetero operations:
371 //
372 template <class U>
get_hetero_test_valuetester373 static U get_hetero_test_value(boost::mpl::false_ const&)
374 {
375 return U(2) / 3;
376 }
377 template <class U>
get_hetero_test_valuetester378 static U get_hetero_test_value(boost::mpl::true_ const&)
379 {
380 return (std::numeric_limits<U>::max)() >> 4;
381 }
382 template <class U>
get_hetero_test_valuetester383 static U get_hetero_test_value()
384 {
385 return get_hetero_test_value<U>(boost::is_integral<U>());
386 }
387 template <class U>
test_multiply_heterotester388 double test_multiply_hetero()
389 {
390 static const U val = get_hetero_test_value<U>();
391 stopwatch<boost::chrono::high_resolution_clock> w;
392 for (unsigned i = 0; i < 1000; ++i)
393 {
394 for (unsigned j = 0; j < b.size(); ++j)
395 a[j] = b[j] * val;
396 }
397 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
398 }
399 template <class U>
test_inplace_multiply_heterotester400 double test_inplace_multiply_hetero()
401 {
402 static const U val = get_hetero_test_value<U>();
403 stopwatch<boost::chrono::high_resolution_clock> w;
404 for (unsigned i = 0; i < 1000; ++i)
405 {
406 for (unsigned j = 0; j < b.size(); ++j)
407 a[j] = b[j], a[j] *= val;
408 }
409 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
410 }
411 template <class U>
test_add_heterotester412 double test_add_hetero()
413 {
414 static const U val = get_hetero_test_value<U>();
415 stopwatch<boost::chrono::high_resolution_clock> w;
416 for (unsigned i = 0; i < 1000; ++i)
417 {
418 for (unsigned j = 0; j < b.size(); ++j)
419 a[j] = b[j] + val;
420 }
421 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
422 }
423 template <class U>
test_inplace_add_heterotester424 double test_inplace_add_hetero()
425 {
426 static const U val = get_hetero_test_value<U>();
427 stopwatch<boost::chrono::high_resolution_clock> w;
428 for (unsigned i = 0; i < 1000; ++i)
429 {
430 for (unsigned j = 0; j < b.size(); ++j)
431 a[j] = b[j], a[j] += val;
432 }
433 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
434 }
435 template <class U>
test_subtract_heterotester436 double test_subtract_hetero()
437 {
438 static const U val = get_hetero_test_value<U>();
439 stopwatch<boost::chrono::high_resolution_clock> w;
440 for (unsigned i = 0; i < 1000; ++i)
441 {
442 for (unsigned j = 0; j < b.size(); ++j)
443 a[j] = b[j] - val;
444 }
445 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
446 }
447 template <class U>
test_inplace_subtract_heterotester448 double test_inplace_subtract_hetero()
449 {
450 static const U val = get_hetero_test_value<U>();
451 stopwatch<boost::chrono::high_resolution_clock> w;
452 for (unsigned i = 0; i < 1000; ++i)
453 {
454 for (unsigned j = 0; j < b.size(); ++j)
455 a[j] = b[j], a[j] -= val;
456 }
457 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
458 }
459 template <class U>
test_divide_heterotester460 double test_divide_hetero()
461 {
462 static const U val = get_hetero_test_value<U>();
463 stopwatch<boost::chrono::high_resolution_clock> w;
464 for (unsigned i = 0; i < 1000; ++i)
465 {
466 for (unsigned j = 0; j < b.size(); ++j)
467 a[j] = b[j] / val;
468 }
469 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
470 }
471 template <class U>
test_inplace_divide_heterotester472 double test_inplace_divide_hetero()
473 {
474 static const U val = get_hetero_test_value<U>();
475 stopwatch<boost::chrono::high_resolution_clock> w;
476 for (unsigned i = 0; i < 1000; ++i)
477 {
478 for (unsigned j = 0; j < b.size(); ++j)
479 a[j] = b[j], a[j] /= val;
480 }
481 return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
482 }
483
484 private:
generate_randomtester485 T generate_random()
486 {
487 return generate_random(boost::mpl::int_<Type>());
488 }
generate_randomtester489 T generate_random(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point>&)
490 {
491 T val = gen();
492 T prev_val = -1;
493 while (val != prev_val)
494 {
495 val *= (gen.max)();
496 prev_val = val;
497 val += gen();
498 }
499 int e;
500 val = frexp(val, &e);
501
502 typedef typename T::backend_type::exponent_type e_type;
503 static boost::random::uniform_int_distribution<e_type> ui(-30, 30);
504 return ldexp(val, static_cast<int>(ui(gen)));
505 }
generate_randomtester506 T generate_random(const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
507 {
508 typedef boost::random::mt19937::result_type random_type;
509
510 T max_val;
511 unsigned digits;
512 if (std::numeric_limits<T>::is_bounded)
513 {
514 max_val = (std::numeric_limits<T>::max)();
515 digits = std::numeric_limits<T>::digits;
516 }
517 else
518 {
519 max_val = T(1) << bits_wanted;
520 digits = bits_wanted;
521 }
522
523 unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
524 while ((random_type(1) << bits_per_r_val) > (gen.max)())
525 --bits_per_r_val;
526
527 unsigned terms_needed = digits / bits_per_r_val + 1;
528
529 T val = 0;
530 for (unsigned i = 0; i < terms_needed; ++i)
531 {
532 val *= (gen.max)();
533 val += gen();
534 }
535 val %= max_val;
536 return val;
537 }
generate_randomtester538 T generate_random(const boost::mpl::int_<boost::multiprecision::number_kind_rational>&)
539 {
540 typedef boost::random::mt19937::result_type random_type;
541 typedef typename boost::multiprecision::component_type<T>::type IntType;
542
543 IntType max_val;
544 unsigned digits;
545 if (std::numeric_limits<IntType>::is_bounded)
546 {
547 max_val = (std::numeric_limits<IntType>::max)();
548 digits = std::numeric_limits<IntType>::digits;
549 }
550 else
551 {
552 max_val = IntType(1) << bits_wanted;
553 digits = bits_wanted;
554 }
555
556 unsigned bits_per_r_val = std::numeric_limits<random_type>::digits - 1;
557 while ((random_type(1) << bits_per_r_val) > (gen.max)())
558 --bits_per_r_val;
559
560 unsigned terms_needed = digits / bits_per_r_val + 1;
561
562 IntType val = 0;
563 IntType denom = 0;
564 for (unsigned i = 0; i < terms_needed; ++i)
565 {
566 val *= (gen.max)();
567 val += gen();
568 }
569 for (unsigned i = 0; i < terms_needed; ++i)
570 {
571 denom *= (gen.max)();
572 denom += gen();
573 }
574 if (denom == 0)
575 denom = 1;
576 val %= max_val;
577 denom %= max_val;
578 return T(val, denom);
579 }
580 std::vector<T> a, b, c, small;
581 static boost::random::mt19937 gen;
582 };
583
584 template <class N, int V>
585 boost::random::mt19937 tester<N, V>::gen;
586
category_name(const boost::mpl::int_<boost::multiprecision::number_kind_integer> &)587 inline const char* category_name(const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
588 {
589 return "integer";
590 }
category_name(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point> &)591 inline const char* category_name(const boost::mpl::int_<boost::multiprecision::number_kind_floating_point>&)
592 {
593 return "float";
594 }
category_name(const boost::mpl::int_<boost::multiprecision::number_kind_rational> &)595 inline const char* category_name(const boost::mpl::int_<boost::multiprecision::number_kind_rational>&)
596 {
597 return "rational";
598 }
599
600 //
601 // Keys in order are:
602 // Category
603 // Operator
604 // Type
605 // Precision
606 // Time
607 //
608 extern std::map<std::string, std::map<std::string, std::map<std::string, std::map<int, double> > > > result_table;
609
report_result(const char * cat,const char * type,const char * op,unsigned precision,double time)610 inline void report_result(const char* cat, const char* type, const char* op, unsigned precision, double time)
611 {
612 std::cout << std::left << std::setw(15) << type << std::setw(10) << precision << std::setw(35) << op << time << std::endl;
613 result_table[cat][op][type][precision] = time;
614 }
615
616 template <class Number, int N>
test_int_ops(tester<Number,N> & t,const char * type,unsigned precision,const boost::mpl::int_<boost::multiprecision::number_kind_integer> &)617 void test_int_ops(tester<Number, N>& t, const char* type, unsigned precision, const boost::mpl::int_<boost::multiprecision::number_kind_integer>&)
618 {
619 const char* cat = "integer";
620 report_result(cat, type, "%", precision, t.test_mod());
621 report_result(cat, type, "|", precision, t.test_or());
622 report_result(cat, type, "&", precision, t.test_and());
623 report_result(cat, type, "^", precision, t.test_xor());
624 //report_result(cat, type, "~", precision, t.test_complement());
625 report_result(cat, type, "<<", precision, t.test_left_shift());
626 report_result(cat, type, ">>", precision, t.test_right_shift());
627 // integer ops:
628 report_result(cat, type, "%(int)", precision, t.test_mod_int());
629 report_result(cat, type, "|(int)", precision, t.test_or_int());
630 report_result(cat, type, "&(int)", precision, t.test_and_int());
631 report_result(cat, type, "^(int)", precision, t.test_xor_int());
632 report_result(cat, type, "gcd", precision, t.test_gcd());
633 if(precision <= 1024)
634 report_result(cat, type, "powm", precision, t.test_powm());
635 }
636 template <class Number, int N, class U>
test_int_ops(tester<Number,N> &,const char *,unsigned,const U &)637 void test_int_ops(tester<Number, N>&, const char*, unsigned, const U&)
638 {
639 }
640
641 template <class Number>
test(const char * type,unsigned precision)642 void test(const char* type, unsigned precision)
643 {
644 bits_wanted = precision;
645 tester<Number, boost::multiprecision::number_category<Number>::value> t;
646 const char* cat = category_name(typename boost::multiprecision::number_category<Number>::type());
647 //
648 // call t.test_multiply() first so that the destination operands are
649 // forced to perform whatever memory allocation may be needed. That way
650 // we measure only algorithm performance, and not memory allocation effects.
651 //
652 t.test_multiply();
653 //
654 // Now the actual tests:
655 //
656 #ifndef TEST_MUL_ONLY
657 report_result(cat, type, "+", precision, t.test_add());
658 report_result(cat, type, "-", precision, t.test_subtract());
659 #endif
660 report_result(cat, type, "*", precision, t.test_multiply());
661 #ifndef TEST_MUL_ONLY
662 report_result(cat, type, "/", precision, t.test_divide());
663 report_result(cat, type, "str", precision, t.test_str());
664 // integer ops:
665 report_result(cat, type, "+(int)", precision, t.test_add_int());
666 report_result(cat, type, "-(int)", precision, t.test_subtract_int());
667 report_result(cat, type, "*(int)", precision, t.test_multiply_int());
668 report_result(cat, type, "/(int)", precision, t.test_divide_int());
669 // construction and destruction:
670 report_result(cat, type, "construct", precision, t.test_construct());
671 report_result(cat, type, "construct(unsigned)", precision, t.test_construct_unsigned());
672 report_result(cat, type, "construct(unsigned long long)", precision, t.test_construct_unsigned_ll());
673 test_int_ops(t, type, precision, typename boost::multiprecision::number_category<Number>::type());
674 // Hetero ops:
675 report_result(cat, type, "+(unsigned long long)", precision, t.template test_add_hetero<unsigned long long>());
676 report_result(cat, type, "-(unsigned long long)", precision, t.template test_subtract_hetero<unsigned long long>());
677 report_result(cat, type, "*(unsigned long long)", precision, t.template test_multiply_hetero<unsigned long long>());
678 report_result(cat, type, "/(unsigned long long)", precision, t.template test_divide_hetero<unsigned long long>());
679 report_result(cat, type, "+=(unsigned long long)", precision, t.template test_inplace_add_hetero<unsigned long long>());
680 report_result(cat, type, "-=(unsigned long long)", precision, t.template test_inplace_subtract_hetero<unsigned long long>());
681 report_result(cat, type, "*=(unsigned long long)", precision, t.template test_inplace_multiply_hetero<unsigned long long>());
682 report_result(cat, type, "/=(unsigned long long)", precision, t.template test_inplace_divide_hetero<unsigned long long>());
683 #endif
684 }
685
686 void test01();
687 void test02();
688 void test03();
689 void test04();
690 void test05();
691 void test06();
692 void test07();
693 void test08();
694 void test09();
695 void test10();
696 void test11();
697 void test12();
698 void test13();
699 void test14();
700 void test15();
701 void test16();
702 void test17();
703 void test18();
704 void test19();
705 void test20();
706 void test21();
707 void test22();
708 void test23();
709 void test24();
710 void test25();
711 void test26();
712 void test27();
713 void test28();
714 void test29();
715 void test30();
716 void test31();
717 void test32();
718 void test33();
719 void test34();
720 void test35();
721 void test36();
722 void test37();
723 void test38();
724 void test39();
725 void test40();
726 void test41();
727 void test42();
728 void test43();
729 void test44();
730 void test45();
731 void test46();
732 void test47();
733 void test48();
734 void test49();
735 void test50();
736 void test51();
737
738