Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /*-------------------------------------------------------------*/ |
3 | | /*--- Block sorting machinery ---*/ |
4 | | /*--- blocksort.c ---*/ |
5 | | /*-------------------------------------------------------------*/ |
6 | | |
7 | | /* ------------------------------------------------------------------ |
8 | | This file is part of bzip2/libbzip2, a program and library for |
9 | | lossless, block-sorting data compression. |
10 | | |
11 | | bzip2/libbzip2 version 1.0.8 of 13 July 2019 |
12 | | Copyright (C) 1996-2019 Julian Seward <jseward@acm.org> |
13 | | |
14 | | Please read the WARNING, DISCLAIMER and PATENTS sections in the |
15 | | README file. |
16 | | |
17 | | This program is released under the terms of the license contained |
18 | | in the file LICENSE. |
19 | | ------------------------------------------------------------------ */ |
20 | | |
21 | | |
22 | | #include "bzlib_private.h" |
23 | | |
24 | | /*---------------------------------------------*/ |
25 | | /*--- Fallback O(N log(N)^2) sorting ---*/ |
26 | | /*--- algorithm, for repetitive blocks ---*/ |
27 | | /*---------------------------------------------*/ |
28 | | |
29 | | /*---------------------------------------------*/ |
30 | | static |
31 | | __inline__ |
32 | | void fallbackSimpleSort ( UInt32* fmap, |
33 | | UInt32* eclass, |
34 | | Int32 lo, |
35 | | Int32 hi ) |
36 | 376M | { |
37 | 376M | Int32 i, j, tmp; |
38 | 376M | UInt32 ec_tmp; |
39 | | |
40 | 376M | if (lo == hi) return; |
41 | | |
42 | 368M | if (hi - lo > 3) { |
43 | 244M | for ( i = hi-4; i >= lo; i-- ) { |
44 | 184M | tmp = fmap[i]; |
45 | 184M | ec_tmp = eclass[tmp]; |
46 | 258M | for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) |
47 | 73.9M | fmap[j-4] = fmap[j]; |
48 | 184M | fmap[j-4] = tmp; |
49 | 184M | } |
50 | 60.3M | } |
51 | | |
52 | 1.13G | for ( i = hi-1; i >= lo; i-- ) { |
53 | 770M | tmp = fmap[i]; |
54 | 770M | ec_tmp = eclass[tmp]; |
55 | 1.12G | for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) |
56 | 351M | fmap[j-1] = fmap[j]; |
57 | 770M | fmap[j-1] = tmp; |
58 | 770M | } |
59 | 368M | } |
60 | | |
61 | | |
62 | | /*---------------------------------------------*/ |
63 | | #define fswap(zz1, zz2) \ |
64 | 7.21G | { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } |
65 | | |
66 | 151M | #define fvswap(zzp1, zzp2, zzn) \ |
67 | 151M | { \ |
68 | 151M | Int32 yyp1 = (zzp1); \ |
69 | 151M | Int32 yyp2 = (zzp2); \ |
70 | 151M | Int32 yyn = (zzn); \ |
71 | 1.22G | while (yyn > 0) { \ |
72 | 1.06G | fswap(fmap[yyp1], fmap[yyp2]); \ |
73 | 1.06G | yyp1++; yyp2++; yyn--; \ |
74 | 1.06G | } \ |
75 | 151M | } |
76 | | |
77 | | |
78 | 151M | #define fmin(a,b) ((a) < (b)) ? (a) : (b) |
79 | | |
80 | 454M | #define fpush(lz,hz) { stackLo[sp] = lz; \ |
81 | 454M | stackHi[sp] = hz; \ |
82 | 454M | sp++; } |
83 | | |
84 | 454M | #define fpop(lz,hz) { sp--; \ |
85 | 454M | lz = stackLo[sp]; \ |
86 | 454M | hz = stackHi[sp]; } |
87 | | |
88 | 454M | #define FALLBACK_QSORT_SMALL_THRESH 10 |
89 | | #define FALLBACK_QSORT_STACK_SIZE 100 |
90 | | |
91 | | |
92 | | static |
93 | | void fallbackQSort3 ( UInt32* fmap, |
94 | | UInt32* eclass, |
95 | | Int32 loSt, |
96 | | Int32 hiSt ) |
97 | 303M | { |
98 | 303M | Int32 unLo, unHi, ltLo, gtHi, n, m; |
99 | 303M | Int32 sp, lo, hi; |
100 | 303M | UInt32 med, r, r3; |
101 | 303M | Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; |
102 | 303M | Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; |
103 | | |
104 | 303M | r = 0; |
105 | | |
106 | 303M | sp = 0; |
107 | 303M | fpush ( loSt, hiSt ); |
108 | | |
109 | 757M | while (sp > 0) { |
110 | | |
111 | 454M | AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 ); |
112 | | |
113 | 454M | fpop ( lo, hi ); |
114 | 454M | if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { |
115 | 376M | fallbackSimpleSort ( fmap, eclass, lo, hi ); |
116 | 376M | continue; |
117 | 376M | } |
118 | | |
119 | | /* Random partitioning. Median of 3 sometimes fails to |
120 | | avoid bad cases. Median of 9 seems to help but |
121 | | looks rather expensive. This too seems to work but |
122 | | is cheaper. Guidance for the magic constants |
123 | | 7621 and 32768 is taken from Sedgewick's algorithms |
124 | | book, chapter 35. |
125 | | */ |
126 | 77.6M | r = ((r * 7621) + 1) % 32768; |
127 | 77.6M | r3 = r % 3; |
128 | 77.6M | if (r3 == 0) med = eclass[fmap[lo]]; else |
129 | 62.4M | if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else |
130 | 25.8M | med = eclass[fmap[hi]]; |
131 | | |
132 | 77.6M | unLo = ltLo = lo; |
133 | 77.6M | unHi = gtHi = hi; |
134 | | |
135 | 795M | while (1) { |
136 | 5.79G | while (1) { |
137 | 5.79G | if (unLo > unHi) break; |
138 | 5.76G | n = (Int32)eclass[fmap[unLo]] - (Int32)med; |
139 | 5.76G | if (n == 0) { |
140 | 2.71G | fswap(fmap[unLo], fmap[ltLo]); |
141 | 2.71G | ltLo++; unLo++; |
142 | 2.71G | continue; |
143 | 3.04G | }; |
144 | 3.04G | if (n > 0) break; |
145 | 2.29G | unLo++; |
146 | 2.29G | } |
147 | 5.79G | while (1) { |
148 | 5.79G | if (unLo > unHi) break; |
149 | 5.71G | n = (Int32)eclass[fmap[unHi]] - (Int32)med; |
150 | 5.71G | if (n == 0) { |
151 | 2.71G | fswap(fmap[unHi], fmap[gtHi]); |
152 | 2.71G | gtHi--; unHi--; |
153 | 2.71G | continue; |
154 | 2.99G | }; |
155 | 2.99G | if (n < 0) break; |
156 | 2.27G | unHi--; |
157 | 2.27G | } |
158 | 795M | if (unLo > unHi) break; |
159 | 717M | fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; |
160 | 717M | } |
161 | | |
162 | 77.6M | AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); |
163 | | |
164 | 77.6M | if (gtHi < ltLo) continue; |
165 | | |
166 | 75.5M | n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); |
167 | 75.5M | m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); |
168 | | |
169 | 75.5M | n = lo + unLo - ltLo - 1; |
170 | 75.5M | m = hi - (gtHi - unHi) + 1; |
171 | | |
172 | 75.5M | if (n - lo > hi - m) { |
173 | 34.7M | fpush ( lo, n ); |
174 | 34.7M | fpush ( m, hi ); |
175 | 40.8M | } else { |
176 | 40.8M | fpush ( m, hi ); |
177 | 40.8M | fpush ( lo, n ); |
178 | 40.8M | } |
179 | 75.5M | } |
180 | 303M | } |
181 | | |
182 | | #undef fmin |
183 | | #undef fpush |
184 | | #undef fpop |
185 | | #undef fswap |
186 | | #undef fvswap |
187 | | #undef FALLBACK_QSORT_SMALL_THRESH |
188 | | #undef FALLBACK_QSORT_STACK_SIZE |
189 | | |
190 | | |
191 | | /*---------------------------------------------*/ |
192 | | /* Pre: |
193 | | nblock > 0 |
194 | | eclass exists for [0 .. nblock-1] |
195 | | ((UChar*)eclass) [0 .. nblock-1] holds block |
196 | | ptr exists for [0 .. nblock-1] |
197 | | |
198 | | Post: |
199 | | ((UChar*)eclass) [0 .. nblock-1] holds block |
200 | | All other areas of eclass destroyed |
201 | | fmap [0 .. nblock-1] holds sorted order |
202 | | bhtab [ 0 .. 2+(nblock/32) ] destroyed |
203 | | */ |
204 | | |
205 | 798M | #define SET_BH(zz) bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31)) |
206 | 304k | #define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31)) |
207 | 13.9G | #define ISSET_BH(zz) (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31))) |
208 | 267M | #define WORD_BH(zz) bhtab[(zz) >> 5] |
209 | 1.62G | #define UNALIGNED_BH(zz) ((zz) & 0x01f) |
210 | | |
211 | | static |
212 | | void fallbackSort ( UInt32* fmap, |
213 | | UInt32* eclass, |
214 | | UInt32* bhtab, |
215 | | Int32 nblock, |
216 | | Int32 verb ) |
217 | 9.51k | { |
218 | 9.51k | Int32 ftab[257]; |
219 | 9.51k | Int32 ftabCopy[256]; |
220 | 9.51k | Int32 H, i, j, k, l, r, cc, cc1; |
221 | 9.51k | Int32 nNotDone; |
222 | 9.51k | Int32 nBhtab; |
223 | 9.51k | UChar* eclass8 = (UChar*)eclass; |
224 | | |
225 | | /*-- |
226 | | Initial 1-char radix sort to generate |
227 | | initial fmap and initial BH bits. |
228 | | --*/ |
229 | 9.51k | if (verb >= 4) |
230 | 0 | VPrintf0 ( " bucket sorting ...\n" ); |
231 | 2.45M | for (i = 0; i < 257; i++) ftab[i] = 0; |
232 | 495M | for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; |
233 | 2.44M | for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; |
234 | 2.44M | for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; |
235 | | |
236 | 495M | for (i = 0; i < nblock; i++) { |
237 | 495M | j = eclass8[i]; |
238 | 495M | k = ftab[j] - 1; |
239 | 495M | ftab[j] = k; |
240 | 495M | fmap[k] = i; |
241 | 495M | } |
242 | | |
243 | 9.51k | nBhtab = 2 + (nblock / 32); |
244 | 15.5M | for (i = 0; i < nBhtab; i++) bhtab[i] = 0; |
245 | 2.44M | for (i = 0; i < 256; i++) SET_BH(ftab[i]); |
246 | | |
247 | | /*-- |
248 | | Inductively refine the buckets. Kind-of an |
249 | | "exponential radix sort" (!), inspired by the |
250 | | Manber-Myers suffix array construction algorithm. |
251 | | --*/ |
252 | | |
253 | | /*-- set sentinel bits for block-end detection --*/ |
254 | 313k | for (i = 0; i < 32; i++) { |
255 | 304k | SET_BH(nblock + 2*i); |
256 | 304k | CLEAR_BH(nblock + 2*i + 1); |
257 | 304k | } |
258 | | |
259 | | /*-- the log(N) loop --*/ |
260 | 9.51k | H = 1; |
261 | 81.7k | while (1) { |
262 | | |
263 | 81.7k | if (verb >= 4) |
264 | 0 | VPrintf1 ( " depth %6d has ", H ); |
265 | | |
266 | 81.7k | j = 0; |
267 | 8.53G | for (i = 0; i < nblock; i++) { |
268 | 8.53G | if (ISSET_BH(i)) j = i; |
269 | 8.53G | k = fmap[i] - H; if (k < 0) k += nblock; |
270 | 8.53G | eclass[k] = j; |
271 | 8.53G | } |
272 | | |
273 | 81.7k | nNotDone = 0; |
274 | 81.7k | r = -1; |
275 | 303M | while (1) { |
276 | | |
277 | | /*-- find the next non-singleton bucket --*/ |
278 | 303M | k = r + 1; |
279 | 1.25G | while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; |
280 | 303M | if (ISSET_BH(k)) { |
281 | 71.5M | while (WORD_BH(k) == 0xffffffff) k += 32; |
282 | 266M | while (ISSET_BH(k)) k++; |
283 | 37.0M | } |
284 | 303M | l = k - 1; |
285 | 303M | if (l >= nblock) break; |
286 | 917M | while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; |
287 | 303M | if (!ISSET_BH(k)) { |
288 | 195M | while (WORD_BH(k) == 0x00000000) k += 32; |
289 | 177M | while (!ISSET_BH(k)) k++; |
290 | 24.1M | } |
291 | 303M | r = k - 1; |
292 | 303M | if (r >= nblock) break; |
293 | | |
294 | | /*-- now [l, r] bracket current bucket --*/ |
295 | 303M | if (r > l) { |
296 | 303M | nNotDone += (r - l + 1); |
297 | 303M | fallbackQSort3 ( fmap, eclass, l, r ); |
298 | | |
299 | | /*-- scan bucket and generate header bits-- */ |
300 | 303M | cc = -1; |
301 | 6.86G | for (i = l; i <= r; i++) { |
302 | 6.55G | cc1 = eclass[fmap[i]]; |
303 | 6.55G | if (cc != cc1) { SET_BH(i); cc = cc1; }; |
304 | 6.55G | } |
305 | 303M | } |
306 | 303M | } |
307 | | |
308 | 81.7k | if (verb >= 4) |
309 | 0 | VPrintf1 ( "%6d unresolved strings\n", nNotDone ); |
310 | | |
311 | 81.7k | H *= 2; |
312 | 81.7k | if (H > nblock || nNotDone == 0) break; |
313 | 81.7k | } |
314 | | |
315 | | /*-- |
316 | | Reconstruct the original block in |
317 | | eclass8 [0 .. nblock-1], since the |
318 | | previous phase destroyed it. |
319 | | --*/ |
320 | 9.51k | if (verb >= 4) |
321 | 0 | VPrintf0 ( " reconstructing block ...\n" ); |
322 | 9.51k | j = 0; |
323 | 495M | for (i = 0; i < nblock; i++) { |
324 | 497M | while (ftabCopy[j] == 0) j++; |
325 | 495M | ftabCopy[j]--; |
326 | 495M | eclass8[fmap[i]] = (UChar)j; |
327 | 495M | } |
328 | 9.51k | AssertH ( j < 256, 1005 ); |
329 | 9.51k | } |
330 | | |
331 | | #undef SET_BH |
332 | | #undef CLEAR_BH |
333 | | #undef ISSET_BH |
334 | | #undef WORD_BH |
335 | | #undef UNALIGNED_BH |
336 | | |
337 | | |
338 | | /*---------------------------------------------*/ |
339 | | /*--- The main, O(N^2 log(N)) sorting ---*/ |
340 | | /*--- algorithm. Faster for "normal" ---*/ |
341 | | /*--- non-repetitive blocks. ---*/ |
342 | | /*---------------------------------------------*/ |
343 | | |
344 | | /*---------------------------------------------*/ |
345 | | static |
346 | | __inline__ |
347 | | Bool mainGtU ( UInt32 i1, |
348 | | UInt32 i2, |
349 | | UChar* block, |
350 | | UInt16* quadrant, |
351 | | UInt32 nblock, |
352 | | Int32* budget ) |
353 | 662M | { |
354 | 662M | Int32 k; |
355 | 662M | UChar c1, c2; |
356 | 662M | UInt16 s1, s2; |
357 | | |
358 | 662M | AssertD ( i1 != i2, "mainGtU" ); |
359 | | /* 1 */ |
360 | 662M | c1 = block[i1]; c2 = block[i2]; |
361 | 662M | if (c1 != c2) return (c1 > c2); |
362 | 376M | i1++; i2++; |
363 | | /* 2 */ |
364 | 376M | c1 = block[i1]; c2 = block[i2]; |
365 | 376M | if (c1 != c2) return (c1 > c2); |
366 | 346M | i1++; i2++; |
367 | | /* 3 */ |
368 | 346M | c1 = block[i1]; c2 = block[i2]; |
369 | 346M | if (c1 != c2) return (c1 > c2); |
370 | 334M | i1++; i2++; |
371 | | /* 4 */ |
372 | 334M | c1 = block[i1]; c2 = block[i2]; |
373 | 334M | if (c1 != c2) return (c1 > c2); |
374 | 325M | i1++; i2++; |
375 | | /* 5 */ |
376 | 325M | c1 = block[i1]; c2 = block[i2]; |
377 | 325M | if (c1 != c2) return (c1 > c2); |
378 | 318M | i1++; i2++; |
379 | | /* 6 */ |
380 | 318M | c1 = block[i1]; c2 = block[i2]; |
381 | 318M | if (c1 != c2) return (c1 > c2); |
382 | 313M | i1++; i2++; |
383 | | /* 7 */ |
384 | 313M | c1 = block[i1]; c2 = block[i2]; |
385 | 313M | if (c1 != c2) return (c1 > c2); |
386 | 308M | i1++; i2++; |
387 | | /* 8 */ |
388 | 308M | c1 = block[i1]; c2 = block[i2]; |
389 | 308M | if (c1 != c2) return (c1 > c2); |
390 | 303M | i1++; i2++; |
391 | | /* 9 */ |
392 | 303M | c1 = block[i1]; c2 = block[i2]; |
393 | 303M | if (c1 != c2) return (c1 > c2); |
394 | 300M | i1++; i2++; |
395 | | /* 10 */ |
396 | 300M | c1 = block[i1]; c2 = block[i2]; |
397 | 300M | if (c1 != c2) return (c1 > c2); |
398 | 298M | i1++; i2++; |
399 | | /* 11 */ |
400 | 298M | c1 = block[i1]; c2 = block[i2]; |
401 | 298M | if (c1 != c2) return (c1 > c2); |
402 | 296M | i1++; i2++; |
403 | | /* 12 */ |
404 | 296M | c1 = block[i1]; c2 = block[i2]; |
405 | 296M | if (c1 != c2) return (c1 > c2); |
406 | 294M | i1++; i2++; |
407 | | |
408 | 294M | k = nblock + 8; |
409 | | |
410 | 7.46G | do { |
411 | | /* 1 */ |
412 | 7.46G | c1 = block[i1]; c2 = block[i2]; |
413 | 7.46G | if (c1 != c2) return (c1 > c2); |
414 | 7.45G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
415 | 7.45G | if (s1 != s2) return (s1 > s2); |
416 | 7.40G | i1++; i2++; |
417 | | /* 2 */ |
418 | 7.40G | c1 = block[i1]; c2 = block[i2]; |
419 | 7.40G | if (c1 != c2) return (c1 > c2); |
420 | 7.39G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
421 | 7.39G | if (s1 != s2) return (s1 > s2); |
422 | 7.36G | i1++; i2++; |
423 | | /* 3 */ |
424 | 7.36G | c1 = block[i1]; c2 = block[i2]; |
425 | 7.36G | if (c1 != c2) return (c1 > c2); |
426 | 7.35G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
427 | 7.35G | if (s1 != s2) return (s1 > s2); |
428 | 7.32G | i1++; i2++; |
429 | | /* 4 */ |
430 | 7.32G | c1 = block[i1]; c2 = block[i2]; |
431 | 7.32G | if (c1 != c2) return (c1 > c2); |
432 | 7.31G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
433 | 7.31G | if (s1 != s2) return (s1 > s2); |
434 | 7.28G | i1++; i2++; |
435 | | /* 5 */ |
436 | 7.28G | c1 = block[i1]; c2 = block[i2]; |
437 | 7.28G | if (c1 != c2) return (c1 > c2); |
438 | 7.27G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
439 | 7.27G | if (s1 != s2) return (s1 > s2); |
440 | 7.24G | i1++; i2++; |
441 | | /* 6 */ |
442 | 7.24G | c1 = block[i1]; c2 = block[i2]; |
443 | 7.24G | if (c1 != c2) return (c1 > c2); |
444 | 7.23G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
445 | 7.23G | if (s1 != s2) return (s1 > s2); |
446 | 7.21G | i1++; i2++; |
447 | | /* 7 */ |
448 | 7.21G | c1 = block[i1]; c2 = block[i2]; |
449 | 7.21G | if (c1 != c2) return (c1 > c2); |
450 | 7.21G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
451 | 7.21G | if (s1 != s2) return (s1 > s2); |
452 | 7.19G | i1++; i2++; |
453 | | /* 8 */ |
454 | 7.19G | c1 = block[i1]; c2 = block[i2]; |
455 | 7.19G | if (c1 != c2) return (c1 > c2); |
456 | 7.18G | s1 = quadrant[i1]; s2 = quadrant[i2]; |
457 | 7.18G | if (s1 != s2) return (s1 > s2); |
458 | 7.17G | i1++; i2++; |
459 | | |
460 | 7.17G | if (i1 >= nblock) i1 -= nblock; |
461 | 7.17G | if (i2 >= nblock) i2 -= nblock; |
462 | | |
463 | 7.17G | k -= 8; |
464 | 7.17G | (*budget)--; |
465 | 7.17G | } |
466 | 7.17G | while (k >= 0); |
467 | | |
468 | 1.98k | return False; |
469 | 294M | } |
470 | | |
471 | | |
472 | | /*---------------------------------------------*/ |
473 | | /*-- |
474 | | Knuth's increments seem to work better |
475 | | than Incerpi-Sedgewick here. Possibly |
476 | | because the number of elems to sort is |
477 | | usually small, typically <= 20. |
478 | | --*/ |
479 | | static |
480 | | Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, |
481 | | 9841, 29524, 88573, 265720, |
482 | | 797161, 2391484 }; |
483 | | |
484 | | static |
485 | | void mainSimpleSort ( UInt32* ptr, |
486 | | UChar* block, |
487 | | UInt16* quadrant, |
488 | | Int32 nblock, |
489 | | Int32 lo, |
490 | | Int32 hi, |
491 | | Int32 d, |
492 | | Int32* budget ) |
493 | 29.0M | { |
494 | 29.0M | Int32 i, j, h, bigN, hp; |
495 | 29.0M | UInt32 v; |
496 | | |
497 | 29.0M | bigN = hi - lo + 1; |
498 | 29.0M | if (bigN < 2) return; |
499 | | |
500 | 27.8M | hp = 0; |
501 | 70.3M | while (incs[hp] < bigN) hp++; |
502 | 27.8M | hp--; |
503 | | |
504 | 70.3M | for (; hp >= 0; hp--) { |
505 | 42.4M | h = incs[hp]; |
506 | | |
507 | 42.4M | i = lo + h; |
508 | 145M | while (True) { |
509 | | |
510 | | /*-- copy 1 --*/ |
511 | 145M | if (i > hi) break; |
512 | 134M | v = ptr[i]; |
513 | 134M | j = i; |
514 | 230M | while ( mainGtU ( |
515 | 230M | ptr[j-h]+d, v+d, block, quadrant, nblock, budget |
516 | 230M | ) ) { |
517 | 125M | ptr[j] = ptr[j-h]; |
518 | 125M | j = j - h; |
519 | 125M | if (j <= (lo + h - 1)) break; |
520 | 125M | } |
521 | 134M | ptr[j] = v; |
522 | 134M | i++; |
523 | | |
524 | | /*-- copy 2 --*/ |
525 | 134M | if (i > hi) break; |
526 | 115M | v = ptr[i]; |
527 | 115M | j = i; |
528 | 221M | while ( mainGtU ( |
529 | 221M | ptr[j-h]+d, v+d, block, quadrant, nblock, budget |
530 | 221M | ) ) { |
531 | 124M | ptr[j] = ptr[j-h]; |
532 | 124M | j = j - h; |
533 | 124M | if (j <= (lo + h - 1)) break; |
534 | 124M | } |
535 | 115M | ptr[j] = v; |
536 | 115M | i++; |
537 | | |
538 | | /*-- copy 3 --*/ |
539 | 115M | if (i > hi) break; |
540 | 102M | v = ptr[i]; |
541 | 102M | j = i; |
542 | 210M | while ( mainGtU ( |
543 | 210M | ptr[j-h]+d, v+d, block, quadrant, nblock, budget |
544 | 210M | ) ) { |
545 | 122M | ptr[j] = ptr[j-h]; |
546 | 122M | j = j - h; |
547 | 122M | if (j <= (lo + h - 1)) break; |
548 | 122M | } |
549 | 102M | ptr[j] = v; |
550 | 102M | i++; |
551 | | |
552 | 102M | if (*budget < 0) return; |
553 | 102M | } |
554 | 42.4M | } |
555 | 27.8M | } |
556 | | |
557 | | |
558 | | /*---------------------------------------------*/ |
559 | | /*-- |
560 | | The following is an implementation of |
561 | | an elegant 3-way quicksort for strings, |
562 | | described in a paper "Fast Algorithms for |
563 | | Sorting and Searching Strings", by Robert |
564 | | Sedgewick and Jon L. Bentley. |
565 | | --*/ |
566 | | |
567 | | #define mswap(zz1, zz2) \ |
568 | 996M | { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } |
569 | | |
570 | 4.96M | #define mvswap(zzp1, zzp2, zzn) \ |
571 | 4.96M | { \ |
572 | 4.96M | Int32 yyp1 = (zzp1); \ |
573 | 4.96M | Int32 yyp2 = (zzp2); \ |
574 | 4.96M | Int32 yyn = (zzn); \ |
575 | 50.3M | while (yyn > 0) { \ |
576 | 45.4M | mswap(ptr[yyp1], ptr[yyp2]); \ |
577 | 45.4M | yyp1++; yyp2++; yyn--; \ |
578 | 45.4M | } \ |
579 | 4.96M | } |
580 | | |
581 | | static |
582 | | __inline__ |
583 | | UChar mmed3 ( UChar a, UChar b, UChar c ) |
584 | 3.56M | { |
585 | 3.56M | UChar t; |
586 | 3.56M | if (a > b) { t = a; a = b; b = t; }; |
587 | 3.56M | if (b > c) { |
588 | 1.29M | b = c; |
589 | 1.29M | if (a > b) b = a; |
590 | 1.29M | } |
591 | 3.56M | return b; |
592 | 3.56M | } |
593 | | |
594 | 4.96M | #define mmin(a,b) ((a) < (b)) ? (a) : (b) |
595 | | |
596 | 32.6M | #define mpush(lz,hz,dz) { stackLo[sp] = lz; \ |
597 | 32.6M | stackHi[sp] = hz; \ |
598 | 32.6M | stackD [sp] = dz; \ |
599 | 32.6M | sp++; } |
600 | | |
601 | 32.6M | #define mpop(lz,hz,dz) { sp--; \ |
602 | 32.6M | lz = stackLo[sp]; \ |
603 | 32.6M | hz = stackHi[sp]; \ |
604 | 32.6M | dz = stackD [sp]; } |
605 | | |
606 | | |
607 | 14.9M | #define mnextsize(az) (nextHi[az]-nextLo[az]) |
608 | | |
609 | | #define mnextswap(az,bz) \ |
610 | 2.92M | { Int32 tz; \ |
611 | 2.92M | tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ |
612 | 2.92M | tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ |
613 | 2.92M | tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } |
614 | | |
615 | | |
616 | 65.2M | #define MAIN_QSORT_SMALL_THRESH 20 |
617 | 3.68M | #define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) |
618 | | #define MAIN_QSORT_STACK_SIZE 100 |
619 | | |
620 | | static |
621 | | void mainQSort3 ( UInt32* ptr, |
622 | | UChar* block, |
623 | | UInt16* quadrant, |
624 | | Int32 nblock, |
625 | | Int32 loSt, |
626 | | Int32 hiSt, |
627 | | Int32 dSt, |
628 | | Int32* budget ) |
629 | 24.0M | { |
630 | 24.0M | Int32 unLo, unHi, ltLo, gtHi, n, m, med; |
631 | 24.0M | Int32 sp, lo, hi, d; |
632 | | |
633 | 24.0M | Int32 stackLo[MAIN_QSORT_STACK_SIZE]; |
634 | 24.0M | Int32 stackHi[MAIN_QSORT_STACK_SIZE]; |
635 | 24.0M | Int32 stackD [MAIN_QSORT_STACK_SIZE]; |
636 | | |
637 | 24.0M | Int32 nextLo[3]; |
638 | 24.0M | Int32 nextHi[3]; |
639 | 24.0M | Int32 nextD [3]; |
640 | | |
641 | 24.0M | sp = 0; |
642 | 24.0M | mpush ( loSt, hiSt, dSt ); |
643 | | |
644 | 56.7M | while (sp > 0) { |
645 | | |
646 | 32.6M | AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 ); |
647 | | |
648 | 32.6M | mpop ( lo, hi, d ); |
649 | 32.6M | if (hi - lo < MAIN_QSORT_SMALL_THRESH || |
650 | 32.6M | d > MAIN_QSORT_DEPTH_THRESH) { |
651 | 29.0M | mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); |
652 | 29.0M | if (*budget < 0) return; |
653 | 29.0M | continue; |
654 | 29.0M | } |
655 | | |
656 | 3.56M | med = (Int32) |
657 | 3.56M | mmed3 ( block[ptr[ lo ]+d], |
658 | 3.56M | block[ptr[ hi ]+d], |
659 | 3.56M | block[ptr[ (lo+hi)>>1 ]+d] ); |
660 | | |
661 | 3.56M | unLo = ltLo = lo; |
662 | 3.56M | unHi = gtHi = hi; |
663 | | |
664 | 26.1M | while (True) { |
665 | 672M | while (True) { |
666 | 672M | if (unLo > unHi) break; |
667 | 670M | n = ((Int32)block[ptr[unLo]+d]) - med; |
668 | 670M | if (n == 0) { |
669 | 582M | mswap(ptr[unLo], ptr[ltLo]); |
670 | 582M | ltLo++; unLo++; continue; |
671 | 582M | }; |
672 | 88.1M | if (n > 0) break; |
673 | 64.3M | unLo++; |
674 | 64.3M | } |
675 | 431M | while (True) { |
676 | 431M | if (unLo > unHi) break; |
677 | 428M | n = ((Int32)block[ptr[unHi]+d]) - med; |
678 | 428M | if (n == 0) { |
679 | 346M | mswap(ptr[unHi], ptr[gtHi]); |
680 | 346M | gtHi--; unHi--; continue; |
681 | 346M | }; |
682 | 82.2M | if (n < 0) break; |
683 | 59.6M | unHi--; |
684 | 59.6M | } |
685 | 26.1M | if (unLo > unHi) break; |
686 | 22.5M | mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; |
687 | 22.5M | } |
688 | | |
689 | 3.56M | AssertD ( unHi == unLo-1, "mainQSort3(2)" ); |
690 | | |
691 | 3.56M | if (gtHi < ltLo) { |
692 | 1.08M | mpush(lo, hi, d+1 ); |
693 | 1.08M | continue; |
694 | 1.08M | } |
695 | | |
696 | 2.48M | n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); |
697 | 2.48M | m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); |
698 | | |
699 | 2.48M | n = lo + unLo - ltLo - 1; |
700 | 2.48M | m = hi - (gtHi - unHi) + 1; |
701 | | |
702 | 2.48M | nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; |
703 | 2.48M | nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; |
704 | 2.48M | nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; |
705 | | |
706 | 2.48M | if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); |
707 | 2.48M | if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); |
708 | 2.48M | if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); |
709 | | |
710 | 2.48M | AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); |
711 | 2.48M | AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); |
712 | | |
713 | 2.48M | mpush (nextLo[0], nextHi[0], nextD[0]); |
714 | 2.48M | mpush (nextLo[1], nextHi[1], nextD[1]); |
715 | 2.48M | mpush (nextLo[2], nextHi[2], nextD[2]); |
716 | 2.48M | } |
717 | 24.0M | } |
718 | | |
719 | | #undef mswap |
720 | | #undef mvswap |
721 | | #undef mpush |
722 | | #undef mpop |
723 | | #undef mmin |
724 | | #undef mnextsize |
725 | | #undef mnextswap |
726 | | #undef MAIN_QSORT_SMALL_THRESH |
727 | | #undef MAIN_QSORT_DEPTH_THRESH |
728 | | #undef MAIN_QSORT_STACK_SIZE |
729 | | |
730 | | |
731 | | /*---------------------------------------------*/ |
732 | | /* Pre: |
733 | | nblock > N_OVERSHOOT |
734 | | block32 exists for [0 .. nblock-1 +N_OVERSHOOT] |
735 | | ((UChar*)block32) [0 .. nblock-1] holds block |
736 | | ptr exists for [0 .. nblock-1] |
737 | | |
738 | | Post: |
739 | | ((UChar*)block32) [0 .. nblock-1] holds block |
740 | | All other areas of block32 destroyed |
741 | | ftab [0 .. 65536 ] destroyed |
742 | | ptr [0 .. nblock-1] holds sorted order |
743 | | if (*budget < 0), sorting was abandoned |
744 | | */ |
745 | | |
746 | 17.4M | #define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) |
747 | 2.03G | #define SETMASK (1 << 21) |
748 | 1.02G | #define CLEARMASK (~(SETMASK)) |
749 | | |
750 | | static |
751 | | void mainSort ( UInt32* ptr, |
752 | | UChar* block, |
753 | | UInt16* quadrant, |
754 | | UInt32* ftab, |
755 | | Int32 nblock, |
756 | | Int32 verb, |
757 | | Int32* budget ) |
758 | 5.28k | { |
759 | 5.28k | Int32 i, j, k, ss, sb; |
760 | 5.28k | Int32 runningOrder[256]; |
761 | 5.28k | Bool bigDone[256]; |
762 | 5.28k | Int32 copyStart[256]; |
763 | 5.28k | Int32 copyEnd [256]; |
764 | 5.28k | UChar c1; |
765 | 5.28k | Int32 numQSorted; |
766 | 5.28k | UInt16 s; |
767 | 5.28k | if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); |
768 | | |
769 | | /*-- set up the 2-byte frequency table --*/ |
770 | 346M | for (i = 65536; i >= 0; i--) ftab[i] = 0; |
771 | | |
772 | 5.28k | j = block[0] << 8; |
773 | 5.28k | i = nblock-1; |
774 | 218M | for (; i >= 3; i -= 4) { |
775 | 218M | quadrant[i] = 0; |
776 | 218M | j = (j >> 8) | ( ((UInt16)block[i]) << 8); |
777 | 218M | ftab[j]++; |
778 | 218M | quadrant[i-1] = 0; |
779 | 218M | j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); |
780 | 218M | ftab[j]++; |
781 | 218M | quadrant[i-2] = 0; |
782 | 218M | j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); |
783 | 218M | ftab[j]++; |
784 | 218M | quadrant[i-3] = 0; |
785 | 218M | j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); |
786 | 218M | ftab[j]++; |
787 | 218M | } |
788 | 11.2k | for (; i >= 0; i--) { |
789 | 5.97k | quadrant[i] = 0; |
790 | 5.97k | j = (j >> 8) | ( ((UInt16)block[i]) << 8); |
791 | 5.97k | ftab[j]++; |
792 | 5.97k | } |
793 | | |
794 | | /*-- (emphasises close relationship of block & quadrant) --*/ |
795 | 184k | for (i = 0; i < BZ_N_OVERSHOOT; i++) { |
796 | 179k | block [nblock+i] = block[i]; |
797 | 179k | quadrant[nblock+i] = 0; |
798 | 179k | } |
799 | | |
800 | 5.28k | if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); |
801 | | |
802 | | /*-- Complete the initial radix sort --*/ |
803 | 346M | for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; |
804 | | |
805 | 5.28k | s = block[0] << 8; |
806 | 5.28k | i = nblock-1; |
807 | 218M | for (; i >= 3; i -= 4) { |
808 | 218M | s = (s >> 8) | (block[i] << 8); |
809 | 218M | j = ftab[s] -1; |
810 | 218M | ftab[s] = j; |
811 | 218M | ptr[j] = i; |
812 | 218M | s = (s >> 8) | (block[i-1] << 8); |
813 | 218M | j = ftab[s] -1; |
814 | 218M | ftab[s] = j; |
815 | 218M | ptr[j] = i-1; |
816 | 218M | s = (s >> 8) | (block[i-2] << 8); |
817 | 218M | j = ftab[s] -1; |
818 | 218M | ftab[s] = j; |
819 | 218M | ptr[j] = i-2; |
820 | 218M | s = (s >> 8) | (block[i-3] << 8); |
821 | 218M | j = ftab[s] -1; |
822 | 218M | ftab[s] = j; |
823 | 218M | ptr[j] = i-3; |
824 | 218M | } |
825 | 11.2k | for (; i >= 0; i--) { |
826 | 5.97k | s = (s >> 8) | (block[i] << 8); |
827 | 5.97k | j = ftab[s] -1; |
828 | 5.97k | ftab[s] = j; |
829 | 5.97k | ptr[j] = i; |
830 | 5.97k | } |
831 | | |
832 | | /*-- |
833 | | Now ftab contains the first loc of every small bucket. |
834 | | Calculate the running order, from smallest to largest |
835 | | big bucket. |
836 | | --*/ |
837 | 1.35M | for (i = 0; i <= 255; i++) { |
838 | 1.35M | bigDone [i] = False; |
839 | 1.35M | runningOrder[i] = i; |
840 | 1.35M | } |
841 | | |
842 | 5.28k | { |
843 | 5.28k | Int32 vv; |
844 | 5.28k | Int32 h = 1; |
845 | 26.4k | do h = 3 * h + 1; while (h <= 256); |
846 | 26.4k | do { |
847 | 26.4k | h = h / 3; |
848 | 5.84M | for (i = h; i <= 255; i++) { |
849 | 5.81M | vv = runningOrder[i]; |
850 | 5.81M | j = i; |
851 | 8.73M | while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { |
852 | 3.24M | runningOrder[j] = runningOrder[j-h]; |
853 | 3.24M | j = j - h; |
854 | 3.24M | if (j <= (h - 1)) goto zero; |
855 | 3.24M | } |
856 | 5.81M | zero: |
857 | 5.81M | runningOrder[j] = vv; |
858 | 5.81M | } |
859 | 26.4k | } while (h != 1); |
860 | 5.28k | } |
861 | | |
862 | | /*-- |
863 | | The main sorting loop. |
864 | | --*/ |
865 | | |
866 | 5.28k | numQSorted = 0; |
867 | | |
868 | 1.32M | for (i = 0; i <= 255; i++) { |
869 | | |
870 | | /*-- |
871 | | Process big buckets, starting with the least full. |
872 | | Basically this is a 3-step process in which we call |
873 | | mainQSort3 to sort the small buckets [ss, j], but |
874 | | also make a big effort to avoid the calls if we can. |
875 | | --*/ |
876 | 1.32M | ss = runningOrder[i]; |
877 | | |
878 | | /*-- |
879 | | Step 1: |
880 | | Complete the big bucket [ss] by quicksorting |
881 | | any unsorted small buckets [ss, j], for j != ss. |
882 | | Hopefully previous pointer-scanning phases have already |
883 | | completed many of the small buckets [ss, j], so |
884 | | we don't have to sort them at all. |
885 | | --*/ |
886 | 340M | for (j = 0; j <= 255; j++) { |
887 | 338M | if (j != ss) { |
888 | 337M | sb = (ss << 8) + j; |
889 | 337M | if ( ! (ftab[sb] & SETMASK) ) { |
890 | 169M | Int32 lo = ftab[sb] & CLEARMASK; |
891 | 169M | Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; |
892 | 169M | if (hi > lo) { |
893 | 24.0M | if (verb >= 4) |
894 | 0 | VPrintf4 ( " qsort [0x%x, 0x%x] " |
895 | 24.0M | "done %d this %d\n", |
896 | 24.0M | ss, j, numQSorted, hi - lo + 1 ); |
897 | 24.0M | mainQSort3 ( |
898 | 24.0M | ptr, block, quadrant, nblock, |
899 | 24.0M | lo, hi, BZ_N_RADIX, budget |
900 | 24.0M | ); |
901 | 24.0M | numQSorted += (hi - lo + 1); |
902 | 24.0M | if (*budget < 0) return; |
903 | 24.0M | } |
904 | 169M | } |
905 | 337M | ftab[sb] |= SETMASK; |
906 | 337M | } |
907 | 338M | } |
908 | | |
909 | 1.32M | AssertH ( !bigDone[ss], 1006 ); |
910 | | |
911 | | /*-- |
912 | | Step 2: |
913 | | Now scan this big bucket [ss] so as to synthesise the |
914 | | sorted order for small buckets [t, ss] for all t, |
915 | | including, magically, the bucket [ss,ss] too. |
916 | | This will avoid doing Real Work in subsequent Step 1's. |
917 | | --*/ |
918 | 1.32M | { |
919 | 340M | for (j = 0; j <= 255; j++) { |
920 | 338M | copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; |
921 | 338M | copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; |
922 | 338M | } |
923 | 200M | for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { |
924 | 199M | k = ptr[j]-1; if (k < 0) k += nblock; |
925 | 199M | c1 = block[k]; |
926 | 199M | if (!bigDone[c1]) |
927 | 113M | ptr[ copyStart[c1]++ ] = k; |
928 | 199M | } |
929 | 223M | for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { |
930 | 222M | k = ptr[j]-1; if (k < 0) k += nblock; |
931 | 222M | c1 = block[k]; |
932 | 222M | if (!bigDone[c1]) |
933 | 117M | ptr[ copyEnd[c1]-- ] = k; |
934 | 222M | } |
935 | 1.32M | } |
936 | | |
937 | 1.32M | AssertH ( (copyStart[ss]-1 == copyEnd[ss]) |
938 | 1.32M | || |
939 | | /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1. |
940 | | Necessity for this case is demonstrated by compressing |
941 | | a sequence of approximately 48.5 million of character |
942 | | 251; 1.0.0/1.0.1 will then die here. */ |
943 | 1.32M | (copyStart[ss] == 0 && copyEnd[ss] == nblock-1), |
944 | 1.32M | 1007 ) |
945 | | |
946 | 340M | for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; |
947 | | |
948 | | /*-- |
949 | | Step 3: |
950 | | The [ss] big bucket is now done. Record this fact, |
951 | | and update the quadrant descriptors. Remember to |
952 | | update quadrants in the overshoot area too, if |
953 | | necessary. The "if (i < 255)" test merely skips |
954 | | this updating for the last bucket processed, since |
955 | | updating for the last bucket is pointless. |
956 | | |
957 | | The quadrant array provides a way to incrementally |
958 | | cache sort orderings, as they appear, so as to |
959 | | make subsequent comparisons in fullGtU() complete |
960 | | faster. For repetitive blocks this makes a big |
961 | | difference (but not big enough to be able to avoid |
962 | | the fallback sorting mechanism, exponential radix sort). |
963 | | |
964 | | The precise meaning is: at all times: |
965 | | |
966 | | for 0 <= i < nblock and 0 <= j <= nblock |
967 | | |
968 | | if block[i] != block[j], |
969 | | |
970 | | then the relative values of quadrant[i] and |
971 | | quadrant[j] are meaningless. |
972 | | |
973 | | else { |
974 | | if quadrant[i] < quadrant[j] |
975 | | then the string starting at i lexicographically |
976 | | precedes the string starting at j |
977 | | |
978 | | else if quadrant[i] > quadrant[j] |
979 | | then the string starting at j lexicographically |
980 | | precedes the string starting at i |
981 | | |
982 | | else |
983 | | the relative ordering of the strings starting |
984 | | at i and j has not yet been determined. |
985 | | } |
986 | | --*/ |
987 | 1.32M | bigDone[ss] = True; |
988 | | |
989 | 1.32M | if (i < 255) { |
990 | 1.32M | Int32 bbStart = ftab[ss << 8] & CLEARMASK; |
991 | 1.32M | Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; |
992 | 1.32M | Int32 shifts = 0; |
993 | | |
994 | 1.32M | while ((bbSize >> shifts) > 65534) shifts++; |
995 | | |
996 | 381M | for (j = bbSize-1; j >= 0; j--) { |
997 | 380M | Int32 a2update = ptr[bbStart + j]; |
998 | 380M | UInt16 qVal = (UInt16)(j >> shifts); |
999 | 380M | quadrant[a2update] = qVal; |
1000 | 380M | if (a2update < BZ_N_OVERSHOOT) |
1001 | 82.8k | quadrant[a2update + nblock] = qVal; |
1002 | 380M | } |
1003 | 1.32M | AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); |
1004 | 1.32M | } |
1005 | | |
1006 | 1.32M | } |
1007 | | |
1008 | 2.42k | if (verb >= 4) |
1009 | 0 | VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", |
1010 | 2.42k | nblock, numQSorted, nblock - numQSorted ); |
1011 | 2.42k | } |
1012 | | |
1013 | | #undef BIGFREQ |
1014 | | #undef SETMASK |
1015 | | #undef CLEARMASK |
1016 | | |
1017 | | |
1018 | | /*---------------------------------------------*/ |
1019 | | /* Pre: |
1020 | | nblock > 0 |
1021 | | arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] |
1022 | | ((UChar*)arr2) [0 .. nblock-1] holds block |
1023 | | arr1 exists for [0 .. nblock-1] |
1024 | | |
1025 | | Post: |
1026 | | ((UChar*)arr2) [0 .. nblock-1] holds block |
1027 | | All other areas of block destroyed |
1028 | | ftab [ 0 .. 65536 ] destroyed |
1029 | | arr1 [0 .. nblock-1] holds sorted order |
1030 | | */ |
1031 | | void BZ2_blockSort ( EState* s ) |
1032 | 11.9k | { |
1033 | 11.9k | UInt32* ptr = s->ptr; |
1034 | 11.9k | UChar* block = s->block; |
1035 | 11.9k | UInt32* ftab = s->ftab; |
1036 | 11.9k | Int32 nblock = s->nblock; |
1037 | 11.9k | Int32 verb = s->verbosity; |
1038 | 11.9k | Int32 wfact = s->workFactor; |
1039 | 11.9k | UInt16* quadrant; |
1040 | 11.9k | Int32 budget; |
1041 | 11.9k | Int32 budgetInit; |
1042 | 11.9k | Int32 i; |
1043 | | |
1044 | 11.9k | if (nblock < 10000) { |
1045 | 6.65k | fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); |
1046 | 6.65k | } else { |
1047 | | /* Calculate the location for quadrant, remembering to get |
1048 | | the alignment right. Assumes that &(block[0]) is at least |
1049 | | 2-byte aligned -- this should be ok since block is really |
1050 | | the first section of arr2. |
1051 | | */ |
1052 | 5.28k | i = nblock+BZ_N_OVERSHOOT; |
1053 | 5.28k | if (i & 1) i++; |
1054 | 5.28k | quadrant = (UInt16*)(&(block[i])); |
1055 | | |
1056 | | /* (wfact-1) / 3 puts the default-factor-30 |
1057 | | transition point at very roughly the same place as |
1058 | | with v0.1 and v0.9.0. |
1059 | | Not that it particularly matters any more, since the |
1060 | | resulting compressed stream is now the same regardless |
1061 | | of whether or not we use the main sort or fallback sort. |
1062 | | */ |
1063 | 5.28k | if (wfact < 1 ) wfact = 1; |
1064 | 5.28k | if (wfact > 100) wfact = 100; |
1065 | 5.28k | budgetInit = nblock * ((wfact-1) / 3); |
1066 | 5.28k | budget = budgetInit; |
1067 | | |
1068 | 5.28k | mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); |
1069 | 5.28k | if (verb >= 3) |
1070 | 0 | VPrintf3 ( " %d work, %d block, ratio %5.2f\n", |
1071 | 5.28k | budgetInit - budget, |
1072 | 5.28k | nblock, |
1073 | 5.28k | (float)(budgetInit - budget) / |
1074 | 5.28k | (float)(nblock==0 ? 1 : nblock) ); |
1075 | 5.28k | if (budget < 0) { |
1076 | 2.85k | if (verb >= 2) |
1077 | 0 | VPrintf0 ( " too repetitive; using fallback" |
1078 | 2.85k | " sorting algorithm\n" ); |
1079 | 2.85k | fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); |
1080 | 2.85k | } |
1081 | 5.28k | } |
1082 | | |
1083 | 11.9k | s->origPtr = -1; |
1084 | 495M | for (i = 0; i < s->nblock; i++) |
1085 | 495M | if (ptr[i] == 0) |
1086 | 11.9k | { s->origPtr = i; break; }; |
1087 | | |
1088 | 11.9k | AssertH( s->origPtr != -1, 1003 ); |
1089 | 11.9k | } |
1090 | | |
1091 | | |
1092 | | /*-------------------------------------------------------------*/ |
1093 | | /*--- end blocksort.c ---*/ |
1094 | | /*-------------------------------------------------------------*/ |