]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdlib/qsort.c
Remove "Contributed by" lines
[thirdparty/glibc.git] / stdlib / qsort.c
CommitLineData
2b778ceb 1/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
6d52618b 2 This file is part of the GNU C Library.
28f540f4 3
6d52618b 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
6d52618b
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4 17
061d137b
UD
18/* If you consider tuning this algorithm, you should consult first:
19 Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
20 Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
21
22#include <alloca.h>
23#include <limits.h>
28f540f4
RM
24#include <stdlib.h>
25#include <string.h>
26
27/* Byte-wise swap two items of size SIZE. */
28#define SWAP(a, b, size) \
29 do \
30 { \
2e09a79a
JM
31 size_t __size = (size); \
32 char *__a = (a), *__b = (b); \
28f540f4
RM
33 do \
34 { \
35 char __tmp = *__a; \
36 *__a++ = *__b; \
37 *__b++ = __tmp; \
38 } while (--__size > 0); \
39 } while (0)
40
41/* Discontinue quicksort algorithm when partition gets below this size.
42 This particular magic number was chosen to work best on a Sun 4/260. */
43#define MAX_THRESH 4
44
45/* Stack node declarations used to store unfulfilled partition obligations. */
6d52618b 46typedef struct
28f540f4
RM
47 {
48 char *lo;
49 char *hi;
50 } stack_node;
51
52/* The next 4 #defines implement a very fast in-line stack abstraction. */
061d137b
UD
53/* The stack needs log (total_elements) entries (we could even subtract
54 log(MAX_THRESH)). Since total_elements has type size_t, we get as
55 upper bound for log (total_elements):
56 bits per byte (CHAR_BIT) * sizeof(size_t). */
c4f50205 57#define STACK_SIZE (CHAR_BIT * sizeof (size_t))
28f540f4
RM
58#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
59#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
6d52618b 60#define STACK_NOT_EMPTY (stack < top)
28f540f4
RM
61
62
63/* Order size using quicksort. This implementation incorporates
64 four optimizations discussed in Sedgewick:
65
6d52618b
UD
66 1. Non-recursive, using an explicit stack of pointer that store the
67 next array partition to sort. To save time, this maximum amount
061d137b
UD
68 of space required to store an array of SIZE_MAX is allocated on the
69 stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
70 only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
71 Pretty cheap, actually.
28f540f4
RM
72
73 2. Chose the pivot element using a median-of-three decision tree.
6d52618b 74 This reduces the probability of selecting a bad pivot value and
28f540f4
RM
75 eliminates certain extraneous comparisons.
76
77 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
6d52618b 78 insertion sort to order the MAX_THRESH items within each partition.
28f540f4 79 This is a big win, since insertion sort is faster for small, mostly
6d52618b 80 sorted array segments.
28f540f4
RM
81
82 4. The larger of the two sub-partitions is always pushed onto the
83 stack first, with the algorithm then concentrating on the
061d137b 84 smaller partition. This *guarantees* no more than log (total_elems)
28f540f4
RM
85 stack size is needed (actually O(1) in this case)! */
86
87void
061d137b 88_quicksort (void *const pbase, size_t total_elems, size_t size,
e458144c 89 __compar_d_fn_t cmp, void *arg)
28f540f4 90{
2e09a79a 91 char *base_ptr = (char *) pbase;
28f540f4 92
7cc27f44 93 const size_t max_thresh = MAX_THRESH * size;
28f540f4
RM
94
95 if (total_elems == 0)
96 /* Avoid lossage with unsigned arithmetic below. */
97 return;
98
99 if (total_elems > MAX_THRESH)
100 {
101 char *lo = base_ptr;
102 char *hi = &lo[size * (total_elems - 1)];
28f540f4 103 stack_node stack[STACK_SIZE];
3f2fb223
UD
104 stack_node *top = stack;
105
106 PUSH (NULL, NULL);
28f540f4
RM
107
108 while (STACK_NOT_EMPTY)
109 {
110 char *left_ptr;
111 char *right_ptr;
112
28f540f4 113 /* Select median value from among LO, MID, and HI. Rearrange
6d52618b
UD
114 LO and HI so the three values are sorted. This lowers the
115 probability of picking a pathological pivot value and
061d137b
UD
116 skips a comparison for both the LEFT_PTR and RIGHT_PTR in
117 the while loops. */
28f540f4
RM
118
119 char *mid = lo + size * ((hi - lo) / size >> 1);
120
e458144c 121 if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
7cc27f44 122 SWAP (mid, lo, size);
e458144c 123 if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
7cc27f44 124 SWAP (mid, hi, size);
6d52618b 125 else
28f540f4 126 goto jump_over;
e458144c 127 if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
7cc27f44 128 SWAP (mid, lo, size);
28f540f4 129 jump_over:;
28f540f4
RM
130
131 left_ptr = lo + size;
6d52618b 132 right_ptr = hi - size;
28f540f4 133
6d52618b
UD
134 /* Here's the famous ``collapse the walls'' section of quicksort.
135 Gotta like those tight inner loops! They are the main reason
28f540f4 136 that this algorithm runs much faster than others. */
6d52618b 137 do
28f540f4 138 {
e458144c 139 while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
28f540f4
RM
140 left_ptr += size;
141
e458144c 142 while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
28f540f4
RM
143 right_ptr -= size;
144
6d52618b 145 if (left_ptr < right_ptr)
28f540f4 146 {
7cc27f44 147 SWAP (left_ptr, right_ptr, size);
fa8d436c
UD
148 if (mid == left_ptr)
149 mid = right_ptr;
150 else if (mid == right_ptr)
151 mid = left_ptr;
28f540f4
RM
152 left_ptr += size;
153 right_ptr -= size;
154 }
6d52618b 155 else if (left_ptr == right_ptr)
28f540f4
RM
156 {
157 left_ptr += size;
158 right_ptr -= size;
159 break;
160 }
6d52618b 161 }
28f540f4
RM
162 while (left_ptr <= right_ptr);
163
164 /* Set up pointers for next iteration. First determine whether
6d52618b 165 left and right partitions are below the threshold size. If so,
28f540f4
RM
166 ignore one or both. Otherwise, push the larger partition's
167 bounds on the stack and continue sorting the smaller one. */
168
169 if ((size_t) (right_ptr - lo) <= max_thresh)
170 {
171 if ((size_t) (hi - left_ptr) <= max_thresh)
172 /* Ignore both small partitions. */
7cc27f44 173 POP (lo, hi);
28f540f4 174 else
6d52618b 175 /* Ignore small left partition. */
28f540f4
RM
176 lo = left_ptr;
177 }
178 else if ((size_t) (hi - left_ptr) <= max_thresh)
179 /* Ignore small right partition. */
180 hi = right_ptr;
181 else if ((right_ptr - lo) > (hi - left_ptr))
6d52618b 182 {
28f540f4 183 /* Push larger left partition indices. */
7cc27f44 184 PUSH (lo, right_ptr);
28f540f4
RM
185 lo = left_ptr;
186 }
187 else
6d52618b 188 {
28f540f4 189 /* Push larger right partition indices. */
7cc27f44 190 PUSH (left_ptr, hi);
28f540f4
RM
191 hi = right_ptr;
192 }
193 }
194 }
195
196 /* Once the BASE_PTR array is partially sorted by quicksort the rest
6d52618b
UD
197 is completely sorted using insertion sort, since this is efficient
198 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
28f540f4
RM
199 of the array to sort, and END_PTR points at the very last element in
200 the array (*not* one beyond it!). */
201
202#define min(x, y) ((x) < (y) ? (x) : (y))
203
204 {
7cc27f44 205 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
28f540f4
RM
206 char *tmp_ptr = base_ptr;
207 char *thresh = min(end_ptr, base_ptr + max_thresh);
2e09a79a 208 char *run_ptr;
28f540f4
RM
209
210 /* Find smallest element in first threshold and place it at the
211 array's beginning. This is the smallest array element,
212 and the operation speeds up insertion sort's inner loop. */
213
214 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
e458144c 215 if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
28f540f4
RM
216 tmp_ptr = run_ptr;
217
218 if (tmp_ptr != base_ptr)
7cc27f44 219 SWAP (tmp_ptr, base_ptr, size);
28f540f4
RM
220
221 /* Insertion sort, running from left-hand-side up to right-hand-side. */
222
223 run_ptr = base_ptr + size;
224 while ((run_ptr += size) <= end_ptr)
225 {
226 tmp_ptr = run_ptr - size;
e458144c 227 while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
28f540f4
RM
228 tmp_ptr -= size;
229
230 tmp_ptr += size;
231 if (tmp_ptr != run_ptr)
232 {
233 char *trav;
234
235 trav = run_ptr + size;
236 while (--trav >= run_ptr)
237 {
238 char c = *trav;
239 char *hi, *lo;
240
241 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
242 *hi = *lo;
243 *hi = c;
244 }
245 }
246 }
247 }
248}