/**********************************************************/
/* Date: Mon, 10 Mar 1997 07:38:18 -0500                  */
/* From: Roy Longbottom <Roy_Longbottom@compuserve.com>   */
/* Subject: WHET02.txt                                    */
/* To: "Alfred A. Aburto Jr." <aburto@cts.com>            */
/**********************************************************/

/*
 *     C/C++ Whetstone Benchmark Single or Double Precision
 *
 *     Original concept        Brian Wichmann NPL      1960's
 *     Original author         Harold Curnow  CCTA     1972
 *     Self timing versions    Roy Longbottom CCTA     1978/87
 *     Optimisation control    Bangor University       1987/90
 *     C/C++ Version           Roy Longbottom          1996
 *     Compatibility & timers  Al Aburto               1996
 *
 ************************************************************
 *
 *              Official version approved by:
 *
 *         Harold Curnow  100421.1615@compuserve.com
 *
 *      Happy 25th birthday Whetstone, 21 November 1997
 *
 ************************************************************
 *
 *     The program normally runs for about 100 seconds
 *     (adjustable in main - variable duration). This time
 *     is necessary because of poor PC clock resolution.
 *     The original concept included such things as a given
 *     number of subroutine calls and divides which may be
 *     changed by optimisation. For comparison purposes the
 *     compiler and level of optimisation should be identified.
 *       
 ************************************************************
 *
 *     The original benchmark had a single variable I which
 *     controlled the running time. Constants with values up
 *     to 899 were multiplied by I to control the number
 *     passes for each loop. It was found that large values
 *     of I could overflow index registers so an extra outer
 *     loop with a second variable J was added.
 *
 *     Self timing versions were produced during the early
 *     days. The 1978 changes supplied timings of individual
 *     loops and these were used later to produce MFLOPS and
 *     MOPS ratings.
 *
 *     1987 changes converted the benchmark to Fortran 77
 *     standards and removed redundant IF statements and
 *     loops to leave the 8 active loops N1 to N8. Procedure
 *     P3 was changed to use global variables to avoid over-
 *     optimisation with the first two statements changed from
 *     X1=X and Y1=Y to X=Y and Y=Z. A self time calibrating
 *     version for PCs was also produced, the facility being
 *     incorporated in this version.
 *
 *     This version has changes to avoid worse than expected
 *     speed ratings, due to underflow, and facilities to show
 *     that consistent numeric output is produced with varying
 *     optimisation levels or versions in different languages.
 *
 *     Some of the procedures produce ever decreasing numbers.
 *     To avoid problems, variables T and T1 have been changed
 *     from 0.499975 and 0.50025 to 0.49999975 and 0.50000025.
 *
 *     Each section now has its own double loop. Inner loops
 *     are run 100 times the loop constants. Calibration
 *     determines the number of outer loop passes. The
 *     numeric results produced in the main output are for
 *     one pass on the outer loop. As underflow problems were
 *     still likely on a processor 100 times faster than a 100
 *     MHZ Pentium, three sections have T=1.0-T inserted in the
 *     outer loop to avoid the problem. The two loops avoid
 *     index register overflows.
 *
 *     The first section is run ten times longer than required
 *     for accuracy in calculating MFLOPS. This time is divided
 *     by ten for inclusion in the MWIPS calculations.
 *
 *     This version has facilities for typing in details of the
 *     particular run. This information is appended to file
 *     whets.res along with the results. The input section can
 *     be avoided using a command line parameter N (for example
 *     Whets.exe N).  
 *
 *     Roy Longbottom  101323.2241@compuserve.com
 *
 ************************************************************
 *
 *     Whetstone benchmark results are available in whets.tbl
 *     from ftp.nosc.mil/pub/aburto. The results include
 *     further details of the benchmarks.
 *
 ************************************************************
 *
 *     Source code is available in C/C++, Fortran, Basic and
 *     Visual Basic in the same format as this version. Pre-
 *     compiled versions for PCs are also available via C++.
 *     These comprise optimised and non-optimised versions
 *     for DOS, Windows and NT.
 *
 *     This version compiles and runs correctly either as a
 *     C or CPP program with a WATCOM and Borland compiler.
 *
 ************************************************************
 *
 * Example of initial calibration display (Pentium 100 MHz)
 *
 * Single Precision C/C++ Whetstone Benchmark
 *
 * Calibrate
 *      0.17 Seconds          1   Passes (x 100)
 *      0.77 Seconds          5   Passes (x 100)
 *      3.70 Seconds         25   Passes (x 100)
 *
 * Use 676  passes (x 100)
 *
 * 676 passes are used for an approximate duration of 100
 * seconds, providing an initial estimate of a speed rating
 * of 67.6 MWIPS.
 *
 * This is followed by the table of results as below. Input
 * statements are then supplied to type in the run details.
 *
 ************************************************************
 * 
 * Examples of results from file whets.res
 *
 * Whetstone Single  Precision Benchmark in C/C++
 *
 * Month run         4/1996
 * PC model          Escom
 * CPU               Pentium
 * Clock MHz         100
 * Cache             256K
 * H/W Options       Neptune chipset
 * OS/DOS            Windows 95
 * Compiler          Watcom C/C++ 10.5  Win386
 * Options           No optimisation
 * Run by            Roy Longbottom
 * From              UK
 * Mail              101323.2241@compuserve.com
 *
 * Loop content                 Result            MFLOPS     MOPS   Seconds
 *
 * N1 floating point    -1.12475025653839100      19.971              0.274
 * N2 floating point    -1.12274754047393800      11.822              3.240
 * N3 if then else       1.00000000000000000               11.659     2.530
 * N4 fixed point       12.00000000000000000               13.962     6.430
 * N5 sin,cos etc.       0.49904659390449520                2.097    11.310
 * N6 floating point     0.99999988079071040       3.360             45.750
 * N7 assignments        3.00000000000000000                2.415    21.810
 * N8 exp,sqrt etc.      0.75110864639282230                1.206     8.790
 *
 * MWIPS                                          28.462            100.134
 *
 * Whetstone Single  Precision Benchmark in C/C++
 *
 * Compiler          Watcom C/C++ 10.5  Win386
 * Options           -otexan -zp4 -om -fp5 -5r
 *
 * Loop content                 Result            MFLOPS     MOPS   Seconds
 *
 * N1 floating point    -1.12475025653839100      26.751              0.478
 * N2 floating point    -1.12274754047393800      17.148              5.220
 * N3 if then else       1.00000000000000000               19.922     3.460
 * N4 fixed point       12.00000000000000000               15.978    13.130
 * N5 sin,cos etc.       0.49904659390449520                2.663    20.810
 * N6 floating point     0.99999988079071040      10.077             35.650
 * N7 assignments        3.00000000000000000               22.877     5.380
 * N8 exp,sqrt etc.      0.75110864639282230                1.513    16.370
 *
 * MWIPS                                          66.270            100.498
 *
 *
 * Whetstone Double  Precision Benchmark in C/C++
 *
 * Compiler          Watcom C/C++ 10.5 Win32NT 
 * Options           -otexan -zp4 -om -fp5 -5r
 *
 * Loop content                 Result           MFLOPS      MOPS   Seconds
 *
 * N1 floating point    -1.12398255667391900     26.548               0.486
 * N2 floating point    -1.12187079889284400     16.542               5.460
 * N3 if then else       1.00000000000000000               19.647     3.540
 * N4 fixed point       12.00000000000000000               15.680    13.500
 * N5 sin,cos etc.       0.49902937281515140                3.019    18.520
 * N6 floating point     0.99999987890802820      9.977              36.330
 * N7 assignments        3.00000000000000000               22.620     5.490
 * N8 exp,sqrt etc.      0.75100163018457870                1.493    16.740
 *
 * MWIPS                                         67.156             100.066
 *
 *  Note different numeric results to single precision. Slight variations
 *  are normal with different compilers and sometimes optimisation levels. 
 *
 *
 *             Example Single Precision Optimised Results
 *
 *     MWIPS   MFLOPS  MFLOPS  MFLOPS  COS     EXP     FIXPT    IF    EQUAL
 * PC            1       2       3     MOPS    MOPS    MOPS    MOPS    MOPS
 *                                                                                                                                                
 * P3  5.68    0.928   0.884   0.673   0.461   0.275   2.36    2.16   0.638
 * P4  16.4    5.09    4.03    2.66    0.526   0.342   6.36    6.00    5.28
 * P5  66.3    26.8    17.1    10.1    2.66    1.51    16.0    19.9    22.9
 * P6  161     50.3    45.2    31.5    4.46    2.77    102     20.6    119
 *
 *            Example Single Precision Non-optimised Results
 *                                                                        
 * P3  3.07    0.860   0.815   0.328   0.355   0.160   1.70    1.32   0.264
 * P4  10.0    4.68    3.51    1.27    0.482   0.298   5.73    5.20    1.18
 * P5  28.5    20.0    11.8    3.36    2.10    1.21    14.0    11.7    2.42
 * P6  81.7    47.5    37.8    10.9    3.91    2.43    51.2    42.8    7.85
 *
 *        Summary results as in whets.tbl at ftp.nosc.mil/pub/aburto 
 *
 *           MFLOPS   = Geometric Mean of three MFLOPS loops
 *           VAX MIPS = 5 * Geometric Mean of last three items above
 *
 *                                                                     VAX
 * PC System  CPU/Options               Cache   MHz   MWIPS   MFLOPS  MIPS
 *
 * P3 Clone   AM80386DX with 387        128K    40    5.68    0.820   7.40
 * P4 Escom   80486DX2 CIS chipset      128K    66    16.4    3.79    29.3
 * P5 Escom   Pentium Neptune chipset   256K   100    66.3    16.7    96.9
 * P6 Dell    PentiumPro 440FX PCIset   256K   200    161     41.5    315 
 *
 * P3 Clone   AM80386DX with 387        128K    40    3.07    0.613   4.20
 * P4 Escom   80486DX2 CIS chipset      128K    66    10.0    2.75    16.4
 * P5 Escom   Pentium Neptune chipset   256K   100    28.5    9.26    36.6
 * P6 Dell    PentiumPro 440FX PCIset   256K   200    81.7    26.9    129
 *
 **************************************************************************
 *
 *                       Running Instructions
 *
 *      1.  In order to compile successfully, include timer option as
 *          indicated below.
 *      2.  If pre-compiled codes are to be distributed, compile with the
 *          -DPRECOMP option or uncomment #define PRECOMP at PRECOMPILE
 *          below. Also insert compiler name and optimisation details
 *          at #define precompiler and #define preoptions.
 *      3.  Compile and run for single precision results. Include run
 *          time parameter N to bipass typing in hardware details etc.
 *      4.  Compile with -DDP option or uncomment #define DP at PRECISION
 *          below and run for double precision results.
 *      5.  Run with maximum and no optimisation (minimum debug)
 *      6.  Notify Roy Longbottom of other necessary changes
 *      7.  Send results file whets.res to Roy Longbottom - with one
 *          sample of each run and system details fully completed
 *
 *      Roy Longbottom  101323.2241@compuserve.com    6 November 1996
 *
 **************************************************************************
 */
 
 #include <math.h>       /* for sin, exp etc.           */
 #include <stdio.h>      /* standard I/O                */ 
 #include <string.h>     /* for strcpy - 3 occurrences  */
 #include <stdlib.h>     /* for exit   - 1 occurrence   */

