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