radix_sort.c revision 1.2 1 1.2 dsl /* $NetBSD: radix_sort.c,v 1.2 2009/09/05 12:00:25 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.2 dsl __RCSID("$NetBSD: radix_sort.c,v 1.2 2009/09/05 12:00:25 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.2 dsl const RECHEADER **sa; /* Base of saved area */
56 1.2 dsl int sn; /* Number of entries */
57 1.2 dsl int si; /* index into data for compare */
58 1.1 dsl } stack;
59 1.1 dsl
60 1.2 dsl static inline int simplesort(const RECHEADER **, int, int, const u_char *, u_int);
61 1.2 dsl static int r_sort_b(const RECHEADER **,
62 1.2 dsl const RECHEADER **, int, int, const u_char *, u_int);
63 1.1 dsl
64 1.1 dsl #define THRESHOLD 20 /* Divert to simplesort(). */
65 1.1 dsl #define SIZE 512 /* Default stack size. */
66 1.1 dsl
67 1.2 dsl #define empty(s) (s >= sp)
68 1.2 dsl #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
69 1.2 dsl #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
70 1.2 dsl #define swap(a, b, t) t = a, a = b, b = t
71 1.2 dsl
72 1.1 dsl int
73 1.2 dsl radix_sort(const RECHEADER **a, const RECHEADER **ta, int n, const u_char *tab, u_int endch)
74 1.1 dsl {
75 1.1 dsl endch = tab[endch];
76 1.2 dsl if (n < THRESHOLD && !DEBUG('r')) {
77 1.2 dsl return simplesort(a, n, 0, tab, endch);
78 1.1 dsl }
79 1.2 dsl return r_sort_b(a, ta, n, 0, tab, endch);
80 1.1 dsl }
81 1.1 dsl
82 1.2 dsl static int
83 1.2 dsl r_sort_b(const RECHEADER **a, const RECHEADER **ta, int n, int i, const u_char *tr, u_int endch)
84 1.1 dsl {
85 1.1 dsl static u_int count[256], nc, bmin;
86 1.1 dsl u_int c;
87 1.2 dsl const RECHEADER **ak, **ai;
88 1.1 dsl stack s[512], *sp, *sp0, *sp1, temp;
89 1.2 dsl const RECHEADER **top[256];
90 1.1 dsl u_int *cp, bigc;
91 1.2 dsl int nrec = n;
92 1.1 dsl
93 1.1 dsl sp = s;
94 1.1 dsl push(a, n, i);
95 1.1 dsl while (!empty(s)) {
96 1.1 dsl pop(a, n, i);
97 1.2 dsl if (n < THRESHOLD && !DEBUG('r')) {
98 1.1 dsl simplesort(a, n, i, tr, endch);
99 1.1 dsl continue;
100 1.1 dsl }
101 1.1 dsl
102 1.1 dsl if (nc == 0) {
103 1.1 dsl bmin = 255;
104 1.1 dsl for (ak = a + n; --ak >= a;) {
105 1.2 dsl c = tr[(*ak)->data[i]];
106 1.1 dsl if (++count[c] == 1 && c != endch) {
107 1.1 dsl if (c < bmin)
108 1.1 dsl bmin = c;
109 1.1 dsl nc++;
110 1.1 dsl }
111 1.1 dsl }
112 1.1 dsl if (sp + nc > s + SIZE) {
113 1.1 dsl r_sort_b(a, ta, n, i, tr, endch);
114 1.1 dsl continue;
115 1.1 dsl }
116 1.1 dsl }
117 1.1 dsl
118 1.1 dsl sp0 = sp1 = sp;
119 1.1 dsl bigc = 2;
120 1.1 dsl if (endch == 0) {
121 1.1 dsl top[0] = ak = a + count[0];
122 1.1 dsl count[0] = 0;
123 1.1 dsl } else {
124 1.1 dsl ak = a;
125 1.1 dsl top[255] = a + n;
126 1.1 dsl count[255] = 0;
127 1.1 dsl }
128 1.1 dsl for (cp = count + bmin; nc > 0; cp++) {
129 1.1 dsl while (*cp == 0)
130 1.1 dsl cp++;
131 1.1 dsl if ((c = *cp) > 1) {
132 1.1 dsl if (c > bigc) {
133 1.1 dsl bigc = c;
134 1.1 dsl sp1 = sp;
135 1.1 dsl }
136 1.1 dsl push(ak, c, i+1);
137 1.1 dsl }
138 1.1 dsl top[cp-count] = ak += c;
139 1.1 dsl *cp = 0; /* Reset count[]. */
140 1.1 dsl nc--;
141 1.1 dsl }
142 1.1 dsl swap(*sp0, *sp1, temp);
143 1.1 dsl
144 1.1 dsl for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
145 1.1 dsl *--ak = *--ai;
146 1.1 dsl for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
147 1.2 dsl *--top[tr[(*ak)->data[i]]] = *ak;
148 1.1 dsl }
149 1.2 dsl
150 1.2 dsl return nrec;
151 1.1 dsl }
152 1.1 dsl
153 1.1 dsl /* insertion sort */
154 1.2 dsl static inline int
155 1.2 dsl simplesort(const RECHEADER **a, int n, int b, const u_char *tr, u_int endch)
156 1.1 dsl {
157 1.2 dsl const RECHEADER **ak, **ai, *tmp;
158 1.2 dsl const RECHEADER **lim = a + n;
159 1.2 dsl const u_char *s, *t;
160 1.1 dsl u_char ch;
161 1.1 dsl
162 1.2 dsl if (n <= 1)
163 1.2 dsl return n;
164 1.1 dsl
165 1.2 dsl for (ak = a+1; ak < lim; ak++) {
166 1.1 dsl for (ai = ak; ai > a; ai--) {
167 1.2 dsl for (s = ai[0]->data + b, t = ai[-1]->data + b;
168 1.1 dsl (ch = tr[*s]) != endch; s++, t++)
169 1.1 dsl if (ch != tr[*t])
170 1.1 dsl break;
171 1.2 dsl if (ch >= tr[*t]) {
172 1.2 dsl
173 1.1 dsl break;
174 1.2 dsl }
175 1.2 dsl swap(ai[0], ai[-1], tmp);
176 1.1 dsl }
177 1.2 dsl }
178 1.2 dsl
179 1.2 dsl return n;
180 1.1 dsl }
181