1 /* $NetBSD: radix_sort.c,v 1.3 2009/09/10 22:02:40 dsl Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Peter McIlroy and by Dan Bernstein at New York University,
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
35 #include <sys/cdefs.h>
36 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid
[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
40 __RCSID("$NetBSD: radix_sort.c,v 1.3 2009/09/10 22:02:40 dsl Exp $");
42 #endif /* LIBC_SCCS and not lint */
45 * 'stable' radix sort initially from libc/stdlib/radixsort.c
48 #include <sys/types.h>
56 RECHEADER
**sa
; /* Base of saved area */
57 int sn
; /* Number of entries */
58 int si
; /* index into data for compare */
61 static void simplesort(RECHEADER
**, int, int);
63 #define THRESHOLD 20 /* Divert to simplesort(). */
65 #define empty(s) (s >= sp)
66 #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
67 #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
68 #define swap(a, b, t) t = a, a = b, b = t
71 radix_sort(RECHEADER
**a
, RECHEADER
**ta
, int n
)
73 u_int count
[256], nc
, bmin
;
75 RECHEADER
**ak
, **tai
, **lim
;
78 stack
*s
, *sp
, *sp0
, *sp1
, temp
;
83 if (n
< THRESHOLD
&& !DEBUG('r')) {
88 s
= emalloc(stack_size
* sizeof *s
);
89 memset(&count
, 0, sizeof count
);
90 /* Technically 'top' doesn't need zeroing */
91 memset(&top
, 0, sizeof top
);
94 push(a
, n
, data_index
);
96 pop(a
, n
, data_index
);
97 if (n
< THRESHOLD
&& !DEBUG('r')) {
98 simplesort(a
, n
, data_index
);
102 /* Count number of times each 'next byte' occurs */
106 for (ak
= a
, tai
= ta
; ak
< lim
; ak
++) {
108 if (data_index
>= hdr
->keylen
) {
109 /* Short key, copy to start of output */
110 if (UNIQUE
&& a
!= sp
->sa
)
111 /* Stop duplicate being written out */
117 /* Save in temp buffer for distribute */
119 c
= hdr
->data
[data_index
];
120 if (++count
[c
] == 1) {
127 * We need save the bounds for each 'next byte' that
128 * occurs more so we can sort each block.
130 if (sp
+ nc
> s
+ stack_size
) {
132 sp1
= erealloc(s
, stack_size
* sizeof *s
);
137 /* Minor optimisation to do the largest set last */
140 /* Convert 'counts' positions, saving bounds for later sorts */
142 for (cp
= count
+ bmin
; nc
> 0; cp
++) {
150 push(ak
, c
, data_index
+1);
154 *cp
= 0; /* Reset count[]. */
157 swap(*sp0
, *sp1
, temp
);
159 for (ak
= ta
+n
; --ak
>= ta
;) /* Deal to piles. */
160 *--top
[(*ak
)->data
[data_index
]] = *ak
;
166 /* insertion sort, short records are sorted before long ones */
168 simplesort(RECHEADER
**a
, int n
, int data_index
)
170 RECHEADER
**ak
, **ai
;
172 RECHEADER
**lim
= a
+ n
;
181 for (ak
= a
+1; ak
< lim
; ak
++) {
187 t_len
= (*ai
)->keylen
;
190 for (i
= data_index
; ; i
++) {
191 if (i
>= s_len
|| i
>= t_len
) {
200 if (r
== 0 && UNIQUE
) {
201 /* Put record below existing */
203 /* Mark as duplicate - ignore */