#include #include #include #include #include #include #include #include #include "cleanbench.h" #include "randnum.h" /******************** ** STRING HEAPSORT ** ********************/ /* ** The following constant STRINGARRAYSIZE determines ** the default # of bytes allocated to each string array. */ #define ARRAY_SIZE 8111 static clock_t DoStringSortIteration(unsigned char *array, unsigned int num_arrays); static unsigned long *LoadStringArray(unsigned char *strarray, unsigned int num_arrays, unsigned long *strings); 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 top); static int str_is_less(unsigned long *optrarray, unsigned char *strarray, 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 ** *****************/ double DoStringSort(void) { unsigned char* array = NULL; clock_t total_time = 0; int iterations = 0; static int num_arrays = 0; static bool is_adjusted = false; if (is_adjusted == false) { is_adjusted = true; /* ** Initialize the number of arrays. */ do { ++num_arrays; /* ** Allocate space for array. We'll add an extra 100 ** bytes to protect memory as strings move around ** (this can happen during string adjustment) */ array = realloc(array, (ARRAY_SIZE + 100) * num_arrays); /* ** 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. */ } while (DoStringSortIteration(array, num_arrays) <= MINIMUM_TICKS); } else { /* ** We don't have to perform self adjustment code. ** Simply allocate the space for the array. */ array = malloc((ARRAY_SIZE + 100) * num_arrays); } do { total_time += DoStringSortIteration(array, num_arrays); iterations += num_arrays; } while (total_time < MINIMUM_SECONDS * CLOCKS_PER_SEC); free(array); return (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 *array, unsigned int num_arrays) { 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(array,num_arrays,&nstrings); /* ** Set temp base pointers...they will be modified as the ** benchmark proceeds. */ tempobase = optrarray; tempsbase = array; start = clock(); for(i = 0; i < num_arrays; i++) { StrHeapSort(tempobase, tempsbase, nstrings, nstrings - 1); tempobase += nstrings; /* Advance base pointers */ tempsbase += ARRAY_SIZE + 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 num_arrays, /* # of arrays */ unsigned long *nstrings) /* # of strings */ { 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>=ARRAY_SIZE) { stringlength=(unsigned char)((ARRAY_SIZE-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 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