/***************************************************************/
/* Timer options. You MUST uncomment one of the options below  */
/* or compile, for example, with the '-DUNIX' option.          */
/***************************************************************/
/* #define Amiga       */
/* #define UNIX        */
/* #define UNIX_Old    */
/* #define VMS         */
/* #define BORLAND_C   */
/* #define MSC         */
/* #define MAC         */
/* #define IPSC        */
/* #define FORTRAN_SEC */
/* #define GTODay      */
/* #define CTimer      */
/* #define UXPM        */
/* #define MAC_TMgr    */
/* #define PARIX       */
/* #define POSIX       */
/* #define WIN32       */
/* #define POSIX1      */
/***********************/
 
/*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/

 /* #define DP */
 
 #ifdef DP 
    #define SPDP double
    #define Precision "Double"
 #else
    #define SPDP float
    #define Precision "Single"
 #endif


/*PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE*/

 /* #define PRECOMP */
 
 #ifdef PRECOMP 
    #define precompiler "INSERT COMPILER NAME HERE"
    #define preoptions  "INSERT OPTIMISATION OPTIONS HERE"
 #endif


 void whetstones(long xtra, long x100, int calibrate);  
 void pa(SPDP e[4], SPDP t, SPDP t2);
 void po(SPDP e1[4], long j, long k, long l);
 void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2);
 void pout(char title[22], float ops, int type, SPDP checknum,
		  SPDP time, int calibrate, int section);
  

 static SPDP loop_time[9];
 static SPDP loop_mops[9];
 static SPDP loop_mflops[9];
 static SPDP TimeUsed;
 static SPDP mwips;
 static char headings[9][18];
 static SPDP Check;
 static SPDP results[9];

