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*55925Sbostic static char sccsid[] = "@(#)radixsort.c 5.15 (Berkeley) 08/20/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 38*55925Sbostic static inline void simplesort 39*55925Sbostic __P((const u_char **, int, int, const u_char *, u_int)); 4054579Sbostic static void r_sort_a __P((const u_char **, int, int, const u_char *, u_int)); 4154579Sbostic static void r_sort_b __P((const u_char **, 4254579Sbostic const u_char **, int, int, const u_char *, u_int)); 4351687Sbostic 4454579Sbostic #define THRESHOLD 20 /* Divert to simplesort(). */ 4554579Sbostic #define SIZE 512 /* Default stack size. */ 4645287Sbostic 4754579Sbostic #define SETUP { \ 4854579Sbostic if (tab == NULL) { \ 4954579Sbostic tr = tr0; \ 5054579Sbostic for (c = 0; c < endch; c++) \ 5154579Sbostic tr0[c] = c + 1; \ 5254579Sbostic tr0[c] = 0; \ 5354579Sbostic for (c++; c < 256; c++) \ 5454579Sbostic tr0[c] = c; \ 5554579Sbostic endch = 0; \ 5654579Sbostic } else { \ 5754579Sbostic endch = tab[endch]; \ 5854579Sbostic tr = tab; \ 5954579Sbostic if (endch != 0 && endch != 255) { \ 6054579Sbostic errno = EINVAL; \ 6154579Sbostic return (-1); \ 6254579Sbostic } \ 6354579Sbostic } \ 6454579Sbostic } 6545427Sbostic 6654579Sbostic int 6754579Sbostic radixsort(a, n, tab, endch) 6854579Sbostic const u_char **a, *tab; 6954579Sbostic int n; 7054579Sbostic u_int endch; 7154579Sbostic { 7254579Sbostic const u_char *tr; 7354579Sbostic int c; 7454579Sbostic u_char tr0[256]; 7545287Sbostic 7654579Sbostic SETUP; 7754579Sbostic r_sort_a(a, n, 0, tr, endch); 7854579Sbostic return (0); 7945287Sbostic } 8054579Sbostic 8146599Sdonn int 8254579Sbostic sradixsort(a, n, tab, endch) 8354579Sbostic const u_char **a, *tab; 8454579Sbostic int n; 8554579Sbostic u_int endch; 8645287Sbostic { 8754579Sbostic const u_char *tr, **ta; 8854579Sbostic int c; 8954579Sbostic u_char tr0[256]; 9045287Sbostic 9154579Sbostic SETUP; 9254579Sbostic if (n < THRESHOLD) 9354579Sbostic simplesort(a, n, 0, tr, endch); 9454579Sbostic else { 9554579Sbostic if ((ta = malloc(n * sizeof(a))) == NULL) 9651687Sbostic return (-1); 9754579Sbostic r_sort_b(a, ta, n, 0, tr, endch); 9854579Sbostic free(ta); 9951687Sbostic } 10054579Sbostic return (0); 10154579Sbostic } 10245345Sbostic 10354579Sbostic #define empty(s) (s >= sp) 10454579Sbostic #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si 10554579Sbostic #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i 10654579Sbostic #define swap(a, b, t) t = a, a = b, b = t 10745287Sbostic 10854579Sbostic /* Unstable, in-place sort. */ 10954579Sbostic void 11054579Sbostic r_sort_a(a, n, i, tr, endch) 11154579Sbostic const u_char **a; 11254579Sbostic int n, i; 11354579Sbostic const u_char *tr; 11454579Sbostic u_int endch; 11554579Sbostic { 11654579Sbostic static int count[256], nc, bmin; 11754579Sbostic register int c; 11854579Sbostic register const u_char **ak, *r; 11954579Sbostic stack s[SIZE], *sp, *sp0, *sp1, temp; 12054579Sbostic int *cp, bigc; 12154579Sbostic const u_char **an, *t, **aj, **top[256]; 12245287Sbostic 12354585Sbostic /* Set up stack. */ 12454579Sbostic sp = s; 12554579Sbostic push(a, n, i); 12654579Sbostic while (!empty(s)) { 12754579Sbostic pop(a, n, i); 12854579Sbostic if (n < THRESHOLD) { 12954579Sbostic simplesort(a, n, i, tr, endch); 13054579Sbostic continue; 13151687Sbostic } 13254579Sbostic an = a + n; 13345287Sbostic 13454579Sbostic /* Make character histogram. */ 13554579Sbostic if (nc == 0) { 13654579Sbostic bmin = 255; /* First occupied bin, excluding eos. */ 13754579Sbostic for (ak = a; ak < an;) { 13854579Sbostic c = tr[(*ak++)[i]]; 13954579Sbostic if (++count[c] == 1 && c != endch) { 14054579Sbostic if (c < bmin) 14154579Sbostic bmin = c; 14254579Sbostic nc++; 14354579Sbostic } 14454579Sbostic } 14554579Sbostic if (sp + nc > s + SIZE) { /* Get more stack. */ 14654579Sbostic r_sort_a(a, n, i, tr, endch); 14754579Sbostic continue; 14854579Sbostic } 14954579Sbostic } 15054579Sbostic 15145287Sbostic /* 15254579Sbostic * Set top[]; push incompletely sorted bins onto stack. 15354579Sbostic * top[] = pointers to last out-of-place element in bins. 15454579Sbostic * count[] = counts of elements in bins. 15554579Sbostic * Before permuting: top[c-1] + count[c] = top[c]; 15654579Sbostic * during deal: top[c] counts down to top[c-1]. 15745287Sbostic */ 15854579Sbostic sp0 = sp1 = sp; /* Stack position of biggest bin. */ 15954579Sbostic bigc = 2; /* Size of biggest bin. */ 16054579Sbostic if (endch == 0) /* Special case: set top[eos]. */ 16154579Sbostic top[0] = ak = a + count[0]; 16254579Sbostic else { 16354579Sbostic ak = a; 16454579Sbostic top[255] = an; 16554579Sbostic } 16654579Sbostic for (cp = count + bmin; nc > 0; cp++) { 16754585Sbostic while (*cp == 0) /* Find next non-empty pile. */ 16854579Sbostic cp++; 16954579Sbostic if (*cp > 1) { 17054579Sbostic if (*cp > bigc) { 17154579Sbostic bigc = *cp; 17254579Sbostic sp1 = sp; 17354579Sbostic } 17454579Sbostic push(ak, *cp, i+1); 17545345Sbostic } 17654579Sbostic top[cp-count] = ak += *cp; 17754579Sbostic nc--; 17845345Sbostic } 17954579Sbostic swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */ 18045287Sbostic 18145287Sbostic /* 18254579Sbostic * Permute misplacements home. Already home: everything 18354579Sbostic * before aj, and in bin[c], items from top[c] on. 18454579Sbostic * Inner loop: 18554579Sbostic * r = next element to put in place; 18654579Sbostic * ak = top[r[i]] = location to put the next element. 18754579Sbostic * aj = bottom of 1st disordered bin. 18854579Sbostic * Outer loop: 18954579Sbostic * Once the 1st disordered bin is done, ie. aj >= ak, 19054579Sbostic * aj<-aj + count[c] connects the bins in a linked list; 19154579Sbostic * reset count[c]. 19245287Sbostic */ 19354579Sbostic for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0) 19454579Sbostic for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);) 19554579Sbostic swap(*ak, r, t); 19654579Sbostic } 19754579Sbostic } 19845287Sbostic 19954579Sbostic /* Stable sort, requiring additional memory. */ 20054579Sbostic void 20154579Sbostic r_sort_b(a, ta, n, i, tr, endch) 20254579Sbostic const u_char **a, **ta; 20354579Sbostic int n, i; 20454579Sbostic const u_char *tr; 20554579Sbostic u_int endch; 20654579Sbostic { 20754579Sbostic static int count[256], nc, bmin; 20854579Sbostic register int c; 20954579Sbostic register const u_char **ak, **ai; 21054579Sbostic stack s[512], *sp, *sp0, *sp1, temp; 21154579Sbostic const u_char **top[256]; 21254579Sbostic int *cp, bigc; 21345287Sbostic 21454579Sbostic sp = s; 21554579Sbostic push(a, n, i); 21654579Sbostic while (!empty(s)) { 21754579Sbostic pop(a, n, i); 21854579Sbostic if (n < THRESHOLD) { 21954579Sbostic simplesort(a, n, i, tr, endch); 22054579Sbostic continue; 22145287Sbostic } 22254579Sbostic 22354579Sbostic if (nc == 0) { 22454579Sbostic bmin = 255; 22554579Sbostic for (ak = a + n; --ak >= a;) { 22654579Sbostic c = tr[(*ak)[i]]; 22754579Sbostic if (++count[c] == 1 && c != endch) { 22854579Sbostic if (c < bmin) 22954579Sbostic bmin = c; 23054579Sbostic nc++; 23154579Sbostic } 23254579Sbostic } 23354579Sbostic if (sp + nc > s + SIZE) { 23454579Sbostic r_sort_b(a, ta, n, i, tr, endch); 23545345Sbostic continue; 23654579Sbostic } 23745345Sbostic } 23854579Sbostic 23954585Sbostic sp0 = sp1 = sp; 24054585Sbostic bigc = 2; 24154585Sbostic if (endch == 0) { 24254579Sbostic top[0] = ak = a + count[0]; 24354579Sbostic count[0] = 0; 24454579Sbostic } else { 24554579Sbostic ak = a; 24654579Sbostic top[255] = a + n; 24754579Sbostic count[255] = 0; 24854579Sbostic } 24954585Sbostic for (cp = count + bmin; nc > 0; cp++) { 25054579Sbostic while (*cp == 0) 25154579Sbostic cp++; 25254579Sbostic if ((c = *cp) > 1) { 25354579Sbostic if (c > bigc) { 25454579Sbostic bigc = c; 25554579Sbostic sp1 = sp; 25654579Sbostic } 25754579Sbostic push(ak, c, i+1); 25854579Sbostic } 25954579Sbostic top[cp-count] = ak += c; 26054585Sbostic *cp = 0; /* Reset count[]. */ 26154585Sbostic nc--; 26254579Sbostic } 26354585Sbostic swap(*sp0, *sp1, temp); 26454579Sbostic 26554585Sbostic for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */ 26654579Sbostic *--ak = *--ai; 26754585Sbostic for (ak = ta+n; --ak >= ta;) /* Deal to piles. */ 26854579Sbostic *--top[tr[(*ak)[i]]] = *ak; 26945287Sbostic } 27045287Sbostic } 27154579Sbostic 272*55925Sbostic static inline void 27354579Sbostic simplesort(a, n, b, tr, endch) /* insertion sort */ 27454579Sbostic register const u_char **a; 27554579Sbostic int n, b; 27654579Sbostic register const u_char *tr; 27754579Sbostic u_int endch; 27845935Sbostic { 27951687Sbostic register u_char ch; 28054579Sbostic const u_char **ak, **ai, *s, *t; 28145935Sbostic 28254579Sbostic for (ak = a+1; --n >= 1; ak++) 28354579Sbostic for (ai = ak; ai > a; ai--) { 28454579Sbostic for (s = ai[0] + b, t = ai[-1] + b; 28554579Sbostic (ch = tr[*s]) != endch; s++, t++) 28654579Sbostic if (ch != tr[*t]) 28745935Sbostic break; 28854579Sbostic if (ch >= tr[*t]) 28954579Sbostic break; 29054579Sbostic swap(ai[0], ai[-1], s); 29154579Sbostic } 29245935Sbostic } 293