/* * tests/qd_timer.cpp * * This work was supported by the Director, Office of Science, Division * of Mathematical, Information, and Computational Sciences of the * U.S. Department of Energy under contract number DE-AC03-76SF00098. * * Copyright (c) 2000-2004 * * Contains code to time basic operations. */ #include #include #include #include #include #include #include #include #include "tictoc.h" using std::cout; using std::cerr; using std::endl; using std::sqrt; using std::strcmp; using std::setw; using std::setprecision; using std::fixed; // Global flags passed to the main program. static bool flag_test_double = false; static bool flag_test_dd = false; static bool flag_test_qd = false; static bool flag_verbose = false; static int long_factor = 1; template class TestSuite { public: void test1(); void test2(); void test3(); void test4(); void test5(); void test6(); void test7(); void test8(); void test9(); void testall(); T pi(); }; template T TestSuite::pi() { return T::_pi; } template <> double TestSuite::pi() { return 3.141592653589793116; } void print_timing(double nops, double t) { double mops = 1.0e-6 * nops / t; cout << fixed; cout << setprecision(6) << setw(10) << 1.0 / mops << " us"; cout << setprecision(4) << setw(10) << mops << " mop/s" << endl; } template void TestSuite::test1() { if (flag_verbose) { cout << endl; cout << "Timing addition..." << endl; } int n = 100000, i; tictoc tv; double t; n *= long_factor; T a1 = 1.0 / T(7.0); T a2 = 1.0 / T(11.0); T a3 = 1.0 / T(13.0); T a4 = 1.0 / T(17.0); T b1 = 0.0, b2 = 0.0, b3 = 0.0, b4 = 0.0; tic(&tv); for (i = 0; i < n; i++) { b1 += a1; b2 += a2; b3 += a3; b4 += a4; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << b1+b2+b3+b4 << endl; cout << 4*n << " operations in " << t << " s." << endl; } else { cout << " add: "; } print_timing(4.0*n, t); } template void TestSuite::test2() { if (flag_verbose) { cout << endl; cout << "Timing multiplication ..." << endl; } int n = 100000, i; tictoc tv; double t; n *= long_factor; T a1 = 1.0 + 1.0 / T(static_cast(n)); T a2 = 1.0 + 2.0 / T(static_cast(n)); T a3 = 1.0 + 3.0 / T(static_cast(n)); T a4 = 1.0 + 4.0 / T(static_cast(n)); T b1 = 1.0, b2 = 1.0, b3 = 1.0, b4 = 1.0; tic(&tv); for (i = 0; i < n; i++) { b1 *= a1; b2 *= a2; b3 *= a3; b4 *= a4; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << b1+b2+b3+b4 << endl; cout << 4*n << " operations in " << t << " s." << endl; } else { cout << " mul: "; } print_timing(4.0*n, t); } template void TestSuite::test3() { if (flag_verbose) { cout << endl; cout << "Timing division ..." << endl; } int n = 100000, i; tictoc tv; double t; n *= long_factor; T a1 = 1.0 + 1.0 / T(static_cast(n)); T a2 = 1.0 + 2.0 / T(static_cast(n)); T a3 = 1.0 + 3.0 / T(static_cast(n)); T a4 = 1.0 + 4.0 / T(static_cast(n)); T b1 = 1.0, b2 = 1.0, b3 = 1.0, b4 = 1.0; tic(&tv); for (i = 0; i < n; i++) { b1 /= a1; b2 /= a2; b3 /= a3; b4 /= a4; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << b1+b2+b3+b4 << endl; cout << 4*n << " operations in " << t << " s." << endl; } else { cout << " div: "; } print_timing(4.0*n, t); } template void TestSuite::test4() { if (flag_verbose) { cout << endl; cout << "Timing square root ..." << endl; } int n = 10000, i; tictoc tv; double t; n *= long_factor; T a1 = 0.0, a2 = 0.0, a3 = 0.0, a4 = 0.0; T b1 = 1.0 + pi(); T b2 = 2.0 + pi(); T b3 = 3.0 + pi(); T b4 = 4.0 + pi(); tic(&tv); for (i = 0; i < n; i++) { a1 = sqrt(a1 + b1); a2 = sqrt(a2 + b2); a3 = sqrt(a3 + b3); a4 = sqrt(a4 + b4); } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << a1+a2+a3+a4 << endl; cout << 4*n << " operations in " << t << " s." << endl; } else { cout << " sqrt: "; } print_timing(4.0*n, t); } template void TestSuite::test5() { if (flag_verbose) { cout << endl; cout << "Timing sin ..." << endl; } int n = 4000, i; tictoc tv; double t; n *= long_factor; T a = 0.0; T b = 3.0 * pi() / static_cast(n); T c = 0.0; tic(&tv); for (i = 0; i < n; i++) { a += b; c += sin(a); } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << c << endl; cout << n << " operations in " << t << " s." << endl; } else { cout << " sin: "; } print_timing(n, t); } template void TestSuite::test6() { if (flag_verbose) { cout << endl; cout << "Timing log ..." << endl; } int n = 1000, i; tictoc tv; double t; n *= long_factor; T a = 0.0; T c = exp(T(-50.1)); T d = exp(T(100.2) / double(n)); tic(&tv); for (i = 0; i < n; i++) { a = a + log(c); c *= d; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "a = " << a << endl; cout << n << " operations in " << t << " s." << endl; } else { cout << " log: "; } print_timing(n, t); } template void TestSuite::test7() { if (flag_verbose) { cout << endl; cout << "Timing dot ..." << endl; } int n = 100000, i; tictoc tv; double t; n *= long_factor; T a1 = 1.0 / T(7.0); T a2 = 1.0 / T(11.0); T a3 = 1.0 / T(13.0); T a4 = 1.0 / T(17.0); T b1 = 1.0 - T(1.0) / static_cast(n); T b2 = 1.0 - T(2.0) / static_cast(n); T b3 = 1.0 - T(3.0) / static_cast(n); T b4 = 1.0 - T(4.0) / static_cast(n); T x1 = 1.0, x2 = 1.0, x3 = 1.0, x4 = 1.0; tic(&tv); for (i = 0; i < n; i++) { x1 = a1 + b1 * x1; x2 = a2 + b2 * x2; x3 = a3 + b3 * x3; x4 = a4 + b4 * x4; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << x1+x2+x3+x4 << endl; cout << 8*n << " operations in " << t << " s." << endl; } else { cout << " dot: "; } print_timing(8.0*n, t); } template void TestSuite::test8() { if (flag_verbose) { cout << endl; cout << "Timing exp ..." << endl; } int n = 1000, i; tictoc tv; double t; n *= long_factor; T a = 0.0; T c = -5.0; T d = 10.0 / static_cast(n); tic(&tv); for (i = 0; i < n; i++) { a = a + exp(c); c += d; } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "a = " << a << endl; cout << n << " operations in " << t << " s." << endl; } else { cout << " exp: "; } print_timing(n, t); } template void TestSuite::test9() { if (flag_verbose) { cout << endl; cout << "Timing cos ..." << endl; } int n = 4000, i; tictoc tv; double t; n *= long_factor; T a = 0.0; T b = 3.0 * pi() / static_cast(n); T c = 0.0; tic(&tv); for (i = 0; i < n; i++) { a += b; c += cos(a); } t = toc(&tv); if (flag_verbose) { cout << "n = " << n << " t = " << t << endl; cout << "r = " << c << endl; cout << n << " operations in " << t << " s." << endl; } else { cout << " cos: "; } print_timing(n, t); } template void TestSuite::testall() { test1(); test2(); test3(); test4(); test5(); test6(); test7(); test8(); test9(); } void print_usage() { cout << "qd_test [-h] [-dd] [-qd] [-all]" << endl; cout << " Performs timing tests of the quad-double library." << endl; cout << " By default, double-double and quad-double arithmetics" << endl; cout << " are timed." << endl; cout << endl; cout << " -h -help Prints this usage message." << endl; cout << " -double Time arithmetic of double." << endl; cout << " -dd Time arithmetic of double-double." << endl; cout << " -qd Time arithmetic of quad-double." << endl; cout << " -all Perform both double-double and quad-double tests." << endl; cout << " -v Verbose output." << endl; cout << " -long Perform a longer timing loop." << endl; } int main(int argc, char *argv[]) { unsigned int old_cw; fpu_fix_start(&old_cw); /* Parse the arguments. */ char *arg; for (int i = 1; i < argc; i++) { arg = argv[i]; if (strcmp(arg, "-h") == 0 || strcmp(arg, "-help") == 0) { print_usage(); std::exit(0); } else if (strcmp(arg, "-double") == 0) { flag_test_double = true; } else if (strcmp(arg, "-dd") == 0) { flag_test_dd = true; } else if (strcmp(arg, "-qd") == 0) { flag_test_qd = true; } else if (strcmp(arg, "-all") == 0) { flag_test_double = flag_test_dd = flag_test_qd = true; } else if (strcmp(arg, "-v") == 0) { flag_verbose = true; } else if (strcmp(arg, "-long") == 0) { long_factor *= 10; } else { cerr << "Unknown flag `" << arg << "'." << endl; } } /* If no flag, test both double-double and quad-double. */ if (!flag_test_double && !flag_test_dd && !flag_test_qd) { flag_test_dd = true; flag_test_qd = true; } if (flag_test_double) { TestSuite test; cout << endl; cout << "Timing double" << endl; cout << "-------------" << endl; test.testall(); } if (flag_test_dd) { TestSuite test; cout << endl; cout << "Timing dd_real" << endl; cout << "--------------" << endl; test.testall(); } if (flag_test_qd) { TestSuite test; cout << endl; cout << "Timing qd_real" << endl; cout << "--------------" << endl; test.testall(); } fpu_fix_end(&old_cw); return 0; }