int main(argc, argv)
int	argc;
char	*argv[];
{
    int count = 10, calibrate = 1;
    long xtra = 1;
    long x100 = 100;
#ifdef UNIXBENCH
    int duration = 10;
#else
    int section;
    int duration = 100;
    FILE *outfile;
    int getinput = 1;
    char compiler[80] = " ", options[256] = " ", general[10][80] = {" "};
    char *endit = " ";
#endif
  
    printf("##########################################\n"); 
    printf("%s Precision C/C++ Whetstone Benchmark\n\n", Precision);


#ifndef UNIXBENCH
    if (argc > 1)
     {
	switch (argv[1][0])
	{
	     case 'N':
	     case 'n':
	       getinput = 0;
	       break;
	}
     }
   if (! getinput)
    {
       printf ("No run time input data\n\n");
    }
    
    outfile = fopen("whets.res","a+");
    if (outfile == NULL)
      {
       printf ("Cannot open results file \n\n");
       printf("Press RETURN to exit\n");
       gets(endit);
       exit (0);
      }
#endif
	    
  printf("Calibrate\n");
  do
   {
    TimeUsed=0;
	    
    whetstones(xtra,x100,calibrate);
	    
    printf("%11.2f Seconds %10.0f   Passes (x 100)\n", TimeUsed, (SPDP)(xtra));
    calibrate++;
    count--;

#ifndef UNIXBENCH
    if (TimeUsed > 2.0)
#else
    if (TimeUsed > 0.5)
#endif
      {
       count = 0;
      }
       else
      {
       xtra = xtra * 5;
      }
   }
   
   while (count > 0);
       
   if (TimeUsed > 0) xtra = (long)((SPDP)(duration * xtra) / TimeUsed);
   if (xtra < 1) xtra = 1;
       
   calibrate = 0;
  
   printf("\nUse %ld  passes (x 100)\n", xtra);

   printf("\n          %s Precision C/C++ Whetstone Benchmark",Precision);
   
   #ifdef PRECOMP
      printf("\n          Compiler  %s", precompiler);
      printf("\n          Options   %s\n", preoptions);
   #else
      printf("\n");
   #endif
   
   printf("\nLoop content                  Result              MFLOPS "
				"     MOPS   Seconds\n\n");

   TimeUsed=0;
   whetstones(xtra,x100,calibrate);

   printf("\nMWIPS            ");
   if (TimeUsed>0)
     {
      mwips=(float)(xtra) * (float)(x100) / (10 * TimeUsed);
     }
      else
     {
      mwips = 0;
     }  
   
   printf("%39.3f%19.3f\n\n",mwips,TimeUsed);
     
   if (Check == 0) printf("Wrong answer  ");

	    

 /************************************************************************/
 /*             Type details of hardware, software etc.                  */
 /************************************************************************/

#ifndef UNIXBENCH
 if (getinput)
   {
     printf ("Enter the following which will be added with results to file WHETS.RES\n");
     printf ("When submitting a number of results you need only provide details once\n");
     printf ("but a cross reference such as an abbreviated CPU type would be useful.\n");    
     printf ("You can kill (exit or close) the program now and no data will be added.\n\n");
    
     printf ("Date:       ");
     gets(general[0]);
    
     printf ("Computer:   ");
     gets(general[1]);
    
     printf ("CPU chip:   ");
     gets(general[2]);
     
     printf ("Clock MHz:  ");
     gets(general[3]);
     
     printf ("Cache size: ");
     gets(general[4]);
     
     printf ("H/W options:");
     gets(general[5]);
      
     printf ("OS version: ");
     gets(general[6]);
    
     #ifdef PRECOMP
	strcpy (compiler, precompiler);
	strcpy (options, preoptions);
     #else
	printf ("Compiler:   ");
	gets(compiler);
    
	printf ("Options:    ");
	gets(options);
     #endif
     
     printf ("Your name:  ");
     gets(general[7]);
     
     printf ("From:       ");
     gets(general[8]);
     
     printf ("Email:      ");
     gets(general[9]);
   }
  else
   {
     #ifdef PRECOMP
	strcpy (compiler, precompiler);
	strcpy (options, preoptions);
     #endif
   }

 /************************************************************************/
 /*               Add results to output file whets.res                   */
 /************************************************************************/
 fprintf (outfile, "\n"); 
 fprintf (outfile, "##############################################\n");
 fprintf (outfile, "Whetstone %s  Precision Benchmark in C/C++\n\n",Precision);
 fprintf (outfile, "Date         %s\n", general[0]);
 fprintf (outfile, "Model        %s\n", general[1]);
 fprintf (outfile, "CPU          %s\n", general[2]);
 fprintf (outfile, "Clock MHz    %s\n", general[3]);
 fprintf (outfile, "Cache        %s\n", general[4]);
 fprintf (outfile, "H/W options  %s\n", general[5]);
 fprintf (outfile, "OS           %s\n", general[6]);
 fprintf (outfile, "Compiler     %s\n", compiler);
 fprintf (outfile, "Options      %s\n", options);
 fprintf (outfile, "Run by       %s\n", general[7]);
 fprintf (outfile, "From         %s\n", general[8]);
 fprintf (outfile, "Email        %s\n", general[9]);
 fprintf (outfile, "\n");

 fprintf (outfile,"Loop content                   Result"
	    "              MFLOPS      MOPS   Seconds\n\n"); 
			   
 for (section=1; section<9; section++)
    {
     fprintf (outfile, "%s  %24.17f   ", headings[section],
					      results[section]);
     if (loop_mops[section] == 99999)
       {          
	fprintf (outfile,"  %9.3f           %9.3f\n",
		 loop_mflops[section], loop_time[section]);
       }
       else
       {       
	fprintf (outfile, "            %9.3f %9.3f\n",
	     loop_mops[section], loop_time[section], results[section]);
       }
    }

 fprintf (outfile, "\nMWIPS             ");
 fprintf (outfile, "%39.3f%20.3f\n\n",mwips,TimeUsed);
 fprintf (outfile, "Results  to  load  to  spreadsheet             ");
 fprintf (outfile, "     MWIPS   Mflops1   Mflops2   Mflops3   Cosmops"
		      "   Expmops  Fixpmops    Ifmops    Eqmops\n");
 fprintf (outfile, "Results  to  load  to  spreadsheet             ");   
		
 fprintf (outfile, " %9.3f %9.3f %9.3f", mwips, loop_mflops[1],
							 loop_mflops[2]);
 fprintf (outfile, " %9.3f %9.3f %9.3f", loop_mflops[6],
					     loop_mops[5], loop_mops[8]);
 fprintf (outfile, " %9.3f %9.3f %9.3f\n\n", loop_mops[4],
					      loop_mops[3], loop_mops[7]);
    
 fclose (outfile);

 printf ("\n");
 printf ("A new results file will have been created in the same directory as the\n");
 printf (".EXE files if one did not already exist. If you made a mistake on input, \n");
 printf ("you can use a text editor to correct it, delete the results or copy \n");
 printf ("them to a different file name. If you intend to run multiple tests you\n");
 printf ("you may wish to rename WHETS.RES with a more informative title.\n\n");
 printf ("Please submit feedback and results files to aburto@nosc.mil or to\n");
 printf ("Roy_Longbottom@compuserve.com\n\n");

#else	/* Unixbench */
	fprintf (stderr, "MWIPS%39.3f%20.3f\n", mwips, TimeUsed);
	exit(0);
#endif
}

    void whetstones(long xtra, long x100, int calibrate)
      {

	long n1,n2,n3,n4,n5,n6,n7,n8,i,ix,n1mult;
	SPDP x,y,z;              
	long j,k,l;
	SPDP e1[4],timea,timeb, dtime();
			
	SPDP t =  0.49999975;
	SPDP t0 = t;        
	SPDP t1 = 0.50000025;
	SPDP t2 = 2.0;
		
	Check=0.0;
       
	n1 = 12*x100;
	n2 = 14*x100;
	n3 = 345*x100;
	n4 = 210*x100;
	n5 = 32*x100;
	n6 = 899*x100;
	n7 = 616*x100;
	n8 = 93*x100;
	n1mult = 10;

	/* Section 1, Array elements */

	e1[0] = 1.0;
	e1[1] = -1.0;
	e1[2] = -1.0;
	e1[3] = -1.0;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0; i<n1*n1mult; i++)
		  {
		      e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
		      e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
		      e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
		      e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
		  }
		t = 1.0 - t;
	      }
	    t =  t0;                    
	 }
	timeb = (dtime()-timea)/(SPDP)(n1mult);
	pout("N1 floating point\0",(float)(n1*16)*(float)(xtra),
			     1,e1[3],timeb,calibrate,1);

	/* Section 2, Array as parameter */

	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      { 
		for(i=0; i<n2; i++)
		  {
		     pa(e1,t,t2);
		  }
		t = 1.0 - t;
	      }
	    t =  t0;
	 }
	timeb = dtime()-timea;
	pout("N2 floating point\0",(float)(n2*96)*(float)(xtra),
			     1,e1[3],timeb,calibrate,2);

	/* Section 3, Conditional jumps */
	j = 1;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0; i<n3; 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;
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N3 if then else  \0",(float)(n3*3)*(float)(xtra),
			2,(SPDP)(j),timeb,calibrate,3);

	/* Section 4, Integer arithmetic */
	j = 1;
	k = 2;
	l = 3;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0; i<n4; i++)
		  {
		     j = j *(k-j)*(l-k);
		     k = l * k - (l-j) * k;
		     l = (l-k) * (k+j);
		     e1[l-2] = j + k + l;
		     e1[k-2] = j * k * l;
		  }
	      }
	 }
	timeb = dtime()-timea;
	x = e1[0]+e1[1];
	pout("N4 fixed point   \0",(float)(n4*15)*(float)(xtra),
				 2,x,timeb,calibrate,4);
     
	/* Section 5, Trig functions */
	x = 0.5;
	y = 0.5;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=1; i<n5; 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));
		  }
		t = 1.0 - t;
	      }
	    t = t0;
	 }
	timeb = dtime()-timea;
	pout("N5 sin,cos etc.  \0",(float)(n5*26)*(float)(xtra),
				 2,y,timeb,calibrate,5);
  
	/* Section 6, Procedure calls */
	x = 1.0;
	y = 1.0;
	z = 1.0;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0; i<n6; i++)
		  {
		     p3(&x,&y,&z,t,t1,t2);
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N6 floating point\0",(float)(n6*6)*(float)(xtra),
				1,z,timeb,calibrate,6);
  
	/* Section 7, Array refrences */
	j = 0;
	k = 1;
	l = 2;
	e1[0] = 1.0;
	e1[1] = 2.0;
	e1[2] = 3.0;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0;i<n7;i++)
		  {
		     po(e1,j,k,l);
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N7 assignments   \0",(float)(n7*3)*(float)(xtra),
			    2,e1[2],timeb,calibrate,7);
	
	/* Section 8, Standard functions */
	x = 0.75;
	timea = dtime();
	 {
	    for (ix=0; ix<xtra; ix++)
	      {
		for(i=0; i<n8; i++)
		  {
		     x = sqrt(exp(log(x)/t1));
		  }
	      }
	 }
	timeb = dtime()-timea;
	pout("N8 exp,sqrt etc. \0",(float)(n8*4)*(float)(xtra),
				2,x,timeb,calibrate,8);

	return;
      }


    void pa(SPDP e[4], SPDP t, SPDP t2)
      {
	 long j;
	 for(j=0;j<6;j++)
	    {
	       e[0] = (e[0]+e[1]+e[2]-e[3])*t;
	       e[1] = (e[0]+e[1]-e[2]+e[3])*t;
	       e[2] = (e[0]-e[1]+e[2]+e[3])*t;
	       e[3] = (-e[0]+e[1]+e[2]+e[3])/t2;
	    }

	 return;
      }

    void po(SPDP e1[4], long j, long k, long l)
      {
	 e1[j] = e1[k];
	 e1[k] = e1[l];
	 e1[l] = e1[j];
	 return;
      }

    void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2)
      {
	 *x = *y;
	 *y = *z;
	 *x = t * (*x + *y);
	 *y = t1 * (*x + *y);
	 *z = (*x + *y)/t2;
	 return;
      }


    void pout(char title[18], float ops, int type, SPDP checknum,
	      SPDP time, int calibrate, int section)
      {
	SPDP mops,mflops;

	Check = Check + checknum;
	loop_time[section] = time;
	strcpy (headings[section],title);
	TimeUsed =  TimeUsed + time;
	if (calibrate == 1)
     
	  {
	      results[section] = checknum;
	  }
	if (calibrate == 0)
	  {              
	    printf("%s %24.17f    ",headings[section],results[section]);    
       
	    if (type == 1)
	     {
		if (time>0)
		 {
		    mflops = ops/(1000000L*time);
		 }
		else
		 {
		   mflops = 0;
		 }
		loop_mops[section] = 99999;
		loop_mflops[section] = mflops;
		printf(" %9.3f          %9.3f\n",
		 loop_mflops[section], loop_time[section]);                
	     }
	    else
	     {
		if (time>0)
		 {
		   mops = ops/(1000000L*time);
		 }
		else
		 {
		   mops = 0;
		 }
		loop_mops[section] = mops;
		loop_mflops[section] = 0;                 
		printf("           %9.3f%9.3f\n",
		 loop_mops[section], loop_time[section]);
	     }
	  }
	  
	return;
      }


