15af32e75SAxel Dörfler /*-
2*bc328a43SAugustin Cavalier * SPDX-License-Identifier: BSD-3-Clause
3*bc328a43SAugustin Cavalier *
45af32e75SAxel Dörfler * Copyright (c) 1990, 1993
55af32e75SAxel Dörfler * The Regents of the University of California. All rights reserved.
65af32e75SAxel Dörfler *
75af32e75SAxel Dörfler * This code is derived from software contributed to Berkeley by
85af32e75SAxel Dörfler * Peter McIlroy and by Dan Bernstein at New York University,
95af32e75SAxel Dörfler *
105af32e75SAxel Dörfler * Redistribution and use in source and binary forms, with or without
115af32e75SAxel Dörfler * modification, are permitted provided that the following conditions
125af32e75SAxel Dörfler * are met:
135af32e75SAxel Dörfler * 1. Redistributions of source code must retain the above copyright
145af32e75SAxel Dörfler * notice, this list of conditions and the following disclaimer.
155af32e75SAxel Dörfler * 2. Redistributions in binary form must reproduce the above copyright
165af32e75SAxel Dörfler * notice, this list of conditions and the following disclaimer in the
175af32e75SAxel Dörfler * documentation and/or other materials provided with the distribution.
18*bc328a43SAugustin Cavalier * 3. Neither the name of the University nor the names of its contributors
195af32e75SAxel Dörfler * may be used to endorse or promote products derived from this software
205af32e75SAxel Dörfler * without specific prior written permission.
215af32e75SAxel Dörfler *
225af32e75SAxel Dörfler * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
235af32e75SAxel Dörfler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
245af32e75SAxel Dörfler * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
255af32e75SAxel Dörfler * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
265af32e75SAxel Dörfler * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
275af32e75SAxel Dörfler * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
285af32e75SAxel Dörfler * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
295af32e75SAxel Dörfler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
305af32e75SAxel Dörfler * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
315af32e75SAxel Dörfler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
325af32e75SAxel Dörfler * SUCH DAMAGE.
335af32e75SAxel Dörfler */
345af32e75SAxel Dörfler
355af32e75SAxel Dörfler #if defined(LIBC_SCCS) && !defined(lint)
365af32e75SAxel Dörfler static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
375af32e75SAxel Dörfler #endif /* LIBC_SCCS and not lint */
385af32e75SAxel Dörfler
395af32e75SAxel Dörfler /*
405af32e75SAxel Dörfler * Radixsort routines.
415af32e75SAxel Dörfler *
425af32e75SAxel Dörfler * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
435af32e75SAxel Dörfler * Use radixsort(a, n, trace, endchar) for this case.
445af32e75SAxel Dörfler *
455af32e75SAxel Dörfler * For stable sorting (using N extra pointers) use sradixsort(), which calls
465af32e75SAxel Dörfler * r_sort_b().
475af32e75SAxel Dörfler *
485af32e75SAxel Dörfler * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
495af32e75SAxel Dörfler * "Engineering Radix Sort".
505af32e75SAxel Dörfler */
515af32e75SAxel Dörfler
525af32e75SAxel Dörfler #include <sys/types.h>
535af32e75SAxel Dörfler #include <stdlib.h>
54*bc328a43SAugustin Cavalier #include <stddef.h>
555af32e75SAxel Dörfler #include <errno.h>
565af32e75SAxel Dörfler
575af32e75SAxel Dörfler typedef struct {
585af32e75SAxel Dörfler const u_char **sa;
595af32e75SAxel Dörfler int sn, si;
605af32e75SAxel Dörfler } stack;
615af32e75SAxel Dörfler
62*bc328a43SAugustin Cavalier static inline void simplesort
63*bc328a43SAugustin Cavalier (const u_char **, int, int, const u_char *, u_int);
64*bc328a43SAugustin Cavalier static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
65*bc328a43SAugustin Cavalier static void r_sort_b(const u_char **, const u_char **, int, int,
66*bc328a43SAugustin Cavalier const u_char *, u_int);
675af32e75SAxel Dörfler
685af32e75SAxel Dörfler #define THRESHOLD 20 /* Divert to simplesort(). */
695af32e75SAxel Dörfler #define SIZE 512 /* Default stack size. */
705af32e75SAxel Dörfler
715af32e75SAxel Dörfler #define SETUP { \
725af32e75SAxel Dörfler if (tab == NULL) { \
735af32e75SAxel Dörfler tr = tr0; \
745af32e75SAxel Dörfler for (c = 0; c < endch; c++) \
755af32e75SAxel Dörfler tr0[c] = c + 1; \
765af32e75SAxel Dörfler tr0[c] = 0; \
775af32e75SAxel Dörfler for (c++; c < 256; c++) \
785af32e75SAxel Dörfler tr0[c] = c; \
795af32e75SAxel Dörfler endch = 0; \
805af32e75SAxel Dörfler } else { \
815af32e75SAxel Dörfler endch = tab[endch]; \
825af32e75SAxel Dörfler tr = tab; \
835af32e75SAxel Dörfler if (endch != 0 && endch != 255) { \
84*bc328a43SAugustin Cavalier errno = EINVAL; \
855af32e75SAxel Dörfler return (-1); \
865af32e75SAxel Dörfler } \
875af32e75SAxel Dörfler } \
885af32e75SAxel Dörfler }
895af32e75SAxel Dörfler
905af32e75SAxel Dörfler int
radixsort(const u_char ** a,int n,const u_char * tab,u_int endch)91*bc328a43SAugustin Cavalier radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
925af32e75SAxel Dörfler {
93*bc328a43SAugustin Cavalier const u_char *tr;
94*bc328a43SAugustin Cavalier int c;
955af32e75SAxel Dörfler u_char tr0[256];
965af32e75SAxel Dörfler
975af32e75SAxel Dörfler SETUP;
985af32e75SAxel Dörfler r_sort_a(a, n, 0, tr, endch);
995af32e75SAxel Dörfler return (0);
1005af32e75SAxel Dörfler }
1015af32e75SAxel Dörfler
1025af32e75SAxel Dörfler int
sradixsort(const u_char ** a,int n,const u_char * tab,u_int endch)103*bc328a43SAugustin Cavalier sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
1045af32e75SAxel Dörfler {
105*bc328a43SAugustin Cavalier const u_char *tr, **ta;
106*bc328a43SAugustin Cavalier int c;
1075af32e75SAxel Dörfler u_char tr0[256];
1085af32e75SAxel Dörfler
1095af32e75SAxel Dörfler SETUP;
1105af32e75SAxel Dörfler if (n < THRESHOLD)
1115af32e75SAxel Dörfler simplesort(a, n, 0, tr, endch);
1125af32e75SAxel Dörfler else {
1135af32e75SAxel Dörfler if ((ta = malloc(n * sizeof(a))) == NULL)
1145af32e75SAxel Dörfler return (-1);
1155af32e75SAxel Dörfler r_sort_b(a, ta, n, 0, tr, endch);
1165af32e75SAxel Dörfler free(ta);
1175af32e75SAxel Dörfler }
1185af32e75SAxel Dörfler return (0);
1195af32e75SAxel Dörfler }
1205af32e75SAxel Dörfler
1215af32e75SAxel Dörfler #define empty(s) (s >= sp)
1225af32e75SAxel Dörfler #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
1235af32e75SAxel Dörfler #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
1245af32e75SAxel Dörfler #define swap(a, b, t) t = a, a = b, b = t
1255af32e75SAxel Dörfler
1265af32e75SAxel Dörfler /* Unstable, in-place sort. */
1275af32e75SAxel Dörfler static void
r_sort_a(const u_char ** a,int n,int i,const u_char * tr,u_int endch)128*bc328a43SAugustin Cavalier r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
1295af32e75SAxel Dörfler {
130*bc328a43SAugustin Cavalier static int count[256], nc, bmin;
131*bc328a43SAugustin Cavalier int c;
132*bc328a43SAugustin Cavalier const u_char **ak, *r;
133*bc328a43SAugustin Cavalier stack s[SIZE], *sp, *sp0, *sp1, temp;
134*bc328a43SAugustin Cavalier int *cp, bigc;
135*bc328a43SAugustin Cavalier const u_char **an, *t, **aj, **top[256];
1365af32e75SAxel Dörfler
1375af32e75SAxel Dörfler /* Set up stack. */
1385af32e75SAxel Dörfler sp = s;
1395af32e75SAxel Dörfler push(a, n, i);
1405af32e75SAxel Dörfler while (!empty(s)) {
1415af32e75SAxel Dörfler pop(a, n, i);
1425af32e75SAxel Dörfler if (n < THRESHOLD) {
1435af32e75SAxel Dörfler simplesort(a, n, i, tr, endch);
1445af32e75SAxel Dörfler continue;
1455af32e75SAxel Dörfler }
1465af32e75SAxel Dörfler an = a + n;
1475af32e75SAxel Dörfler
1485af32e75SAxel Dörfler /* Make character histogram. */
1495af32e75SAxel Dörfler if (nc == 0) {
1505af32e75SAxel Dörfler bmin = 255; /* First occupied bin, excluding eos. */
1515af32e75SAxel Dörfler for (ak = a; ak < an;) {
1525af32e75SAxel Dörfler c = tr[(*ak++)[i]];
1535af32e75SAxel Dörfler if (++count[c] == 1 && c != endch) {
1545af32e75SAxel Dörfler if (c < bmin)
1555af32e75SAxel Dörfler bmin = c;
1565af32e75SAxel Dörfler nc++;
1575af32e75SAxel Dörfler }
1585af32e75SAxel Dörfler }
1595af32e75SAxel Dörfler if (sp + nc > s + SIZE) { /* Get more stack. */
1605af32e75SAxel Dörfler r_sort_a(a, n, i, tr, endch);
1615af32e75SAxel Dörfler continue;
1625af32e75SAxel Dörfler }
1635af32e75SAxel Dörfler }
1645af32e75SAxel Dörfler
1655af32e75SAxel Dörfler /*
166*bc328a43SAugustin Cavalier * Special case: if all strings have the same
167*bc328a43SAugustin Cavalier * character at position i, move on to the next
168*bc328a43SAugustin Cavalier * character.
169*bc328a43SAugustin Cavalier */
170*bc328a43SAugustin Cavalier if (nc == 1 && count[bmin] == n) {
171*bc328a43SAugustin Cavalier push(a, n, i+1);
172*bc328a43SAugustin Cavalier nc = count[bmin] = 0;
173*bc328a43SAugustin Cavalier continue;
174*bc328a43SAugustin Cavalier }
175*bc328a43SAugustin Cavalier
176*bc328a43SAugustin Cavalier /*
1775af32e75SAxel Dörfler * Set top[]; push incompletely sorted bins onto stack.
1785af32e75SAxel Dörfler * top[] = pointers to last out-of-place element in bins.
1795af32e75SAxel Dörfler * count[] = counts of elements in bins.
1805af32e75SAxel Dörfler * Before permuting: top[c-1] + count[c] = top[c];
1815af32e75SAxel Dörfler * during deal: top[c] counts down to top[c-1].
1825af32e75SAxel Dörfler */
1835af32e75SAxel Dörfler sp0 = sp1 = sp; /* Stack position of biggest bin. */
1845af32e75SAxel Dörfler bigc = 2; /* Size of biggest bin. */
1855af32e75SAxel Dörfler if (endch == 0) /* Special case: set top[eos]. */
1865af32e75SAxel Dörfler top[0] = ak = a + count[0];
1875af32e75SAxel Dörfler else {
1885af32e75SAxel Dörfler ak = a;
1895af32e75SAxel Dörfler top[255] = an;
1905af32e75SAxel Dörfler }
1915af32e75SAxel Dörfler for (cp = count + bmin; nc > 0; cp++) {
1925af32e75SAxel Dörfler while (*cp == 0) /* Find next non-empty pile. */
1935af32e75SAxel Dörfler cp++;
1945af32e75SAxel Dörfler if (*cp > 1) {
1955af32e75SAxel Dörfler if (*cp > bigc) {
1965af32e75SAxel Dörfler bigc = *cp;
1975af32e75SAxel Dörfler sp1 = sp;
1985af32e75SAxel Dörfler }
1995af32e75SAxel Dörfler push(ak, *cp, i+1);
2005af32e75SAxel Dörfler }
2015af32e75SAxel Dörfler top[cp-count] = ak += *cp;
2025af32e75SAxel Dörfler nc--;
2035af32e75SAxel Dörfler }
2045af32e75SAxel Dörfler swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
2055af32e75SAxel Dörfler
2065af32e75SAxel Dörfler /*
2075af32e75SAxel Dörfler * Permute misplacements home. Already home: everything
2085af32e75SAxel Dörfler * before aj, and in bin[c], items from top[c] on.
2095af32e75SAxel Dörfler * Inner loop:
2105af32e75SAxel Dörfler * r = next element to put in place;
2115af32e75SAxel Dörfler * ak = top[r[i]] = location to put the next element.
2125af32e75SAxel Dörfler * aj = bottom of 1st disordered bin.
2135af32e75SAxel Dörfler * Outer loop:
2145af32e75SAxel Dörfler * Once the 1st disordered bin is done, ie. aj >= ak,
2155af32e75SAxel Dörfler * aj<-aj + count[c] connects the bins in a linked list;
2165af32e75SAxel Dörfler * reset count[c].
2175af32e75SAxel Dörfler */
2185af32e75SAxel Dörfler for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
2195af32e75SAxel Dörfler for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
2205af32e75SAxel Dörfler swap(*ak, r, t);
2215af32e75SAxel Dörfler }
2225af32e75SAxel Dörfler }
2235af32e75SAxel Dörfler
2245af32e75SAxel Dörfler /* Stable sort, requiring additional memory. */
225*bc328a43SAugustin Cavalier static void
r_sort_b(const u_char ** a,const u_char ** ta,int n,int i,const u_char * tr,u_int endch)226*bc328a43SAugustin Cavalier r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
227*bc328a43SAugustin Cavalier u_int endch)
2285af32e75SAxel Dörfler {
229*bc328a43SAugustin Cavalier static int count[256], nc, bmin;
230*bc328a43SAugustin Cavalier int c;
231*bc328a43SAugustin Cavalier const u_char **ak, **ai;
2325af32e75SAxel Dörfler stack s[512], *sp, *sp0, *sp1, temp;
233*bc328a43SAugustin Cavalier const u_char **top[256];
234*bc328a43SAugustin Cavalier int *cp, bigc;
2355af32e75SAxel Dörfler
2365af32e75SAxel Dörfler sp = s;
2375af32e75SAxel Dörfler push(a, n, i);
2385af32e75SAxel Dörfler while (!empty(s)) {
2395af32e75SAxel Dörfler pop(a, n, i);
2405af32e75SAxel Dörfler if (n < THRESHOLD) {
2415af32e75SAxel Dörfler simplesort(a, n, i, tr, endch);
2425af32e75SAxel Dörfler continue;
2435af32e75SAxel Dörfler }
2445af32e75SAxel Dörfler
2455af32e75SAxel Dörfler if (nc == 0) {
2465af32e75SAxel Dörfler bmin = 255;
2475af32e75SAxel Dörfler for (ak = a + n; --ak >= a;) {
2485af32e75SAxel Dörfler c = tr[(*ak)[i]];
2495af32e75SAxel Dörfler if (++count[c] == 1 && c != endch) {
2505af32e75SAxel Dörfler if (c < bmin)
2515af32e75SAxel Dörfler bmin = c;
2525af32e75SAxel Dörfler nc++;
2535af32e75SAxel Dörfler }
2545af32e75SAxel Dörfler }
2555af32e75SAxel Dörfler if (sp + nc > s + SIZE) {
2565af32e75SAxel Dörfler r_sort_b(a, ta, n, i, tr, endch);
2575af32e75SAxel Dörfler continue;
2585af32e75SAxel Dörfler }
2595af32e75SAxel Dörfler }
2605af32e75SAxel Dörfler
2615af32e75SAxel Dörfler sp0 = sp1 = sp;
2625af32e75SAxel Dörfler bigc = 2;
2635af32e75SAxel Dörfler if (endch == 0) {
2645af32e75SAxel Dörfler top[0] = ak = a + count[0];
2655af32e75SAxel Dörfler count[0] = 0;
2665af32e75SAxel Dörfler } else {
2675af32e75SAxel Dörfler ak = a;
2685af32e75SAxel Dörfler top[255] = a + n;
2695af32e75SAxel Dörfler count[255] = 0;
2705af32e75SAxel Dörfler }
2715af32e75SAxel Dörfler for (cp = count + bmin; nc > 0; cp++) {
2725af32e75SAxel Dörfler while (*cp == 0)
2735af32e75SAxel Dörfler cp++;
2745af32e75SAxel Dörfler if ((c = *cp) > 1) {
2755af32e75SAxel Dörfler if (c > bigc) {
2765af32e75SAxel Dörfler bigc = c;
2775af32e75SAxel Dörfler sp1 = sp;
2785af32e75SAxel Dörfler }
2795af32e75SAxel Dörfler push(ak, c, i+1);
2805af32e75SAxel Dörfler }
2815af32e75SAxel Dörfler top[cp-count] = ak += c;
2825af32e75SAxel Dörfler *cp = 0; /* Reset count[]. */
2835af32e75SAxel Dörfler nc--;
2845af32e75SAxel Dörfler }
2855af32e75SAxel Dörfler swap(*sp0, *sp1, temp);
2865af32e75SAxel Dörfler
2875af32e75SAxel Dörfler for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
2885af32e75SAxel Dörfler *--ak = *--ai;
2895af32e75SAxel Dörfler for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
2905af32e75SAxel Dörfler *--top[tr[(*ak)[i]]] = *ak;
2915af32e75SAxel Dörfler }
2925af32e75SAxel Dörfler }
2935af32e75SAxel Dörfler
294*bc328a43SAugustin Cavalier /* insertion sort */
295*bc328a43SAugustin Cavalier static inline void
simplesort(const u_char ** a,int n,int b,const u_char * tr,u_int endch)296*bc328a43SAugustin Cavalier simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
2975af32e75SAxel Dörfler {
2985af32e75SAxel Dörfler u_char ch;
299*bc328a43SAugustin Cavalier const u_char **ak, **ai, *s, *t;
3005af32e75SAxel Dörfler
301*bc328a43SAugustin Cavalier for (ak = a+1; --n >= 1; ak++)
3025af32e75SAxel Dörfler for (ai = ak; ai > a; ai--) {
3035af32e75SAxel Dörfler for (s = ai[0] + b, t = ai[-1] + b;
3045af32e75SAxel Dörfler (ch = tr[*s]) != endch; s++, t++)
3055af32e75SAxel Dörfler if (ch != tr[*t])
3065af32e75SAxel Dörfler break;
3075af32e75SAxel Dörfler if (ch >= tr[*t])
3085af32e75SAxel Dörfler break;
3095af32e75SAxel Dörfler swap(ai[0], ai[-1], s);
3105af32e75SAxel Dörfler }
3115af32e75SAxel Dörfler }
312