nbench1.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,217 行 · 第 1/5 页
C
2,217 行
** DoFourier **
***************
** Perform the transcendental/trigonometric portion of the
** benchmark. This benchmark calculates the first n
** fourier coefficients of the function (x+1)^x defined
** on the interval 0,2.
*/
void DoFourier(void)
{
FourierStruct *locfourierstruct; /* Local fourier struct */
fardouble *abase; /* Base of A[] coefficients array */
fardouble *bbase; /* Base of B[] coefficients array */
unsigned long accumtime; /* Accumulated time in ticks */
double iterations; /* # of iterations */
char *errorcontext; /* Error context string pointer */
int systemerror; /* For error code */
double tot_time;
double wat_time;
/*
** Link to global structure
*/
locfourierstruct=&global_fourierstruct;
/*
** Set error context string
*/
errorcontext="FPU:Transcendental";
/*
** See if we need to do self-adjustment code.
*/
if(locfourierstruct->adjust==0)
{
locfourierstruct->arraysize=100L; /* Start at 100 elements */
while(1)
{
abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
ErrorExit();
}
bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
FreeMemory((void *)abase,&systemerror);
ErrorExit();
}
/*
** Do an iteration of the tests. If the elapsed time is
** less than or equal to the permitted minimum, re-allocate
** larger arrays and try again.
*/
if(DoFPUTransIteration(abase,bbase,
locfourierstruct->arraysize, NULL)>global_min_ticks)
break; /* We're ok...exit */
/*
** Make bigger arrays and try again.
*/
FreeMemory((farvoid *)abase,&systemerror);
FreeMemory((farvoid *)bbase,&systemerror);
locfourierstruct->arraysize+=50L;
}
}
else
{ /*
** Don't need self-adjustment. Just allocate the
** arrays, and go.
*/
abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
ErrorExit();
}
bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double),
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
FreeMemory((void *)abase,&systemerror);
ErrorExit();
}
}
/*
** All's well if we get here. Repeatedly perform integration
** tests until the accumulated time is greater than the
** # of seconds requested.
*/
accumtime=0L;
iterations=(double)0.0;
tot_time = (double)0.0;
do {
accumtime+=DoFPUTransIteration(abase,bbase,locfourierstruct->arraysize,
&wat_time);
iterations+=(double)locfourierstruct->arraysize*(double)2.0-(double)1.0;
tot_time += wat_time;
} while(TicksToSecs(accumtime)<locfourierstruct->request_secs);
/*
** Clean up, calculate results, and go home.
** Also set adjustment flag to indicate no adjust code needed.
*/
FreeMemory((farvoid *)abase,&systemerror);
FreeMemory((farvoid *)bbase,&systemerror);
locfourierstruct->fflops=iterations/(double)TicksToFracSecs(accumtime);
tot_time /= iterations;
ReportTime( tot_time );
if(locfourierstruct->adjust==0)
locfourierstruct->adjust=1;
return;
}
/************************
** DoFPUTransIteration **
*************************
** Perform an iteration of the FPU Transcendental/trigonometric
** benchmark. Here, an iteration consists of calculating the
** first n fourier coefficients of the function (x+1)^x on
** the interval 0,2. n is given by arraysize.
** NOTE: The # of integration steps is fixed at
** 200.
*/
static ulong DoFPUTransIteration(fardouble *abase, /* A coeffs. */
fardouble *bbase, /* B coeffs. */
ulong arraysize, double *wat_time) /* # of coeffs */
{
double omega; /* Fundamental frequency */
unsigned long i; /* Index */
unsigned long elapsed; /* Elapsed time */
/*
** Start the stopwatch
*/
elapsed=StartStopwatch();
TimerOn();
/*
** Calculate the fourier series. Begin by
** calculating A[0].
*/
*abase=TrapezoidIntegrate((double)0.0,
(double)2.0,
200,
(double)0.0, /* No omega * n needed */
0 )/(double)2.0;
/*
** Calculate the fundamental frequency.
** ( 2 * pi ) / period...and since the period
** is 2, omega is simply pi.
*/
omega=(double)3.1415926535897932;
for(i=1;i<arraysize;i++)
{
/*
** Calculate A[i] terms. Note, once again, that we
** can ignore the 2/period term outside the integral
** since the period is 2 and the term cancels itself
** out.
*/
*(abase+i)=TrapezoidIntegrate((double)0.0,
(double)2.0,
200,
omega * (double)i,
1);
/*
** Calculate the B[i] terms.
*/
*(bbase+i)=TrapezoidIntegrate((double)0.0,
(double)2.0,
200,
omega * (double)i,
2);
}
/*
** All done, stop the stopwatch
*/
TimerOff();
elapsed = StopStopwatch(elapsed);
if( wat_time ) {
*wat_time = TimerElapsed();
}
return( elapsed );
}
/***********************
** TrapezoidIntegrate **
************************
** Perform a simple trapezoid integration on the
** function (x+1)**x.
** x0,x1 set the lower and upper bounds of the
** integration.
** nsteps indicates # of trapezoidal sections
** omegan is the fundamental frequency times
** the series member #
** select = 0 for the A[0] term, 1 for cosine terms, and
** 2 for sine terms.
** Returns the value.
*/
static double TrapezoidIntegrate( double x0, /* Lower bound */
double x1, /* Upper bound */
int nsteps, /* # of steps */
double omegan, /* omega * n */
int select)
{
double x; /* Independent variable */
double dx; /* Stepsize */
double rvalue; /* Return value */
/*
** Initialize independent variable
*/
x=x0;
/*
** Calculate stepsize
*/
dx=(x1 - x0) / (double)nsteps;
/*
** Initialize the return value.
*/
rvalue=thefunction(x0,omegan,select)/(double)2.0;
/*
** Compute the other terms of the integral.
*/
if(nsteps!=1)
{ --nsteps; /* Already done 1 step */
while(--nsteps )
{
x+=dx;
rvalue+=thefunction(x,omegan,select);
}
}
/*
** Finish computation
*/
rvalue=(rvalue+thefunction(x1,omegan,select)/(double)2.0)*dx;
return(rvalue);
}
/****************
** thefunction **
*****************
** This routine selects the function to be used
** in the Trapezoid integration.
** x is the independent variable
** omegan is omega * n
** select chooses which of the sine/cosine functions
** are used. note the special case for select=0.
*/
static double thefunction(double x, /* Independent variable */
double omegan, /* Omega * term */
int select) /* Choose term */
{
/*
** Use select to pick which function we call.
*/
switch(select)
{
case 0: return(pow(x+(double)1.0,x));
case 1: return(pow(x+(double)1.0,x) * cos(omegan * x));
case 2: return(pow(x+(double)1.0,x) * sin(omegan * x));
}
/*
** We should never reach this point, but the following
** keeps compilers from issuing a warning message.
*/
return(0.0);
}
/*************************
** ASSIGNMENT ALGORITHM **
*************************/
/*************
** DoAssign **
**************
** Perform an assignment algorithm.
** The algorithm was adapted from the step by step guide found
** in "Quantitative Decision Making for Business" (Gordon,
** Pressman, and Cohn; Prentice-Hall)
**
**
** NOTES:
** 1. Even though the algorithm distinguishes between
** ASSIGNROWS and ASSIGNCOLS, as though the two might
** be different, it does presume a square matrix.
** I.E., ASSIGNROWS and ASSIGNCOLS must be the same.
** This makes for some algorithmically-correct but
** probably non-optimal constructs.
**
*/
void DoAssign(void)
{
AssignStruct *locassignstruct; /* Local structure ptr */
farlong *arraybase;
char *errorcontext;
int systemerror;
ulong accumtime;
double iterations;
double tot_time;
double wat_time;
/*
** Link to global structure
*/
locassignstruct=&global_assignstruct;
/*
** Set the error context string.
*/
errorcontext="CPU:Assignment";
/*
** See if we need to do self adjustment code.
*/
if(locassignstruct->adjust==0)
{
/*
** Self-adjustment code. The system begins by working on 1
** array. If it does that in no time, then two arrays
** are built. This process continues until
** enough arrays are built to handle the tolerance.
*/
locassignstruct->numarrays=1;
while(1)
{
/*
** Allocate space for arrays
*/
arraybase=(farlong *) AllocateMemory(sizeof(long)*
ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays,
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
FreeMemory((farvoid *)arraybase,
&systemerror);
ErrorExit();
}
/*
** Do an iteration of the assignment alg. If the
** elapsed time is less than or equal to the permitted
** minimum, then allocate for more arrays and
** try again.
*/
if(DoAssignIteration(arraybase,
locassignstruct->numarrays, NULL)>global_min_ticks)
break; /* We're ok...exit */
FreeMemory((farvoid *)arraybase, &systemerror);
locassignstruct->numarrays++;
}
}
else
{ /*
** Allocate space for arrays
*/
arraybase=(farlong *)AllocateMemory(sizeof(long)*
ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays,
&systemerror);
if(systemerror)
{ ReportError(errorcontext,systemerror);
FreeMemory((farvoid *)arraybase,
&systemerror);
ErrorExit();
}
}
/*
** All's well if we get here. Do the tests.
*/
accumtime=0L;
iterations=(double)0.0;
tot_time=(double)0.0;
do {
accumtime+=DoAssignIteration(arraybase,
locassignstruct->numarrays, &wat_time);
iterations+=(double)1.0;
tot_time += wat_time;
} while(TicksToSecs(accumtime)<locassignstruct->request_secs);
/*
** Clean up, calculate results, and go home. Be sure to
** show that we don't have to rerun adjustment code.
*/
FreeMemory((farvoid *)arraybase,&systemerror);
locassignstruct->iterspersec=iterations *
(double)locassignstruct->numarrays / TicksToFracSecs(accumtime);
tot_time /= ((double)(locassignstruct->numarrays) * iterations );
ReportTime( tot_time );
if(locassignstruct->adjust==0)
locassignstruct->adjust=1;
return;
}
/**********************
** DoAssignIteration **
***********************
** This routine executes one iteration of the assignment test.
** It returns the number of ticks elapsed in the iteration.
*/
static ulong DoAssignIteration(farlong *arraybase,
ulong numarrays, double *wat_time)
{
longptr abase; /* local pointer */
ulong elapsed; /* Elapsed ticks */
ulong i;
/*
** Set up local pointer
*/
abase.ptrs.p=arraybase;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?