/*****************************************************/
/* Various timer routines.                           */
/* Al Aburto, aburto@nosc.mil, 18 Feb 1997           */
/*                                                   */
/* t = dtime() outputs the current time in seconds.  */
/* Use CAUTION as some of these routines will mess   */
/* up when timing across the hour mark!!!            */
/*                                                   */
/* For timing I use the 'user' time whenever         */
/* possible. Using 'user+sys' time is a separate     */
/* issue.                                            */
/*                                                   */
/* Example Usage:                                    */
/* [timer options added here]                        */
/* main()                                            */
/* {                                                 */
/*  double starttime,benchtime,dtime();              */
/*                                                   */
/*  starttime = dtime();                             */ 
/*  [routine to time]                                */
/*  benchtime = dtime() - starttime;                 */
/* }                                                 */
/*                                                   */
/* [timer code below added here]                     */
/*****************************************************/

/*********************************/
/* Timer code.                   */
/*********************************/
/*******************/
/*  Amiga dtime()  */
/*******************/
#ifdef Amiga
#include <ctype.h>
#define HZ 50

SPDP dtime()
{
 SPDP q;

 struct tt
       {
	long  days;
	long  minutes;
	long  ticks;
       } tt;

 DateStamp(&tt);

 q = ((SPDP)(tt.ticks + (tt.minutes * 60L * 50L))) / (SPDP)HZ;

 return q;
}
#endif

