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 #if defined(I_AM_QSORT_R)
66 #define _BSD_SOURCE
67 #else
68 #define _DEFAULT_SOURCE
69 #endif
70 #include <stdlib.h>
71 #include <stdint.h>
72
73 #if defined(I_AM_QSORT_R)
74 typedef int cmp_t(void *, const void *, const void *);
75 #elif defined(I_AM_GNU_QSORT_R)
76 typedef int cmp_t(const void *, const void *, void *);
77 #else
78 typedef int cmp_t(const void *, const void *);
79 #endif
80 static inline char *med3 (char *, char *, char *, cmp_t *, void *);
81 static inline void swapfunc(char *, char *, size_t, int, int);
82
83 #define min(a, b) (a) < (b) ? a : b
84
85 /*
86 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
87 */
88 #define swapcode(TYPE, parmi, parmj, n) { \
89 size_t i = (n) / sizeof (TYPE); \
90 TYPE *pi = (TYPE *) (parmi); \
91 TYPE *pj = (TYPE *) (parmj); \
92 do { \
93 TYPE t = *pi; \
94 *pi++ = *pj; \
95 *pj++ = t; \
96 } while (--i > 0); \
97 }
98
99 #define SWAPINIT(TYPE, a, es) swaptype_ ## TYPE = \
100 ((uintptr_t)(a) % sizeof(TYPE)) || \
101 ((es) % sizeof(TYPE)) ? 2 : ((es) == sizeof(TYPE)) ? 0 : 1;
102
103 static inline void
swapfunc(char * a,char * b,size_t n,int swaptype_intptr_t,int swaptype_int)104 swapfunc(char *a, char *b, size_t n, int swaptype_intptr_t, int swaptype_int)
105 {
106 if (swaptype_intptr_t <= 1)
107 swapcode(intptr_t, a, b, n)
108 else if (swaptype_int <= 1)
109 swapcode(int, a, b, n)
110 else
111 swapcode(char, a, b, n)
112 }
113
114 #define swap(a, b) \
115 if (swaptype_intptr_t == 0) { \
116 intptr_t t = *(intptr_t *)(a); \
117 *(intptr_t *)(a) = *(intptr_t *)(b); \
118 *(intptr_t *)(b) = t; \
119 } else if (swaptype_int == 0) { \
120 int t = *(int *)(a); \
121 *(int *)(a) = *(int *)(b); \
122 *(int *)(b) = t; \
123 } else \
124 swapfunc(a, b, es, swaptype_intptr_t, swaptype_int)
125
126 #define vecswap(a, b, n) \
127 if ((n) > 0) swapfunc(a, b, n, swaptype_intptr_t, swaptype_int)
128
129 #if defined(I_AM_QSORT_R)
130 #define CMP(t, x, y) (cmp((t), (x), (y)))
131 #elif defined(I_AM_GNU_QSORT_R)
132 #define CMP(t, x, y) (cmp((x), (y), (t)))
133 #else
134 #define CMP(t, x, y) (cmp((x), (y)))
135 #endif
136
137 static __inline char *
med3(char * a,char * b,char * c,cmp_t * cmp,void * thunk __unused)138 med3 (char *a,
139 char *b,
140 char *c,
141 cmp_t *cmp,
142 void *thunk
143 #if !defined(I_AM_QSORT_R) && !defined(I_AM_GNU_QSORT_R)
144 __unused
145 #endif
146 )
147 {
148 return CMP(thunk, a, b) < 0 ?
149 (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
150 :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
151 }
152
153 /*
154 * Classical function call recursion wastes a lot of stack space. Each
155 * recursion level requires a full stack frame comprising all local variables
156 * and additional space as dictated by the processor calling convention.
157 *
158 * This implementation instead stores the variables that are unique for each
159 * recursion level in a parameter stack array, and uses iteration to emulate
160 * recursion. Function call recursion is not used until the array is full.
161 *
162 * To ensure the stack consumption isn't worsened by this design, the size of
163 * the parameter stack array is chosen to be similar to the stack frame
164 * excluding the array. Each function call recursion level can handle this
165 * number of iterative recursion levels.
166 */
167 #define PARAMETER_STACK_LEVELS 8u
168
169 #if defined(I_AM_QSORT_R)
170 void
171 __bsd_qsort_r (void *a,
172 size_t n,
173 size_t es,
174 void *thunk,
175 cmp_t *cmp);
176
177 void
__bsd_qsort_r(void * a,size_t n,size_t es,void * thunk,cmp_t * cmp)178 __bsd_qsort_r (void *a,
179 size_t n,
180 size_t es,
181 void *thunk,
182 cmp_t *cmp)
183 #elif defined(I_AM_GNU_QSORT_R)
184 void
185 qsort_r (void *a,
186 size_t n,
187 size_t es,
188 cmp_t *cmp,
189 void *thunk)
190 #else
191 #define thunk NULL
192 void
193 qsort (void *a,
194 size_t n,
195 size_t es,
196 cmp_t *cmp)
197 #endif
198 {
199 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
200 size_t d, r;
201 int cmp_result;
202 int swaptype_intptr_t, swaptype_int, swap_cnt;
203 size_t recursion_level = 0;
204 struct { void *a; size_t n; } parameter_stack[PARAMETER_STACK_LEVELS];
205
206 SWAPINIT(intptr_t, a, es);
207 SWAPINIT(int, a, es);
208 loop: swap_cnt = 0;
209 if (n < 7) {
210 /* Short arrays are insertion sorted. */
211 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
212 for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
213 pl -= es)
214 swap(pl, pl - es);
215 goto pop;
216 }
217
218 /* Select a pivot element, move it to the left. */
219 pm = (char *) a + (n / 2) * es;
220 if (n > 7) {
221 pl = a;
222 pn = (char *) a + (n - 1) * es;
223 if (n > 40) {
224 d = (n / 8) * es;
225 pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
226 pm = med3(pm - d, pm, pm + d, cmp, thunk);
227 pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
228 }
229 pm = med3(pl, pm, pn, cmp, thunk);
230 }
231 swap(a, pm);
232
233 /*
234 * Sort the array relative the pivot in four ranges as follows:
235 * { elems == pivot, elems < pivot, elems > pivot, elems == pivot }
236 */
237 pa = pb = (char *) a + es;
238 pc = pd = (char *) a + (n - 1) * es;
239 for (;;) {
240 /* Scan left to right stopping at first element > pivot. */
241 while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
242 /* Move elements == pivot to the left (to pa) */
243 if (cmp_result == 0) {
244 swap_cnt = 1;
245 swap(pa, pb);
246 pa += es;
247 }
248 pb += es;
249 }
250 /* Scan right to left stopping at first element < pivot. */
251 while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
252 /* Move elements == pivot to the right (to pd) */
253 if (cmp_result == 0) {
254 swap_cnt = 1;
255 swap(pc, pd);
256 pd -= es;
257 }
258 pc -= es;
259 }
260 if (pb > pc)
261 break;
262 /* The scan has found two elements to swap with each other. */
263 swap(pb, pc);
264 swap_cnt = 1;
265 pb += es;
266 pc -= es;
267 }
268 if (swap_cnt == 0) { /* Switch to insertion sort */
269 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
270 for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
271 pl -= es)
272 swap(pl, pl - es);
273 goto pop;
274 }
275
276 /*
277 * Rearrange the array in three parts sorted like this:
278 * { elements < pivot, elements == pivot, elements > pivot }
279 */
280 pn = (char *) a + n * es;
281 r = min(pa - (char *)a, pb - pa);
282 vecswap(a, pb - r, r);
283 r = min((size_t) (pd - pc), (size_t) (pn - pd) - es);
284 vecswap(pb, pn - r, r);
285 d = pb - pa; /* d = Size of left part. */
286 r = pd - pc; /* r = Size of right part. */
287 pn -= r; /* pn = Base of right part. */
288
289 /*
290 * Check which of the left and right parts are larger.
291 * Set (a, n) to (base, size) of the larger part.
292 * Set (pa, r) to (base, size) of the smaller part.
293 */
294 if (r > d) { /* Right part is the larger part */
295 pa = a;
296 a = pn;
297 n = r;
298 r = d;
299 }
300 else { /* Left part is the larger part, or both are equal. */
301 pa = pn;
302 n = d;
303 }
304
305 /*
306 * The left and right parts each need further sorting if they
307 * contain two elements or more. If both need sorting we use
308 * recursion to sort the smaller part and save the larger part
309 * to be sorted by iteration after the recursion.
310 * Using recursion only for the smaller part guarantees a
311 * recursion depth that is bounded to be less than (log2(n)).
312 */
313 if (r > es) { /* Smaller part > 1 element. Both parts need sorting. */
314 if (recursion_level < PARAMETER_STACK_LEVELS) {
315 /*
316 * The smaller part needs to be recursively sorted
317 * before the larger part is sorted. To avoid function
318 * call recursion the parameters for the larger part
319 * are pushed on the parameter_stack array. The smaller
320 * part is sorted using iteration and the larger part
321 * will be sorted when the parameter_stack is popped
322 * after the smaller part has been sorted.
323 */
324 parameter_stack[recursion_level].a = a;
325 parameter_stack[recursion_level].n = n / es;
326 recursion_level++;
327 a = pa;
328 n = r / es;
329 goto loop;
330 }
331 else {
332 /*
333 * The parameter_stack array is full. The smaller part
334 * is sorted using function call recursion. The larger
335 * part will be sorted after the function call returns.
336 */
337 #if defined(I_AM_QSORT_R)
338 __bsd_qsort_r(pa, r / es, es, thunk, cmp);
339 #elif defined(I_AM_GNU_QSORT_R)
340 qsort_r(pa, r / es, es, cmp, thunk);
341 #else
342 qsort(pa, r / es, es, cmp);
343 #endif
344 }
345 }
346 if (n > es) { /* The larger part needs sorting. Iterate to sort. */
347 n = n / es;
348 goto loop;
349 }
350 /* Both left and right parts are one element or less - level done. */
351 pop:
352 if (recursion_level != 0) {
353 recursion_level--;
354 a = parameter_stack[recursion_level].a;
355 n = parameter_stack[recursion_level].n;
356 goto loop;
357 }
358 }
359