#include #include #include #include #include #include #include #include "nmglobal.h" #include "randnum.h" /******************** ** STRING HEAPSORT ** ********************/ static clock_t DoStringSortIteration(unsigned char *arraybase, unsigned int numarrays, unsigned long arraysize); static unsigned long *LoadStringArray(unsigned char *strarray, unsigned int numarrays, unsigned long *strings, unsigned long arraysize); static void stradjust(unsigned long *optrarray, unsigned char *strarray, unsigned long nstrings, unsigned long i, unsigned char l); static void StrHeapSort(unsigned long *optrarray, unsigned char *strarray, unsigned long numstrings, unsigned long bottom, unsigned long top); static int str_is_less(unsigned long *optrarray, unsigned char *strarray, unsigned long numstrings, unsigned long a, unsigned long b); static void strsift(unsigned long *optrarray, unsigned char *strarray, unsigned long numstrings, unsigned long i, unsigned long j); /***************** ** 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) { const char* context = "CPU:String Sort"; SortStruct* strsortstruct = &global_strsortstruct; unsigned char* arraybase = NULL; clock_t total_time = 0; int iterations = 0; /* ** See if we have to perform self-adjustment code */ if (strsortstruct->adjust == FALSE) { strsortstruct->adjust = TRUE; /* ** 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 = realloc(arraybase, (strsortstruct->arraysize + 100) * strsortstruct->numarrays); if (!arraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } /* ** 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; } ++strsortstruct->numarrays; } } else { /* ** We don't have to perform self adjustment code. ** Simply allocate the space for the array. */ arraybase = malloc((strsortstruct->arraysize + 100) * strsortstruct->numarrays); if (!arraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } } do { total_time += DoStringSortIteration(arraybase, strsortstruct->numarrays, strsortstruct->arraysize); iterations += strsortstruct->numarrays; } while (total_time < strsortstruct->request_secs * CLOCKS_PER_SEC); free(arraybase); strsortstruct->sortspersec = (double)(iterations * CLOCKS_PER_SEC) / (double)total_time; } /************************** ** 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 clock_t DoStringSortIteration(unsigned char *arraybase, unsigned int numarrays,unsigned long arraysize) { unsigned long *optrarray; /* Offset pointer array */ clock_t start, stop; unsigned long nstrings; /* # of strings in array */ 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 = clock(); for(i = 0; i < numarrays; i++) { StrHeapSort(tempobase, tempsbase, nstrings, 0L, nstrings - 1); tempobase += nstrings; /* Advance base pointers */ tempsbase += arraysize+100; } stop = clock(); free(optrarray); return stop - start; } /******************** ** LoadStringArray ** ********************* ** Initialize the string array with random strings of ** varying sizes. ** Returns the pointer to the offset pointer array. ** Note that since we're creating a number of arrays, this ** routine builds one array, then copies it into the others. */ static unsigned long *LoadStringArray(unsigned char *strarray, /* String array */ unsigned int numarrays, /* # of arrays */ unsigned long *nstrings, /* # of strings */ unsigned long arraysize) /* Size of array */ { unsigned char *tempsbase; /* Temporary string base pointer */ unsigned long *optrarray; /* Local for pointer */ unsigned long *tempobase; /* Temporary offset pointer base pointer */ unsigned long curroffset; /* Current offset */ int fullflag; /* Indicates full array */ unsigned char stringlength; /* Length of string */ unsigned char i; /* Index */ unsigned long j; /* Another index */ unsigned int k; /* Yet another index */ unsigned int l; /* Ans still one more index */ /* ** Initialize random number generator. */ /* randnum(13L); */ randnum((int32_t)13); /* ** Start with no strings. Initialize our current offset pointer ** to 0. */ *nstrings=0L; curroffset=0L; fullflag=0; do { /* ** Allocate a string with a random length no ** shorter than 4 bytes and no longer than ** 80 bytes. Note we have to also make sure ** there's room in the array. */ /* stringlength=(unsigned char)((1+abs_randwc(76L)) & 0xFFL);*/ stringlength=(unsigned char)((1+abs_randwc((int32_t)76)) & 0xFFL); if((unsigned long)stringlength+curroffset+1L>=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; memmove(&temp[0], strarray, tlen + 1); /* string[0]=string[i] */ tlen=*(strarray+*(optrarray+i)); stradjust(optrarray,strarray,numstrings,0,tlen); memmove(strarray, (strarray + *(optrarray + i)), tlen + 1); /* string[i]=temp */ tlen=temp[0]; stradjust(optrarray,strarray,numstrings,i,tlen); memmove(strarray + *(optrarray + i), &temp[0], tlen + 1); } } /**************** ** 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