#include /*#include #include #include #include #include */ #include "nmglobal.h" #include "nbench1.h" #ifdef DEBUG static int numsort_status=0; static int stringsort_status=0; #endif /******************** ** STRING HEAPSORT ** ********************/ /***************** ** DoStringSort ** ****************** ** This routine performs the CPU string sort test. ** Arguments: ** requested_secs = # of seconds to execute test ** stringspersec = # of strings per second sorted (RETURNED) */ void DoStringSort(void) { SortStruct *strsortstruct; /* Local for sort structure */ unsigned char *arraybase; /* Base pointer of char array */ long accumtime; /* Accumulated time */ double iterations; /* # of iterations */ char *errorcontext; /* Error context string pointer */ int systemerror; /* For holding error code */ /* ** Link to global structure */ strsortstruct=&global_strsortstruct; /* ** Set the error context */ errorcontext="CPU:String Sort"; /* ** See if we have to perform self-adjustment code */ if(strsortstruct->adjust==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=(unsigned char *)AllocateMemory((strsortstruct->arraysize+100L) * (long)strsortstruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); } /* ** 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((void *)arraybase,&systemerror); strsortstruct->numarrays+=1; } } else { /* ** We don't have to perform self adjustment code. ** Simply allocate the space for the array. */ arraybase=(unsigned char *)AllocateMemory((strsortstruct->arraysize+100L) * (long)strsortstruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); } } /* ** 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((void *)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 unsigned long DoStringSortIteration(unsigned char *arraybase, unsigned int numarrays,unsigned long arraysize) { unsigned long *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 */ unsigned long *tempobase; /* Temporary offset pointer base */ unsigned char *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((void *)&temp[0], /* Perform exchange */ (void *)strarray, (unsigned long)(tlen+1)); /* string[0]=string[i] */ tlen=*(strarray+*(optrarray+i)); stradjust(optrarray,strarray,numstrings,0,tlen); MoveMemory((void *)strarray, (void *)(strarray+*(optrarray+i)), (unsigned long)(tlen+1)); /* string[i]=temp */ tlen=temp[0]; stradjust(optrarray,strarray,numstrings,i,tlen); MoveMemory((void *)(strarray+*(optrarray+i)), (void *)&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(unsigned long *optrarray, /* Offset pointers */ unsigned char *strarray, /* String array */ unsigned long numstrings, /* # of strings */ unsigned long a, unsigned long 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(unsigned long *optrarray, /* Offset pointers */ unsigned char *strarray, /* String array */ unsigned long numstrings, /* # of strings */ unsigned long i, unsigned long j) /* Offsets */ { unsigned long k; /* Temporaries */ unsigned char temp[80]; unsigned char tlen; /* For string lengths */ while((i+i)<=j) { k=i+i; if(k