/Users/deen/code/yugabyte-db/build/debugcov-clang-dynamic-arm64-ninja/postgres_build/src/backend/utils/sort/qsort_tuple.c
Line | Count | Source |
1 | | /* |
2 | | * autogenerated by src/backend/utils/sort/gen_qsort_tuple.pl, do not edit! |
3 | | * |
4 | | * This file is included by tuplesort.c, rather than compiled separately. |
5 | | */ |
6 | | |
7 | | /* $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $ */ |
8 | | |
9 | | /*- |
10 | | * Copyright (c) 1992, 1993 |
11 | | * The Regents of the University of California. All rights reserved. |
12 | | * |
13 | | * Redistribution and use in source and binary forms, with or without |
14 | | * modification, are permitted provided that the following conditions |
15 | | * are met: |
16 | | * 1. Redistributions of source code must retain the above copyright |
17 | | * notice, this list of conditions and the following disclaimer. |
18 | | * 2. Redistributions in binary form must reproduce the above copyright |
19 | | * notice, this list of conditions and the following disclaimer in the |
20 | | * documentation and/or other materials provided with the distribution. |
21 | | * 3. Neither the name of the University nor the names of its contributors |
22 | | * may be used to endorse or promote products derived from this software |
23 | | * without specific prior written permission. |
24 | | * |
25 | | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
26 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
29 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
30 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
31 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
32 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
33 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
34 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 | | * SUCH DAMAGE. |
36 | | */ |
37 | | |
38 | | /* |
39 | | * Qsort routine based on J. L. Bentley and M. D. McIlroy, |
40 | | * "Engineering a sort function", |
41 | | * Software--Practice and Experience 23 (1993) 1249-1265. |
42 | | * |
43 | | * We have modified their original by adding a check for already-sorted input, |
44 | | * which seems to be a win per discussions on pgsql-hackers around 2006-03-21. |
45 | | * |
46 | | * Also, we recurse on the smaller partition and iterate on the larger one, |
47 | | * which ensures we cannot recurse more than log(N) levels (since the |
48 | | * partition recursed to is surely no more than half of the input). Bentley |
49 | | * and McIlroy explicitly rejected doing this on the grounds that it's "not |
50 | | * worth the effort", but we have seen crashes in the field due to stack |
51 | | * overrun, so that judgment seems wrong. |
52 | | */ |
53 | | |
54 | | static void |
55 | | swapfunc(SortTuple *a, SortTuple *b, size_t n) |
56 | 17.5k | { |
57 | 17.5k | do |
58 | 77.4k | { |
59 | 77.4k | SortTuple t = *a; |
60 | 77.4k | *a++ = *b; |
61 | 77.4k | *b++ = t; |
62 | 77.4k | } while (--n > 0); |
63 | 17.5k | } |
64 | | |
65 | | #define swap(a, b) \ |
66 | 343k | do { \ |
67 | 343k | SortTuple t = *(a); \ |
68 | 343k | *(a) = *(b); \ |
69 | 343k | *(b) = t; \ |
70 | 343k | } while (0); |
71 | | |
72 | 30.8k | #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n) |
73 | | |
74 | | static SortTuple * |
75 | | med3_tuple(SortTuple *a, SortTuple *b, SortTuple *c, SortTupleComparator cmp_tuple, Tuplesortstate *state) |
76 | 9.05k | { |
77 | 9.05k | return cmp_tuple(a, b, state) < 0 ? |
78 | 4.37k | (cmp_tuple(b, c, state) < 0 ? b : |
79 | 3.15k | (cmp_tuple(a, c, state) < 0 ? c : a)) |
80 | 4.67k | : (cmp_tuple(b, c, state) > 0 ? b : |
81 | 3.16k | (cmp_tuple(a, c, state) < 0 ? a : c)); |
82 | 9.05k | } |
83 | | |
84 | | static void |
85 | | qsort_tuple(SortTuple *a, size_t n, SortTupleComparator cmp_tuple, Tuplesortstate *state) |
86 | 5.58k | { |
87 | 5.58k | SortTuple *pa, |
88 | 5.58k | *pb, |
89 | 5.58k | *pc, |
90 | 5.58k | *pd, |
91 | 5.58k | *pl, |
92 | 5.58k | *pm, |
93 | 5.58k | *pn; |
94 | 5.58k | size_t d1, |
95 | 5.58k | d2; |
96 | 5.58k | int r, |
97 | 5.58k | presorted; |
98 | | |
99 | 11.6k | loop: |
100 | 11.6k | CHECK_FOR_INTERRUPTS(); |
101 | 11.6k | if (n < 7) |
102 | 5.40k | { |
103 | 21.9k | for (pm = a + 1; pm < a + n; pm++) |
104 | 35.0k | for (pl = pm; pl > a && cmp_tuple(pl - 1, pl, state) > 0; pl--) |
105 | 18.4k | swap(pl, pl - 1); |
106 | 5.40k | return; |
107 | 5.40k | } |
108 | 6.21k | presorted = 1; |
109 | 37.2k | for (pm = a + 1; pm < a + n; pm++) |
110 | 37.0k | { |
111 | 37.0k | CHECK_FOR_INTERRUPTS(); |
112 | 37.0k | if (cmp_tuple(pm - 1, pm, state) > 0) |
113 | 6.03k | { |
114 | 6.03k | presorted = 0; |
115 | 6.03k | break; |
116 | 6.03k | } |
117 | 37.0k | } |
118 | 6.21k | if (presorted) |
119 | 173 | return; |
120 | 6.03k | pm = a + (n / 2); |
121 | 6.03k | if (n > 7) |
122 | 5.39k | { |
123 | 5.39k | pl = a; |
124 | 5.39k | pn = a + (n - 1); |
125 | 5.39k | if (n > 40) |
126 | 1.22k | { |
127 | 1.22k | size_t d = (n / 8); |
128 | | |
129 | 1.22k | pl = med3_tuple(pl, pl + d, pl + 2 * d, cmp_tuple, state); |
130 | 1.22k | pm = med3_tuple(pm - d, pm, pm + d, cmp_tuple, state); |
131 | 1.22k | pn = med3_tuple(pn - 2 * d, pn - d, pn, cmp_tuple, state); |
132 | 1.22k | } |
133 | 5.39k | pm = med3_tuple(pl, pm, pn, cmp_tuple, state); |
134 | 5.39k | } |
135 | 6.03k | swap(a, pm); |
136 | 6.03k | pa = pb = a + 1; |
137 | 6.03k | pc = pd = a + (n - 1); |
138 | 6.03k | for (;;) |
139 | 69.8k | { |
140 | 159k | while (pb <= pc && (r = cmp_tuple(pb, a, state)) <= 0) |
141 | 89.5k | { |
142 | 89.5k | if (r == 0) |
143 | 5.44k | { |
144 | 5.44k | swap(pa, pb); |
145 | 5.44k | pa++; |
146 | 5.44k | } |
147 | 89.5k | pb++; |
148 | 89.5k | CHECK_FOR_INTERRUPTS(); |
149 | 89.5k | } |
150 | 160k | while (pb <= pc && (r = cmp_tuple(pc, a, state)) >= 0) |
151 | 90.2k | { |
152 | 90.2k | if (r == 0) |
153 | 4.49k | { |
154 | 4.49k | swap(pc, pd); |
155 | 4.49k | pd--; |
156 | 4.49k | } |
157 | 90.2k | pc--; |
158 | 90.2k | CHECK_FOR_INTERRUPTS(); |
159 | 90.2k | } |
160 | 69.8k | if (pb > pc) |
161 | 6.03k | break; |
162 | 63.8k | swap(pb, pc); |
163 | 63.8k | pb++; |
164 | 63.8k | pc--; |
165 | 63.8k | } |
166 | 6.03k | pn = a + n; |
167 | 6.03k | d1 = Min(pa - a, pb - pa); |
168 | 6.03k | vecswap(a, pb - d1, d1); |
169 | 6.03k | d1 = Min(pd - pc, pn - pd - 1); |
170 | 6.03k | vecswap(pb, pn - d1, d1); |
171 | 6.03k | d1 = pb - pa; |
172 | 6.03k | d2 = pd - pc; |
173 | 6.03k | if (d1 <= d2) |
174 | 3.18k | { |
175 | | /* Recurse on left partition, then iterate on right partition */ |
176 | 3.18k | if (d1 > 1) |
177 | 2.70k | qsort_tuple(a, d1, cmp_tuple, state); |
178 | 3.18k | if (d2 > 1) |
179 | 3.18k | { |
180 | | /* Iterate rather than recurse to save stack space */ |
181 | | /* qsort_tuple(pn - d2, d2, cmp_tuple, state); */ |
182 | 3.18k | a = pn - d2; |
183 | 3.18k | n = d2; |
184 | 3.18k | goto loop; |
185 | 3.18k | } |
186 | 2.85k | } |
187 | 2.85k | else |
188 | 2.85k | { |
189 | | /* Recurse on right partition, then iterate on left partition */ |
190 | 2.85k | if (d2 > 1) |
191 | 2.46k | qsort_tuple(pn - d2, d2, cmp_tuple, state); |
192 | 2.85k | if (d1 > 1) |
193 | 2.84k | { |
194 | | /* Iterate rather than recurse to save stack space */ |
195 | | /* qsort_tuple(a, d1, cmp_tuple, state); */ |
196 | 2.84k | n = d1; |
197 | 2.84k | goto loop; |
198 | 2.84k | } |
199 | 2.85k | } |
200 | 6.03k | } |
201 | | |
202 | | #define cmp_ssup(a, b, ssup) \ |
203 | 950k | ApplySortComparator((a)->datum1, (a)->isnull1, \ |
204 | 950k | (b)->datum1, (b)->isnull1, ssup) |
205 | | |
206 | | static SortTuple * |
207 | | med3_ssup(SortTuple *a, SortTuple *b, SortTuple *c, SortSupport ssup) |
208 | 16.6k | { |
209 | 16.6k | return cmp_ssup(a, b, ssup) < 0 ? |
210 | 7.60k | (cmp_ssup(b, c, ssup) < 0 ? b : |
211 | 5.58k | (cmp_ssup(a, c, ssup) < 0 ? c : a)) |
212 | 9.05k | : (cmp_ssup(b, c, ssup) > 0 ? b : |
213 | 6.28k | (cmp_ssup(a, c, ssup) < 0 ? a : c)); |
214 | 16.6k | } |
215 | | |
216 | | static void |
217 | | qsort_ssup(SortTuple *a, size_t n, SortSupport ssup) |
218 | 7.62k | { |
219 | 7.62k | SortTuple *pa, |
220 | 7.62k | *pb, |
221 | 7.62k | *pc, |
222 | 7.62k | *pd, |
223 | 7.62k | *pl, |
224 | 7.62k | *pm, |
225 | 7.62k | *pn; |
226 | 7.62k | size_t d1, |
227 | 7.62k | d2; |
228 | 7.62k | int r, |
229 | 7.62k | presorted; |
230 | | |
231 | 17.0k | loop: |
232 | 17.0k | CHECK_FOR_INTERRUPTS(); |
233 | 17.0k | if (n < 7) |
234 | 5.28k | { |
235 | 21.0k | for (pm = a + 1; pm < a + n; pm++) |
236 | 33.6k | for (pl = pm; pl > a && cmp_ssup(pl - 1, pl, ssup) > 0; pl--) |
237 | 17.8k | swap(pl, pl - 1); |
238 | 5.28k | return; |
239 | 5.28k | } |
240 | 11.7k | presorted = 1; |
241 | 63.5k | for (pm = a + 1; pm < a + n; pm++) |
242 | 61.2k | { |
243 | 61.2k | CHECK_FOR_INTERRUPTS(); |
244 | 61.2k | if (cmp_ssup(pm - 1, pm, ssup) > 0) |
245 | 9.40k | { |
246 | 9.40k | presorted = 0; |
247 | 9.40k | break; |
248 | 9.40k | } |
249 | 61.2k | } |
250 | 11.7k | if (presorted) |
251 | 2.34k | return; |
252 | 9.40k | pm = a + (n / 2); |
253 | 9.40k | if (n > 7) |
254 | 8.76k | { |
255 | 8.76k | pl = a; |
256 | 8.76k | pn = a + (n - 1); |
257 | 8.76k | if (n > 40) |
258 | 2.63k | { |
259 | 2.63k | size_t d = (n / 8); |
260 | | |
261 | 2.63k | pl = med3_ssup(pl, pl + d, pl + 2 * d, ssup); |
262 | 2.63k | pm = med3_ssup(pm - d, pm, pm + d, ssup); |
263 | 2.63k | pn = med3_ssup(pn - 2 * d, pn - d, pn, ssup); |
264 | 2.63k | } |
265 | 8.76k | pm = med3_ssup(pl, pm, pn, ssup); |
266 | 8.76k | } |
267 | 9.40k | swap(a, pm); |
268 | 9.40k | pa = pb = a + 1; |
269 | 9.40k | pc = pd = a + (n - 1); |
270 | 9.40k | for (;;) |
271 | 171k | { |
272 | 403k | while (pb <= pc && (r = cmp_ssup(pb, a, ssup)) <= 0) |
273 | 232k | { |
274 | 232k | if (r == 0) |
275 | 29.1k | { |
276 | 29.1k | swap(pa, pb); |
277 | 29.1k | pa++; |
278 | 29.1k | } |
279 | 232k | pb++; |
280 | 232k | CHECK_FOR_INTERRUPTS(); |
281 | 232k | } |
282 | 426k | while (pb <= pc && (r = cmp_ssup(pc, a, ssup)) >= 0) |
283 | 254k | { |
284 | 254k | if (r == 0) |
285 | 26.3k | { |
286 | 26.3k | swap(pc, pd); |
287 | 26.3k | pd--; |
288 | 26.3k | } |
289 | 254k | pc--; |
290 | 254k | CHECK_FOR_INTERRUPTS(); |
291 | 254k | } |
292 | 171k | if (pb > pc) |
293 | 9.40k | break; |
294 | 161k | swap(pb, pc); |
295 | 161k | pb++; |
296 | 161k | pc--; |
297 | 161k | } |
298 | 9.40k | pn = a + n; |
299 | 9.40k | d1 = Min(pa - a, pb - pa); |
300 | 9.40k | vecswap(a, pb - d1, d1); |
301 | 9.40k | d1 = Min(pd - pc, pn - pd - 1); |
302 | 9.40k | vecswap(pb, pn - d1, d1); |
303 | 9.40k | d1 = pb - pa; |
304 | 9.40k | d2 = pd - pc; |
305 | 9.40k | if (d1 <= d2) |
306 | 5.30k | { |
307 | | /* Recurse on left partition, then iterate on right partition */ |
308 | 5.30k | if (d1 > 1) |
309 | 4.04k | qsort_ssup(a, d1, ssup); |
310 | 5.30k | if (d2 > 1) |
311 | 5.30k | { |
312 | | /* Iterate rather than recurse to save stack space */ |
313 | | /* qsort_ssup(pn - d2, d2, ssup); */ |
314 | 5.30k | a = pn - d2; |
315 | 5.30k | n = d2; |
316 | 5.30k | goto loop; |
317 | 5.30k | } |
318 | 4.09k | } |
319 | 4.09k | else |
320 | 4.09k | { |
321 | | /* Recurse on right partition, then iterate on left partition */ |
322 | 4.09k | if (d2 > 1) |
323 | 2.96k | qsort_ssup(pn - d2, d2, ssup); |
324 | 4.09k | if (d1 > 1) |
325 | 4.09k | { |
326 | | /* Iterate rather than recurse to save stack space */ |
327 | | /* qsort_ssup(a, d1, ssup); */ |
328 | 4.09k | n = d1; |
329 | 4.09k | goto loop; |
330 | 4.09k | } |
331 | 4.09k | } |
332 | 9.40k | } |