void sort_array (ARRAY array, OBJCMPFNC cmp, VPTR param) { struct tag_sort_array_info info; info.cmp = cmp; info.param = param; partition_sort((SORTEL *)&AData(array)[0], ASize(array), array_comparator, &info); }
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { /* Sort an array (base) with nmemb items each of size bytes. */ /* This uses a quicksort method, but one that is arranged to complete in */ /* about n*log(n) steps for sorted and inverse sorted inputs. */ char *b, *endp; if (size <= 0) return; if (nmemb > SUBDIVISION_LIMIT) partition_sort(base, nmemb, size, compar); /* Now I do an insertion sort on the array that is left over. This makes */ /* sense because the quicksort activity above has arranged that the */ /* array is nearly sorted - at most segments of size SUBDIVISION_LIMIT */ /* contain locally unsorted segments. In this case insertion sort goes */ /* as fast as anything else. Doing things this way avoids the need for */ /* a certain amount of partitioning/recursing overhead in the main body */ /* of the quicksort procedure. */ /* Note: some sorts of bugs in the above quicksort could be compensated */ /* for here, leaving this entire procedure as just an insertion sort. */ /* This would yield correct results but would be somewhat slow. */ b = (char *) base; endp = b + (nmemb-1) * size; while (b < endp) { char *b1 = b; b += size; /* Find out where to insert this item. */ while (b1>=(char *)base && (*compar)(b1, b)>0) b1 -= size; b1 += size; /* The fact that I do not know how large the objects that are being */ /* sorted are is horrible - I do an exchange here copying things one */ /* word at a time or one byte at a time depending on the value of size. */ if (((size | (int) b) & 0x3)==0) { int j; for (j=0; j<size; j+=4) { char *bx = b + j; /* Even when moving word by word I use (char *) pointers so as to avoid */ /* muddles about pointer arithmetic. I cast to (int *) pointers when I */ /* am about to dereference something. */ int save = *(int *)bx; char *by = bx - size; while (by>=b1) { *(int *)(by + size) = *(int *)by; by -= size; } *(int *)(by + size) = save; } } else /* If size is not a multiple of 4 I behave with great caution and copy */ /* byte by byte. I could, of course, copy by words up to the last 1, 2 */ /* or 3 bytes - I count that as too much effort for now. */ { int j; for (j=0; j<size; j++) { char *bx = b + j; char save = *bx; char *by = bx - size; while (by>=b1) { *(by + size) = *by; by -= size; } *(by + size) = save; } } } }