/*****************************************************/
/*  UNIX dtime(). This is the preferred UNIX timer.  */
/*  Provided by: Markku Kolkka, mk59200@cc.tut.fi    */
/*  HP-UX Addition by: Bo Thide', bt@irfu.se         */
/*****************************************************/
#ifdef UNIX
#include <sys/time.h>
#include <sys/resource.h>

#ifdef hpux
#include <sys/syscall.h>
#define getrusage(a,b) syscall(SYS_getrusage,a,b)
#endif

struct rusage rusage;

SPDP dtime()
{
 SPDP q;

 getrusage(RUSAGE_SELF,&rusage);

 q = (SPDP)(rusage.ru_utime.tv_sec);
 q = q + (SPDP)(rusage.ru_utime.tv_usec) * 1.0e-06;
	
 return q;
}
#endif

/***************************************************/
/*  UNIX_Old dtime(). This is the old UNIX timer.  */
/*  Use only if absolutely necessary as HZ may be  */
/*  ill defined on your system.                    */
/***************************************************/
#ifdef UNIX_Old
#include <sys/types.h>
#include <sys/times.h>
#include <sys/param.h>

#ifndef HZ
#define HZ 60
#endif

struct tms tms;

SPDP dtime()
{
 SPDP q;

 times(&tms);

 q = (SPDP)(tms.tms_utime) / (SPDP)HZ;
	
 return q;
}
#endif

