/*
* 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 <cstring>
#include <cstdlib>
#include <cmath>
#include <limits>
#include <iostream>
#include <iomanip>
#include <qd/qd_real.h>
#include <qd/fpu.h>
#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 bool flag_long = false;
template <class T>
class TestSuite {
public:
void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void testall();
T pi();
};
template <class T>
T TestSuite<T>::pi() { return T::_pi; }
template <>
double TestSuite<double>::pi() { return 3.141592653589793116; }
template <class T>
void TestSuite<T>::test1() {
if (flag_verbose) {
cout << endl;
cout << "Timing addition..." << endl;
}
int n = 100000, i;
tictoc tv;
double t;
std::ios_base::fmtflags fmt = cout.flags();
if (flag_long) n *= 10;
T a = 1.0 / T(7.0);
T b = 0.0;
tic(&tv);
for (i = 0; i < n; i++) {
b += a;
}
t = toc(&tv);
if (flag_verbose) {
cout << "n = " << n << " t = " << t << endl;
cout << "b = " << b << endl;
cout << n << " operations in " << t << " s." << endl;
} else {
cout << " add: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
cout.flags(fmt);
}
template <class T>
void TestSuite<T>::test2() {
if (flag_verbose) {
cout << endl;
cout << "Timing multiplication ..." << endl;
}
int n = 100000, i;
tictoc tv;
double t;
if (flag_long) n *= 10;
T a = 1.0 + 1.0 / T(static_cast<double>(n));
T b = 1.0;
tic(&tv);
for (i = 0; i < n; i++) {
b *= a;
}
t = toc(&tv);
if (flag_verbose) {
cout << "n = " << n << " t = " << t << endl;
cout << "b = " << b << endl;
cout << n << " operations in " << t << " s." << endl;
} else {
cout << " mul: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
}
template <class T>
void TestSuite<T>::test3() {
if (flag_verbose) {
cout << endl;
cout << "Timing division ..." << endl;
}
int n = 100000, i;
tictoc tv;
double t;
if (flag_long) n *= 10;
T a = 1.0 + 1.0 / T(static_cast<double>(n));
T b = 1.0;
tic(&tv);
for (i = 0; i < n; i++) {
b /= a;
}
t = toc(&tv);
if (flag_verbose) {
cout << "n = " << n << " t = " << t << endl;
cout << "b = " << b << endl;
cout << n << " operations in " << t << " s." << endl;
} else {
cout << " div: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
}
template <class T>
void TestSuite<T>::test4() {
if (flag_verbose) {
cout << endl;
cout << "Timing square root ..." << endl;
}
int n = 10000, i;
tictoc tv;
double t;
if (flag_long) n *= 10;
T a = 0.0;
T b = 2.0 + pi();
tic(&tv);
for (i = 0; i < n; i++) {
a = sqrt(a + b);
}
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 << " sqrt: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
}
template <class T>
void TestSuite<T>::test5() {
if (flag_verbose) {
cout << endl;
cout << "Timing sin ..." << endl;
}
int n = 2000, i;
tictoc tv;
double t;
if (flag_long) n *= 10;
T a = 0.0;
T b = pi() / static_cast<double>(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 << "a = " << a << endl;
cout << n << " operations in " << t << " s." << endl;
} else {
cout << " sin: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
}
template <class T>
void TestSuite<T>::test6() {
if (flag_verbose) {
cout << endl;
cout << "Timing log ..." << endl;
}
int n = 1000, i;
tictoc tv;
double t;
if (flag_long) n *= 10;
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: ";
}
cout << fixed << setprecision(6) << setw(10) << t/n*1.0e6 << " us" << endl;
}
template <class T>
void TestSuite<T>::testall() {
test1();
test2();
test3();
test4();
test5();
test6();
}
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) {
flag_long = true;
} 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<double> test;
cout << endl;
cout << "Timing double" << endl;
cout << "-------------" << endl;
test.testall();
}
if (flag_test_dd) {
TestSuite<dd_real> test;
cout << endl;
cout << "Timing dd_real" << endl;
cout << "--------------" << endl;
test.testall();
}
if (flag_test_qd) {
TestSuite<qd_real> test;
cout << endl;
cout << "Timing qd_real" << endl;
cout << "--------------" << endl;
test.testall();
}
fpu_fix_end(&old_cw);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1