/* ** nbench1.c */ /******************************** ** BYTEmark (tm) ** ** BYTE NATIVE MODE BENCHMARKS ** ** VERSION 2 ** ** ** ** Included in this source ** ** file: ** ** Numeric Heapsort ** ** String Heapsort ** ** Bitfield test ** ** Floating point emulation ** ** Fourier coefficients ** ** Assignment algorithm ** ** IDEA Encyption ** ** Huffman compression ** ** Back prop. neural net ** ** LU Decomposition ** ** (linear equations) ** ** ---------- ** ** Rick Grehan, BYTE Magazine ** ********************************* ** ** BYTEmark (tm) ** BYTE's Native Mode Benchmarks ** Rick Grehan, BYTE Magazine ** ** Creation: ** Revision: 3/95;10/95 ** 10/95 - Removed allocation that was taking place inside ** the LU Decomposition benchmark. Though it didn't seem to ** make a difference on systems we ran it on, it nonetheless ** removes an operating system dependency that probably should ** not have been there. ** ** DISCLAIMER ** The source, executable, and documentation files that comprise ** the BYTEmark benchmarks are made available on an "as is" basis. ** This means that we at BYTE Magazine have made every reasonable ** effort to verify that the there are no errors in the source and ** executable code. We cannot, however, guarantee that the programs ** are error-free. Consequently, McGraw-HIll and BYTE Magazine make ** no claims in regard to the fitness of the source code, executable ** code, and documentation of the BYTEmark. ** Furthermore, BYTE Magazine, McGraw-Hill, and all employees ** of McGraw-Hill cannot be held responsible for any damages resulting ** from the use of this code or the results obtained from using ** this code. */ /* ** INCLUDES */ #include #include #include #include #include #include "nmglobal.h" #include "nbench1.h" #include "wordcat.h" #ifdef DEBUG static int numsort_status=0; static int stringsort_status=0; #endif /********************* ** NUMERIC HEAPSORT ** ********************** ** This test implements a heapsort algorithm, performed on an ** array of longs. */ /************** ** DoNumSort ** *************** ** This routine performs the CPU numeric sort test. ** NOTE: Last version incorrectly stated that the routine ** returned result in # of longword sorted per second. ** Not so; the routine returns # of iterations per sec. */ void DoNumSort(void) { SortStruct *numsortstruct; /* Local pointer to global struct */ farlong *arraybase; /* Base pointers of array */ long accumtime; /* Accumulated time */ double iterations; /* Iteration counter */ char *errorcontext; /* Error context string pointer */ int systemerror; /* For holding error codes */ /* ** Link to global structure */ numsortstruct=&global_numsortstruct; /* ** Set the error context string. */ errorcontext="CPU:Numeric Sort"; /* ** See if we need to do self adjustment code. */ if(numsortstruct->adjust==0) { /* ** Self-adjustment code. The system begins by sorting 1 ** array. If it does that in no time, then two arrays ** are built and sorted. This process continues until ** enough arrays are built to handle the tolerance. */ numsortstruct->numarrays=1; while(1) { /* ** Allocate space for arrays */ arraybase=(farlong *)AllocateMemory(sizeof(long) * numsortstruct->numarrays * numsortstruct->arraysize, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)arraybase, &systemerror); ErrorExit(); } /* ** Do an iteration of the numeric sort. If the ** elapsed time is less than or equal to the permitted ** minimum, then allocate for more arrays and ** try again. */ if(DoNumSortIteration(arraybase, numsortstruct->arraysize, numsortstruct->numarrays)>global_min_ticks) break; /* We're ok...exit */ FreeMemory((farvoid *)arraybase,&systemerror); if(numsortstruct->numarrays++>NUMNUMARRAYS) { printf("CPU:NSORT -- NUMNUMARRAYS hit.\n"); ErrorExit(); } } } else { /* ** Allocate space for arrays */ arraybase=(farlong *)AllocateMemory(sizeof(long) * numsortstruct->numarrays * numsortstruct->arraysize, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)arraybase, &systemerror); ErrorExit(); } } /* ** All's well if we get here. Repeatedly perform sorts until the ** accumulated elapsed time is greater than # of seconds requested. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoNumSortIteration(arraybase, numsortstruct->arraysize, numsortstruct->numarrays); iterations+=(double)1.0; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ FreeMemory((farvoid *)arraybase,&systemerror); numsortstruct->sortspersec=iterations * (double)numsortstruct->numarrays / TicksToFracSecs(accumtime); if(numsortstruct->adjust==0) numsortstruct->adjust=1; #ifdef DEBUG if (numsort_status==0) printf("Numeric sort: OK\n"); numsort_status=0; #endif return; } /*********************** ** DoNumSortIteration ** ************************ ** This routine executes one iteration of the numeric ** sort benchmark. It returns the number of ticks ** elapsed for the iteration. */ static ulong DoNumSortIteration(farlong *arraybase, ulong arraysize, uint numarrays) { ulong elapsed; /* Elapsed ticks */ ulong i; /* ** Load up the array with random numbers */ LoadNumArrayWithRand(arraybase,arraysize,numarrays); /* ** Start the stopwatch */ elapsed=StartStopwatch(); /* ** Execute a heap of heapsorts */ for(i=0;i0; --i) NumSift(array,i,top); /* ** Repeatedly extract maximum from heap and place it at the ** end of the array. When we get done, we'll have a sorted ** array. */ for(i=top; i>0; --i) { NumSift(array,bottom,i); temp=*array; /* Perform exchange */ *array=*(array+i); *(array+i)=temp; } return; } /************ ** NumSift ** ************* ** Peforms the sift operation on a numeric array, ** constructing a heap in the array. */ static void NumSift(farlong *array, /* Array of numbers */ ulong i, /* Minimum of array */ ulong j) /* Maximum of array */ { unsigned long k; long temp; /* Used for exchange */ while((i+i)<=j) { k=i+i; if(kadjust==0) { /* ** Initialize the number of arrays. */ strsortstruct->numarrays=1; while(1) { /* ** Allocate space for array. We'll add an extra 100 ** bytes to protect memory as strings move around ** (this can happen during string adjustment) */ arraybase=(faruchar *)AllocateMemory((strsortstruct->arraysize+100L) * (long)strsortstruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } /* ** Do an iteration of the string sort. If the ** elapsed time is less than or equal to the permitted ** minimum, then de-allocate the array, reallocate a ** an additional array, and try again. */ if(DoStringSortIteration(arraybase, strsortstruct->numarrays, strsortstruct->arraysize)>global_min_ticks) break; /* We're ok...exit */ FreeMemory((farvoid *)arraybase,&systemerror); strsortstruct->numarrays+=1; } } else { /* ** We don't have to perform self adjustment code. ** Simply allocate the space for the array. */ arraybase=(faruchar *)AllocateMemory((strsortstruct->arraysize+100L) * (long)strsortstruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } } /* ** All's well if we get here. Repeatedly perform sorts until the ** accumulated elapsed time is greater than # of seconds requested. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoStringSortIteration(arraybase, strsortstruct->numarrays, strsortstruct->arraysize); iterations+=(double)strsortstruct->numarrays; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. ** Set flag to show we don't need to rerun adjustment code. */ FreeMemory((farvoid *)arraybase,&systemerror); strsortstruct->sortspersec=iterations / (double)TicksToFracSecs(accumtime); if(strsortstruct->adjust==0) strsortstruct->adjust=1; #ifdef DEBUG if (stringsort_status==0) printf("String sort: OK\n"); stringsort_status=0; #endif return; } /************************** ** DoStringSortIteration ** *************************** ** This routine executes one iteration of the string ** sort benchmark. It returns the number of ticks ** Note that this routine also builds the offset pointer ** array. */ static ulong DoStringSortIteration(faruchar *arraybase, uint numarrays,ulong arraysize) { farulong *optrarray; /* Offset pointer array */ unsigned long elapsed; /* Elapsed ticks */ unsigned long nstrings; /* # of strings in array */ int syserror; /* System error code */ unsigned int i; /* Index */ farulong *tempobase; /* Temporary offset pointer base */ faruchar *tempsbase; /* Temporary string base pointer */ /* ** Load up the array(s) with random numbers */ optrarray=LoadStringArray(arraybase,numarrays,&nstrings,arraysize); /* ** Set temp base pointers...they will be modified as the ** benchmark proceeds. */ tempobase=optrarray; tempsbase=arraybase; /* ** Start the stopwatch */ elapsed=StartStopwatch(); /* ** Execute heapsorts */ for(i=0;i=arraysize) { stringlength=(unsigned char)((arraysize-curroffset-1L) & 0xFF); fullflag=1; /* Indicates a full */ } /* ** Store length at curroffset and advance current offset. */ *(strarray+curroffset)=stringlength; curroffset++; /* ** Fill up the rest of the string with random bytes. */ for(i=0;i0; --i) strsift(optrarray,strarray,numstrings,i,top); /* ** Repeatedly extract maximum from heap and place it at the ** end of the array. When we get done, we'll have a sorted ** array. */ for(i=top; i>0; --i) { strsift(optrarray,strarray,numstrings,0,i); /* temp = string[0] */ tlen=*strarray; MoveMemory((farvoid *)&temp[0], /* Perform exchange */ (farvoid *)strarray, (unsigned long)(tlen+1)); /* string[0]=string[i] */ tlen=*(strarray+*(optrarray+i)); stradjust(optrarray,strarray,numstrings,0,tlen); MoveMemory((farvoid *)strarray, (farvoid *)(strarray+*(optrarray+i)), (unsigned long)(tlen+1)); /* string[i]=temp */ tlen=temp[0]; stradjust(optrarray,strarray,numstrings,i,tlen); MoveMemory((farvoid *)(strarray+*(optrarray+i)), (farvoid *)&temp[0], (unsigned long)(tlen+1)); } return; } /**************** ** str_is_less ** ***************** ** Pass this function: ** 1) A pointer to an array of offset pointers ** 2) A pointer to a string array ** 3) The number of elements in the string array ** 4) Offsets to two strings (a & b) ** This function returns TRUE if string a is < string b. */ static int str_is_less(farulong *optrarray, /* Offset pointers */ faruchar *strarray, /* String array */ ulong numstrings, /* # of strings */ ulong a, ulong b) /* Offsets */ { int slen; /* String length */ /* ** Determine which string has the minimum length. Use that ** to call strncmp(). If they match up to that point, the ** string with the longer length wins. */ slen=(int)*(strarray+*(optrarray+a)); if(slen > (int)*(strarray+*(optrarray+b))) slen=(int)*(strarray+*(optrarray+b)); slen=strncmp((char *)(strarray+*(optrarray+a)), (char *)(strarray+*(optrarray+b)),slen); if(slen==0) { /* ** They match. Return true if the length of a ** is greater than the length of b. */ if(*(strarray+*(optrarray+a)) > *(strarray+*(optrarray+b))) return(TRUE); return(FALSE); } if(slen<0) return(TRUE); /* a is strictly less than b */ return(FALSE); /* Only other possibility */ } /************ ** strsift ** ************* ** Pass this function: ** 1) A pointer to an array of offset pointers ** 2) A pointer to a string array ** 3) The number of elements in the string array ** 4) Offset within which to sort. ** Sift the array within the bounds of those offsets (thus ** building a heap). */ static void strsift(farulong *optrarray, /* Offset pointers */ faruchar *strarray, /* String array */ ulong numstrings, /* # of strings */ ulong i, ulong j) /* Offsets */ { unsigned long k; /* Temporaries */ unsigned char temp[80]; unsigned char tlen; /* For string lengths */ while((i+i)<=j) { k=i+i; if(kadjust==0) { bitarraybase=(farulong *)AllocateMemory(locbitopstruct->bitfieldarraysize * sizeof(ulong),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } /* ** Initialize bitfield operations array to [2,30] elements */ locbitopstruct->bitoparraysize=30L; while(1) { /* ** Allocate space for operations array */ bitoparraybase=(farulong *)AllocateMemory(locbitopstruct->bitoparraysize*2L* sizeof(ulong), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)bitarraybase,&systemerror); ErrorExit(); } /* ** Do an iteration of the bitmap test. If the ** elapsed time is less than or equal to the permitted ** minimum, then de-allocate the array, reallocate a ** larger version, and try again. */ ticks=DoBitfieldIteration(bitarraybase, bitoparraybase, locbitopstruct->bitoparraysize, &nbitops); #ifdef DEBUG #ifdef LINUX if (locbitopstruct->bitoparraysize==30L){ /* this is the first loop, write a debug file */ FILE *file; unsigned long *running_base; /* same as farulong */ long counter; file=fopen("debugbit.dat","w"); running_base=bitarraybase; for (counter=0;counter<(long)(locbitopstruct->bitfieldarraysize);counter++){ #ifdef LONG64 fprintf(file,"%08X",(unsigned int)(*running_base&0xFFFFFFFFL)); fprintf(file,"%08X",(unsigned int)((*running_base>>32)&0xFFFFFFFFL)); if ((counter+1)%4==0) fprintf(file,"\n"); #else fprintf(file,"%08lX",*running_base); if ((counter+1)%8==0) fprintf(file,"\n"); #endif running_base=running_base+1; } fclose(file); printf("\nWrote the file debugbit.dat, you may want to compare it to debugbit.good\n"); } #endif #endif if (ticks>global_min_ticks) break; /* We're ok...exit */ FreeMemory((farvoid *)bitoparraybase,&systemerror); locbitopstruct->bitoparraysize+=100L; } } else { /* ** Don't need to do self adjustment, just allocate ** the array space. */ bitarraybase=(farulong *)AllocateMemory(locbitopstruct->bitfieldarraysize * sizeof(ulong),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } bitoparraybase=(farulong *)AllocateMemory(locbitopstruct->bitoparraysize*2L* sizeof(ulong), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)bitarraybase,&systemerror); ErrorExit(); } } /* ** All's well if we get here. Repeatedly perform bitops until the ** accumulated elapsed time is greater than # of seconds requested. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoBitfieldIteration(bitarraybase, bitoparraybase, locbitopstruct->bitoparraysize,&nbitops); iterations+=(double)nbitops; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. ** Also, set adjustment flag to show that we don't have ** to do self adjusting in the future. */ FreeMemory((farvoid *)bitarraybase,&systemerror); FreeMemory((farvoid *)bitoparraybase,&systemerror); locbitopstruct->bitopspersec=iterations /TicksToFracSecs(accumtime); if(locbitopstruct->adjust==0) locbitopstruct->adjust=1; return; } /************************ ** DoBitfieldIteration ** ************************* ** Perform a single iteration of the bitfield benchmark. ** Return the # of ticks accumulated by the operation. */ static ulong DoBitfieldIteration(farulong *bitarraybase, farulong *bitoparraybase, long bitoparraysize, ulong *nbitops) { long i; /* Index */ ulong bitoffset; /* Offset into bitmap */ ulong elapsed; /* Time to execute */ /* ** Clear # bitops counter */ *nbitops=0L; /* ** Construct a set of bitmap offsets and run lengths. ** The offset can be any random number from 0 to the ** size of the bitmap (in bits). The run length can ** be any random number from 1 to the number of bits ** between the offset and the end of the bitmap. ** Note that the bitmap has 8192 * 32 bits in it. ** (262,144 bits) */ /* ** Reset random number generator so things repeat. ** Also reset the bit array we work on. ** added by Uwe F. Mayer */ randnum((int32)13); for (i=0;i>6; /* Index is number /64 */ bitnumb=bit_addr % 64; /* Bit number in word */ #else bindex=bit_addr>>5; /* Index is number /32 */ bitnumb=bit_addr % 32; /* bit number in word */ #endif if(val) bitmap[bindex]|=(1L<>6; /* Index is number /64 */ bitnumb=bit_addr % 64; /* Bit number in longword */ #else bindex=bit_addr>>5; /* Index is number /32 */ bitnumb=bit_addr % 32; /* Bit number in longword */ #endif bitmap[bindex]^=(1L<arraysize*sizeof(InternalFPF), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } bbase=(InternalFPF *)AllocateMemory(locemfloatstruct->arraysize*sizeof(InternalFPF), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)abase,&systemerror); ErrorExit(); } cbase=(InternalFPF *)AllocateMemory(locemfloatstruct->arraysize*sizeof(InternalFPF), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); ErrorExit(); } /* ** Set up the arrays */ SetupCPUEmFloatArrays(abase,bbase,cbase,locemfloatstruct->arraysize); /* ** See if we need to do self-adjusting code. */ if(locemfloatstruct->adjust==0) { locemfloatstruct->loops=0; /* ** Do an iteration of the tests. If the elapsed time is ** less than minimum, increase the loop count and try ** again. */ for(loops=1;loopsarraysize, loops); if(tickcount>global_min_ticks) { locemfloatstruct->loops=loops; break; } } } /* ** Verify that selft adjustment code worked. */ if(locemfloatstruct->loops==0) { printf("CPU:EMFPU -- CMPUEMFLOATLOOPMAX limit hit\n"); FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); FreeMemory((farvoid *)cbase,&systemerror); ErrorExit(); } /* ** All's well if we get here. Repeatedly perform floating ** tests until the accumulated time is greater than the ** # of seconds requested. ** Each iteration performs arraysize * 3 operations. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoEmFloatIteration(abase,bbase,cbase, locemfloatstruct->arraysize, locemfloatstruct->loops); iterations+=(double)1.0; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. ** Also, indicate that adjustment is done. */ FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); FreeMemory((farvoid *)cbase,&systemerror); locemfloatstruct->emflops=(iterations*(double)locemfloatstruct->loops)/ (double)TicksToFracSecs(accumtime); if(locemfloatstruct->adjust==0) locemfloatstruct->adjust=1; #ifdef DEBUG printf("----------------------------------------------------------------------------\n"); #endif return; } /************************* ** FOURIER COEFFICIENTS ** *************************/ /************** ** DoFourier ** *************** ** Perform the transcendental/trigonometric portion of the ** benchmark. This benchmark calculates the first n ** fourier coefficients of the function (x+1)^x defined ** on the interval 0,2. */ void DoFourier(void) { FourierStruct *locfourierstruct; /* Local fourier struct */ fardouble *abase; /* Base of A[] coefficients array */ fardouble *bbase; /* Base of B[] coefficients array */ unsigned long accumtime; /* Accumulated time in ticks */ double iterations; /* # of iterations */ char *errorcontext; /* Error context string pointer */ int systemerror; /* For error code */ /* ** Link to global structure */ locfourierstruct=&global_fourierstruct; /* ** Set error context string */ errorcontext="FPU:Transcendental"; /* ** See if we need to do self-adjustment code. */ if(locfourierstruct->adjust==0) { locfourierstruct->arraysize=100L; /* Start at 100 elements */ while(1) { abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((void *)abase,&systemerror); ErrorExit(); } /* ** Do an iteration of the tests. If the elapsed time is ** less than or equal to the permitted minimum, re-allocate ** larger arrays and try again. */ if(DoFPUTransIteration(abase,bbase, locfourierstruct->arraysize)>global_min_ticks) break; /* We're ok...exit */ /* ** Make bigger arrays and try again. */ FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); locfourierstruct->arraysize+=50L; } } else { /* ** Don't need self-adjustment. Just allocate the ** arrays, and go. */ abase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } bbase=(fardouble *)AllocateMemory(locfourierstruct->arraysize*sizeof(double), &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((void *)abase,&systemerror); ErrorExit(); } } /* ** All's well if we get here. Repeatedly perform integration ** tests until the accumulated time is greater than the ** # of seconds requested. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoFPUTransIteration(abase,bbase,locfourierstruct->arraysize); iterations+=(double)locfourierstruct->arraysize*(double)2.0-(double)1.0; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. ** Also set adjustment flag to indicate no adjust code needed. */ FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); locfourierstruct->fflops=iterations/(double)TicksToFracSecs(accumtime); if(locfourierstruct->adjust==0) locfourierstruct->adjust=1; return; } /************************ ** DoFPUTransIteration ** ************************* ** Perform an iteration of the FPU Transcendental/trigonometric ** benchmark. Here, an iteration consists of calculating the ** first n fourier coefficients of the function (x+1)^x on ** the interval 0,2. n is given by arraysize. ** NOTE: The # of integration steps is fixed at ** 200. */ static ulong DoFPUTransIteration(fardouble *abase, /* A coeffs. */ fardouble *bbase, /* B coeffs. */ ulong arraysize) /* # of coeffs */ { double omega; /* Fundamental frequency */ unsigned long i; /* Index */ unsigned long elapsed; /* Elapsed time */ /* ** Start the stopwatch */ elapsed=StartStopwatch(); /* ** Calculate the fourier series. Begin by ** calculating A[0]. */ *abase=TrapezoidIntegrate((double)0.0, (double)2.0, 200, (double)0.0, /* No omega * n needed */ 0 )/(double)2.0; /* ** Calculate the fundamental frequency. ** ( 2 * pi ) / period...and since the period ** is 2, omega is simply pi. */ omega=(double)3.1415926535897932; for(i=1;iadjust==0) { /* ** Self-adjustment code. The system begins by working on 1 ** array. If it does that in no time, then two arrays ** are built. This process continues until ** enough arrays are built to handle the tolerance. */ locassignstruct->numarrays=1; while(1) { /* ** Allocate space for arrays */ arraybase=(farlong *) AllocateMemory(sizeof(long)* ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)arraybase, &systemerror); ErrorExit(); } /* ** Do an iteration of the assignment alg. If the ** elapsed time is less than or equal to the permitted ** minimum, then allocate for more arrays and ** try again. */ if(DoAssignIteration(arraybase, locassignstruct->numarrays)>global_min_ticks) break; /* We're ok...exit */ FreeMemory((farvoid *)arraybase, &systemerror); locassignstruct->numarrays++; } } else { /* ** Allocate space for arrays */ arraybase=(farlong *)AllocateMemory(sizeof(long)* ASSIGNROWS*ASSIGNCOLS*locassignstruct->numarrays, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)arraybase, &systemerror); ErrorExit(); } } /* ** All's well if we get here. Do the tests. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoAssignIteration(arraybase, locassignstruct->numarrays); iterations+=(double)1.0; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ FreeMemory((farvoid *)arraybase,&systemerror); locassignstruct->iterspersec=iterations * (double)locassignstruct->numarrays / TicksToFracSecs(accumtime); if(locassignstruct->adjust==0) locassignstruct->adjust=1; return; } /********************** ** DoAssignIteration ** *********************** ** This routine executes one iteration of the assignment test. ** It returns the number of ticks elapsed in the iteration. */ static ulong DoAssignIteration(farlong *arraybase, ulong numarrays) { longptr abase; /* local pointer */ ulong elapsed; /* Elapsed ticks */ ulong i; /* ** Set up local pointer */ abase.ptrs.p=arraybase; /* ** Load up the arrays with a random table. */ LoadAssignArrayWithRand(arraybase,numarrays); /* ** Start the stopwatch */ elapsed=StartStopwatch(); /* ** Execute assignment algorithms */ for(i=0;i1) for(i=1;i>encrypt>> crypt1 >>decrypt>> plain2. ** So, plain1 and plain2 should match. ** Also, fill up plain1 with sample text. */ plain1=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } crypt1=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)plain1,&systemerror); ErrorExit(); } plain2=(faruchar *)AllocateMemory(locideastruct->arraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory((farvoid *)plain1,&systemerror); FreeMemory((farvoid *)crypt1,&systemerror); ErrorExit(); } /* ** Note that we build the "plaintext" by simply loading ** the array up with random numbers. */ for(i=0;iarraysize;i++) plain1[i]=(uchar)(abs_randwc(255) & 0xFF); /* ** See if we need to perform self adjustment loop. */ if(locideastruct->adjust==0) { /* ** Do self-adjustment. This involves initializing the ** # of loops and increasing the loop count until we ** get a number of loops that we can use. */ for(locideastruct->loops=100L; locideastruct->loopsloops+=10L) if(DoIDEAIteration(plain1,crypt1,plain2, locideastruct->arraysize, locideastruct->loops, Z,DK)>global_min_ticks) break; } /* ** All's well if we get here. Do the test. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoIDEAIteration(plain1,crypt1,plain2, locideastruct->arraysize, locideastruct->loops,Z,DK); iterations+=(double)locideastruct->loops; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ FreeMemory((farvoid *)plain1,&systemerror); FreeMemory((farvoid *)crypt1,&systemerror); FreeMemory((farvoid *)plain2,&systemerror); locideastruct->iterspersec=iterations / TicksToFracSecs(accumtime); if(locideastruct->adjust==0) locideastruct->adjust=1; return; } /******************** ** DoIDEAIteration ** ********************* ** Execute a single iteration of the IDEA encryption algorithm. ** Actually, a single iteration is one encryption and one ** decryption. */ static ulong DoIDEAIteration(faruchar *plain1, faruchar *crypt1, faruchar *plain2, ulong arraysize, ulong nloops, IDEAkey Z, IDEAkey DK) { register ulong i; register ulong j; ulong elapsed; #ifdef DEBUG int status=0; #endif /* ** Start the stopwatch. */ elapsed=StartStopwatch(); /* ** Do everything for nloops. */ for(i=0;i>16); return(b-a+(b> 7); Z+=i&8; i&=7; } return; } /**************** ** de_key_idea ** ***************** ** Compute IDEA decryption subkeys DK from encryption ** subkeys Z. */ static void de_key_idea(IDEAkey Z, IDEAkey DK) { IDEAkey TT; int j; u16 t1, t2, t3; u16 *p; p=(u16 *)(TT+KEYLEN); t1=inv(*Z++); t2=-*Z++; t3=-*Z++; *--p=inv(*Z++); *--p=t3; *--p=t2; *--p=t1; for(j=1;jarraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); ErrorExit(); } comparray=(farchar *)AllocateMemory(lochuffstruct->arraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory(plaintext,&systemerror); ErrorExit(); } decomparray=(farchar *)AllocateMemory(lochuffstruct->arraysize,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory(plaintext,&systemerror); FreeMemory(comparray,&systemerror); ErrorExit(); } hufftree=(huff_node *)AllocateMemory(sizeof(huff_node) * 512, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); FreeMemory(plaintext,&systemerror); FreeMemory(comparray,&systemerror); FreeMemory(decomparray,&systemerror); ErrorExit(); } /* ** Build the plaintext buffer. Since we want this to ** actually be able to compress, we'll use the ** wordcatalog to build the plaintext stuff. */ /* ** Reset random number generator so things repeat. ** added by Uwe F. Mayer */ randnum((int32)13); create_text_block(plaintext,lochuffstruct->arraysize-1,(ushort)500); plaintext[lochuffstruct->arraysize-1L]='\0'; plaintextlen=lochuffstruct->arraysize; /* ** See if we need to perform self adjustment loop. */ if(lochuffstruct->adjust==0) { /* ** Do self-adjustment. This involves initializing the ** # of loops and increasing the loop count until we ** get a number of loops that we can use. */ for(lochuffstruct->loops=100L; lochuffstruct->loopsloops+=10L) if(DoHuffIteration(plaintext, comparray, decomparray, lochuffstruct->arraysize, lochuffstruct->loops, hufftree)>global_min_ticks) break; } /* ** All's well if we get here. Do the test. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoHuffIteration(plaintext, comparray, decomparray, lochuffstruct->arraysize, lochuffstruct->loops, hufftree); iterations+=(double)lochuffstruct->loops; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ FreeMemory((farvoid *)plaintext,&systemerror); FreeMemory((farvoid *)comparray,&systemerror); FreeMemory((farvoid *)decomparray,&systemerror); FreeMemory((farvoid *)hufftree,&systemerror); lochuffstruct->iterspersec=iterations / TicksToFracSecs(accumtime); if(lochuffstruct->adjust==0) lochuffstruct->adjust=1; } /********************* ** create_text_line ** ********************** ** Create a random line of text, stored at *dt. The line may be ** no more than nchars long. */ static void create_text_line(farchar *dt, long nchars) { long charssofar; /* # of characters so far */ long tomove; /* # of characters to move */ char myword[40]; /* Local buffer for words */ farchar *wordptr; /* Pointer to word from catalog */ charssofar=0; do { /* ** Grab a random word from the wordcatalog */ /* wordptr=wordcatarray[abs_randwc((long)WORDCATSIZE)];*/ wordptr=wordcatarray[abs_randwc((int32)WORDCATSIZE)]; MoveMemory((farvoid *)myword, (farvoid *)wordptr, (unsigned long)strlen(wordptr)+1); /* ** Append a blank. */ tomove=strlen(myword)+1; myword[tomove-1]=' '; /* ** See how long it is. If its length+charssofar > nchars, we have ** to trim it. */ if((tomove+charssofar)>nchars) tomove=nchars-charssofar; /* ** Attach the word to the current line. Increment counter. */ MoveMemory((farvoid *)dt,(farvoid *)myword,(unsigned long)tomove); charssofar+=tomove; dt+=tomove; /* ** If we're done, bail out. Otherwise, go get another word. */ } while(charssofartblen) linelen=tblen-bytessofar; if(linelen>1) { create_text_line(tb,linelen); } tb+=linelen-1; /* Add the carriage return */ *tb++='\n'; bytessofar+=linelen; } while(bytessofar>3; bitnumb=bitoffset % 8; /* ** Set or clear */ if(bitchar=='1') comparray[byteoffset]|=(1<>3; bitnumb=bitoffset % 8; /* ** Fetch */ return((1<adjust==0) { /* ** Do self-adjustment. This involves initializing the ** # of loops and increasing the loop count until we ** get a number of loops that we can use. */ for(locnnetstruct->loops=1L; locnnetstruct->loopsloops++) { /*randnum(3L); */ randnum((int32)3); if(DoNNetIteration(locnnetstruct->loops) >global_min_ticks) break; } } /* ** All's well if we get here. Do the test. */ accumtime=0L; iterations=(double)0.0; do { /* randnum(3L); */ /* Gotta do this for Neural Net */ randnum((int32)3); /* Gotta do this for Neural Net */ accumtime+=DoNNetIteration(locnnetstruct->loops); iterations+=(double)locnnetstruct->loops; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ locnnetstruct->iterspersec=iterations / TicksToFracSecs(accumtime); if(locnnetstruct->adjust==0) locnnetstruct->adjust=1; return; } /******************** ** DoNNetIteration ** ********************* ** Do a single iteration of the neural net benchmark. ** By iteration, we mean a "learning" pass. */ static ulong DoNNetIteration(ulong nloops) { ulong elapsed; /* Elapsed time */ int patt; /* ** Run nloops learning cycles. Notice that, counted with ** the learning cycle is the weight randomization and ** zeroing of changes. This should reduce clock jitter, ** since we don't have to stop and start the clock for ** each iteration. */ elapsed=StartStopwatch(); while(nloops--) { randomize_wts(); zero_changes(); iteration_count=1; learned = F; numpasses = 0; while (learned == F) { for (patt=0; patt tot_error) tot_error = -error; /* worst error this pattern */ } else { sum += error; if (error > tot_error) tot_error = error; /* worst error this pattern */ } } avg_out_error[patt] = sum/OUT_SIZE; tot_out_error[patt] = tot_error; return; } /*********************** ** worst_pass_error() ** ************************ ** Find the worst and average error in the pass and save it **/ static void worst_pass_error() { double error,sum; int i; error = 0.0; sum = 0.0; for (i=0; i error) error = tot_out_error[i]; sum += avg_out_error[i]; } worst_error = error; average_error = sum/numpats; return; } /******************* ** do_mid_error() ** ******************** ** Compute the error for the middle layer neurodes ** This is based on the output errors computed above. ** Note that the derivative of the sigmoid f(x) is ** f'(x) = f(x)(1 - f(x)) ** Recall that f(x) is merely the output of the middle ** layer neurode on the forward pass. **/ static void do_mid_error() { double sum; int neurode, i; for (neurode=0; neurode= STOP) result = F; if (tot_out_error[i] >= 16.0) error = T; } if (error == T) result = ERR; #ifdef DEBUG /* printf("\n Error this pass thru data: Worst: %8.3f; Average: %8.3f", worst_error,average_error); */ /* fprintf(outfile, "\n Error this pass thru data: Worst: %8.3f; Average: %8.3f", worst_error, average_error); */ #endif return(result); } /******************* ** zero_changes() ** ******************** ** Zero out all the wt change arrays **/ static void zero_changes() { int i,j; for (i = 0; i MAXPATS) numpats = MAXPATS; for (patt=0; patt= 0.9) in_pats[patt][i] = 0.9; if (in_pats[patt][i] <= 0.1) in_pats[patt][i] = 0.1; } element = 0; vals_read = fscanf(infile,"%d %d %d %d %d %d %d %d", &val1, &val2, &val3, &val4, &val5, &val6, &val7, &val8); out_pats[patt][element] = (double) val1; element++; out_pats[patt][element] = (double) val2; element++; out_pats[patt][element] = (double) val3; element++; out_pats[patt][element] = (double) val4; element++; out_pats[patt][element] = (double) val5; element++; out_pats[patt][element] = (double) val6; element++; out_pats[patt][element] = (double) val7; element++; out_pats[patt][element] = (double) val8; element++; } /* printf("\n Closing the input file now. "); */ fclose(infile); return(0); } /********************* ** initialize_net() ** ********************** ** Do all the initialization stuff before beginning */ /* static int initialize_net() { int err_code; randomize_wts(); zero_changes(); err_code = read_data_file(); iteration_count = 1; return(err_code); } */ /********************** ** display_mid_wts() ** *********************** ** Display the weights on the middle layer neurodes ** NOTE: This routine is not used in the benchmark ** test -- RG **/ /* static void display_mid_wts() { int neurode, weight, row, col; fprintf(outfile,"\n Weights of Middle Layer neurodes:"); for (neurode=0; neurodeadjust==0) { loclustruct->numarrays=0; for(i=1;i<=MAXLUARRAYS;i++) { abase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL); ErrorExit(); } bbase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(fardouble *)NULL); ErrorExit(); } if(DoLUIteration(a,b,abase,bbase,i)>global_min_ticks) { loclustruct->numarrays=i; break; } /* ** Not enough arrays...free them all and try again */ FreeMemory((farvoid *)abase,&systemerror); FreeMemory((farvoid *)bbase,&systemerror); } /* ** Were we able to do it? */ if(loclustruct->numarrays==0) { printf("FPU:LU -- Array limit reached\n"); LUFreeMem(a,b,abase,bbase); ErrorExit(); } } else { /* ** Don't need to adjust -- just allocate the proper ** number of arrays and proceed. */ abase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*loclustruct->numarrays, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL); ErrorExit(); } bbase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYROWS*loclustruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(fardouble *)NULL); ErrorExit(); } } /* ** All's well if we get here. Do the test. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoLUIteration(a,b,abase,bbase, loclustruct->numarrays); iterations+=(double)loclustruct->numarrays; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ loclustruct->iterspersec=iterations / TicksToFracSecs(accumtime); if(loclustruct->adjust==0) loclustruct->adjust=1; LUFreeMem(a,b,abase,bbase); return; } /************** ** LUFreeMem ** *************** ** Release memory associated with LU benchmark. */ static void LUFreeMem(fardouble *a, fardouble *b, fardouble *abase,fardouble *bbase) { int systemerror; FreeMemory((farvoid *)a,&systemerror); FreeMemory((farvoid *)b,&systemerror); FreeMemory((farvoid *)LUtempvv,&systemerror); if(abase!=(fardouble *)NULL) FreeMemory((farvoid *)abase,&systemerror); if(bbase!=(fardouble *)NULL) FreeMemory((farvoid *)bbase,&systemerror); return; } /****************** ** DoLUIteration ** ******************* ** Perform an iteration of the LU decomposition benchmark. ** An iteration refers to the repeated solution of several ** identical matrices. */ static ulong DoLUIteration(fardouble *a,fardouble *b, fardouble *abase, fardouble *bbase, ulong numarrays) { fardouble *locabase; fardouble *locbbase; LUdblptr ptra; /* For converting ptr to 2D array */ ulong elapsed; ulong j,i; /* Indexes */ /* ** Move the seed arrays (a & b) into the destination ** arrays; */ for(j=0;j big) big=fabs(a[i][j]); /* Bail out on singular matrix */ if(big==(double)0.0) return(0); LUtempvv[i]=1.0/big; } /* ** Crout's algorithm...loop over columns. */ for(j=0;j=big) { big=dum; imax=i; } } if(j!=imax) /* Interchange rows if necessary */ { for(k=0;k=0;i--) { sum=b[i]; if(i!=(n-1)) for(j=(i+1);j