/*********************************************************/
/*  VMS dtime() for VMS systems.                         */
/*  Provided by: RAMO@uvphys.phys.UVic.CA                */
/*  Some people have run into problems with this timer.  */
/*********************************************************/
#ifdef VMS
#include time

#ifndef HZ
#define HZ 100
#endif

struct tbuffer_t
       {
	int proc_user_time;
	int proc_system_time;
	int child_user_time;
	int child_system_time;
       };
struct tbuffer_t tms;

SPDP dtime()
{
 SPDP q;

 times(&tms);

 q = (SPDP)(tms.proc_user_time) / (SPDP)HZ;
	
 return q;
}
#endif

/******************************/
/*  BORLAND C dtime() for DOS */
/******************************/
#ifdef BORLAND_C
#include <ctype.h>
#include <dos.h>
#include <time.h>

#define HZ 100
struct time tnow;

SPDP dtime()
{
 SPDP q;

 gettime(&tnow);

 q = 60.0 * (SPDP)(tnow.ti_min);
 q = q + (SPDP)(tnow.ti_sec);
 q = q + (SPDP)(tnow.ti_hund)/(SPDP)HZ;
	
 return q;
}
#endif

/***************************************/
/*  Microsoft C (MSC) dtime() for DOS  */
/*  Also suitable for Watcom C/C++ and */
/*  some other PC compilers            */
/***************************************/
#ifdef MSC
#include <time.h>
#include <ctype.h>

