/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 | 104k | { |
57 | 104k | do |
58 | 151k | { |
59 | 151k | SortTuple t = *a; |
60 | 151k | *a++ = *b; |
61 | 151k | *b++ = t; |
62 | 151k | } while (--n > 0); |
63 | 104k | } |
64 | | |
65 | | #define swap(a, b) \ |
66 | 1.63M | do 337k { \ |
67 | 1.63M | SortTuple t = *(a); \ |
68 | 1.63M | *(a) = *(b); \ |
69 | 1.63M | *(b) = t; \ |
70 | 1.63M | } while (0); |
71 | | |
72 | 212k | #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n)104k |
73 | | |
74 | | static SortTuple * |
75 | | med3_tuple(SortTuple *a, SortTuple *b, SortTuple *c, SortTupleComparator cmp_tuple, Tuplesortstate *state) |
76 | 32.4k | { |
77 | 32.4k | return cmp_tuple(a, b, state) < 0 ? |
78 | 16.6k | (cmp_tuple(b, c, state) < 0 ? b5.08k : |
79 | 16.6k | (11.5k cmp_tuple(a, c, state) < 011.5k ? c5.73k : a5.81k )) |
80 | 32.4k | : (15.8k cmp_tuple(b, c, state) > 015.8k ? b5.20k : |
81 | 15.8k | (10.6k cmp_tuple(a, c, state) < 010.6k ? a5.46k : c5.18k )); |
82 | 32.4k | } |
83 | | |
84 | | static void |
85 | | qsort_tuple(SortTuple *a, size_t n, SortTupleComparator cmp_tuple, Tuplesortstate *state) |
86 | 21.6k | { |
87 | 21.6k | SortTuple *pa, |
88 | 21.6k | *pb, |
89 | 21.6k | *pc, |
90 | 21.6k | *pd, |
91 | 21.6k | *pl, |
92 | 21.6k | *pm, |
93 | 21.6k | *pn; |
94 | 21.6k | size_t d1, |
95 | 21.6k | d2; |
96 | 21.6k | int r, |
97 | 21.6k | presorted; |
98 | | |
99 | 44.8k | loop: |
100 | 44.8k | CHECK_FOR_INTERRUPTS(); |
101 | 44.8k | if (n < 7) |
102 | 21.5k | { |
103 | 87.7k | for (pm = a + 1; pm < a + n; pm++66.2k ) |
104 | 141k | for (pl = pm; 66.2k pl > a && cmp_tuple(pl - 1, pl, state) > 0119k ; pl--75.5k ) |
105 | 75.5k | swap(pl, pl - 1); |
106 | 21.5k | return; |
107 | 21.5k | } |
108 | 23.3k | presorted = 1; |
109 | 114k | for (pm = a + 1; pm < a + n; pm++91.6k ) |
110 | 114k | { |
111 | 114k | CHECK_FOR_INTERRUPTS(); |
112 | 114k | if (cmp_tuple(pm - 1, pm, state) > 0) |
113 | 23.2k | { |
114 | 23.2k | presorted = 0; |
115 | 23.2k | break; |
116 | 23.2k | } |
117 | 114k | } |
118 | 23.3k | if (presorted) |
119 | 174 | return; |
120 | 23.2k | pm = a + (n / 2); |
121 | 23.2k | if (n > 7) |
122 | 20.6k | { |
123 | 20.6k | pl = a; |
124 | 20.6k | pn = a + (n - 1); |
125 | 20.6k | if (n > 40) |
126 | 3.93k | { |
127 | 3.93k | size_t d = (n / 8); |
128 | | |
129 | 3.93k | pl = med3_tuple(pl, pl + d, pl + 2 * d, cmp_tuple, state); |
130 | 3.93k | pm = med3_tuple(pm - d, pm, pm + d, cmp_tuple, state); |
131 | 3.93k | pn = med3_tuple(pn - 2 * d, pn - d, pn, cmp_tuple, state); |
132 | 3.93k | } |
133 | 20.6k | pm = med3_tuple(pl, pm, pn, cmp_tuple, state); |
134 | 20.6k | } |
135 | 23.2k | swap(a, pm); |
136 | 23.2k | pa = pb = a + 1; |
137 | 23.2k | pc = pd = a + (n - 1); |
138 | 23.2k | for (;;) |
139 | 276k | { |
140 | 622k | while (pb <= pc && (r = cmp_tuple(pb, a, state)) <= 0611k ) |
141 | 345k | { |
142 | 345k | if (r == 0) |
143 | 14.8k | { |
144 | 14.8k | swap(pa, pb); |
145 | 14.8k | pa++; |
146 | 14.8k | } |
147 | 345k | pb++; |
148 | 345k | CHECK_FOR_INTERRUPTS(); |
149 | 345k | } |
150 | 660k | while (pb <= pc && (r = cmp_tuple(pc, a, state)) >= 0637k ) |
151 | 384k | { |
152 | 384k | if (r == 0) |
153 | 14.7k | { |
154 | 14.7k | swap(pc, pd); |
155 | 14.7k | pd--; |
156 | 14.7k | } |
157 | 384k | pc--; |
158 | 384k | CHECK_FOR_INTERRUPTS(); |
159 | 384k | } |
160 | 276k | if (pb > pc) |
161 | 23.2k | break; |
162 | 253k | swap(pb, pc); |
163 | 253k | pb++; |
164 | 253k | pc--; |
165 | 253k | } |
166 | 23.2k | pn = a + n; |
167 | 23.2k | d1 = Min(pa - a, pb - pa); |
168 | 23.2k | vecswap(a, pb - d1, d1); |
169 | 23.2k | d1 = Min(pd - pc, pn - pd - 1); |
170 | 23.2k | vecswap(pb, pn - d1, d1); |
171 | 23.2k | d1 = pb - pa; |
172 | 23.2k | d2 = pd - pc; |
173 | 23.2k | if (d1 <= d2) |
174 | 12.1k | { |
175 | | /* Recurse on left partition, then iterate on right partition */ |
176 | 12.1k | if (d1 > 1) |
177 | 10.5k | qsort_tuple(a, d1, cmp_tuple, state); |
178 | 12.1k | if (d2 > 1) |
179 | 12.1k | { |
180 | | /* Iterate rather than recurse to save stack space */ |
181 | | /* qsort_tuple(pn - d2, d2, cmp_tuple, state); */ |
182 | 12.1k | a = pn - d2; |
183 | 12.1k | n = d2; |
184 | 12.1k | goto loop; |
185 | 12.1k | } |
186 | 12.1k | } |
187 | 11.0k | else |
188 | 11.0k | { |
189 | | /* Recurse on right partition, then iterate on left partition */ |
190 | 11.0k | if (d2 > 1) |
191 | 9.43k | qsort_tuple(pn - d2, d2, cmp_tuple, state); |
192 | 11.0k | if (d1 > 1) |
193 | 11.0k | { |
194 | | /* Iterate rather than recurse to save stack space */ |
195 | | /* qsort_tuple(a, d1, cmp_tuple, state); */ |
196 | 11.0k | n = d1; |
197 | 11.0k | goto loop; |
198 | 11.0k | } |
199 | 11.0k | } |
200 | 23.2k | } |
201 | | |
202 | | #define cmp_ssup(a, b, ssup) \ |
203 | 5.07M | ApplySortComparator((a)->datum1, (a)->isnull1, \ |
204 | 5.07M | (b)->datum1, (b)->isnull1, ssup) |
205 | | |
206 | | static SortTuple * |
207 | | med3_ssup(SortTuple *a, SortTuple *b, SortTuple *c, SortSupport ssup) |
208 | 115k | { |
209 | 115k | return cmp_ssup(a, b, ssup) < 0 ? |
210 | 58.0k | (cmp_ssup(b, c, ssup) < 0 ? b19.3k : |
211 | 58.0k | (38.6k cmp_ssup38.6k (a, c, ssup) < 038.6k ? c19.6k : a19.0k )) |
212 | 115k | : (57.9k cmp_ssup57.9k (b, c, ssup) > 057.9k ? b19.7k : |
213 | 57.9k | (38.2k cmp_ssup38.2k (a, c, ssup) < 038.2k ? a19.2k : c19.0k )); |
214 | 115k | } |
215 | | |
216 | | static void |
217 | | qsort_ssup(SortTuple *a, size_t n, SortSupport ssup) |
218 | 73.2k | { |
219 | 73.2k | SortTuple *pa, |
220 | 73.2k | *pb, |
221 | 73.2k | *pc, |
222 | 73.2k | *pd, |
223 | 73.2k | *pl, |
224 | 73.2k | *pm, |
225 | 73.2k | *pn; |
226 | 73.2k | size_t d1, |
227 | 73.2k | d2; |
228 | 73.2k | int r, |
229 | 73.2k | presorted; |
230 | | |
231 | 156k | loop: |
232 | 156k | CHECK_FOR_INTERRUPTS(); |
233 | 156k | if (n < 7) |
234 | 73.0k | { |
235 | 297k | for (pm = a + 1; pm < a + n; pm++224k ) |
236 | 486k | for (pl = pm; 224k pl > a && cmp_ssup410k (pl - 1, pl, ssup) > 0410k ; pl--261k ) |
237 | 261k | swap(pl, pl - 1); |
238 | 73.0k | return; |
239 | 73.0k | } |
240 | 83.0k | presorted = 1; |
241 | 172k | for (pm = a + 1; pm < a + n; pm++89.7k ) |
242 | 172k | { |
243 | 172k | CHECK_FOR_INTERRUPTS(); |
244 | 172k | if (cmp_ssup(pm - 1, pm, ssup) > 0) |
245 | 82.8k | { |
246 | 82.8k | presorted = 0; |
247 | 82.8k | break; |
248 | 82.8k | } |
249 | 172k | } |
250 | 83.0k | if (presorted) |
251 | 199 | return; |
252 | 82.8k | pm = a + (n / 2); |
253 | 82.8k | if (n > 7) |
254 | 73.4k | { |
255 | 73.4k | pl = a; |
256 | 73.4k | pn = a + (n - 1); |
257 | 73.4k | if (n > 40) |
258 | 14.1k | { |
259 | 14.1k | size_t d = (n / 8); |
260 | | |
261 | 14.1k | pl = med3_ssup(pl, pl + d, pl + 2 * d, ssup); |
262 | 14.1k | pm = med3_ssup(pm - d, pm, pm + d, ssup); |
263 | 14.1k | pn = med3_ssup(pn - 2 * d, pn - d, pn, ssup); |
264 | 14.1k | } |
265 | 73.4k | pm = med3_ssup(pl, pm, pn, ssup); |
266 | 73.4k | } |
267 | 82.8k | swap(a, pm); |
268 | 82.8k | pa = pb = a + 1; |
269 | 82.8k | pc = pd = a + (n - 1); |
270 | 82.8k | for (;;) |
271 | 972k | { |
272 | 2.13M | while (pb <= pc && (r = 2.09M cmp_ssup2.09M (pb, a, ssup)) <= 0) |
273 | 1.16M | { |
274 | 1.16M | if (r == 0) |
275 | 8.52k | { |
276 | 8.52k | swap(pa, pb); |
277 | 8.52k | pa++; |
278 | 8.52k | } |
279 | 1.16M | pb++; |
280 | 1.16M | CHECK_FOR_INTERRUPTS(); |
281 | 1.16M | } |
282 | 2.17M | while (pb <= pc && (r = 2.08M cmp_ssup2.08M (pc, a, ssup)) >= 0) |
283 | 1.20M | { |
284 | 1.20M | if (r == 0) |
285 | 12.1k | { |
286 | 12.1k | swap(pc, pd); |
287 | 12.1k | pd--; |
288 | 12.1k | } |
289 | 1.20M | pc--; |
290 | 1.20M | CHECK_FOR_INTERRUPTS(); |
291 | 1.20M | } |
292 | 972k | if (pb > pc) |
293 | 82.8k | break; |
294 | 889k | swap(pb, pc); |
295 | 889k | pb++; |
296 | 889k | pc--; |
297 | 889k | } |
298 | 82.8k | pn = a + n; |
299 | 82.8k | d1 = Min(pa - a, pb - pa); |
300 | 82.8k | vecswap(a, pb - d1, d1); |
301 | 82.8k | d1 = Min(pd - pc, pn - pd - 1); |
302 | 82.8k | vecswap(pb, pn - d1, d1); |
303 | 82.8k | d1 = pb - pa; |
304 | 82.8k | d2 = pd - pc; |
305 | 82.8k | if (d1 <= d2) |
306 | 44.2k | { |
307 | | /* Recurse on left partition, then iterate on right partition */ |
308 | 44.2k | if (d1 > 1) |
309 | 38.5k | qsort_ssup(a, d1, ssup); |
310 | 44.2k | if (d2 > 1) |
311 | 44.2k | { |
312 | | /* Iterate rather than recurse to save stack space */ |
313 | | /* qsort_ssup(pn - d2, d2, ssup); */ |
314 | 44.2k | a = pn - d2; |
315 | 44.2k | n = d2; |
316 | 44.2k | goto loop; |
317 | 44.2k | } |
318 | 44.2k | } |
319 | 38.5k | else |
320 | 38.5k | { |
321 | | /* Recurse on right partition, then iterate on left partition */ |
322 | 38.5k | if (d2 > 1) |
323 | 33.0k | qsort_ssup(pn - d2, d2, ssup); |
324 | 38.5k | if (d1 > 1) |
325 | 38.5k | { |
326 | | /* Iterate rather than recurse to save stack space */ |
327 | | /* qsort_ssup(a, d1, ssup); */ |
328 | 38.5k | n = d1; |
329 | 38.5k | goto loop; |
330 | 38.5k | } |
331 | 38.5k | } |
332 | 82.8k | } |