145287Sbostic /*- 245287Sbostic * Copyright (c) 1990 The Regents of the University of California. 345287Sbostic * All rights reserved. 445287Sbostic * 550859Sbostic * This code is derived from software contributed to Berkeley by 650859Sbostic * Dan Bernstein at New York University. 750859Sbostic * 845287Sbostic * %sccs.include.redist.c% 945287Sbostic */ 1045287Sbostic 1145287Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*51687Sbostic static char sccsid[] = "@(#)radixsort.c 5.11 (Berkeley) 11/13/91"; 1345287Sbostic #endif /* LIBC_SCCS and not lint */ 1445287Sbostic 1545287Sbostic #include <sys/types.h> 1645287Sbostic #include <limits.h> 1745287Sbostic #include <stdlib.h> 1845287Sbostic #include <stddef.h> 1946599Sdonn #include <string.h> 20*51687Sbostic #include <errno.h> 2145287Sbostic 22*51687Sbostic static void shellsort __P((const u_char **, int, int, const u_char *, int)); 23*51687Sbostic 2445287Sbostic /* 2545287Sbostic * __rspartition is the cutoff point for a further partitioning instead 2645287Sbostic * of a shellsort. If it changes check __rsshell_increments. Both of 2745935Sbostic * these are exported, as the best values are data dependent. 2845287Sbostic */ 29*51687Sbostic #define NPARTITION 30 30*51687Sbostic 3145287Sbostic int __rspartition = NPARTITION; 3245287Sbostic int __rsshell_increments[] = { 4, 1, 0, 0, 0, 0, 0, 0 }; 3345287Sbostic 3445287Sbostic /* 3545345Sbostic * Stackp points to context structures, where each structure schedules a 3645345Sbostic * partitioning. Radixsort exits when the stack is empty. 3745287Sbostic * 3845346Sbostic * If the buckets are placed on the stack randomly, the worst case is when 39*51687Sbostic * all the buckets but one contain (__rspartition + 1) elements and the bucket 4045346Sbostic * pushed on the stack last contains the rest of the elements. In this case, 4145346Sbostic * stack growth is bounded by: 4245345Sbostic * 43*51687Sbostic * limit = (nelements / (__rspartitions + 1)) - 1; 4445345Sbostic * 45*51687Sbostic * This is a very large number, 102,261,125 for the maximum 32-bit signed 46*51687Sbostic * integer if NPARTITION is 20. 4745345Sbostic * 4845427Sbostic * By forcing the largest bucket to be pushed on the stack first, the worst 49*51687Sbostic * case is when all but two buckets each contain (__rspartition + 1) elements, 5045427Sbostic * with the remaining elements split equally between the first and last 51*51687Sbostic * buckets pushed on the stack. In this case, stack growth is bounded by 52*51687Sbostic * the recurrence relation: 5345427Sbostic * 54*51687Sbostic * nelements_max[1] = (NBINS-1) * (__rspartition + 1); 55*51687Sbostic * nelements_max[i] = (NBINS-3) * (__rspartition + 1) + 2 * npartitions[i-1]; 56*51687Sbostic * which resolves to: 57*51687Sbostic * nelements_max[i] = ((NBINS-2) * (2^i - 1) + 1) * (__rspartitions + 1), 58*51687Sbostic * 59*51687Sbostic * which yields, for a given nelements, 60*51687Sbostic * 61*51687Sbostic * i = ceil(log2((((nelements / (__rspartition + 1)) - 1) / (NBINS - 2)) + 1)); 62*51687Sbostic * 6345345Sbostic * The bound is: 6445345Sbostic * 65*51687Sbostic * limit = i * (NBINS - 1); 6645346Sbostic * 67*51687Sbostic * This is a much smaller number, 4845 for the maximum 32-bit signed int. 6845287Sbostic */ 6945427Sbostic #define NBUCKETS (UCHAR_MAX + 1) 7045427Sbostic 7145287Sbostic typedef struct _stack { 7246599Sdonn const u_char **bot; 7345287Sbostic int indx, nmemb; 7445287Sbostic } CONTEXT; 7545287Sbostic 7645287Sbostic #define STACKPUSH { \ 7745287Sbostic stackp->bot = p; \ 7845287Sbostic stackp->nmemb = nmemb; \ 7945287Sbostic stackp->indx = indx; \ 8045287Sbostic ++stackp; \ 8145287Sbostic } 8245287Sbostic #define STACKPOP { \ 8345287Sbostic if (stackp == stack) \ 8445287Sbostic break; \ 8545287Sbostic --stackp; \ 8645287Sbostic bot = stackp->bot; \ 8745287Sbostic nmemb = stackp->nmemb; \ 8845287Sbostic indx = stackp->indx; \ 8945287Sbostic } 9045287Sbostic /* 9145287Sbostic * A variant of MSD radix sorting; see Knuth Vol. 3, page 177, and 5.2.5, 9245345Sbostic * Ex. 10 and 12. Also, "Three Partition Refinement Algorithms, Paige 9345345Sbostic * and Tarjan, SIAM J. Comput. Vol. 16, No. 6, December 1987. 9445287Sbostic * 9545345Sbostic * This uses a simple sort as soon as a bucket crosses a cutoff point, 9645345Sbostic * rather than sorting the entire list after partitioning is finished. 9745345Sbostic * This should be an advantage. 9845287Sbostic * 9945345Sbostic * This is pure MSD instead of LSD of some number of MSD, switching to 10045345Sbostic * the simple sort as soon as possible. Takes linear time relative to 10145345Sbostic * the number of bytes in the strings. 10245287Sbostic */ 10346599Sdonn int 10445287Sbostic radixsort(l1, nmemb, tab, endbyte) 10546599Sdonn const u_char **l1; 10645287Sbostic register int nmemb; 10746599Sdonn const u_char *tab; 10850481Sbostic u_int endbyte; 10945287Sbostic { 110*51687Sbostic register int *cpos, *first, *last, i, indx; 111*51687Sbostic register const u_char **bot, **l2, **p, *tr; 11245345Sbostic CONTEXT *stack, *stackp; 113*51687Sbostic int c[NBUCKETS + 1], *max, *recd, t1, t2; 11445427Sbostic u_char ltab[NBUCKETS]; 11545287Sbostic 11645287Sbostic if (nmemb <= 1) 117*51687Sbostic return (0); 11845287Sbostic 11945346Sbostic /* 12045345Sbostic * T1 is the constant part of the equation, the number of elements 121*51687Sbostic * represented on the stack between the top and bottom entries. 12245346Sbostic */ 123*51687Sbostic if (nmemb > __rspartition) 124*51687Sbostic t1 = (nmemb / (__rspartition + 1) - 1) / (NBUCKETS - 2) + 1; 125*51687Sbostic else 126*51687Sbostic t1 = 0; 127*51687Sbostic for (i = 0; t1; ++i) 128*51687Sbostic t1 /= 2; 12945345Sbostic if (i) { 130*51687Sbostic i *= NBUCKETS - 1; 131*51687Sbostic if ((stack = stackp = malloc(i * sizeof(CONTEXT))) == NULL) 132*51687Sbostic return (-1); 133*51687Sbostic } 134*51687Sbostic else 13545345Sbostic stack = stackp = NULL; 13645345Sbostic 13745287Sbostic /* 138*51687Sbostic * There are two arrays, l1 and l2. The data is sorted into the temp 139*51687Sbostic * stack, and then copied back. The speedup of using the index to 140*51687Sbostic * determine which stack the data is on and simply swapping stacks back 141*51687Sbostic * and forth, thus avoiding the copy every iteration, turns out to not 14245287Sbostic * be any faster than the current implementation. 14345287Sbostic */ 144*51687Sbostic if ((l2 = malloc(nmemb * sizeof(u_char **))) == NULL) 145*51687Sbostic return (-1); 14645287Sbostic /* 14745345Sbostic * Tr references a table of sort weights; multiple entries may 14845287Sbostic * map to the same weight; EOS char must have the lowest weight. 14945287Sbostic */ 150*51687Sbostic if (tab) { 15145287Sbostic tr = tab; 152*51687Sbostic recd = c + tr[endbyte]; 153*51687Sbostic if (recd != c && recd != c + NBUCKETS - 1) { 154*51687Sbostic errno = EINVAL; 155*51687Sbostic return (-1); 156*51687Sbostic } 157*51687Sbostic } 15845287Sbostic else { 15945287Sbostic for (t1 = 0, t2 = endbyte; t1 < t2; ++t1) 16046599Sdonn ltab[t1] = t1 + 1; 16146599Sdonn ltab[t2] = 0; 16245427Sbostic for (t1 = endbyte + 1; t1 < NBUCKETS; ++t1) 16346599Sdonn ltab[t1] = t1; 16446599Sdonn tr = ltab; 16545287Sbostic } 166*51687Sbostic last = c + NBUCKETS; 167*51687Sbostic first = c; 168*51687Sbostic endbyte = tr[endbyte]; 16945287Sbostic 170*51687Sbostic /* First sort is entire stack. */ 17145287Sbostic bot = l1; 17245287Sbostic indx = 0; 17345287Sbostic 17445287Sbostic for (;;) { 17545345Sbostic /* Clear bucket count array */ 176*51687Sbostic bzero(first, sizeof(c[0]) * (last - first + 1)); 177*51687Sbostic *recd = 0; 17845287Sbostic 17945287Sbostic /* 18045345Sbostic * Compute number of items that sort to the same bucket 18145287Sbostic * for this index. 18245287Sbostic */ 183*51687Sbostic first = c + NBUCKETS - 1; 184*51687Sbostic last = c; 185*51687Sbostic for (p = bot, i = nmemb; --i >= 0;) { 186*51687Sbostic ++*(cpos = c + tr[(*p++)[indx]]); 187*51687Sbostic if (cpos > last && cpos != recd) 188*51687Sbostic last = cpos; 189*51687Sbostic if (cpos < first && cpos != recd) 190*51687Sbostic first = cpos; 191*51687Sbostic } 192*51687Sbostic ++last; 19345287Sbostic 19445287Sbostic /* 19545345Sbostic * Sum the number of characters into c, dividing the temp 19645287Sbostic * stack into the right number of buckets for this bucket, 19745287Sbostic * this index. C contains the cumulative total of keys 198*51687Sbostic * before and included in this bucket, and will later be used 199*51687Sbostic * as an index to the bucket. c[NBUCKETS] (or *last) contains 20045287Sbostic * the total number of elements, for determining how many 20145345Sbostic * elements the last bucket contains. At the same time 20245427Sbostic * find the largest bucket so it gets pushed first. 20345287Sbostic */ 204*51687Sbostic t1 = (c == recd) ? c[0] : 0; 205*51687Sbostic t2 = __rspartition; 206*51687Sbostic for (i = last - (cpos = max = first); i-- >= 0;) { 207*51687Sbostic if (*cpos > t2) { 208*51687Sbostic t2 = *cpos; 209*51687Sbostic max = cpos; 21045345Sbostic } 211*51687Sbostic t1 = *cpos++ += t1; 21245345Sbostic } 213*51687Sbostic if (c != recd) 214*51687Sbostic *recd += t1; 21545287Sbostic 21645287Sbostic /* 21745427Sbostic * Partition the elements into buckets; c decrements through 21845427Sbostic * the bucket, and ends up pointing to the first element of 21945427Sbostic * the bucket. 22045287Sbostic */ 22145935Sbostic for (i = nmemb; --i >= 0;) { 22245287Sbostic --p; 22345287Sbostic l2[--c[tr[(*p)[indx]]]] = *p; 22445287Sbostic } 22545287Sbostic 22645345Sbostic /* Copy the partitioned elements back to user stack */ 22745287Sbostic bcopy(l2, bot, nmemb * sizeof(u_char *)); 22845287Sbostic 22945287Sbostic ++indx; 23045287Sbostic /* 231*51687Sbostic * Sort buckets as necessary; don't sort the EOS character 232*51687Sbostic * bucket c[endbyte] since it is already sorted. *max is 233*51687Sbostic * pushed first. 23445287Sbostic */ 235*51687Sbostic for (i = last - (cpos = max); --i >= 0;) { 236*51687Sbostic if ((nmemb = *(cpos+1) - (t1 = *cpos++)) < 2) 23745287Sbostic continue; 23845287Sbostic p = bot + t1; 23945287Sbostic if (nmemb > __rspartition) 24045287Sbostic STACKPUSH 24145287Sbostic else 242*51687Sbostic shellsort(p, indx, nmemb, tr, endbyte); 24345287Sbostic } 244*51687Sbostic for (i = max - (cpos = first); --i >= 0;) { 245*51687Sbostic if ((nmemb = *(cpos + 1) - (t1 = *cpos++)) < 2) 24645345Sbostic continue; 24745345Sbostic p = bot + t1; 24845345Sbostic if (nmemb > __rspartition) 24945345Sbostic STACKPUSH 25045345Sbostic else 251*51687Sbostic shellsort(p, indx, nmemb, tr, endbyte); 25245345Sbostic } 253*51687Sbostic /* Break out when stack is empty. */ 25445287Sbostic STACKPOP 25545287Sbostic } 256*51687Sbostic free(stack); 257*51687Sbostic free(l2); 258*51687Sbostic return (0); 25945287Sbostic } 26045935Sbostic 26145935Sbostic /* 26245935Sbostic * Shellsort (diminishing increment sort) from Data Structures and 26345935Sbostic * Algorithms, Aho, Hopcraft and Ullman, 1983 Edition, page 290; 26445935Sbostic * see also Knuth Vol. 3, page 84. The increments are selected from 26545935Sbostic * formula (8), page 95. Roughly O(N^3/2). 26645935Sbostic */ 26745935Sbostic static void 268*51687Sbostic shellsort(p, indx, nmemb, tr, recd) 269*51687Sbostic register const u_char **p, *tr; 270*51687Sbostic register int indx, nmemb, recd; 27145935Sbostic { 272*51687Sbostic register const u_char *s1, *s2; 273*51687Sbostic register u_char ch; 27445935Sbostic register int incr, *incrp, t1, t2; 27545935Sbostic 27645935Sbostic for (incrp = __rsshell_increments; incr = *incrp++;) 27745935Sbostic for (t1 = incr; t1 < nmemb; ++t1) 27845935Sbostic for (t2 = t1 - incr; t2 >= 0;) { 27945935Sbostic s1 = p[t2] + indx; 28045935Sbostic s2 = p[t2 + incr] + indx; 281*51687Sbostic while ((ch = tr[*s1++]) == tr[*s2] && 282*51687Sbostic (ch != recd)) 28345935Sbostic ++s2; 28445935Sbostic if (ch > tr[*s2]) { 28545935Sbostic s1 = p[t2]; 28645935Sbostic p[t2] = p[t2 + incr]; 28745935Sbostic p[t2 + incr] = s1; 28845935Sbostic t2 -= incr; 28945935Sbostic } else 29045935Sbostic break; 29145935Sbostic } 29245935Sbostic } 293