#define HZ CLOCKS_PER_SEC
clock_t tnow;

SPDP dtime()
{
 SPDP q;

 tnow = clock();
 q = (SPDP)tnow / (SPDP)HZ;
 return q;
}
#endif

/*************************************/
/*  Macintosh (MAC) Think C dtime()  */
/*************************************/
#ifdef MAC
#include <time.h>

#define HZ 60

SPDP dtime()
{
 SPDP q;

 q = (SPDP)clock() / (SPDP)HZ;
	
 return q;
}
#endif

/************************************************************/
/*  iPSC/860 (IPSC) dtime() for i860.                       */
/*  Provided by: Dan Yergeau, yergeau@gloworm.Stanford.EDU  */
/************************************************************/
#ifdef IPSC
extern double dclock();

SPDP dtime()
{
 SPDP q;

 q = dclock();
	
 return q;
}
#endif

/**************************************************/
/*  FORTRAN dtime() for Cray type systems.        */
/*  This is the preferred timer for Cray systems. */
/**************************************************/
#ifdef FORTRAN_SEC

fortran double second();

SPDP dtime()
{
 SPDP q;

 second(&q);
	
 return q;
}
#endif

/***********************************************************/
/*  UNICOS C dtime() for Cray UNICOS systems.  Don't use   */
/*  unless absolutely necessary as returned time includes  */
/*  'user+system' time.  Provided by: R. Mike Dority,      */
/*  dority@craysea.cray.com                                */
/***********************************************************/
#ifdef CTimer
#include <time.h>

