/**************************************************************************
*
* 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 ();
}
|