Coverage Report

Created: 2025-07-23 06:37

/src/bzip2/blocksort.c
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
/*-------------------------------------------------------------*/