SPDP dtime()
{
 SPDP q;
 clock_t   clock(void);

 q = (SPDP)clock() / (SPDP)CLOCKS_PER_SEC;

 return q;
}
#endif

/********************************************/
/* Another UNIX timer using gettimeofday(). */
/* However, getrusage() is preferred.       */
/********************************************/
#ifdef GTODay
#include <sys/time.h>

struct timeval tnow;

SPDP dtime()
{
 SPDP q;

 gettimeofday(&tnow,NULL);
 q = (SPDP)tnow.tv_sec + (SPDP)tnow.tv_usec * 1.0e-6;

 return q;
}
#endif

/*****************************************************/
/*  Fujitsu UXP/M timer.                             */
/*  Provided by: Mathew Lim, ANUSF, M.Lim@anu.edu.au */
/*****************************************************/
#ifdef UXPM
#include <sys/types.h>
#include <sys/timesu.h>
struct tmsu rusage;

SPDP dtime()
{
 SPDP q;

 timesu(&rusage);

 q = (SPDP)(rusage.tms_utime) * 1.0e-06;
	
 return q;
}
#endif

/**********************************************/
/*    Macintosh (MAC_TMgr) Think C dtime()    */
/*   requires Think C Language Extensions or  */
/*    #include <MacHeaders> in the prefix     */
/*  provided by Francis H Schiffer 3rd (fhs)  */
/*         skipschiffer@genie.geis.com        */
/**********************************************/
#ifdef MAC_TMgr
#include <Timer.h>
#include <stdlib.h>

static TMTask   mgrTimer;
static Boolean  mgrInited = false;
static SPDP     mgrClock;

#define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer )
#define MAX_TIME  1800000000L
/* MAX_TIME limits time between calls to */
/* dtime( ) to no more than 30 minutes   */
/* this limitation could be removed by   */
/* creating a completion routine to sum  */
/* 30 minute segments (fhs 1994 feb 9)   */

static void Remove_timer( )
{
 RMV_TIMER;
 mgrInited = false;
}

SPDP dtime( )
{
 if( mgrInited ) {
	RMV_TIMER;
	mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6;
 } else {
	if( _atexit( &Remove_timer ) == 0 ) mgrInited = true;
	mgrClock = 0.0;
}
	if( mgrInited ) {
		mgrTimer.tmAddr = NULL;
		mgrTimer.tmCount = 0;
		mgrTimer.tmWakeUp = 0;
		mgrTimer.tmReserved = 0;
		InsTime( (QElemPtr)&mgrTimer );
		PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME );
	}
	return( mgrClock );
}
#endif

/***********************************************************/
/*  Parsytec GCel timer.                                   */
/*  Provided by: Georg Wambach, gw@informatik.uni-koeln.de */
/***********************************************************/
#ifdef PARIX
#include <sys/time.h>

SPDP dtime()
{
 SPDP q;

 q = (SPDP) (TimeNowHigh()) / (SPDP) CLK_TCK_HIGH;

 return q;
}
#endif

/************************************************/
/*  Sun Solaris POSIX dtime() routine           */
/*  Provided by: Case Larsen, CTLarsen.lbl.gov  */
/************************************************/
#ifdef POSIX
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/rusage.h>

#ifdef __hpux
#include <sys/syscall.h>
#endif

struct rusage rusage;

SPDP dtime()
{
 SPDP q;

 getrusage(RUSAGE_SELF,&rusage);

 q = (SPDP)(rusage.ru_utime.tv_sec);
 q = q + (SPDP)(rusage.ru_utime.tv_nsec) * 1.0e-09;
	
 return q;
}
#endif


/****************************************************/
/*  Windows NT (32 bit) dtime() routine             */
/*  Provided by: Piers Haken, piersh@microsoft.com  */
/****************************************************/
#ifdef WIN32
#include <windows.h>

SPDP dtime(void)
{
 SPDP q;

 q = (SPDP)GetTickCount() * 1.0e-03;
	
 return q;
}
#endif

/*****************************************************/
/* Time according to POSIX.1  -  <J.Pelan@qub.ac.uk> */
/* Ref: "POSIX Programmer's Guide"  O'Reilly & Assoc.*/
/*****************************************************/
#ifdef POSIX1
#define _POSIX_SOURCE 1
#include <unistd.h>
#include <limits.h>
#include <sys/times.h>

struct tms tms;

SPDP dtime()
{
 SPDP q;
 times(&tms);
 q = (SPDP)tms.tms_utime / (SPDP)CLK_TCK;
 return q;
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1