radix_sort.c revision 1.1 1 1.1 dsl /* $NetBSD: radix_sort.c,v 1.1 2009/09/05 09:16:18 dsl Exp $ */
2 1.1 dsl
3 1.1 dsl /*-
4 1.1 dsl * Copyright (c) 1990, 1993
5 1.1 dsl * The Regents of the University of California. All rights reserved.
6 1.1 dsl *
7 1.1 dsl * This code is derived from software contributed to Berkeley by
8 1.1 dsl * Peter McIlroy and by Dan Bernstein at New York University,
9 1.1 dsl *
10 1.1 dsl * Redistribution and use in source and binary forms, with or without
11 1.1 dsl * modification, are permitted provided that the following conditions
12 1.1 dsl * are met:
13 1.1 dsl * 1. Redistributions of source code must retain the above copyright
14 1.1 dsl * notice, this list of conditions and the following disclaimer.
15 1.1 dsl * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 dsl * notice, this list of conditions and the following disclaimer in the
17 1.1 dsl * documentation and/or other materials provided with the distribution.
18 1.1 dsl * 3. Neither the name of the University nor the names of its contributors
19 1.1 dsl * may be used to endorse or promote products derived from this software
20 1.1 dsl * without specific prior written permission.
21 1.1 dsl *
22 1.1 dsl * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 dsl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 dsl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 dsl * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 dsl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 dsl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 dsl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 dsl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 dsl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 dsl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 dsl * SUCH DAMAGE.
33 1.1 dsl */
34 1.1 dsl
35 1.1 dsl #include <sys/cdefs.h>
36 1.1 dsl #if defined(LIBC_SCCS) && !defined(lint)
37 1.1 dsl #if 0
38 1.1 dsl static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
39 1.1 dsl #else
40 1.1 dsl __RCSID("$NetBSD: radix_sort.c,v 1.1 2009/09/05 09:16:18 dsl Exp $");
41 1.1 dsl #endif
42 1.1 dsl #endif /* LIBC_SCCS and not lint */
43 1.1 dsl
44 1.1 dsl /*
45 1.1 dsl * 'stable' radix sort initially from libc/stdlib/radixsort.c
46 1.1 dsl */
47 1.1 dsl
48 1.1 dsl #include <sys/types.h>
49 1.1 dsl
50 1.1 dsl #include <assert.h>
51 1.1 dsl #include <errno.h>
52 1.1 dsl #include "sort.h"
53 1.1 dsl
54 1.1 dsl typedef struct {
55 1.1 dsl const u_char **sa;
56 1.1 dsl int sn, si;
57 1.1 dsl } stack;
58 1.1 dsl
59 1.1 dsl static inline void simplesort(const u_char **, int, int, const u_char *, u_int);
60 1.1 dsl static void r_sort_b(const u_char **,
61 1.1 dsl const u_char **, int, int, const u_char *, u_int);
62 1.1 dsl
63 1.1 dsl #define THRESHOLD 20 /* Divert to simplesort(). */
64 1.1 dsl #define SIZE 512 /* Default stack size. */
65 1.1 dsl
66 1.1 dsl int
67 1.1 dsl radix_sort(const u_char **a, int n, const u_char *tab, u_int endch)
68 1.1 dsl {
69 1.1 dsl const u_char **ta;
70 1.1 dsl
71 1.1 dsl endch = tab[endch];
72 1.1 dsl if (n < THRESHOLD)
73 1.1 dsl simplesort(a, n, 0, tab, endch);
74 1.1 dsl else {
75 1.1 dsl if ((ta = malloc(n * sizeof(a))) == NULL)
76 1.1 dsl return (-1);
77 1.1 dsl r_sort_b(a, ta, n, 0, tab, endch);
78 1.1 dsl free(ta);
79 1.1 dsl }
80 1.1 dsl return (0);
81 1.1 dsl }
82 1.1 dsl
83 1.1 dsl #define empty(s) (s >= sp)
84 1.1 dsl #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
85 1.1 dsl #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
86 1.1 dsl #define swap(a, b, t) t = a, a = b, b = t
87 1.1 dsl
88 1.1 dsl /* Stable sort, requiring additional memory. */
89 1.1 dsl static void
90 1.1 dsl r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
91 1.1 dsl u_int endch)
92 1.1 dsl {
93 1.1 dsl static u_int count[256], nc, bmin;
94 1.1 dsl u_int c;
95 1.1 dsl const u_char **ak, **ai;
96 1.1 dsl stack s[512], *sp, *sp0, *sp1, temp;
97 1.1 dsl const u_char **top[256];
98 1.1 dsl u_int *cp, bigc;
99 1.1 dsl
100 1.1 dsl _DIAGASSERT(a != NULL);
101 1.1 dsl _DIAGASSERT(ta != NULL);
102 1.1 dsl _DIAGASSERT(tr != NULL);
103 1.1 dsl
104 1.1 dsl sp = s;
105 1.1 dsl push(a, n, i);
106 1.1 dsl while (!empty(s)) {
107 1.1 dsl pop(a, n, i);
108 1.1 dsl if (n < THRESHOLD) {
109 1.1 dsl simplesort(a, n, i, tr, endch);
110 1.1 dsl continue;
111 1.1 dsl }
112 1.1 dsl
113 1.1 dsl if (nc == 0) {
114 1.1 dsl bmin = 255;
115 1.1 dsl for (ak = a + n; --ak >= a;) {
116 1.1 dsl c = tr[(*ak)[i]];
117 1.1 dsl if (++count[c] == 1 && c != endch) {
118 1.1 dsl if (c < bmin)
119 1.1 dsl bmin = c;
120 1.1 dsl nc++;
121 1.1 dsl }
122 1.1 dsl }
123 1.1 dsl if (sp + nc > s + SIZE) {
124 1.1 dsl r_sort_b(a, ta, n, i, tr, endch);
125 1.1 dsl continue;
126 1.1 dsl }
127 1.1 dsl }
128 1.1 dsl
129 1.1 dsl sp0 = sp1 = sp;
130 1.1 dsl bigc = 2;
131 1.1 dsl if (endch == 0) {
132 1.1 dsl top[0] = ak = a + count[0];
133 1.1 dsl count[0] = 0;
134 1.1 dsl } else {
135 1.1 dsl ak = a;
136 1.1 dsl top[255] = a + n;
137 1.1 dsl count[255] = 0;
138 1.1 dsl }
139 1.1 dsl for (cp = count + bmin; nc > 0; cp++) {
140 1.1 dsl while (*cp == 0)
141 1.1 dsl cp++;
142 1.1 dsl if ((c = *cp) > 1) {
143 1.1 dsl if (c > bigc) {
144 1.1 dsl bigc = c;
145 1.1 dsl sp1 = sp;
146 1.1 dsl }
147 1.1 dsl push(ak, c, i+1);
148 1.1 dsl }
149 1.1 dsl top[cp-count] = ak += c;
150 1.1 dsl *cp = 0; /* Reset count[]. */
151 1.1 dsl nc--;
152 1.1 dsl }
153 1.1 dsl swap(*sp0, *sp1, temp);
154 1.1 dsl
155 1.1 dsl for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
156 1.1 dsl *--ak = *--ai;
157 1.1 dsl for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
158 1.1 dsl *--top[tr[(*ak)[i]]] = *ak;
159 1.1 dsl }
160 1.1 dsl }
161 1.1 dsl
162 1.1 dsl /* insertion sort */
163 1.1 dsl static inline void
164 1.1 dsl simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
165 1.1 dsl {
166 1.1 dsl u_char ch;
167 1.1 dsl const u_char **ak, **ai, *s, *t;
168 1.1 dsl
169 1.1 dsl _DIAGASSERT(a != NULL);
170 1.1 dsl _DIAGASSERT(tr != NULL);
171 1.1 dsl
172 1.1 dsl for (ak = a+1; --n >= 1; ak++)
173 1.1 dsl for (ai = ak; ai > a; ai--) {
174 1.1 dsl for (s = ai[0] + b, t = ai[-1] + b;
175 1.1 dsl (ch = tr[*s]) != endch; s++, t++)
176 1.1 dsl if (ch != tr[*t])
177 1.1 dsl break;
178 1.1 dsl if (ch >= tr[*t])
179 1.1 dsl break;
180 1.1 dsl swap(ai[0], ai[-1], s);
181 1.1 dsl }
182 1.1 dsl }
183