/************************************************************************** * * Filename: * * whetstone.c * * Description: * * Performs one million Whetstone instructions, a number of times, then * prints the execution speed in K Whetstone Instructions per Second * (KWIPS). For example, if ntimes = 1, and the execution time is 1 * second, then the result is 1000 KWIPS. * * Credits: * * This source text was translated from the Ada PIWG test A000093 by * Chris Nettleton, November 1996. * * Revision: * * $Id: whetstone.c,v 1.1.1.1 2004/05/10 20:33:29 cvs Exp $ * **************************************************************************/ #include <report.h> #include <time.h> /* The KWIPS rating is the number of Kilo Whetstone Instructions Per * Second. The following code is worth 1 million whetstones for each * iteration, so to compute the rating, run the code ntimes, then: rating * = 1000 / time taken in secs / ntimes ntimes should be set so the * benchmark takes about ten seconds to run so you can get an approximate * verification of the printed rating. * * A 25MHz Motorola 68020 with 68881 scores about 2000 KWIPS, so by setting * ntimes to 20, the execution time is 10 secs, which is a good time from * the point of view of timing the clock function, and from checking using * a stop watch. ntimes = 100 is good on a Pentium. */ static const int ntimes = 1; /* Benchmark timing stuff */ static long rating; static clock_t start_time; static clock_t stop_time; /* * My floating abs (we don't have a math library) */ double fabs (double x); /* These routines are provided for use by ACM SIGAda PIWG for making * measurements. These routines are copyrighted and may only be used for * performance measurements. These math routines must not be distributed * without this notice. No permission is granted to any party to modify, * to redistribute, to sell, to give away, or to otherwise use or transmit * these math routines without express written permission from Westinghous * Electric Corporation, c/o Jon Squire, P.O. Box 746 MS1615, Baltimore, * MD 21203. */ const float pi_2 = 1.57079632679489661; static float sin (float x) { const float c1 = 1.57079631847; const float c3 = -0.64596371106; const float c5 = 0.07968967928; const float c7 = -0.00467376557; const float c9 = 0.00015148419; float x_norm; float x_int; float x_2; float y; x_norm = x / pi_2; if (fabs (x_norm) > 4.0) { x_int = (float) ((int) (x_norm / 4.0)); x_norm = x_norm - 4.0 * x_int; } if (x_norm > 2.0) x_norm = 2.0 - x_norm; else if (x_norm < -2.0) x_norm = -2.0 - x_norm; if (x_norm > 1.0) x_norm = 2.0 - x_norm; else if (x_norm < -1.0) x_norm = -2.0 - x_norm; x_2 = x_norm * x_norm; y = (c1 + (c3 + (c5 + (c7 + c9 * x_2) * x_2) * x_2) * x_2) * x_norm; return y; } static float cos (float x) { return sin (x + pi_2); } static float atan (float x) { const float c1 = 0.9999993329; const float c3 = -0.3332985605; const float c5 = 0.1994653599; const float c7 = -0.1390853351; const float c9 = 0.0964200441; const float c11 = -0.0559098861; const float c13 = 0.0218612288; const float c15 = -0.0040540580; float a_2; float y; float a; a = x; if (fabs (a) > 1.0) a = 1.0 / a; a_2 = a * a; y = (c1 + (c3 + (c5 + (c7 + (c9 + (c11 + (c13 + c15 * a_2) * a_2) * a_2) * a_2) * a_2) * a_2) * a_2) * a; if (fabs (x) >= 1.0) { if (x < 0.0) y = -(pi_2 + y); else y = pi_2 - y; } return y; } static float sqrt (float x) { float y, root_pwr, x_norm; const float a = 2.1902; const float b = -3.0339; const float c = 1.5451; x_norm = x; root_pwr = 1.0; if (x <= 0.0) return 0.0; if (x > 1.0) { while (x_norm > 1.0) { root_pwr = root_pwr * 2.0; x_norm = x_norm * 0.25; } } else { while (x_norm < 0.25) { root_pwr = root_pwr * 0.5; x_norm = x_norm * 4.0; } } y = a + b / (c + x_norm); y = 0.5 * (y + x_norm / y); y = 0.5 * (y + x_norm / y); y = y * root_pwr; return y; } static float exp (float x) { const float c1 = 9.99999900943303e-01; const float c2 = 5.00006347344554e-01; const float c3 = 1.66667985598315e-01; const float c4 = 4.16350120350139e-02; const float c5 = 8.32859610677671e-03; const float c6 = 1.43927433449119e-03; const float c7 = 2.04699933614437e-04; float x1; float y; float e_pwr = 1.0; float e = 2.71828182845905; x1 = fabs (x); if (x1 > 88.0) return 0.0; while (x1 >= 1.0) { e_pwr = e_pwr * e * e; x1 = x1 - 2.0; } y = 1.0 + (c1 + (c2 + (c3 + (c4 + (c5 + (c6 + c7 * x1) * x1) * x1) * x1) * x1) * x1) * x1; y = y * e_pwr; if (x < 0.0) y = 1.0 / y; return y; } static float log10 (float x) { const float c1 = 0.868591718; const float c3 = 0.289335524; const float c5 = 0.177522071; const float c7 = 0.094376476; const float c9 = 0.191337714; const float c_r10 = 3.1622777; float y; float x_norm; float x_log; float frac; float frac_2; x_log = 0.5; x_norm = x; if (x <= 0.0) return 0.0; if (x >= 10.0) { while (x_norm >= 10.0) /* reduce to 1.0 .. 10.0 */ { x_log = x_log + 1.0; x_norm = x_norm * 0.1; } } else { while (x_norm < 1.0) /* reduce to 1.0 .. 10.0 */ { x_log = x_log - 1.0; x_norm = x_norm * 10.0; } } frac = (x_norm - c_r10) / (x_norm + c_r10); frac_2 = frac * frac; y = (c1 + (c3 + (c5 + (c7 + c9 * frac_2) * frac_2) * frac_2) * frac_2) * frac; return y + x_log; } static float log (float x) { return 2.302585093 * log10 (x); } /* * End of copyrighted section */ float x1, x2, x3, x4, x, y, z, t, t1, t2; float e1[5]; int j, k, l, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11; static void pa (float *e) { /* tests computations with an array as a parameter */ int j; /* T,T2 : FLOAT are global variables */ j = 0; LAB: e[1] = (e[1] + e[2] + e[3] - e[4]) * t; e[2] = (e[1] + e[2] - e[3] + e[4]) * t; e[3] = (e[1] - e[2] + e[3] + e[4]) * t; e[4] = (-e[1] + e[2] + e[3] + e[4]) / t2; j = j + 1; if (j < 6) goto LAB; } static void p0 () { /* * tests computations with no parameters * T1,T2 : FLOAT are global * E1 : VECTOR (1..4) is global * J,K,L : INTEGER are global */ e1[j] = e1[k]; e1[k] = e1[l]; e1[l] = e1[j]; } static void p3 (float *x, float *y, float *z) { /* * tests computations with simple identifiers as parameters * T,T2 : FLOAT are global */ *x = t * (*x + *y); *y = t * (*x + *y); *z = (*x + *y) / t2; } /* * Whetstone proper starts here */ int main () { int I = 10; /* loop count weighting factor */ int cycle_no; /* major loop counter */ int i; /* loop counter */ test ("whetstone", "Whetstone scientific benchmark"); /* Set constants */ t = 0.499975; t1 = 0.50025; t2 = 2.0; /* Compute the execution frequency for the benchmark modules */ n1 = 0; /* Module 1 not executed */ n2 = 12 * I; n3 = 14 * I; n4 = 345 * I; n5 = 0; /* Module 5 not executed */ n6 = 210 * I; n7 = 32 * I; n8 = 899 * I; n9 = 616 * I; n10 = 0; /* Module 10 not executed */ n11 = 93 * I; start_time = clock (); /* Get Whetstone start time */ cycle_loop: for (cycle_no = 1; cycle_no <= ntimes; cycle_no++) { /* Module 1 : computations with simple identifiers */ x1 = 1.0; x2 = -1.0; x3 = -1.0; x4 = -1.0; for (i = 1; i <= n1; i++) { x1 = (x1 + x2 + x3 - x4) * t; x2 = (x1 + x2 - x3 + x4) * t; x3 = (x1 + x2 + x3 + x4) * t; x4 = (-x1 + x2 + x3 + x4) * t; } /* end Module 1 */ /* Module 2: computations with array elements */ e1[1] = 1.0; e1[2] = -1.0; e1[3] = -1.0; e1[4] = -1.0; for (i = 1; i <= n2; i++) { e1[1] = (e1[1] + e1[2] + e1[3] - e1[4]) * t; e1[2] = (e1[1] + e1[2] - e1[3] + e1[4]) * t; e1[3] = (e1[1] - e1[2] + e1[3] + e1[4]) * t; e1[4] = (-e1[1] + e1[2] + e1[3] + e1[4]) * t; } /* end Module 2 */ /* Module 3 : passing an array as a parmeter */ for (i = 1; i <= n3; i++) pa (e1); /* end Module 3 */ /* Module 4 : performing conditional jumps */ j = 1; for (i = 1; i <= n4; i++) { if (j == 1) j = 2; else j = 3; if (j > 2) j = 0; else j = 1; if (j < 1) j = 1; else j = 0; } /* end Module 4 */ /* Module 5 : omitted */ /* Module 6 : performing integer arithmetic */ j = 1; k = 2; l = 3; for (i = 1; i <= n6; i++) { j = j * (k - j) * (l - k); k = l * k - (l - j) * k; l = (l - k) * (k + j); e1[l - 1] = (float) (j + k + l); e1[k - 1] = (float) (j * k * l); } /* end Module 6 */ /* Module 7 : performing computations using trigonometric functions */ x = 0.5; y = 0.5; for (i = 1; i <= n7; i++) { x = t * atan (t2 * sin (x) * cos (x) / (cos (x + y) + cos (x - y) - 1.0)); y = t * atan (t2 * sin (y) * cos (y) / (cos (x + y) + cos (x - y) - 1.0)); } /* end Module 7 */ /* Module 8 : procedure calls with simple identifiers as parameters */ x = 1.0; y = 1.0; z = 1.0; for (i = 1; i <= n8; i++) p3 (&x, &y, &z); /* end Module 8 */ /* Module 9 : array reference and procedure calls with no parameters */ j = 1; k = 2; l = 3; e1[1] = 1.0; e1[2] = 2.0; e1[3] = 3.0; for (i = 1; i <= n9; i++) p0 (); /* end Module 9 */ /* Module 10 : integer arithmetic */ j = 2; k = 3; for (i = 1; i <= n10; i++) { j = j + k; k = k + j; j = k - j; k = k - j - j; } /* end Module 10 */ /* Module 11 : performing computations using standard mathematical functions */ x = 0.75; for (i = 1; i <= n11; i++) x = sqrt (exp (log (x) / t1)); /* end Moudle 11 */ } /* Get stop time after ntimes */ stop_time = clock (); /* Now compute number of K Whetstones per sec */ rating = (long) (1000.0 / (((double) stop_time - (double) start_time) / (double) CLOCKS_PER_SEC / (double) (ntimes))); comment ("Rating = %ld KWIPS", rating); if (rating < 100.0 || rating > 100000.0) failed ("measured rating out of limits"); result (); }