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 654579Sbostic * Peter McIlroy and by Dan Bernstein at New York University, 750859Sbostic * 845287Sbostic * %sccs.include.redist.c% 945287Sbostic */ 1045287Sbostic 1145287Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*54585Sbostic static char sccsid[] = "@(#)radixsort.c 5.14 (Berkeley) 07/01/92"; 1345287Sbostic #endif /* LIBC_SCCS and not lint */ 1445287Sbostic 1554579Sbostic /* 1654579Sbostic * Radixsort routines. 1754579Sbostic * 1854579Sbostic * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack. 1954579Sbostic * Use radixsort(a, n, trace, endchar) for this case. 2054579Sbostic * 2154579Sbostic * For stable sorting (using N extra pointers) use sradixsort(), which calls 2254579Sbostic * r_sort_b(). 2354579Sbostic * 2454579Sbostic * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic, 2554579Sbostic * "Engineering Radix Sort". 2654579Sbostic */ 2754579Sbostic 2845287Sbostic #include <sys/types.h> 2945287Sbostic #include <stdlib.h> 3045287Sbostic #include <stddef.h> 3151687Sbostic #include <errno.h> 3245287Sbostic 3354579Sbostic typedef struct { 3454579Sbostic const u_char **sa; 3554579Sbostic int sn, si; 3654579Sbostic } stack; 3751687Sbostic 3854579Sbostic static void simplesort __P((const u_char **, int, int, const u_char *, u_int)); 3954579Sbostic static void r_sort_a __P((const u_char **, int, int, const u_char *, u_int)); 4054579Sbostic static void r_sort_b __P((const u_char **, 4154579Sbostic const u_char **, int, int, const u_char *, u_int)); 4251687Sbostic 4354579Sbostic #define THRESHOLD 20 /* Divert to simplesort(). */ 4454579Sbostic #define SIZE 512 /* Default stack size. */ 4545287Sbostic 4654579Sbostic #define SETUP { \ 4754579Sbostic if (tab == NULL) { \ 4854579Sbostic tr = tr0; \ 4954579Sbostic for (c = 0; c < endch; c++) \ 5054579Sbostic tr0[c] = c + 1; \ 5154579Sbostic tr0[c] = 0; \ 5254579Sbostic for (c++; c < 256; c++) \ 5354579Sbostic tr0[c] = c; \ 5454579Sbostic endch = 0; \ 5554579Sbostic } else { \ 5654579Sbostic endch = tab[endch]; \ 5754579Sbostic tr = tab; \ 5854579Sbostic if (endch != 0 && endch != 255) { \ 5954579Sbostic errno = EINVAL; \ 6054579Sbostic return (-1); \ 6154579Sbostic } \ 6254579Sbostic } \ 6354579Sbostic } 6445427Sbostic 6554579Sbostic int 6654579Sbostic radixsort(a, n, tab, endch) 6754579Sbostic const u_char **a, *tab; 6854579Sbostic int n; 6954579Sbostic u_int endch; 7054579Sbostic { 7154579Sbostic const u_char *tr; 7254579Sbostic int c; 7354579Sbostic u_char tr0[256]; 7445287Sbostic 7554579Sbostic SETUP; 7654579Sbostic r_sort_a(a, n, 0, tr, endch); 7754579Sbostic return (0); 7845287Sbostic } 7954579Sbostic 8046599Sdonn int 8154579Sbostic sradixsort(a, n, tab, endch) 8254579Sbostic const u_char **a, *tab; 8354579Sbostic int n; 8454579Sbostic u_int endch; 8545287Sbostic { 8654579Sbostic const u_char *tr, **ta; 8754579Sbostic int c; 8854579Sbostic u_char tr0[256]; 8945287Sbostic 9054579Sbostic SETUP; 9154579Sbostic if (n < THRESHOLD) 9254579Sbostic simplesort(a, n, 0, tr, endch); 9354579Sbostic else { 9454579Sbostic if ((ta = malloc(n * sizeof(a))) == NULL) 9551687Sbostic return (-1); 9654579Sbostic r_sort_b(a, ta, n, 0, tr, endch); 9754579Sbostic free(ta); 9851687Sbostic } 9954579Sbostic return (0); 10054579Sbostic } 10145345Sbostic 10254579Sbostic #define empty(s) (s >= sp) 10354579Sbostic #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si 10454579Sbostic #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i 10554579Sbostic #define swap(a, b, t) t = a, a = b, b = t 10645287Sbostic 10754579Sbostic /* Unstable, in-place sort. */ 10854579Sbostic void 10954579Sbostic r_sort_a(a, n, i, tr, endch) 11054579Sbostic const u_char **a; 11154579Sbostic int n, i; 11254579Sbostic const u_char *tr; 11354579Sbostic u_int endch; 11454579Sbostic { 11554579Sbostic static int count[256], nc, bmin; 11654579Sbostic register int c; 11754579Sbostic register const u_char **ak, *r; 11854579Sbostic stack s[SIZE], *sp, *sp0, *sp1, temp; 11954579Sbostic int *cp, bigc; 12054579Sbostic const u_char **an, *t, **aj, **top[256]; 12145287Sbostic 122*54585Sbostic /* Set up stack. */ 12354579Sbostic sp = s; 12454579Sbostic push(a, n, i); 12554579Sbostic while (!empty(s)) { 12654579Sbostic pop(a, n, i); 12754579Sbostic if (n < THRESHOLD) { 12854579Sbostic simplesort(a, n, i, tr, endch); 12954579Sbostic continue; 13051687Sbostic } 13154579Sbostic an = a + n; 13245287Sbostic 13354579Sbostic /* Make character histogram. */ 13454579Sbostic if (nc == 0) { 13554579Sbostic bmin = 255; /* First occupied bin, excluding eos. */ 13654579Sbostic for (ak = a; ak < an;) { 13754579Sbostic c = tr[(*ak++)[i]]; 13854579Sbostic if (++count[c] == 1 && c != endch) { 13954579Sbostic if (c < bmin) 14054579Sbostic bmin = c; 14154579Sbostic nc++; 14254579Sbostic } 14354579Sbostic } 14454579Sbostic if (sp + nc > s + SIZE) { /* Get more stack. */ 14554579Sbostic r_sort_a(a, n, i, tr, endch); 14654579Sbostic continue; 14754579Sbostic } 14854579Sbostic } 14954579Sbostic 15045287Sbostic /* 15154579Sbostic * Set top[]; push incompletely sorted bins onto stack. 15254579Sbostic * top[] = pointers to last out-of-place element in bins. 15354579Sbostic * count[] = counts of elements in bins. 15454579Sbostic * Before permuting: top[c-1] + count[c] = top[c]; 15554579Sbostic * during deal: top[c] counts down to top[c-1]. 15645287Sbostic */ 15754579Sbostic sp0 = sp1 = sp; /* Stack position of biggest bin. */ 15854579Sbostic bigc = 2; /* Size of biggest bin. */ 15954579Sbostic if (endch == 0) /* Special case: set top[eos]. */ 16054579Sbostic top[0] = ak = a + count[0]; 16154579Sbostic else { 16254579Sbostic ak = a; 16354579Sbostic top[255] = an; 16454579Sbostic } 16554579Sbostic for (cp = count + bmin; nc > 0; cp++) { 166*54585Sbostic while (*cp == 0) /* Find next non-empty pile. */ 16754579Sbostic cp++; 16854579Sbostic if (*cp > 1) { 16954579Sbostic if (*cp > bigc) { 17054579Sbostic bigc = *cp; 17154579Sbostic sp1 = sp; 17254579Sbostic } 17354579Sbostic push(ak, *cp, i+1); 17445345Sbostic } 17554579Sbostic top[cp-count] = ak += *cp; 17654579Sbostic nc--; 17745345Sbostic } 17854579Sbostic swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */ 17945287Sbostic 18045287Sbostic /* 18154579Sbostic * Permute misplacements home. Already home: everything 18254579Sbostic * before aj, and in bin[c], items from top[c] on. 18354579Sbostic * Inner loop: 18454579Sbostic * r = next element to put in place; 18554579Sbostic * ak = top[r[i]] = location to put the next element. 18654579Sbostic * aj = bottom of 1st disordered bin. 18754579Sbostic * Outer loop: 18854579Sbostic * Once the 1st disordered bin is done, ie. aj >= ak, 18954579Sbostic * aj<-aj + count[c] connects the bins in a linked list; 19054579Sbostic * reset count[c]. 19145287Sbostic */ 19254579Sbostic for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0) 19354579Sbostic for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);) 19454579Sbostic swap(*ak, r, t); 19554579Sbostic } 19654579Sbostic } 19745287Sbostic 19854579Sbostic /* Stable sort, requiring additional memory. */ 19954579Sbostic void 20054579Sbostic r_sort_b(a, ta, n, i, tr, endch) 20154579Sbostic const u_char **a, **ta; 20254579Sbostic int n, i; 20354579Sbostic const u_char *tr; 20454579Sbostic u_int endch; 20554579Sbostic { 20654579Sbostic static int count[256], nc, bmin; 20754579Sbostic register int c; 20854579Sbostic register const u_char **ak, **ai; 20954579Sbostic stack s[512], *sp, *sp0, *sp1, temp; 21054579Sbostic const u_char **top[256]; 21154579Sbostic int *cp, bigc; 21245287Sbostic 21354579Sbostic sp = s; 21454579Sbostic push(a, n, i); 21554579Sbostic while (!empty(s)) { 21654579Sbostic pop(a, n, i); 21754579Sbostic if (n < THRESHOLD) { 21854579Sbostic simplesort(a, n, i, tr, endch); 21954579Sbostic continue; 22045287Sbostic } 22154579Sbostic 22254579Sbostic if (nc == 0) { 22354579Sbostic bmin = 255; 22454579Sbostic for (ak = a + n; --ak >= a;) { 22554579Sbostic c = tr[(*ak)[i]]; 22654579Sbostic if (++count[c] == 1 && c != endch) { 22754579Sbostic if (c < bmin) 22854579Sbostic bmin = c; 22954579Sbostic nc++; 23054579Sbostic } 23154579Sbostic } 23254579Sbostic if (sp + nc > s + SIZE) { 23354579Sbostic r_sort_b(a, ta, n, i, tr, endch); 23445345Sbostic continue; 23554579Sbostic } 23645345Sbostic } 23754579Sbostic 238*54585Sbostic sp0 = sp1 = sp; 239*54585Sbostic bigc = 2; 240*54585Sbostic if (endch == 0) { 24154579Sbostic top[0] = ak = a + count[0]; 24254579Sbostic count[0] = 0; 24354579Sbostic } else { 24454579Sbostic ak = a; 24554579Sbostic top[255] = a + n; 24654579Sbostic count[255] = 0; 24754579Sbostic } 248*54585Sbostic for (cp = count + bmin; nc > 0; cp++) { 24954579Sbostic while (*cp == 0) 25054579Sbostic cp++; 25154579Sbostic if ((c = *cp) > 1) { 25254579Sbostic if (c > bigc) { 25354579Sbostic bigc = c; 25454579Sbostic sp1 = sp; 25554579Sbostic } 25654579Sbostic push(ak, c, i+1); 25754579Sbostic } 25854579Sbostic top[cp-count] = ak += c; 259*54585Sbostic *cp = 0; /* Reset count[]. */ 260*54585Sbostic nc--; 26154579Sbostic } 262*54585Sbostic swap(*sp0, *sp1, temp); 26354579Sbostic 264*54585Sbostic for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */ 26554579Sbostic *--ak = *--ai; 266*54585Sbostic for (ak = ta+n; --ak >= ta;) /* Deal to piles. */ 26754579Sbostic *--top[tr[(*ak)[i]]] = *ak; 26845287Sbostic } 26945287Sbostic } 27054579Sbostic 27145935Sbostic static void 27254579Sbostic simplesort(a, n, b, tr, endch) /* insertion sort */ 27354579Sbostic register const u_char **a; 27454579Sbostic int n, b; 27554579Sbostic register const u_char *tr; 27654579Sbostic u_int endch; 27745935Sbostic { 27851687Sbostic register u_char ch; 27954579Sbostic const u_char **ak, **ai, *s, *t; 28045935Sbostic 28154579Sbostic for (ak = a+1; --n >= 1; ak++) 28254579Sbostic for (ai = ak; ai > a; ai--) { 28354579Sbostic for (s = ai[0] + b, t = ai[-1] + b; 28454579Sbostic (ch = tr[*s]) != endch; s++, t++) 28554579Sbostic if (ch != tr[*t]) 28645935Sbostic break; 28754579Sbostic if (ch >= tr[*t]) 28854579Sbostic break; 28954579Sbostic swap(ai[0], ai[-1], s); 29054579Sbostic } 29145935Sbostic } 292