1 
2 /*
3 ** nbench0.c
4 */
5 
6 /*******************************************
7 **             BYTEmark (tm)              **
8 ** BYTE MAGAZINE'S NATIVE MODE BENCHMARKS **
9 **           FOR CPU/FPU                  **
10 **             ver 2.0                    **
11 **       Rick Grehan, BYTE Magazine       **
12 ********************************************
13 ** NOTE: These benchmarks do NOT check for the presence
14 ** of an FPU.  You have to find that out manually.
15 **
16 ** REVISION HISTORY FOR BENCHMARKS
17 **  9/94 -- First beta. --RG
18 **  12/94 -- Bug discovered in some of the integer routines
19 **    (IDEA, Huffman,...).  Routines were not accurately counting
20 **    the number of loops.  Fixed. --RG (Thanks to Steve A.)
21 **  12/94 -- Added routines to calculate and display index
22 **    values. Indexes based on DELL XPS 90 (90 MHz Pentium).
23 **  1/95 -- Added Mac time manager routines for more accurate
24 **    timing on Macintosh (said to be good to 20 usecs) -- RG
25 **  1/95 -- Re-did all the #defines so they made more
26 **    sense.  See NMGLOBAL.H -- RG
27 **  3/95 -- Fixed memory leak in LU decomposition.  Did not
28 **    invalidate previous results, just made it easier to run.--RG
29 **  3/95 -- Added TOOLHELP.DLL timing routine to Windows timer. --RG
30 **  10/95 -- Added memory array & alignment; moved memory
31 **      allocation out of LU Decomposition -- RG
32 **
33 ** DISCLAIMER
34 ** The source, executable, and documentation files that comprise
35 ** the BYTEmark benchmarks are made available on an "as is" basis.
36 ** This means that we at BYTE Magazine have made every reasonable
37 ** effort to verify that the there are no errors in the source and
38 ** executable code.  We cannot, however, guarantee that the programs
39 ** are error-free.  Consequently, McGraw-HIll and BYTE Magazine make
40 ** no claims in regard to the fitness of the source code, executable
41 ** code, and documentation of the BYTEmark.
42 **  Furthermore, BYTE Magazine, McGraw-Hill, and all employees
43 ** of McGraw-Hill cannot be held responsible for any damages resulting
44 ** from the use of this code or the results obtained from using
45 ** this code.
46 */
47 
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <ctype.h>
51 #include <string.h>
52 #include <time.h>
53 #include <math.h>
54 #include "nmglobal.h"
55 #include "nbench0.h"
56 #include "hardware.h"
57 
58 /*************
59 **** main ****
60 *************/
61 #ifdef MAC
main(void)62 void main(void)
63 #else
64 int main(int argc, char *argv[])
65 #endif
66 {
67 int i;                  /* Index */
68 time_t time_and_date;   /* Self-explanatory */
69 struct tm *loctime;
70 double bmean;           /* Benchmark mean */
71 double bstdev;          /* Benchmark stdev */
72 double lx_memindex;     /* Linux memory index (mainly integer operations)*/
73 double lx_intindex;     /* Linux integer index */
74 double lx_fpindex;      /* Linux floating-point index */
75 double intindex;        /* Integer index */
76 double fpindex;         /* Floating-point index */
77 ulong bnumrun;          /* # of runs */
78 
79 #ifdef MAC
80         MaxApplZone();
81 #endif
82 
83 #ifdef MACTIMEMGR
84 /* Set up high res timer */
85 MacHSTdelay=600*1000*1000;      /* Delay is 10 minutes */
86 
87 memset((char *)&myTMTask,0,sizeof(TMTask));
88 
89 /* Prime and remove the task, calculating overhead */
90 PrimeTime((QElemPtr)&myTMTask,-MacHSTdelay);
91 RmvTime((QElemPtr)&myTMTask);
92 MacHSTohead=MacHSTdelay+myTMTask.tmCount;
93 #endif
94 
95 #ifdef WIN31TIMER
96 /* Set up the size of the timer info structure */
97 win31tinfo.dwSize=(DWORD)sizeof(TIMERINFO);
98 /* Load library */
99 if((hThlp=LoadLibrary("TOOLHELP.DLL"))<32)
100 {       printf("Error loading TOOLHELP\n");
101         exit(0);
102 }
103 if(!(lpfn=GetProcAddress(hThlp,"TimerCount")))
104 {       printf("TOOLHELP error\n");
105         exit(0);
106 }
107 #endif
108 
109 /*
110 ** Set global parameters to default.
111 */
112 global_min_ticks=MINIMUM_TICKS;
113 global_min_seconds=MINIMUM_SECONDS;
114 global_allstats=0;
115 global_custrun=0;
116 global_align=8;
117 write_to_file=0;
118 lx_memindex=(double)1.0;        /* set for geometric mean computations */
119 lx_intindex=(double)1.0;
120 lx_fpindex=(double)1.0;
121 intindex=(double)1.0;
122 fpindex=(double)1.0;
123 mem_array_ents=0;               /* Nothing in mem array */
124 
125 /*
126 ** We presume all tests will be run unless told
127 ** otherwise
128 */
129 for(i=0;i<NUMTESTS;i++)
130         tests_to_do[i]=1;
131 
132 /*
133 ** Initialize test data structures to default
134 ** values.
135 */
136 set_request_secs();     /* Set all request_secs fields */
137 global_numsortstruct.adjust=0;
138 global_numsortstruct.arraysize=NUMARRAYSIZE;
139 
140 global_strsortstruct.adjust=0;
141 global_strsortstruct.arraysize=STRINGARRAYSIZE;
142 
143 global_bitopstruct.adjust=0;
144 global_bitopstruct.bitfieldarraysize=BITFARRAYSIZE;
145 
146 global_emfloatstruct.adjust=0;
147 global_emfloatstruct.arraysize=EMFARRAYSIZE;
148 
149 global_fourierstruct.adjust=0;
150 
151 global_assignstruct.adjust=0;
152 
153 global_ideastruct.adjust=0;
154 global_ideastruct.arraysize=IDEAARRAYSIZE;
155 
156 global_huffstruct.adjust=0;
157 global_huffstruct.arraysize=HUFFARRAYSIZE;
158 
159 global_nnetstruct.adjust=0;
160 
161 global_lustruct.adjust=0;
162 
163 /*
164 ** For Macintosh -- read the command line.
165 */
166 #ifdef MAC
167 UCommandLine();
168 #endif
169 
170 /*
171 ** Handle any command-line arguments.
172 */
173 if(argc>1)
174         for(i=1;i<argc;i++)
175                 if(parse_arg(argv[i])==-1)
176                 {       display_help(argv[0]);
177                         exit(0);
178                 }
179 /*
180 ** Output header
181 */
182 #ifdef LINUX
183 output_string("\nBYTEmark* Native Mode Benchmark ver. 2 (10/95)\n");
184 output_string("Index-split by Andrew D. Balsa (11/97)\n");
185 output_string("Linux/Unix* port by Uwe F. Mayer (12/96,11/97)\n");
186 #else
187 output_string("BBBBBB   YYY   Y  TTTTTTT  EEEEEEE\n");
188 output_string("BBB   B  YYY   Y    TTT    EEE\n");
189 output_string("BBB   B  YYY   Y    TTT    EEE\n");
190 output_string("BBBBBB    YYY Y     TTT    EEEEEEE\n");
191 output_string("BBB   B    YYY      TTT    EEE\n");
192 output_string("BBB   B    YYY      TTT    EEE\n");
193 output_string("BBBBBB     YYY      TTT    EEEEEEE\n\n");
194 output_string("\nBYTEmark (tm) Native Mode Benchmark ver. 2 (10/95)\n");
195 #endif
196 /*
197 ** See if the user wants all stats.  Output heading info
198 ** if so.
199 */
200 if(global_allstats)
201 {
202                 output_string("\n");
203                 output_string("============================== ALL STATISTICS ===============================\n");
204         time(&time_and_date);
205         loctime=localtime(&time_and_date);
206         sprintf(buffer,"**Date and time of benchmark run: %s",asctime(loctime));
207         output_string(buffer);
208         sprintf(buffer,"**Sizeof: char:%u short:%u int:%u long:%u u8:%u u16:%u u32:%u int32:%u\n",
209                 (unsigned int)sizeof(char),
210                 (unsigned int)sizeof(short),
211                 (unsigned int)sizeof(int),
212                 (unsigned int)sizeof(long),
213                 (unsigned int)sizeof(u8),
214                 (unsigned int)sizeof(u16),
215                 (unsigned int)sizeof(u32),
216                 (unsigned int)sizeof(int32));
217         output_string(buffer);
218 #ifdef LINUX
219 #include "sysinfo.c"
220 #else
221         sprintf(buffer,"**%s\n",sysname);
222         output_string(buffer);
223         sprintf(buffer,"**%s\n",compilername);
224         output_string(buffer);
225         sprintf(buffer,"**%s\n",compilerversion);
226         output_string(buffer);
227 #endif
228                 output_string("=============================================================================\n");
229 }
230 
231 /*
232 ** Execute the tests.
233 */
234 #ifdef LINUX
235 output_string("\nTEST                : Iterations/sec.  : Old Index   : New Index\n");
236 output_string("                    :                  : Pentium 90* : AMD K6/233*\n");
237 output_string("--------------------:------------------:-------------:------------\n");
238 #endif
239 
240 for(i=0;i<NUMTESTS;i++)
241 {
242         if(tests_to_do[i])
243         {       sprintf(buffer,"%s    :",ftestnames[i]);
244                                 output_string(buffer);
245                 if (0!=bench_with_confidence(i,
246                         &bmean,
247                         &bstdev,
248                         &bnumrun)){
249 		  output_string("\n** WARNING: The current test result is NOT 95 % statistically certain.\n");
250 		  output_string("** WARNING: The variation among the individual results is too large.\n");
251 		  output_string("                    :");
252 		}
253 #ifdef LINUX
254                 sprintf(buffer," %15.5g  :  %9.2f  :  %9.2f\n",
255                         bmean,bmean/bindex[i],bmean/lx_bindex[i]);
256 #else
257 		sprintf(buffer,"  Iterations/sec.: %13.2f  Index: %6.2f\n",
258                         bmean,bmean/bindex[i]);
259 #endif
260                 output_string(buffer);
261 		/*
262 		** Gather integer or FP indexes
263 		*/
264 		if((i==4)||(i==8)||(i==9)){
265 		  /* FP index */
266 		  fpindex=fpindex*(bmean/bindex[i]);
267 		  /* Linux FP index */
268 		  lx_fpindex=lx_fpindex*(bmean/lx_bindex[i]);
269 		}
270 		else{
271 		  /* Integer index */
272 		  intindex=intindex*(bmean/bindex[i]);
273 		  if((i==0)||(i==3)||(i==6)||(i==7))
274 		    /* Linux integer index */
275 		    lx_intindex=lx_intindex*(bmean/lx_bindex[i]);
276 		  else
277 		    /* Linux memory index */
278 		    lx_memindex=lx_memindex*(bmean/lx_bindex[i]);
279 		}
280 
281                 if(global_allstats)
282                 {
283                         sprintf(buffer,"  Absolute standard deviation: %g\n",bstdev);
284                         output_string(buffer);
285 			if (bmean>(double)1e-100){
286 			  /* avoid division by zero */
287 			  sprintf(buffer,"  Relative standard deviation: %g %%\n",
288 				  (double)100*bstdev/bmean);
289 			  output_string(buffer);
290 			}
291                         sprintf(buffer,"  Number of runs: %lu\n",bnumrun);
292                         output_string(buffer);
293                         show_stats(i);
294                         sprintf(buffer,"Done with %s\n\n",ftestnames[i]);
295                         output_string(buffer);
296                 }
297         }
298 }
299 /* printf("...done...\n"); */
300 
301 /*
302 ** Output the total indexes
303 */
304 if(global_custrun==0)
305 {
306         output_string("==========================ORIGINAL BYTEMARK RESULTS==========================\n");
307         sprintf(buffer,"INTEGER INDEX       : %.3f\n",
308                        pow(intindex,(double).142857));
309         output_string(buffer);
310         sprintf(buffer,"FLOATING-POINT INDEX: %.3f\n",
311                         pow(fpindex,(double).33333));
312         output_string(buffer);
313         output_string("Baseline (MSDOS*)   : Pentium* 90, 256 KB L2-cache, Watcom* compiler 10.0\n");
314 #ifdef LINUX
315         output_string("==============================LINUX DATA BELOW===============================\n");
316 	hardware(write_to_file, global_ofile);
317 #include "sysinfoc.c"
318         sprintf(buffer,"MEMORY INDEX        : %.3f\n",
319                        pow(lx_memindex,(double).3333333333));
320         output_string(buffer);
321         sprintf(buffer,"INTEGER INDEX       : %.3f\n",
322                        pow(lx_intindex,(double).25));
323         output_string(buffer);
324         sprintf(buffer,"FLOATING-POINT INDEX: %.3f\n",
325                         pow(lx_fpindex,(double).3333333333));
326         output_string(buffer);
327         output_string("Baseline (LINUX)    : AMD K6/233*, 512 KB L2-cache, gcc 2.7.2.3, libc-5.4.38\n");
328 #endif
329 output_string("* Trademarks are property of their respective holder.\n");
330 }
331 
332 exit(0);
333 }
334 
335 /**************
336 ** parse_arg **
337 ***************
338 ** Given a pointer to a string, we assume that's an argument.
339 ** Parse that argument and act accordingly.
340 ** Return 0 if ok, else return -1.
341 */
parse_arg(char * argptr)342 static int parse_arg(char *argptr)
343 {
344 int i;          /* Index */
345 FILE *cfile;    /* Command file identifier */
346 
347 /*
348 ** First character has got to be a hyphen.
349 */
350 if(*argptr++!='-') return(-1);
351 
352 /*
353 ** Convert the rest of the argument to upper case
354 ** so there's little chance of confusion.
355 */
356 for(i=0;i<strlen(argptr);i++)
357         argptr[i]=(char)toupper((int)argptr[i]);
358 
359 /*
360 ** Next character picks the action.
361 */
362 switch(*argptr++)
363 {
364         case '?':       return(-1);     /* Will display help */
365 
366         case 'V': global_allstats=1; return(0); /* verbose mode */
367 
368         case 'C':                       /* Command file name */
369                 /*
370                 ** First try to open the file for reading.
371                 */
372                 cfile=fopen(argptr,"r");
373                 if(cfile==(FILE *)NULL)
374                 {       printf("**Error opening file: %s\n",argptr);
375                         return(-1);
376                 }
377                 read_comfile(cfile);    /* Read commands */
378                 fclose(cfile);
379                 break;
380         default:
381                 return(-1);
382 }
383 return(0);
384 }
385 
386 /*******************
387 ** display_help() **
388 ********************
389 ** Display a help message showing argument requirements and such.
390 ** Exit when you're done...I mean, REALLY exit.
391 */
display_help(char * progname)392 void display_help(char *progname)
393 {
394         printf("Usage: %s [-v] [-c<FILE>]\n",progname);
395         printf(" -v = verbose\n");
396         printf(" -c = input parameters thru command file <FILE>\n");
397         exit(0);
398 }
399 
400 
401 /*****************
402 ** read_comfile **
403 ******************
404 ** Read the command file.  Set global parameters as
405 ** specified.  This routine assumes that the command file
406 ** is already open.
407 */
read_comfile(FILE * cfile)408 static void read_comfile(FILE *cfile)
409 {
410 char inbuf[40];
411 char *eptr;             /* Offset to "=" sign */
412 int i;                  /* Index */
413 
414 /*
415 ** Sit in a big loop, reading a line from the file at each
416 ** pass.  Terminate on EOF.
417 */
418 while(fgets(inbuf,39,cfile)!=(char *)NULL)
419 {
420         /* Overwrite the CR character */
421         if(strlen(inbuf)>0)
422                 inbuf[strlen(inbuf)-1]='\0';
423 
424         /*
425         ** Parse up to the "=" sign.  If we don't find an
426         ** "=", then flag an error.
427         */
428         if((eptr=strchr(inbuf,(int)'='))==(char *)NULL)
429         {       printf("**COMMAND FILE ERROR at LINE:\n %s\n",
430                         inbuf);
431                 goto skipswitch;        /* A GOTO!!!! */
432         }
433 
434         /*
435         ** Insert a null where the "=" was, then convert
436         ** the substring to uppercase.  That will enable
437         ** us to perform the match.
438         */
439         *eptr++='\0';
440         strtoupper((char *)&inbuf[0]);
441         i=MAXPARAM;
442         do {
443                 if(strcmp(inbuf,paramnames[i])==0)
444                         break;
445         } while(--i>=0);
446 
447         if(i<0)
448         {       printf("**COMMAND FILE ERROR -- UNKNOWN PARAM: %s",
449                         inbuf);
450                 goto skipswitch;
451         }
452 
453         /*
454         ** Advance eptr to the next field...which should be
455         ** the value assigned to the parameter.
456         */
457         switch(i)
458         {
459                 case PF_GMTICKS:        /* GLOBALMINTICKS */
460                         global_min_ticks=(ulong)atol(eptr);
461                         break;
462 
463                 case PF_MINSECONDS:     /* MINSECONDS */
464                         global_min_seconds=(ulong)atol(eptr);
465                         set_request_secs();
466                         break;
467 
468                 case PF_ALLSTATS:       /* ALLSTATS */
469                         global_allstats=getflag(eptr);
470                         break;
471 
472                 case PF_OUTFILE:        /* OUTFILE */
473                         strcpy(global_ofile_name,eptr);
474                         global_ofile=fopen(global_ofile_name,"a");
475                         /*
476                         ** Open the output file.
477                         */
478                         if(global_ofile==(FILE *)NULL)
479                         {       printf("**Error opening output file: %s\n",
480                                         global_ofile_name);
481                                 ErrorExit();
482                         }
483                         write_to_file=-1;
484                         break;
485 
486                 case PF_CUSTOMRUN:      /* CUSTOMRUN */
487                         global_custrun=getflag(eptr);
488                         for(i=0;i<NUMTESTS;i++)
489                                 tests_to_do[i]=1-global_custrun;
490                         break;
491 
492                 case PF_DONUM:          /* DONUMSORT */
493                         tests_to_do[TF_NUMSORT]=getflag(eptr);
494                         break;
495 
496                 case PF_NUMNUMA:        /* NUMNUMARRAYS */
497                         global_numsortstruct.numarrays=
498                                 (ushort)atoi(eptr);
499                         global_numsortstruct.adjust=1;
500                         break;
501 
502                 case PF_NUMASIZE:       /* NUMARRAYSIZE */
503                         global_numsortstruct.arraysize=
504                                 (ulong)atol(eptr);
505                         break;
506 
507                 case PF_NUMMINS:        /* NUMMINSECONDS */
508                         global_numsortstruct.request_secs=
509                                 (ulong)atol(eptr);
510                         break;
511 
512                 case PF_DOSTR:          /* DOSTRINGSORT */
513                         tests_to_do[TF_SSORT]=getflag(eptr);
514                         break;
515 
516                 case PF_STRASIZE:       /* STRARRAYSIZE */
517                         global_strsortstruct.arraysize=
518                                 (ulong)atol(eptr);
519                         break;
520 
521                 case PF_NUMSTRA:        /* NUMSTRARRAYS */
522                         global_strsortstruct.numarrays=
523                                 (ushort)atoi(eptr);
524                         global_strsortstruct.adjust=1;
525                         break;
526 
527                 case PF_STRMINS:        /* STRMINSECONDS */
528                         global_strsortstruct.request_secs=
529                                 (ulong)atol(eptr);
530                         break;
531 
532                 case PF_DOBITF: /* DOBITFIELD */
533                         tests_to_do[TF_BITOP]=getflag(eptr);
534                         break;
535 
536                 case PF_NUMBITOPS:      /* NUMBITOPS */
537                         global_bitopstruct.bitoparraysize=
538                                 (ulong)atol(eptr);
539                         global_bitopstruct.adjust=1;
540                         break;
541 
542                 case PF_BITFSIZE:       /* BITFIELDSIZE */
543                         global_bitopstruct.bitfieldarraysize=
544                                 (ulong)atol(eptr);
545                         break;
546 
547                 case PF_BITMINS:        /* BITMINSECONDS */
548                         global_bitopstruct.request_secs=
549                                 (ulong)atol(eptr);
550                         break;
551 
552                 case PF_DOEMF:          /* DOEMF */
553                         tests_to_do[TF_FPEMU]=getflag(eptr);
554                         break;
555 
556                 case PF_EMFASIZE:       /* EMFARRAYSIZE */
557                         global_emfloatstruct.arraysize=
558                                 (ulong)atol(eptr);
559                         break;
560 
561                 case PF_EMFLOOPS:       /* EMFLOOPS */
562                         global_emfloatstruct.loops=
563                                 (ulong)atol(eptr);
564                         break;
565 
566                 case PF_EMFMINS:        /* EMFMINSECOND */
567                         global_emfloatstruct.request_secs=
568                                 (ulong)atol(eptr);
569                         break;
570 
571                 case PF_DOFOUR: /* DOFOUR */
572                         tests_to_do[TF_FFPU]=getflag(eptr);
573                         break;
574 
575                 case PF_FOURASIZE:      /* FOURASIZE */
576                         global_fourierstruct.arraysize=
577                                 (ulong)atol(eptr);
578                         global_fourierstruct.adjust=1;
579                         break;
580 
581                 case PF_FOURMINS:       /* FOURMINSECONDS */
582                         global_fourierstruct.request_secs=
583                                 (ulong)atol(eptr);
584                         break;
585 
586                 case PF_DOASSIGN:       /* DOASSIGN */
587                         tests_to_do[TF_ASSIGN]=getflag(eptr);
588                         break;
589 
590                 case PF_AARRAYS:        /* ASSIGNARRAYS */
591                         global_assignstruct.numarrays=
592                                 (ulong)atol(eptr);
593                         break;
594 
595                 case PF_ASSIGNMINS:     /* ASSIGNMINSECONDS */
596                         global_assignstruct.request_secs=
597                                 (ulong)atol(eptr);
598                         break;
599 
600                 case PF_DOIDEA: /* DOIDEA */
601                         tests_to_do[TF_IDEA]=getflag(eptr);
602                         break;
603 
604                 case PF_IDEAASIZE:      /* IDEAARRAYSIZE */
605                         global_ideastruct.arraysize=
606                                 (ulong)atol(eptr);
607                         break;
608 
609                 case PF_IDEALOOPS:      /* IDEALOOPS */
610                         global_ideastruct.loops=
611                                 (ulong)atol(eptr);
612                         break;
613 
614                 case PF_IDEAMINS:       /* IDEAMINSECONDS */
615                         global_ideastruct.request_secs=
616                                 (ulong)atol(eptr);
617                         break;
618 
619                 case PF_DOHUFF: /* DOHUFF */
620                         tests_to_do[TF_HUFF]=getflag(eptr);
621                         break;
622 
623                 case PF_HUFFASIZE:      /* HUFFARRAYSIZE */
624                         global_huffstruct.arraysize=
625                                 (ulong)atol(eptr);
626                         break;
627 
628                 case PF_HUFFLOOPS:      /* HUFFLOOPS */
629                         global_huffstruct.loops=
630                                 (ulong)atol(eptr);
631                         global_huffstruct.adjust=1;
632                         break;
633 
634                 case PF_HUFFMINS:       /* HUFFMINSECONDS */
635                         global_huffstruct.request_secs=
636                                 (ulong)atol(eptr);
637                         break;
638 
639                 case PF_DONNET: /* DONNET */
640                         tests_to_do[TF_NNET]=getflag(eptr);
641                         break;
642 
643                 case PF_NNETLOOPS:      /* NNETLOOPS */
644                         global_nnetstruct.loops=
645                                 (ulong)atol(eptr);
646                         global_nnetstruct.adjust=1;
647                         break;
648 
649                 case PF_NNETMINS:       /* NNETMINSECONDS */
650                         global_nnetstruct.request_secs=
651                                 (ulong)atol(eptr);
652                         break;
653 
654                 case PF_DOLU:           /* DOLU */
655                         tests_to_do[TF_LU]=getflag(eptr);
656                         break;
657 
658                 case PF_LUNARRAYS:      /* LUNUMARRAYS */
659                         global_lustruct.numarrays=
660                                 (ulong)atol(eptr);
661                         global_lustruct.adjust=1;
662                         break;
663 
664                 case PF_LUMINS: /* LUMINSECONDS */
665                         global_lustruct.request_secs=
666                                 (ulong)atol(eptr);
667                         break;
668 
669                                 case PF_ALIGN:          /* ALIGN */
670                                                 global_align=atoi(eptr);
671                                                 break;
672         }
673 skipswitch:
674         continue;
675 }       /* End while */
676 
677 return;
678 }
679 
680 /************
681 ** getflag **
682 *************
683 ** Return 1 if cptr points to "T"; 0 otherwise.
684 */
getflag(char * cptr)685 static int getflag(char *cptr)
686 {
687         if(toupper((int)*cptr)=='T') return(1);
688 return(0);
689 }
690 
691 /***************
692 ** strtoupper **
693 ****************
694 ** Convert's a string to upper case.  The string is presumed
695 ** to consist only of alphabetic characters, and to be terminated
696 ** with a null.
697 */
strtoupper(char * s)698 static void strtoupper(char *s)
699 {
700 
701 do {
702 /*
703 ** Oddly enough, the following line did not work under THINK C.
704 ** So, I modified it....hmmmm. --RG
705         *s++=(char)toupper((int)*s);
706 */
707         *s=(char)toupper((int)*s);
708         s++;
709 } while(*s!=(char)'\0');
710 return;
711 }
712 
713 /*********************
714 ** set_request_secs **
715 **********************
716 ** Set everyone's "request_secs" entry to whatever
717 ** value is in global_min_secs.  This is done
718 ** at the beginning, and possibly later if the
719 ** user redefines global_min_secs in the command file.
720 */
set_request_secs(void)721 static void set_request_secs(void)
722 {
723 
724 global_numsortstruct.request_secs=global_min_seconds;
725 global_strsortstruct.request_secs=global_min_seconds;
726 global_bitopstruct.request_secs=global_min_seconds;
727 global_emfloatstruct.request_secs=global_min_seconds;
728 global_fourierstruct.request_secs=global_min_seconds;
729 global_assignstruct.request_secs=global_min_seconds;
730 global_ideastruct.request_secs=global_min_seconds;
731 global_huffstruct.request_secs=global_min_seconds;
732 global_nnetstruct.request_secs=global_min_seconds;
733 global_lustruct.request_secs=global_min_seconds;
734 
735 return;
736 }
737 
738 
739 /**************************
740 ** bench_with_confidence **
741 ***************************
742 ** Given a benchmark id that indicates a function, this routine
743 ** repeatedly calls that benchmark, seeking to collect and replace
744 ** scores to get 5 that meet the confidence criteria.
745 **
746 ** The above is mathematically questionable, as the statistical theory
747 ** depends on independent observations, and if we exchange data points
748 ** depending on what we already have then this certainly violates
749 ** independence of the observations. Hence I changed this so that at
750 ** most 30 observations are done, but none are deleted as we go
751 ** along. We simply do more runs and hope to get a big enough sample
752 ** size so that things stabilize. Uwe F. Mayer
753 **
754 ** Return 0 if ok, -1 if failure.  Returns mean
755 ** and std. deviation of results if successful.
756 */
bench_with_confidence(int fid,double * mean,double * stdev,ulong * numtries)757 static int bench_with_confidence(int fid,       /* Function id */
758         double *mean,                   /* Mean of scores */
759         double *stdev,                  /* Standard deviation */
760         ulong *numtries)                /* # of attempts */
761 {
762 double myscores[30];            /* Need at least 5 scores, use at most 30 */
763 double c_half_interval;         /* Confidence half interval */
764 int i;                          /* Index */
765 /* double newscore; */          /* For improving confidence interval */
766 
767 /*
768 ** Get first 5 scores.  Then begin confidence testing.
769 */
770 for (i=0;i<5;i++)
771 {       (*funcpointer[fid])();
772         myscores[i]=getscore(fid);
773 #ifdef DEBUG
774 	printf("score # %d = %g\n", i, myscores[i]);
775 #endif
776 }
777 *numtries=5;            /* Show 5 attempts */
778 
779 /*
780 ** The system allows a maximum of 30 tries before it gives
781 ** up.  Since we've done 5 already, we'll allow 25 more.
782 */
783 
784 /*
785 ** Enter loop to test for confidence criteria.
786 */
787 while(1)
788 {
789         /*
790         ** Calculate confidence. Should always return 0.
791         */
792         if (0!=calc_confidence(myscores,
793 		*numtries,
794                 &c_half_interval,
795                 mean,
796                 stdev)) return(-1);
797 
798         /*
799         ** Is the length of the half interval 5% or less of mean?
800         ** If so, we can go home.  Otherwise, we have to continue.
801         */
802         if(c_half_interval/ (*mean) <= (double)0.05)
803                 break;
804 
805 #ifdef OLDCODE
806 #undef OLDCODE
807 #endif
808 #ifdef OLDCODE
809 /* this code is no longer valid, we now do not replace but add new scores */
810 /* Uwe F. Mayer */
811 	      /*
812 	      ** Go get a new score and see if it
813 	      ** improves existing scores.
814 	      */
815 	      do {
816 		      if(*numtries==10)
817 			      return(-1);
818 		      (*funcpointer[fid])();
819 		      *numtries+=1;
820 		      newscore=getscore(fid);
821 	      } while(seek_confidence(myscores,&newscore,
822 		      &c_half_interval,mean,stdev)==0);
823 #endif
824 	/* We now simply add a new test run and hope that the runs
825            finally stabilize, Uwe F. Mayer */
826 	if(*numtries==30) return(-1);
827 	(*funcpointer[fid])();
828 	myscores[*numtries]=getscore(fid);
829 #ifdef DEBUG
830 	printf("score # %ld = %g\n", *numtries, myscores[*numtries]);
831 #endif
832 	*numtries+=1;
833 }
834 
835 return(0);
836 }
837 
838 #ifdef OLDCODE
839 /* this procecdure is no longer needed, Uwe F. Mayer */
840   /********************
841   ** seek_confidence **
842   *********************
843   ** Pass this routine an array of 5 scores PLUS a new score.
844   ** This routine tries the new score in place of each of
845   ** the other five scores to determine if the new score,
846   ** when replacing one of the others, improves the confidence
847   ** half-interval.
848   ** Return 0 if failure.  Original 5 scores unchanged.
849   ** Return -1 if success.  Also returns new half-interval,
850   ** mean, and standard deviation of the sample.
851   */
seek_confidence(double scores[5],double * newscore,double * c_half_interval,double * smean,double * sdev)852   static int seek_confidence( double scores[5],
853   		double *newscore,
854   		double *c_half_interval,
855   		double *smean,
856   		double *sdev)
857   {
858   double sdev_to_beat;    /* Original sdev to be beaten */
859   double temp;            /* For doing a swap */
860   int is_beaten;          /* Indicates original was beaten */
861   int i;                  /* Index */
862 
863   /*
864   ** First calculate original standard deviation
865   */
866   calc_confidence(scores,c_half_interval,smean,sdev);
867   sdev_to_beat=*sdev;
868   is_beaten=-1;
869 
870   /*
871   ** Try to beat original score.  We'll come out of this
872   ** loop with a flag.
873   */
874   for(i=0;i<5;i++)
875   {
876   	temp=scores[i];
877   	scores[i]=*newscore;
878   	calc_confidence(scores,c_half_interval,smean,sdev);
879   	scores[i]=temp;
880   	if(sdev_to_beat>*sdev)
881   	{       is_beaten=i;
882   		sdev_to_beat=*sdev;
883   	}
884   }
885 
886   if(is_beaten!=-1)
887   {       scores[is_beaten]=*newscore;
888   	return(-1);
889   }
890   return(0);
891   }
892 #endif
893 
894 /********************
895 ** calc_confidence **
896 *********************
897 ** Given a set of numtries scores, calculate the confidence
898 ** half-interval.  We'll also return the sample mean and sample
899 ** standard deviation.
900 ** NOTE: This routines presumes a confidence of 95% and
901 ** a confidence coefficient of .95
902 ** returns 0 if there is an error, otherwise -1
903 */
calc_confidence(double scores[],int num_scores,double * c_half_interval,double * smean,double * sdev)904 static int calc_confidence(double scores[], /* Array of scores */
905 		int num_scores,             /* number of scores in array */
906                 double *c_half_interval,    /* Confidence half-int */
907                 double *smean,              /* Standard mean */
908                 double *sdev)               /* Sample stand dev */
909 {
910 /* Here is a list of the student-t distribution up to 29 degrees of
911    freedom. The value at 0 is bogus, as there is no value for zero
912    degrees of freedom. */
913 double student_t[30]={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 ,
914                              2.447 , 2.365 , 2.306 , 2.262 , 2.228 ,
915                              2.201 , 2.179 , 2.160 , 2.145 , 2.131 ,
916                              2.120 , 2.110 , 2.101 , 2.093 , 2.086 ,
917                              2.080 , 2.074 , 2.069 , 2.064 , 2.060 ,
918 		             2.056 , 2.052 , 2.048 , 2.045 };
919 int i;          /* Index */
920 if ((num_scores<2) || (num_scores>30)) {
921   output_string("Internal error: calc_confidence called with an illegal number of scores\n");
922   return(-1);
923 }
924 /*
925 ** First calculate mean.
926 */
927 *smean=(double)0.0;
928 for(i=0;i<num_scores;i++){
929   *smean+=scores[i];
930 }
931 *smean/=(double)num_scores;
932 
933 /* Get standard deviation */
934 *sdev=(double)0.0;
935 for(i=0;i<num_scores;i++) {
936   *sdev+=(scores[i]-(*smean))*(scores[i]-(*smean));
937 }
938 *sdev/=(double)(num_scores-1);
939 *sdev=sqrt(*sdev);
940 
941 /* Now calculate the length of the confidence half-interval.  For a
942 ** confidence level of 95% our confidence coefficient gives us a
943 ** multiplying factor of the upper .025 quartile of a t distribution
944 ** with num_scores-1 degrees of freedom, and dividing by sqrt(number of
945 ** observations). See any introduction to statistics.
946 */
947 *c_half_interval=student_t[num_scores-1] * (*sdev) / sqrt((double)num_scores);
948 return(0);
949 }
950 
951 /*************
952 ** getscore **
953 **************
954 ** Return the score for a particular benchmark.
955 */
getscore(int fid)956 static double getscore(int fid)
957 {
958 
959 /*
960 ** Fid tells us the function.  This is really a matter of
961 ** doing the proper coercion.
962 */
963 switch(fid)
964 {
965         case TF_NUMSORT:
966                 return(global_numsortstruct.sortspersec);
967         case TF_SSORT:
968                 return(global_strsortstruct.sortspersec);
969         case TF_BITOP:
970                 return(global_bitopstruct.bitopspersec);
971         case TF_FPEMU:
972                 return(global_emfloatstruct.emflops);
973         case TF_FFPU:
974                 return(global_fourierstruct.fflops);
975         case TF_ASSIGN:
976                 return(global_assignstruct.iterspersec);
977         case TF_IDEA:
978                 return(global_ideastruct.iterspersec);
979         case TF_HUFF:
980                 return(global_huffstruct.iterspersec);
981         case TF_NNET:
982                 return(global_nnetstruct.iterspersec);
983         case TF_LU:
984                 return(global_lustruct.iterspersec);
985 }
986 return((double)0.0);
987 }
988 
989 /******************
990 ** output_string **
991 *******************
992 ** Displays a string on the screen.  Also, if the flag
993 ** write_to_file is set, outputs the string to the output file.
994 ** Note, this routine presumes that you've included a carriage
995 ** return at the end of the buffer.
996 */
output_string(char * buffer)997 static void output_string(char *buffer)
998 {
999 
1000 printf("%s",buffer);
1001 if(write_to_file!=0)
1002         fprintf(global_ofile,"%s",buffer);
1003 return;
1004 }
1005 
1006 /***************
1007 ** show_stats **
1008 ****************
1009 ** This routine displays statistics for a particular benchmark.
1010 ** The benchmark is identified by its id.
1011 */
show_stats(int bid)1012 static void show_stats (int bid)
1013 {
1014 char buffer[80];        /* Display buffer */
1015 
1016 switch(bid)
1017 {
1018         case TF_NUMSORT:                /* Numeric sort */
1019                 sprintf(buffer,"  Number of arrays: %d\n",
1020                         global_numsortstruct.numarrays);
1021                 output_string(buffer);
1022                 sprintf(buffer,"  Array size: %ld\n",
1023                         global_numsortstruct.arraysize);
1024                 output_string(buffer);
1025                 break;
1026 
1027         case TF_SSORT:          /* String sort */
1028                 sprintf(buffer,"  Number of arrays: %d\n",
1029                         global_strsortstruct.numarrays);
1030                 output_string(buffer);
1031                 sprintf(buffer,"  Array size: %ld\n",
1032                         global_strsortstruct.arraysize);
1033                 output_string(buffer);
1034                 break;
1035 
1036         case TF_BITOP:          /* Bitmap operation */
1037                 sprintf(buffer,"  Operations array size: %ld\n",
1038                         global_bitopstruct.bitoparraysize);
1039                 output_string(buffer);
1040                 sprintf(buffer,"  Bitfield array size: %ld\n",
1041                         global_bitopstruct.bitfieldarraysize);
1042                 output_string(buffer);
1043                 break;
1044 
1045         case TF_FPEMU:          /* Floating-point emulation */
1046                 sprintf(buffer,"  Number of loops: %lu\n",
1047                         global_emfloatstruct.loops);
1048                 output_string(buffer);
1049                 sprintf(buffer,"  Array size: %lu\n",
1050                         global_emfloatstruct.arraysize);
1051                 output_string(buffer);
1052                 break;
1053 
1054         case TF_FFPU:           /* Fourier test */
1055                 sprintf(buffer,"  Number of coefficients: %lu\n",
1056                         global_fourierstruct.arraysize);
1057                 output_string(buffer);
1058                 break;
1059 
1060         case TF_ASSIGN:
1061                 sprintf(buffer,"  Number of arrays: %lu\n",
1062                         global_assignstruct.numarrays);
1063                 output_string(buffer);
1064                 break;
1065 
1066         case TF_IDEA:
1067                 sprintf(buffer,"  Array size: %lu\n",
1068                         global_ideastruct.arraysize);
1069                 output_string(buffer);
1070                 sprintf(buffer," Number of loops: %lu\n",
1071                         global_ideastruct.loops);
1072                 output_string(buffer);
1073                 break;
1074 
1075         case TF_HUFF:
1076                 sprintf(buffer,"  Array size: %lu\n",
1077                         global_huffstruct.arraysize);
1078                 output_string(buffer);
1079                 sprintf(buffer,"  Number of loops: %lu\n",
1080                         global_huffstruct.loops);
1081                 output_string(buffer);
1082                 break;
1083 
1084         case TF_NNET:
1085                 sprintf(buffer,"  Number of loops: %lu\n",
1086                         global_nnetstruct.loops);
1087                 output_string(buffer);
1088                 break;
1089 
1090         case TF_LU:
1091                 sprintf(buffer,"  Number of arrays: %lu\n",
1092                         global_lustruct.numarrays);
1093                 output_string(buffer);
1094                 break;
1095 }
1096 return;
1097 }
1098 
1099 /*
1100 ** Following code added for Mac stuff, so that we can emulate command
1101 ** lines.
1102 */
1103 
1104 #ifdef MAC
1105 
1106 /*****************
1107 ** UCommandLine **
1108 ******************
1109 ** Reads in a command line, and sets up argc and argv appropriately.
1110 ** Note that this routine uses gets() to read in the line.  This means
1111 ** you'd better not enter more than 128 characters on a command line, or
1112 ** things will overflow, and oh boy...
1113 */
UCommandLine(void)1114 void UCommandLine(void)
1115 {
1116 printf("Enter command line\n:");
1117 gets((char *)Uargbuff);
1118 UParse();
1119 return;
1120 }
1121 
1122 /***********
1123 ** UParse **
1124 ************
1125 ** Parse the pseudo command-line.  This code appeared as part of the
1126 ** Small-C library in Dr. Dobb's ToolBook of C.
1127 ** It expects the following globals:
1128 ** argc = arg count
1129 ** argv = Pointer to array of char pointers
1130 ** Uargbuff = Character array that holds the arguments.  Should be 129 bytes long.
1131 ** Udummy1 = This is a 2-byte buffer that holds a "*", and acts as the first
1132 **  argument in the argument list.  This maintains compatibility with other
1133 **  C's, though it does not provide access to the executable filename.
1134 ** This routine allows for up to 20 individual command-line arguments.
1135 ** Also note that this routine does NOT allow for redirection.
1136 */
UParse(void)1137 void UParse(void)
1138 {
1139 unsigned char *ptr;
1140 
1141 argc=0;         /* Start arg count */
1142 Udummy[0]='*';  /* Set dummy first argument */
1143 Udummy[1]='\0';
1144 argv[argc++]=(char *)Udummy;
1145 
1146 ptr=Uargbuff;           /* Start pointer */
1147 while(*ptr)
1148 {
1149         if(isspace(*ptr))
1150         {       ++ptr;
1151                 continue;
1152         }
1153         if(argc<20) argv[argc++]=(char *)ptr;
1154         ptr=UField(ptr);
1155 }
1156 return;
1157 }
1158 /***********
1159 ** UField **
1160 ************
1161 ** Isolate the next command-line field.
1162 */
UField(unsigned char * ptr)1163 unsigned char *UField(unsigned char *ptr)
1164 {
1165 while(*ptr)
1166 {       if(isspace(*ptr))
1167         {       *ptr=(unsigned char)NULL;
1168                 return(++ptr);
1169         }
1170         ++ptr;
1171 }
1172 return(ptr);
1173 }
1174 #endif
1175