1 /**********************************************************/
2 /* Date: Mon, 10 Mar 1997 07:38:18 -0500                  */
3 /* From: Roy Longbottom <Roy_Longbottom@compuserve.com>   */
4 /* Subject: WHET02.txt                                    */
5 /* To: "Alfred A. Aburto Jr." <aburto@cts.com>            */
6 /**********************************************************/
7 
8 /*
9  *     C/C++ Whetstone Benchmark Single or Double Precision
10  *
11  *     Original concept        Brian Wichmann NPL      1960's
12  *     Original author         Harold Curnow  CCTA     1972
13  *     Self timing versions    Roy Longbottom CCTA     1978/87
14  *     Optimisation control    Bangor University       1987/90
15  *     C/C++ Version           Roy Longbottom          1996
16  *     Compatibility & timers  Al Aburto               1996
17  *
18  ************************************************************
19  *
20  *              Official version approved by:
21  *
22  *         Harold Curnow  100421.1615@compuserve.com
23  *
24  *      Happy 25th birthday Whetstone, 21 November 1997
25  *
26  ************************************************************
27  *
28  *     The program normally runs for about 100 seconds
29  *     (adjustable in main - variable duration). This time
30  *     is necessary because of poor PC clock resolution.
31  *     The original concept included such things as a given
32  *     number of subroutine calls and divides which may be
33  *     changed by optimisation. For comparison purposes the
34  *     compiler and level of optimisation should be identified.
35  *
36  ************************************************************
37  *
38  *     The original benchmark had a single variable I which
39  *     controlled the running time. Constants with values up
40  *     to 899 were multiplied by I to control the number
41  *     passes for each loop. It was found that large values
42  *     of I could overflow index registers so an extra outer
43  *     loop with a second variable J was added.
44  *
45  *     Self timing versions were produced during the early
46  *     days. The 1978 changes supplied timings of individual
47  *     loops and these were used later to produce MFLOPS and
48  *     MOPS ratings.
49  *
50  *     1987 changes converted the benchmark to Fortran 77
51  *     standards and removed redundant IF statements and
52  *     loops to leave the 8 active loops N1 to N8. Procedure
53  *     P3 was changed to use global variables to avoid over-
54  *     optimisation with the first two statements changed from
55  *     X1=X and Y1=Y to X=Y and Y=Z. A self time calibrating
56  *     version for PCs was also produced, the facility being
57  *     incorporated in this version.
58  *
59  *     This version has changes to avoid worse than expected
60  *     speed ratings, due to underflow, and facilities to show
61  *     that consistent numeric output is produced with varying
62  *     optimisation levels or versions in different languages.
63  *
64  *     Some of the procedures produce ever decreasing numbers.
65  *     To avoid problems, variables T and T1 have been changed
66  *     from 0.499975 and 0.50025 to 0.49999975 and 0.50000025.
67  *
68  *     Each section now has its own double loop. Inner loops
69  *     are run 100 times the loop constants. Calibration
70  *     determines the number of outer loop passes. The
71  *     numeric results produced in the main output are for
72  *     one pass on the outer loop. As underflow problems were
73  *     still likely on a processor 100 times faster than a 100
74  *     MHZ Pentium, three sections have T=1.0-T inserted in the
75  *     outer loop to avoid the problem. The two loops avoid
76  *     index register overflows.
77  *
78  *     The first section is run ten times longer than required
79  *     for accuracy in calculating MFLOPS. This time is divided
80  *     by ten for inclusion in the MWIPS calculations.
81  *
82  *     This version has facilities for typing in details of the
83  *     particular run. This information is appended to file
84  *     whets.res along with the results. The input section can
85  *     be avoided using a command line parameter N (for example
86  *     Whets.exe N).
87  *
88  *     Roy Longbottom  101323.2241@compuserve.com
89  *
90  ************************************************************
91  *
92  *     Whetstone benchmark results are available in whets.tbl
93  *     from ftp.nosc.mil/pub/aburto. The results include
94  *     further details of the benchmarks.
95  *
96  ************************************************************
97  *
98  *     Source code is available in C/C++, Fortran, Basic and
99  *     Visual Basic in the same format as this version. Pre-
100  *     compiled versions for PCs are also available via C++.
101  *     These comprise optimised and non-optimised versions
102  *     for DOS, Windows and NT.
103  *
104  *     This version compiles and runs correctly either as a
105  *     C or CPP program with a WATCOM and Borland compiler.
106  *
107  ************************************************************
108  *
109  * Example of initial calibration display (Pentium 100 MHz)
110  *
111  * Single Precision C/C++ Whetstone Benchmark
112  *
113  * Calibrate
114  *      0.17 Seconds          1   Passes (x 100)
115  *      0.77 Seconds          5   Passes (x 100)
116  *      3.70 Seconds         25   Passes (x 100)
117  *
118  * Use 676  passes (x 100)
119  *
120  * 676 passes are used for an approximate duration of 100
121  * seconds, providing an initial estimate of a speed rating
122  * of 67.6 MWIPS.
123  *
124  * This is followed by the table of results as below. Input
125  * statements are then supplied to type in the run details.
126  *
127  ************************************************************
128  *
129  * Examples of results from file whets.res
130  *
131  * Whetstone Single  Precision Benchmark in C/C++
132  *
133  * Month run         4/1996
134  * PC model          Escom
135  * CPU               Pentium
136  * Clock MHz         100
137  * Cache             256K
138  * H/W Options       Neptune chipset
139  * OS/DOS            Windows 95
140  * Compiler          Watcom C/C++ 10.5  Win386
141  * Options           No optimisation
142  * Run by            Roy Longbottom
143  * From              UK
144  * Mail              101323.2241@compuserve.com
145  *
146  * Loop content                 Result            MFLOPS     MOPS   Seconds
147  *
148  * N1 floating point    -1.12475025653839100      19.971              0.274
149  * N2 floating point    -1.12274754047393800      11.822              3.240
150  * N3 if then else       1.00000000000000000               11.659     2.530
151  * N4 fixed point       12.00000000000000000               13.962     6.430
152  * N5 sin,cos etc.       0.49904659390449520                2.097    11.310
153  * N6 floating point     0.99999988079071040       3.360             45.750
154  * N7 assignments        3.00000000000000000                2.415    21.810
155  * N8 exp,sqrt etc.      0.75110864639282230                1.206     8.790
156  *
157  * MWIPS                                          28.462            100.134
158  *
159  * Whetstone Single  Precision Benchmark in C/C++
160  *
161  * Compiler          Watcom C/C++ 10.5  Win386
162  * Options           -otexan -zp4 -om -fp5 -5r
163  *
164  * Loop content                 Result            MFLOPS     MOPS   Seconds
165  *
166  * N1 floating point    -1.12475025653839100      26.751              0.478
167  * N2 floating point    -1.12274754047393800      17.148              5.220
168  * N3 if then else       1.00000000000000000               19.922     3.460
169  * N4 fixed point       12.00000000000000000               15.978    13.130
170  * N5 sin,cos etc.       0.49904659390449520                2.663    20.810
171  * N6 floating point     0.99999988079071040      10.077             35.650
172  * N7 assignments        3.00000000000000000               22.877     5.380
173  * N8 exp,sqrt etc.      0.75110864639282230                1.513    16.370
174  *
175  * MWIPS                                          66.270            100.498
176  *
177  *
178  * Whetstone Double  Precision Benchmark in C/C++
179  *
180  * Compiler          Watcom C/C++ 10.5 Win32NT
181  * Options           -otexan -zp4 -om -fp5 -5r
182  *
183  * Loop content                 Result           MFLOPS      MOPS   Seconds
184  *
185  * N1 floating point    -1.12398255667391900     26.548               0.486
186  * N2 floating point    -1.12187079889284400     16.542               5.460
187  * N3 if then else       1.00000000000000000               19.647     3.540
188  * N4 fixed point       12.00000000000000000               15.680    13.500
189  * N5 sin,cos etc.       0.49902937281515140                3.019    18.520
190  * N6 floating point     0.99999987890802820      9.977              36.330
191  * N7 assignments        3.00000000000000000               22.620     5.490
192  * N8 exp,sqrt etc.      0.75100163018457870                1.493    16.740
193  *
194  * MWIPS                                         67.156             100.066
195  *
196  *  Note different numeric results to single precision. Slight variations
197  *  are normal with different compilers and sometimes optimisation levels.
198  *
199  *
200  *             Example Single Precision Optimised Results
201  *
202  *     MWIPS   MFLOPS  MFLOPS  MFLOPS  COS     EXP     FIXPT    IF    EQUAL
203  * PC            1       2       3     MOPS    MOPS    MOPS    MOPS    MOPS
204  *
205  * P3  5.68    0.928   0.884   0.673   0.461   0.275   2.36    2.16   0.638
206  * P4  16.4    5.09    4.03    2.66    0.526   0.342   6.36    6.00    5.28
207  * P5  66.3    26.8    17.1    10.1    2.66    1.51    16.0    19.9    22.9
208  * P6  161     50.3    45.2    31.5    4.46    2.77    102     20.6    119
209  *
210  *            Example Single Precision Non-optimised Results
211  *
212  * P3  3.07    0.860   0.815   0.328   0.355   0.160   1.70    1.32   0.264
213  * P4  10.0    4.68    3.51    1.27    0.482   0.298   5.73    5.20    1.18
214  * P5  28.5    20.0    11.8    3.36    2.10    1.21    14.0    11.7    2.42
215  * P6  81.7    47.5    37.8    10.9    3.91    2.43    51.2    42.8    7.85
216  *
217  *        Summary results as in whets.tbl at ftp.nosc.mil/pub/aburto
218  *
219  *           MFLOPS   = Geometric Mean of three MFLOPS loops
220  *           VAX MIPS = 5 * Geometric Mean of last three items above
221  *
222  *                                                                     VAX
223  * PC System  CPU/Options               Cache   MHz   MWIPS   MFLOPS  MIPS
224  *
225  * P3 Clone   AM80386DX with 387        128K    40    5.68    0.820   7.40
226  * P4 Escom   80486DX2 CIS chipset      128K    66    16.4    3.79    29.3
227  * P5 Escom   Pentium Neptune chipset   256K   100    66.3    16.7    96.9
228  * P6 Dell    PentiumPro 440FX PCIset   256K   200    161     41.5    315
229  *
230  * P3 Clone   AM80386DX with 387        128K    40    3.07    0.613   4.20
231  * P4 Escom   80486DX2 CIS chipset      128K    66    10.0    2.75    16.4
232  * P5 Escom   Pentium Neptune chipset   256K   100    28.5    9.26    36.6
233  * P6 Dell    PentiumPro 440FX PCIset   256K   200    81.7    26.9    129
234  *
235  **************************************************************************
236  *
237  *                       Running In     fprintf(stderr,"TIMEBASE|60\n");
238 structions
239  *
240  *      1.  In order to compile successfully, include timer option as
241  *          indicated below.
242  *      2.  If pre-compiled codes are to be distributed, compile with the
243  *          -DPRECOMP option or uncomment #define PRECOMP at PRECOMPILE
244  *          below. Also insert compiler name and optimisation details
245  *          at #define precompiler and #define preoptions.
246  *      3.  Compile and run for single precision results. Include run
247  *          time parameter N to bipass typing in hardware details etc.
248  *      4.  Compile with -DDP option or uncomment #define DP at PRECISION
249  *          below and run for double precision results.
250  *      5.  Run with maximum and no optimisation (minimum debug)
251  *      6.  Notify Roy Longbottom of other necessary changes
252  *      7.  Send results file whets.res to Roy Longbottom - with one
253  *          sample of each run and system details fully completed
254  *
255  *      Roy Longbottom  101323.2241@compuserve.com    6 November 1996
256  *
257  **************************************************************************
258  */
259 
260  #include <math.h>       /* for sin, exp etc.           */
261  #include <stdio.h>      /* standard I/O                */
262  #include <string.h>     /* for strcpy - 3 occurrences  */
263  #include <stdlib.h>     /* for exit   - 1 occurrence   */
264 
265 /***************************************************************/
266 /* Timer options. You MUST uncomment one of the options below  */
267 /* or compile, for example, with the '-DUNIX' option.          */
268 /***************************************************************/
269 /* #define Amiga       */
270 /* #define UNIX        */
271 /* #define UNIX_Old    */
272 /* #define VMS         */
273 /* #define BORLAND_C   */
274 /* #define MSC         */
275 /* #define MAC         */
276 /* #define IPSC        */
277 /* #define FORTRAN_SEC */
278 /* #define GTODay      */
279 /* #define CTimer      */
280 /* #define UXPM        */
281 /* #define MAC_TMgr    */
282 /* #define PARIX       */
283 /* #define POSIX       */
284 /* #define WIN32       */
285 /* #define POSIX1      */
286 /***********************/
287 
288 /*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/
289 
290  /* #define DP */
291 
292  #ifdef DP
293     #define SPDP double
294     #define Precision "Double"
295  #else
296     #define SPDP float
297     #define Precision "Single"
298  #endif
299 
300 
301 /*PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE  PRECOMPILE*/
302 
303  /* #define PRECOMP */
304 
305  #ifdef PRECOMP
306     #define precompiler "INSERT COMPILER NAME HERE"
307     #define preoptions  "INSERT OPTIMISATION OPTIONS HERE"
308  #endif
309 
310 
311  void whetstones(long xtra, long x100, int calibrate);
312  void pa(SPDP e[4], SPDP t, SPDP t2);
313  void po(SPDP e1[4], long j, long k, long l);
314  void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2);
315  void pout(char title[22], float ops, int type, SPDP checknum,
316 		  SPDP time, int calibrate, int section);
317 
318 
319  static SPDP loop_time[9];
320  static SPDP loop_mops[9];
321  static SPDP loop_mflops[9];
322  static SPDP TimeUsed;
323  static SPDP mwips;
324  static char headings[9][18];
325  static SPDP Check;
326  static SPDP results[9];
327 
main(argc,argv)328 int main(argc, argv)
329 int	argc;
330 char	*argv[];
331 {
332     int count = 10, calibrate = 1;
333     long xtra = 1;
334     long x100 = 100;
335 #ifdef UNIXBENCH
336     int duration = 10;
337 #else
338     int section;
339     int duration = 100;
340     FILE *outfile;
341     int getinput = 1;
342     char compiler[80] = " ", options[256] = " ", general[10][80] = {" "};
343     char *endit = " ";
344 
345     printf("##########################################\n");
346     printf("%s Precision C/C++ Whetstone Benchmark\n\n", Precision);
347 #endif
348 
349 
350 #ifndef UNIXBENCH
351     if (argc > 1)
352      {
353 	switch (argv[1][0])
354 	{
355 	     case 'N':
356 	     case 'n':
357 	       getinput = 0;
358 	       break;
359 	}
360      }
361    if (! getinput)
362     {
363        printf ("No run time input data\n\n");
364     }
365 
366     outfile = fopen("whets.res","a+");
367     if (outfile == NULL)
368       {
369        printf ("Cannot open results file \n\n");
370        printf("Press RETURN to exit\n");
371        gets(endit);
372        exit (0);
373       }
374 #endif
375 
376   printf("Calibrate\n");
377   do
378    {
379     TimeUsed=0;
380 
381     whetstones(xtra,x100,calibrate);
382 
383     printf("%11.2f Seconds %10.0f   Passes (x 100)\n", TimeUsed, (SPDP)(xtra));
384     calibrate++;
385     count--;
386 
387 #ifndef UNIXBENCH
388     if (TimeUsed > 2.0)
389 #else
390     if (TimeUsed > 0.5)
391 #endif
392       {
393        count = 0;
394       }
395        else
396       {
397        xtra = xtra * 5;
398       }
399    }
400 
401    while (count > 0);
402 
403    if (TimeUsed > 0) xtra = (long)((SPDP)(duration * xtra) / TimeUsed);
404    if (xtra < 1) xtra = 1;
405 
406    calibrate = 0;
407 
408    printf("\nUse %ld  passes (x 100)\n", xtra);
409 
410    printf("\n          %s Precision C/C++ Whetstone Benchmark",Precision);
411 
412    #ifdef PRECOMP
413       printf("\n          Compiler  %s", precompiler);
414       printf("\n          Options   %s\n", preoptions);
415    #else
416       printf("\n");
417    #endif
418 
419    printf("\nLoop content                  Result              MFLOPS "
420 				"     MOPS   Seconds\n\n");
421 
422    TimeUsed=0;
423    whetstones(xtra,x100,calibrate);
424 
425    printf("\nMWIPS            ");
426    if (TimeUsed>0)
427      {
428       mwips=(float)(xtra) * (float)(x100) / (10 * TimeUsed);
429      }
430       else
431      {
432       mwips = 0;
433      }
434 
435    printf("%39.3f%19.3f\n\n",mwips,TimeUsed);
436 
437    if (Check == 0) printf("Wrong answer  ");
438 
439 
440 
441  /************************************************************************/
442  /*             Type details of hardware, software etc.                  */
443  /************************************************************************/
444 
445 #ifndef UNIXBENCH
446  if (getinput)
447    {
448      printf ("Enter the following which will be added with results to file WHETS.RES\n");
449      printf ("When submitting a number of results you need only provide details once\n");
450      printf ("but a cross reference such as an abbreviated CPU type would be useful.\n");
451      printf ("You can kill (exit or close) the program now and no data will be added.\n\n");
452 
453      printf ("Date:       ");
454      gets(general[0]);
455 
456      printf ("Computer:   ");
457      gets(general[1]);
458 
459      printf ("CPU chip:   ");
460      gets(general[2]);
461 
462      printf ("Clock MHz:  ");
463      gets(general[3]);
464 
465      printf ("Cache size: ");
466      gets(general[4]);
467 
468      printf ("H/W options:");
469      gets(general[5]);
470 
471      printf ("OS version: ");
472      gets(general[6]);
473 
474      #ifdef PRECOMP
475 	strcpy (compiler, precompiler);
476 	strcpy (options, preoptions);
477      #else
478 	printf ("Compiler:   ");
479 	gets(compiler);
480 
481 	printf ("Options:    ");
482 	gets(options);
483      #endif
484 
485      printf ("Your name:  ");
486      gets(general[7]);
487 
488      printf ("From:       ");
489      gets(general[8]);
490 
491      printf ("Email:      ");
492      gets(general[9]);
493    }
494   else
495    {
496      #ifdef PRECOMP
497 	strcpy (compiler, precompiler);
498 	strcpy (options, preoptions);
499      #endif
500    }
501 
502  /************************************************************************/
503  /*               Add results to output file whets.res                   */
504  /************************************************************************/
505  fprintf (outfile, "\n");
506  fprintf (outfile, "##############################################\n");
507  fprintf (outfile, "Whetstone %s  Precision Benchmark in C/C++\n\n",Precision);
508  fprintf (outfile, "Date         %s\n", general[0]);
509  fprintf (outfile, "Model        %s\n", general[1]);
510  fprintf (outfile, "CPU          %s\n", general[2]);
511  fprintf (outfile, "Clock MHz    %s\n", general[3]);
512  fprintf (outfile, "Cache        %s\n", general[4]);
513  fprintf (outfile, "H/W options  %s\n", general[5]);
514  fprintf (outfile, "OS           %s\n", general[6]);
515  fprintf (outfile, "Compiler     %s\n", compiler);
516  fprintf (outfile, "Options      %s\n", options);
517  fprintf (outfile, "Run by       %s\n", general[7]);
518  fprintf (outfile, "From         %s\n", general[8]);
519  fprintf (outfile, "Email        %s\n", general[9]);
520  fprintf (outfile, "\n");
521 
522  fprintf (outfile,"Loop content                   Result"
523 	    "              MFLOPS      MOPS   Seconds\n\n");
524 
525  for (section=1; section<9; section++)
526     {
527      fprintf (outfile, "%s  %24.17f   ", headings[section],
528 					      results[section]);
529      if (loop_mops[section] == 99999)
530        {
531 	fprintf (outfile,"  %9.3f           %9.3f\n",
532 		 loop_mflops[section], loop_time[section]);
533        }
534        else
535        {
536 	fprintf (outfile, "            %9.3f %9.3f\n",
537 	     loop_mops[section], loop_time[section], results[section]);
538        }
539     }
540 
541  fprintf (outfile, "\nMWIPS             ");
542  fprintf (outfile, "%39.3f%20.3f\n\n",mwips,TimeUsed);
543  fprintf (outfile, "Results  to  load  to  spreadsheet             ");
544  fprintf (outfile, "     MWIPS   Mflops1   Mflops2   Mflops3   Cosmops"
545 		      "   Expmops  Fixpmops    Ifmops    Eqmops\n");
546  fprintf (outfile, "Results  to  load  to  spreadsheet             ");
547 
548  fprintf (outfile, " %9.3f %9.3f %9.3f", mwips, loop_mflops[1],
549 							 loop_mflops[2]);
550  fprintf (outfile, " %9.3f %9.3f %9.3f", loop_mflops[6],
551 					     loop_mops[5], loop_mops[8]);
552  fprintf (outfile, " %9.3f %9.3f %9.3f\n\n", loop_mops[4],
553 					      loop_mops[3], loop_mops[7]);
554 
555  fclose (outfile);
556 
557  printf ("\n");
558  printf ("A new results file will have been created in the same directory as the\n");
559  printf (".EXE files if one did not already exist. If you made a mistake on input, \n");
560  printf ("you can use a text editor to correct it, delete the results or copy \n");
561  printf ("them to a different file name. If you intend to run multiple tests you\n");
562  printf ("you may wish to rename WHETS.RES with a more informative title.\n\n");
563  printf ("Please submit feedback and results files to aburto@nosc.mil or to\n");
564  printf ("Roy_Longbottom@compuserve.com\n\n");
565 
566 #else	/* Unixbench */
567 	fprintf (stderr, "COUNT|%.3f|0|MWIPS\n", mwips);
568         fprintf (stderr, "TIME|%.3f\n", TimeUsed);
569 	exit(0);
570 #endif
571 }
572 
whetstones(long xtra,long x100,int calibrate)573     void whetstones(long xtra, long x100, int calibrate)
574       {
575 
576 	long n1,n2,n3,n4,n5,n6,n7,n8,i,ix,n1mult;
577 	SPDP x,y,z;
578 	long j,k,l;
579 	SPDP e1[4],timea,timeb, dtime();
580 
581 	SPDP t =  0.49999975;
582 	SPDP t0 = t;
583 	SPDP t1 = 0.50000025;
584 	SPDP t2 = 2.0;
585 
586 	Check=0.0;
587 
588 	n1 = 12*x100;
589 	n2 = 14*x100;
590 	n3 = 345*x100;
591 	n4 = 210*x100;
592 	n5 = 32*x100;
593 	n6 = 899*x100;
594 	n7 = 616*x100;
595 	n8 = 93*x100;
596 	n1mult = 10;
597 
598 	/* Section 1, Array elements */
599 
600 	e1[0] = 1.0;
601 	e1[1] = -1.0;
602 	e1[2] = -1.0;
603 	e1[3] = -1.0;
604 	timea = dtime();
605 	 {
606 	    for (ix=0; ix<xtra; ix++)
607 	      {
608 		for(i=0; i<n1*n1mult; i++)
609 		  {
610 		      e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
611 		      e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
612 		      e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
613 		      e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
614 		  }
615 		t = 1.0 - t;
616 	      }
617 	    t =  t0;
618 	 }
619 	timeb = (dtime()-timea)/(SPDP)(n1mult);
620 	pout("N1 floating point\0",(float)(n1*16)*(float)(xtra),
621 			     1,e1[3],timeb,calibrate,1);
622 
623 	/* Section 2, Array as parameter */
624 
625 	timea = dtime();
626 	 {
627 	    for (ix=0; ix<xtra; ix++)
628 	      {
629 		for(i=0; i<n2; i++)
630 		  {
631 		     pa(e1,t,t2);
632 		  }
633 		t = 1.0 - t;
634 	      }
635 	    t =  t0;
636 	 }
637 	timeb = dtime()-timea;
638 	pout("N2 floating point\0",(float)(n2*96)*(float)(xtra),
639 			     1,e1[3],timeb,calibrate,2);
640 
641 	/* Section 3, Conditional jumps */
642 	j = 1;
643 	timea = dtime();
644 	 {
645 	    for (ix=0; ix<xtra; ix++)
646 	      {
647 		for(i=0; i<n3; i++)
648 		  {
649 		     if(j==1)       j = 2;
650 		     else           j = 3;
651 		     if(j>2)        j = 0;
652 		     else           j = 1;
653 		     if(j<1)        j = 1;
654 		     else           j = 0;
655 		  }
656 	      }
657 	 }
658 	timeb = dtime()-timea;
659 	pout("N3 if then else  \0",(float)(n3*3)*(float)(xtra),
660 			2,(SPDP)(j),timeb,calibrate,3);
661 
662 	/* Section 4, Integer arithmetic */
663 	j = 1;
664 	k = 2;
665 	l = 3;
666 	timea = dtime();
667 	 {
668 	    for (ix=0; ix<xtra; ix++)
669 	      {
670 		for(i=0; i<n4; i++)
671 		  {
672 		     j = j *(k-j)*(l-k);
673 		     k = l * k - (l-j) * k;
674 		     l = (l-k) * (k+j);
675 		     e1[l-2] = j + k + l;
676 		     e1[k-2] = j * k * l;
677 		  }
678 	      }
679 	 }
680 	timeb = dtime()-timea;
681 	x = e1[0]+e1[1];
682 	pout("N4 fixed point   \0",(float)(n4*15)*(float)(xtra),
683 				 2,x,timeb,calibrate,4);
684 
685 	/* Section 5, Trig functions */
686 	x = 0.5;
687 	y = 0.5;
688 	timea = dtime();
689 	 {
690 	    for (ix=0; ix<xtra; ix++)
691 	      {
692 		for(i=1; i<n5; i++)
693 		  {
694 		     x = t*atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
695 		     y = t*atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
696 		  }
697 		t = 1.0 - t;
698 	      }
699 	    t = t0;
700 	 }
701 	timeb = dtime()-timea;
702 	pout("N5 sin,cos etc.  \0",(float)(n5*26)*(float)(xtra),
703 				 2,y,timeb,calibrate,5);
704 
705 	/* Section 6, Procedure calls */
706 	x = 1.0;
707 	y = 1.0;
708 	z = 1.0;
709 	timea = dtime();
710 	 {
711 	    for (ix=0; ix<xtra; ix++)
712 	      {
713 		for(i=0; i<n6; i++)
714 		  {
715 		     p3(&x,&y,&z,t,t1,t2);
716 		  }
717 	      }
718 	 }
719 	timeb = dtime()-timea;
720 	pout("N6 floating point\0",(float)(n6*6)*(float)(xtra),
721 				1,z,timeb,calibrate,6);
722 
723 	/* Section 7, Array refrences */
724 	j = 0;
725 	k = 1;
726 	l = 2;
727 	e1[0] = 1.0;
728 	e1[1] = 2.0;
729 	e1[2] = 3.0;
730 	timea = dtime();
731 	 {
732 	    for (ix=0; ix<xtra; ix++)
733 	      {
734 		for(i=0;i<n7;i++)
735 		  {
736 		     po(e1,j,k,l);
737 		  }
738 	      }
739 	 }
740 	timeb = dtime()-timea;
741 	pout("N7 assignments   \0",(float)(n7*3)*(float)(xtra),
742 			    2,e1[2],timeb,calibrate,7);
743 
744 	/* Section 8, Standard functions */
745 	x = 0.75;
746 	timea = dtime();
747 	 {
748 	    for (ix=0; ix<xtra; ix++)
749 	      {
750 		for(i=0; i<n8; i++)
751 		  {
752 		     x = sqrt(exp(log(x)/t1));
753 		  }
754 	      }
755 	 }
756 	timeb = dtime()-timea;
757 	pout("N8 exp,sqrt etc. \0",(float)(n8*4)*(float)(xtra),
758 				2,x,timeb,calibrate,8);
759 
760 	return;
761       }
762 
763 
pa(SPDP e[4],SPDP t,SPDP t2)764     void pa(SPDP e[4], SPDP t, SPDP t2)
765       {
766 	 long j;
767 	 for(j=0;j<6;j++)
768 	    {
769 	       e[0] = (e[0]+e[1]+e[2]-e[3])*t;
770 	       e[1] = (e[0]+e[1]-e[2]+e[3])*t;
771 	       e[2] = (e[0]-e[1]+e[2]+e[3])*t;
772 	       e[3] = (-e[0]+e[1]+e[2]+e[3])/t2;
773 	    }
774 
775 	 return;
776       }
777 
po(SPDP e1[4],long j,long k,long l)778     void po(SPDP e1[4], long j, long k, long l)
779       {
780 	 e1[j] = e1[k];
781 	 e1[k] = e1[l];
782 	 e1[l] = e1[j];
783 	 return;
784       }
785 
p3(SPDP * x,SPDP * y,SPDP * z,SPDP t,SPDP t1,SPDP t2)786     void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2)
787       {
788 	 *x = *y;
789 	 *y = *z;
790 	 *x = t * (*x + *y);
791 	 *y = t1 * (*x + *y);
792 	 *z = (*x + *y)/t2;
793 	 return;
794       }
795 
796 
pout(char title[18],float ops,int type,SPDP checknum,SPDP time,int calibrate,int section)797     void pout(char title[18], float ops, int type, SPDP checknum,
798 	      SPDP time, int calibrate, int section)
799       {
800 	SPDP mops,mflops;
801 
802 	Check = Check + checknum;
803 	loop_time[section] = time;
804 	strcpy (headings[section],title);
805 	TimeUsed =  TimeUsed + time;
806 	if (calibrate == 1)
807 
808 	  {
809 	      results[section] = checknum;
810 	  }
811 	if (calibrate == 0)
812 	  {
813 	    printf("%s %24.17f    ",headings[section],results[section]);
814 
815 	    if (type == 1)
816 	     {
817 		if (time>0)
818 		 {
819 		    mflops = ops/(1000000L*time);
820 		 }
821 		else
822 		 {
823 		   mflops = 0;
824 		 }
825 		loop_mops[section] = 99999;
826 		loop_mflops[section] = mflops;
827 		printf(" %9.3f          %9.3f\n",
828 		 loop_mflops[section], loop_time[section]);
829 	     }
830 	    else
831 	     {
832 		if (time>0)
833 		 {
834 		   mops = ops/(1000000L*time);
835 		 }
836 		else
837 		 {
838 		   mops = 0;
839 		 }
840 		loop_mops[section] = mops;
841 		loop_mflops[section] = 0;
842 		printf("           %9.3f%9.3f\n",
843 		 loop_mops[section], loop_time[section]);
844 	     }
845 	  }
846 
847 	return;
848       }
849 
850 
851 /*****************************************************/
852 /* Various timer routines.                           */
853 /* Al Aburto, aburto@nosc.mil, 18 Feb 1997           */
854 /*                                                   */
855 /* t = dtime() outputs the current time in seconds.  */
856 /* Use CAUTION as some of these routines will mess   */
857 /* up when timing across the hour mark!!!            */
858 /*                                                   */
859 /* For timing I use the 'user' time whenever         */
860 /* possible. Using 'user+sys' time is a separate     */
861 /* issue.                                            */
862 /*                                                   */
863 /* Example Usage:                                    */
864 /* [timer options added here]                        */
865 /* main()                                            */
866 /* {                                                 */
867 /*  double starttime,benchtime,dtime();              */
868 /*                                                   */
869 /*  starttime = dtime();                             */
870 /*  [routine to time]                                */
871 /*  benchtime = dtime() - starttime;                 */
872 /* }                                                 */
873 /*                                                   */
874 /* [timer code below added here]                     */
875 /*****************************************************/
876 
877 /*********************************/
878 /* Timer code.                   */
879 /*********************************/
880 /*******************/
881 /*  Amiga dtime()  */
882 /*******************/
883 #ifdef Amiga
884 #include <ctype.h>
885 #define HZ 50
886 
dtime()887 SPDP dtime()
888 {
889  SPDP q;
890 
891  struct tt
892        {
893 	long  days;
894 	long  minutes;
895 	long  ticks;
896        } tt;
897 
898  DateStamp(&tt);
899 
900  q = ((SPDP)(tt.ticks + (tt.minutes * 60L * 50L))) / (SPDP)HZ;
901 
902  return q;
903 }
904 #endif
905 
906 /*****************************************************/
907 /*  UNIX dtime(). This is the preferred UNIX timer.  */
908 /*  Provided by: Markku Kolkka, mk59200@cc.tut.fi    */
909 /*  HP-UX Addition by: Bo Thide', bt@irfu.se         */
910 /*****************************************************/
911 #ifdef UNIX
912 #include <sys/time.h>
913 #include <sys/resource.h>
914 
915 #ifdef hpux
916 #include <sys/syscall.h>
917 #define getrusage(a,b) syscall(SYS_getrusage,a,b)
918 #endif
919 
920 struct rusage rusage;
921 
dtime()922 SPDP dtime()
923 {
924  SPDP q;
925 
926  getrusage(RUSAGE_SELF,&rusage);
927 
928  q = (SPDP)(rusage.ru_utime.tv_sec);
929  q = q + (SPDP)(rusage.ru_utime.tv_usec) * 1.0e-06;
930 
931  return q;
932 }
933 #endif
934 
935 /***************************************************/
936 /*  UNIX_Old dtime(). This is the old UNIX timer.  */
937 /*  Use only if absolutely necessary as HZ may be  */
938 /*  ill defined on your system.                    */
939 /***************************************************/
940 #ifdef UNIX_Old
941 #include <sys/types.h>
942 #include <sys/times.h>
943 #include <sys/param.h>
944 
945 #ifndef HZ
946 #define HZ 60
947 #endif
948 
949 struct tms tms;
950 
dtime()951 SPDP dtime()
952 {
953  SPDP q;
954 
955  times(&tms);
956 
957  q = (SPDP)(tms.tms_utime) / (SPDP)HZ;
958 
959  return q;
960 }
961 #endif
962 
963 /*********************************************************/
964 /*  VMS dtime() for VMS systems.                         */
965 /*  Provided by: RAMO@uvphys.phys.UVic.CA                */
966 /*  Some people have run into problems with this timer.  */
967 /*********************************************************/
968 #ifdef VMS
969 #include time
970 
971 #ifndef HZ
972 #define HZ 100
973 #endif
974 
975 struct tbuffer_t
976        {
977 	int proc_user_time;
978 	int proc_system_time;
979 	int child_user_time;
980 	int child_system_time;
981        };
982 struct tbuffer_t tms;
983 
dtime()984 SPDP dtime()
985 {
986  SPDP q;
987 
988  times(&tms);
989 
990  q = (SPDP)(tms.proc_user_time) / (SPDP)HZ;
991 
992  return q;
993 }
994 #endif
995 
996 /******************************/
997 /*  BORLAND C dtime() for DOS */
998 /******************************/
999 #ifdef BORLAND_C
1000 #include <ctype.h>
1001 #include <dos.h>
1002 #include <time.h>
1003 
1004 #define HZ 100
1005 struct time tnow;
1006 
dtime()1007 SPDP dtime()
1008 {
1009  SPDP q;
1010 
1011  gettime(&tnow);
1012 
1013  q = 60.0 * (SPDP)(tnow.ti_min);
1014  q = q + (SPDP)(tnow.ti_sec);
1015  q = q + (SPDP)(tnow.ti_hund)/(SPDP)HZ;
1016 
1017  return q;
1018 }
1019 #endif
1020 
1021 /***************************************/
1022 /*  Microsoft C (MSC) dtime() for DOS  */
1023 /*  Also suitable for Watcom C/C++ and */
1024 /*  some other PC compilers            */
1025 /***************************************/
1026 #ifdef MSC
1027 #include <time.h>
1028 #include <ctype.h>
1029 
1030 #define HZ CLOCKS_PER_SEC
1031 clock_t tnow;
1032 
dtime()1033 SPDP dtime()
1034 {
1035  SPDP q;
1036 
1037  tnow = clock();
1038  q = (SPDP)tnow / (SPDP)HZ;
1039  return q;
1040 }
1041 #endif
1042 
1043 /*************************************/
1044 /*  Macintosh (MAC) Think C dtime()  */
1045 /*************************************/
1046 #ifdef MAC
1047 #include <time.h>
1048 
1049 #define HZ 60
1050 
dtime()1051 SPDP dtime()
1052 {
1053  SPDP q;
1054 
1055  q = (SPDP)clock() / (SPDP)HZ;
1056 
1057  return q;
1058 }
1059 #endif
1060 
1061 /************************************************************/
1062 /*  iPSC/860 (IPSC) dtime() for i860.                       */
1063 /*  Provided by: Dan Yergeau, yergeau@gloworm.Stanford.EDU  */
1064 /************************************************************/
1065 #ifdef IPSC
1066 extern double dclock();
1067 
dtime()1068 SPDP dtime()
1069 {
1070  SPDP q;
1071 
1072  q = dclock();
1073 
1074  return q;
1075 }
1076 #endif
1077 
1078 /**************************************************/
1079 /*  FORTRAN dtime() for Cray type systems.        */
1080 /*  This is the preferred timer for Cray systems. */
1081 /**************************************************/
1082 #ifdef FORTRAN_SEC
1083 
1084 fortran double second();
1085 
dtime()1086 SPDP dtime()
1087 {
1088  SPDP q;
1089 
1090  second(&q);
1091 
1092  return q;
1093 }
1094 #endif
1095 
1096 /***********************************************************/
1097 /*  UNICOS C dtime() for Cray UNICOS systems.  Don't use   */
1098 /*  unless absolutely necessary as returned time includes  */
1099 /*  'user+system' time.  Provided by: R. Mike Dority,      */
1100 /*  dority@craysea.cray.com                                */
1101 /***********************************************************/
1102 #ifdef CTimer
1103 #include <time.h>
1104 
dtime()1105 SPDP dtime()
1106 {
1107  SPDP q;
1108  clock_t   clock(void);
1109 
1110  q = (SPDP)clock() / (SPDP)CLOCKS_PER_SEC;
1111 
1112  return q;
1113 }
1114 #endif
1115 
1116 /********************************************/
1117 /* Another UNIX timer using gettimeofday(). */
1118 /* However, getrusage() is preferred.       */
1119 /********************************************/
1120 #ifdef GTODay
1121 #include <sys/time.h>
1122 
1123 struct timeval tnow;
1124 
dtime()1125 SPDP dtime()
1126 {
1127  SPDP q;
1128 
1129  gettimeofday(&tnow,NULL);
1130  q = (SPDP)tnow.tv_sec + (SPDP)tnow.tv_usec * 1.0e-6;
1131 
1132  return q;
1133 }
1134 #endif
1135 
1136 /*****************************************************/
1137 /*  Fujitsu UXP/M timer.                             */
1138 /*  Provided by: Mathew Lim, ANUSF, M.Lim@anu.edu.au */
1139 /*****************************************************/
1140 #ifdef UXPM
1141 #include <sys/types.h>
1142 #include <sys/timesu.h>
1143 struct tmsu rusage;
1144 
dtime()1145 SPDP dtime()
1146 {
1147  SPDP q;
1148 
1149  timesu(&rusage);
1150 
1151  q = (SPDP)(rusage.tms_utime) * 1.0e-06;
1152 
1153  return q;
1154 }
1155 #endif
1156 
1157 /**********************************************/
1158 /*    Macintosh (MAC_TMgr) Think C dtime()    */
1159 /*   requires Think C Language Extensions or  */
1160 /*    #include <MacHeaders> in the prefix     */
1161 /*  provided by Francis H Schiffer 3rd (fhs)  */
1162 /*         skipschiffer@genie.geis.com        */
1163 /**********************************************/
1164 #ifdef MAC_TMgr
1165 #include <Timer.h>
1166 #include <stdlib.h>
1167 
1168 static TMTask   mgrTimer;
1169 static Boolean  mgrInited = false;
1170 static SPDP     mgrClock;
1171 
1172 #define RMV_TIMER RmvTime( (QElemPtr)&mgrTimer )
1173 #define MAX_TIME  1800000000L
1174 /* MAX_TIME limits time between calls to */
1175 /* dtime( ) to no more than 30 minutes   */
1176 /* this limitation could be removed by   */
1177 /* creating a completion routine to sum  */
1178 /* 30 minute segments (fhs 1994 feb 9)   */
1179 
Remove_timer()1180 static void Remove_timer( )
1181 {
1182  RMV_TIMER;
1183  mgrInited = false;
1184 }
1185 
dtime()1186 SPDP dtime( )
1187 {
1188  if( mgrInited ) {
1189 	RMV_TIMER;
1190 	mgrClock += (MAX_TIME + mgrTimer.tmCount)*1.0e-6;
1191  } else {
1192 	if( _atexit( &Remove_timer ) == 0 ) mgrInited = true;
1193 	mgrClock = 0.0;
1194 }
1195 	if( mgrInited ) {
1196 		mgrTimer.tmAddr = NULL;
1197 		mgrTimer.tmCount = 0;
1198 		mgrTimer.tmWakeUp = 0;
1199 		mgrTimer.tmReserved = 0;
1200 		InsTime( (QElemPtr)&mgrTimer );
1201 		PrimeTime( (QElemPtr)&mgrTimer, -MAX_TIME );
1202 	}
1203 	return( mgrClock );
1204 }
1205 #endif
1206 
1207 /***********************************************************/
1208 /*  Parsytec GCel timer.                                   */
1209 /*  Provided by: Georg Wambach, gw@informatik.uni-koeln.de */
1210 /***********************************************************/
1211 #ifdef PARIX
1212 #include <sys/time.h>
1213 
dtime()1214 SPDP dtime()
1215 {
1216  SPDP q;
1217 
1218  q = (SPDP) (TimeNowHigh()) / (SPDP) CLK_TCK_HIGH;
1219 
1220  return q;
1221 }
1222 #endif
1223 
1224 /************************************************/
1225 /*  Sun Solaris POSIX dtime() routine           */
1226 /*  Provided by: Case Larsen, CTLarsen.lbl.gov  */
1227 /************************************************/
1228 #ifdef POSIX
1229 #include <sys/time.h>
1230 #include <sys/resource.h>
1231 #include <sys/rusage.h>
1232 
1233 #ifdef __hpux
1234 #include <sys/syscall.h>
1235 #endif
1236 
1237 struct rusage rusage;
1238 
dtime()1239 SPDP dtime()
1240 {
1241  SPDP q;
1242 
1243  getrusage(RUSAGE_SELF,&rusage);
1244 
1245  q = (SPDP)(rusage.ru_utime.tv_sec);
1246  q = q + (SPDP)(rusage.ru_utime.tv_nsec) * 1.0e-09;
1247 
1248  return q;
1249 }
1250 #endif
1251 
1252 
1253 /****************************************************/
1254 /*  Windows NT (32 bit) dtime() routine             */
1255 /*  Provided by: Piers Haken, piersh@microsoft.com  */
1256 /****************************************************/
1257 #ifdef WIN32
1258 #include <windows.h>
1259 
dtime(void)1260 SPDP dtime(void)
1261 {
1262  SPDP q;
1263 
1264  q = (SPDP)GetTickCount() * 1.0e-03;
1265 
1266  return q;
1267 }
1268 #endif
1269 
1270 /*****************************************************/
1271 /* Time according to POSIX.1  -  <J.Pelan@qub.ac.uk> */
1272 /* Ref: "POSIX Programmer's Guide"  O'Reilly & Assoc.*/
1273 /*****************************************************/
1274 #ifdef POSIX1
1275 #define _POSIX_SOURCE 1
1276 #include <unistd.h>
1277 #include <limits.h>
1278 #include <sys/times.h>
1279 
1280 struct tms tms;
1281 
dtime()1282 SPDP dtime()
1283 {
1284  SPDP q;
1285  times(&tms);
1286  q = (SPDP)tms.tms_utime / (SPDP)CLK_TCK;
1287  return q;
1288 }
1289 #endif
1290