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