1 /*
2 FUNCTION
3 <<qsort>>---sort an array
4
5 INDEX
6 qsort
7
8 SYNOPSIS
9 #include <stdlib.h>
10 void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
11 int (*<[compar]>)(const void *, const void *) );
12
13 DESCRIPTION
14 <<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
15 <[size]> describes the size of each element of the array.
16
17 You must supply a pointer to a comparison function, using the argument
18 shown as <[compar]>. (This permits sorting objects of unknown
19 properties.) Define the comparison function to accept two arguments,
20 each a pointer to an element of the array starting at <[base]>. The
21 result of <<(*<[compar]>)>> must be negative if the first argument is
22 less than the second, zero if the two arguments match, and positive if
23 the first argument is greater than the second (where ``less than'' and
24 ``greater than'' refer to whatever arbitrary ordering is appropriate).
25
26 The array is sorted in place; that is, when <<qsort>> returns, the
27 array elements beginning at <[base]> have been reordered.
28
29 RETURNS
30 <<qsort>> does not return a result.
31
32 PORTABILITY
33 <<qsort>> is required by ANSI (without specifying the sorting algorithm).
34 */
35
36 /*-
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California. All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65 #include <_ansi.h>
66 #include <sys/cdefs.h>
67 #include <stdlib.h>
68 #include <stdint.h>
69
70 #ifndef __GNUC__
71 #define inline
72 #endif
73
74 #if defined(I_AM_QSORT_R)
75 typedef int cmp_t(void *, const void *, const void *);
76 #elif defined(I_AM_GNU_QSORT_R)
77 typedef int cmp_t(const void *, const void *, void *);
78 #else
79 typedef int cmp_t(const void *, const void *);
80 #endif
81 static inline char *med3 (char *, char *, char *, cmp_t *, void *);
82 static inline void swapfunc (char *, char *, int, int);
83
84 #define min(a, b) (a) < (b) ? a : b
85
86 /*
87 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
88 */
89 #define swapcode(TYPE, parmi, parmj, n) { \
90 long i = (n) / sizeof (TYPE); \
91 TYPE *pi = (TYPE *) (parmi); \
92 TYPE *pj = (TYPE *) (parmj); \
93 do { \
94 TYPE t = *pi; \
95 *pi++ = *pj; \
96 *pj++ = t; \
97 } while (--i > 0); \
98 }
99
100 #define SWAPINIT(a, es) swaptype = ((uintptr_t)(a) % sizeof(long)) || \
101 ((es) % sizeof(long)) ? 2 : ((es) == sizeof(long)) ? 0 : 1
102
103 static inline void
swapfunc(char * a,char * b,int n,int swaptype)104 swapfunc (char *a,
105 char *b,
106 int n,
107 int swaptype)
108 {
109 if(swaptype <= 1)
110 swapcode(long, a, b, n)
111 else
112 swapcode(char, a, b, n)
113 }
114
115 #define swap(a, b) \
116 if (swaptype == 0) { \
117 long t = *(long *)(a); \
118 *(long *)(a) = *(long *)(b); \
119 *(long *)(b) = t; \
120 } else \
121 swapfunc(a, b, es, swaptype)
122
123 #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
124
125 #if defined(I_AM_QSORT_R)
126 #define CMP(t, x, y) (cmp((t), (x), (y)))
127 #elif defined(I_AM_GNU_QSORT_R)
128 #define CMP(t, x, y) (cmp((x), (y), (t)))
129 #else
130 #define CMP(t, x, y) (cmp((x), (y)))
131 #endif
132
133 static inline char *
med3(char * a,char * b,char * c,cmp_t * cmp,void * thunk __unused)134 med3 (char *a,
135 char *b,
136 char *c,
137 cmp_t *cmp,
138 void *thunk
139 #if !defined(I_AM_QSORT_R) && !defined(I_AM_GNU_QSORT_R)
140 __unused
141 #endif
142 )
143 {
144 return CMP(thunk, a, b) < 0 ?
145 (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
146 :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
147 }
148
149 /*
150 * Classical function call recursion wastes a lot of stack space. Each
151 * recursion level requires a full stack frame comprising all local variables
152 * and additional space as dictated by the processor calling convention.
153 *
154 * This implementation instead stores the variables that are unique for each
155 * recursion level in a parameter stack array, and uses iteration to emulate
156 * recursion. Function call recursion is not used until the array is full.
157 *
158 * To ensure the stack consumption isn't worsened by this design, the size of
159 * the parameter stack array is chosen to be similar to the stack frame
160 * excluding the array. Each function call recursion level can handle this
161 * number of iterative recursion levels.
162 */
163 #define PARAMETER_STACK_LEVELS 8u
164
165 #if defined(I_AM_QSORT_R)
166 void
__bsd_qsort_r(void * a,size_t n,size_t es,void * thunk,cmp_t * cmp)167 __bsd_qsort_r (void *a,
168 size_t n,
169 size_t es,
170 void *thunk,
171 cmp_t *cmp)
172 #elif defined(I_AM_GNU_QSORT_R)
173 void
174 qsort_r (void *a,
175 size_t n,
176 size_t es,
177 cmp_t *cmp,
178 void *thunk)
179 #else
180 #define thunk NULL
181 void
182 qsort (void *a,
183 size_t n,
184 size_t es,
185 cmp_t *cmp)
186 #endif
187 {
188 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
189 size_t d, r;
190 int cmp_result;
191 int swaptype, swap_cnt;
192 size_t recursion_level = 0;
193 struct { void *a; size_t n; } parameter_stack[PARAMETER_STACK_LEVELS];
194
195 SWAPINIT(a, es);
196 loop: swap_cnt = 0;
197 if (n < 7) {
198 /* Short arrays are insertion sorted. */
199 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
200 for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
201 pl -= es)
202 swap(pl, pl - es);
203 goto pop;
204 }
205
206 /* Select a pivot element, move it to the left. */
207 pm = (char *) a + (n / 2) * es;
208 if (n > 7) {
209 pl = a;
210 pn = (char *) a + (n - 1) * es;
211 if (n > 40) {
212 d = (n / 8) * es;
213 pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
214 pm = med3(pm - d, pm, pm + d, cmp, thunk);
215 pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
216 }
217 pm = med3(pl, pm, pn, cmp, thunk);
218 }
219 swap(a, pm);
220
221 /*
222 * Sort the array relative the pivot in four ranges as follows:
223 * { elems == pivot, elems < pivot, elems > pivot, elems == pivot }
224 */
225 pa = pb = (char *) a + es;
226 pc = pd = (char *) a + (n - 1) * es;
227 for (;;) {
228 /* Scan left to right stopping at first element > pivot. */
229 while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
230 /* Move elements == pivot to the left (to pa) */
231 if (cmp_result == 0) {
232 swap_cnt = 1;
233 swap(pa, pb);
234 pa += es;
235 }
236 pb += es;
237 }
238 /* Scan right to left stopping at first element < pivot. */
239 while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
240 /* Move elements == pivot to the right (to pd) */
241 if (cmp_result == 0) {
242 swap_cnt = 1;
243 swap(pc, pd);
244 pd -= es;
245 }
246 pc -= es;
247 }
248 if (pb > pc)
249 break;
250 /* The scan has found two elements to swap with each other. */
251 swap(pb, pc);
252 swap_cnt = 1;
253 pb += es;
254 pc -= es;
255 }
256 if (swap_cnt == 0) { /* Switch to insertion sort */
257 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
258 for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
259 pl -= es)
260 swap(pl, pl - es);
261 goto pop;
262 }
263
264 /*
265 * Rearrange the array in three parts sorted like this:
266 * { elements < pivot, elements == pivot, elements > pivot }
267 */
268 pn = (char *) a + n * es;
269 r = min(pa - (char *)a, pb - pa);
270 vecswap(a, pb - r, r);
271 r = min((size_t) (pd - pc), (size_t) (pn - pd) - es);
272 vecswap(pb, pn - r, r);
273 d = pb - pa; /* d = Size of left part. */
274 r = pd - pc; /* r = Size of right part. */
275 pn -= r; /* pn = Base of right part. */
276
277 /*
278 * Check which of the left and right parts are larger.
279 * Set (a, n) to (base, size) of the larger part.
280 * Set (pa, r) to (base, size) of the smaller part.
281 */
282 if (r > d) { /* Right part is the larger part */
283 pa = a;
284 a = pn;
285 n = r;
286 r = d;
287 }
288 else { /* Left part is the larger part, or both are equal. */
289 pa = pn;
290 n = d;
291 }
292
293 /*
294 * The left and right parts each need further sorting if they
295 * contain two elements or more. If both need sorting we use
296 * recursion to sort the smaller part and save the larger part
297 * to be sorted by iteration after the recursion.
298 * Using recursion only for the smaller part guarantees a
299 * recursion depth that is bounded to be less than (log2(n)).
300 */
301 if (r > es) { /* Smaller part > 1 element. Both parts need sorting. */
302 if (recursion_level < PARAMETER_STACK_LEVELS) {
303 /*
304 * The smaller part needs to be recursively sorted
305 * before the larger part is sorted. To avoid function
306 * call recursion the parameters for the larger part
307 * are pushed on the parameter_stack array. The smaller
308 * part is sorted using iteration and the larger part
309 * will be sorted when the parameter_stack is popped
310 * after the smaller part has been sorted.
311 */
312 parameter_stack[recursion_level].a = a;
313 parameter_stack[recursion_level].n = n / es;
314 recursion_level++;
315 a = pa;
316 n = r / es;
317 goto loop;
318 }
319 else {
320 /*
321 * The parameter_stack array is full. The smaller part
322 * is sorted using function call recursion. The larger
323 * part will be sorted after the function call returns.
324 */
325 #if defined(I_AM_QSORT_R)
326 __bsd_qsort_r(pa, r / es, es, thunk, cmp);
327 #elif defined(I_AM_GNU_QSORT_R)
328 qsort_r(pa, r / es, es, cmp, thunk);
329 #else
330 qsort(pa, r / es, es, cmp);
331 #endif
332 }
333 }
334 if (n > es) { /* The larger part needs sorting. Iterate to sort. */
335 n = n / es;
336 goto loop;
337 }
338 /* Both left and right parts are one element or less - level done. */
339 pop:
340 if (recursion_level != 0) {
341 recursion_level--;
342 a = parameter_stack[recursion_level].a;
343 n = parameter_stack[recursion_level].n;
344 goto loop;
345 }
346 }
347