Coverage Report

Created: 2026-03-31 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bzip2/blocksort.c
Line
Count
Source
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
420M
{
37
420M
   Int32 i, j, tmp;
38
420M
   UInt32 ec_tmp;
39
40
420M
   if (lo == hi) return;
41
42
411M
   if (hi - lo > 3) {
43
274M
      for ( i = hi-4; i >= lo; i-- ) {
44
205M
         tmp = fmap[i];
45
205M
         ec_tmp = eclass[tmp];
46
289M
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
47
83.8M
            fmap[j-4] = fmap[j];
48
205M
         fmap[j-4] = tmp;
49
205M
      }
50
68.3M
   }
51
52
1.26G
   for ( i = hi-1; i >= lo; i-- ) {
53
851M
      tmp = fmap[i];
54
851M
      ec_tmp = eclass[tmp];
55
1.25G
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
56
401M
         fmap[j-1] = fmap[j];
57
851M
      fmap[j-1] = tmp;
58
851M
   }
59
411M
}
60
61
62
/*---------------------------------------------*/
63
#define fswap(zz1, zz2) \
64
8.13G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
65
66
170M
#define fvswap(zzp1, zzp2, zzn)       \
67
170M
{                                     \
68
170M
   Int32 yyp1 = (zzp1);               \
69
170M
   Int32 yyp2 = (zzp2);               \
70
170M
   Int32 yyn  = (zzn);                \
71
1.36G
   while (yyn > 0) {                  \
72
1.19G
      fswap(fmap[yyp1], fmap[yyp2]);  \
73
1.19G
      yyp1++; yyp2++; yyn--;          \
74
1.19G
   }                                  \
75
170M
}
76
77
78
170M
#define fmin(a,b) ((a) < (b)) ? (a) : (b)
79
80
507M
#define fpush(lz,hz) { stackLo[sp] = lz; \
81
507M
                       stackHi[sp] = hz; \
82
507M
                       sp++; }
83
84
507M
#define fpop(lz,hz) { sp--;              \
85
507M
                      lz = stackLo[sp];  \
86
507M
                      hz = stackHi[sp]; }
87
88
507M
#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
337M
{
98
337M
   Int32 unLo, unHi, ltLo, gtHi, n, m;
99
337M
   Int32 sp, lo, hi;
100
337M
   UInt32 med, r, r3;
101
337M
   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
102
337M
   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
103
104
337M
   r = 0;
105
106
337M
   sp = 0;
107
337M
   fpush ( loSt, hiSt );
108
109
844M
   while (sp > 0) {
110
111
507M
      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
112
113
507M
      fpop ( lo, hi );
114
507M
      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
115
420M
         fallbackSimpleSort ( fmap, eclass, lo, hi );
116
420M
         continue;
117
420M
      }
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
86.7M
      r = ((r * 7621) + 1) % 32768;
127
86.7M
      r3 = r % 3;
128
86.7M
      if (r3 == 0) med = eclass[fmap[lo]]; else
129
68.6M
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
130
28.5M
                   med = eclass[fmap[hi]];
131
132
86.7M
      unLo = ltLo = lo;
133
86.7M
      unHi = gtHi = hi;
134
135
929M
      while (1) {
136
6.57G
         while (1) {
137
6.57G
            if (unLo > unHi) break;
138
6.53G
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
139
6.53G
            if (n == 0) { 
140
2.99G
               fswap(fmap[unLo], fmap[ltLo]); 
141
2.99G
               ltLo++; unLo++; 
142
2.99G
               continue; 
143
3.54G
            };
144
3.54G
            if (n > 0) break;
145
2.65G
            unLo++;
146
2.65G
         }
147
6.65G
         while (1) {
148
6.65G
            if (unLo > unHi) break;
149
6.57G
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
150
6.57G
            if (n == 0) { 
151
3.10G
               fswap(fmap[unHi], fmap[gtHi]); 
152
3.10G
               gtHi--; unHi--; 
153
3.10G
               continue; 
154
3.46G
            };
155
3.46G
            if (n < 0) break;
156
2.62G
            unHi--;
157
2.62G
         }
158
929M
         if (unLo > unHi) break;
159
843M
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
160
843M
      }
161
162
86.7M
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
163
164
86.7M
      if (gtHi < ltLo) continue;
165
166
85.1M
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
167
85.1M
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
168
169
85.1M
      n = lo + unLo - ltLo - 1;
170
85.1M
      m = hi - (gtHi - unHi) + 1;
171
172
85.1M
      if (n - lo > hi - m) {
173
39.2M
         fpush ( lo, n );
174
39.2M
         fpush ( m, hi );
175
45.9M
      } else {
176
45.9M
         fpush ( m, hi );
177
45.9M
         fpush ( lo, n );
178
45.9M
      }
179
85.1M
   }
180
337M
}
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
901M
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31))
206
323k
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31))
207
15.5G
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31)))
208
301M
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
209
1.77G
#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
10.1k
{
218
10.1k
   Int32 ftab[257];
219
10.1k
   Int32 ftabCopy[256];
220
10.1k
   Int32 H, i, j, k, l, r, cc, cc1;
221
10.1k
   Int32 nNotDone;
222
10.1k
   Int32 nBhtab;
223
10.1k
   UChar* eclass8 = (UChar*)eclass;
224
225
   /*--
226
      Initial 1-char radix sort to generate
227
      initial fmap and initial BH bits.
228
   --*/
229
10.1k
   if (verb >= 4)
230
0
      VPrintf0 ( "        bucket sorting ...\n" );
231
2.61M
   for (i = 0; i < 257;    i++) ftab[i] = 0;
232
563M
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
233
2.60M
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
234
2.60M
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
235
236
563M
   for (i = 0; i < nblock; i++) {
237
563M
      j = eclass8[i];
238
563M
      k = ftab[j] - 1;
239
563M
      ftab[j] = k;
240
563M
      fmap[k] = i;
241
563M
   }
242
243
10.1k
   nBhtab = 2 + (nblock / 32);
244
17.6M
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
245
2.60M
   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
334k
   for (i = 0; i < 32; i++) { 
255
323k
      SET_BH(nblock + 2*i);
256
323k
      CLEAR_BH(nblock + 2*i + 1);
257
323k
   }
258
259
   /*-- the log(N) loop --*/
260
10.1k
   H = 1;
261
88.9k
   while (1) {
262
263
88.9k
      if (verb >= 4) 
264
0
         VPrintf1 ( "        depth %6d has ", H );
265
266
88.9k
      j = 0;
267
9.64G
      for (i = 0; i < nblock; i++) {
268
9.64G
         if (ISSET_BH(i)) j = i;
269
9.64G
         k = fmap[i] - H; if (k < 0) k += nblock;
270
9.64G
         eclass[k] = j;
271
9.64G
      }
272
273
88.9k
      nNotDone = 0;
274
88.9k
      r = -1;
275
337M
      while (1) {
276
277
   /*-- find the next non-singleton bucket --*/
278
337M
         k = r + 1;
279
1.39G
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
280
337M
         if (ISSET_BH(k)) {
281
82.5M
            while (WORD_BH(k) == 0xffffffff) k += 32;
282
290M
            while (ISSET_BH(k)) k++;
283
41.2M
         }
284
337M
         l = k - 1;
285
337M
         if (l >= nblock) break;
286
989M
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
287
337M
         if (!ISSET_BH(k)) {
288
219M
            while (WORD_BH(k) == 0x00000000) k += 32;
289
171M
            while (!ISSET_BH(k)) k++;
290
25.0M
         }
291
337M
         r = k - 1;
292
337M
         if (r >= nblock) break;
293
294
         /*-- now [l, r] bracket current bucket --*/
295
337M
         if (r > l) {
296
337M
            nNotDone += (r - l + 1);
297
337M
            fallbackQSort3 ( fmap, eclass, l, r );
298
299
            /*-- scan bucket and generate header bits-- */
300
337M
            cc = -1;
301
7.68G
            for (i = l; i <= r; i++) {
302
7.35G
               cc1 = eclass[fmap[i]];
303
7.35G
               if (cc != cc1) { SET_BH(i); cc = cc1; };
304
7.35G
            }
305
337M
         }
306
337M
      }
307
308
88.9k
      if (verb >= 4) 
309
0
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
310
311
88.9k
      H *= 2;
312
88.9k
      if (H > nblock || nNotDone == 0) break;
313
88.9k
   }
314
315
   /*-- 
316
      Reconstruct the original block in
317
      eclass8 [0 .. nblock-1], since the
318
      previous phase destroyed it.
319
   --*/
320
10.1k
   if (verb >= 4)
321
0
      VPrintf0 ( "        reconstructing block ...\n" );
322
10.1k
   j = 0;
323
563M
   for (i = 0; i < nblock; i++) {
324
566M
      while (ftabCopy[j] == 0) j++;
325
563M
      ftabCopy[j]--;
326
563M
      eclass8[fmap[i]] = (UChar)j;
327
563M
   }
328
10.1k
   AssertH ( j < 256, 1005 );
329
10.1k
}
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
767M
{
354
767M
   Int32  k;
355
767M
   UChar  c1, c2;
356
767M
   UInt16 s1, s2;
357
358
767M
   AssertD ( i1 != i2, "mainGtU" );
359
   /* 1 */
360
767M
   c1 = block[i1]; c2 = block[i2];
361
767M
   if (c1 != c2) return (c1 > c2);
362
366M
   i1++; i2++;
363
   /* 2 */
364
366M
   c1 = block[i1]; c2 = block[i2];
365
366M
   if (c1 != c2) return (c1 > c2);
366
326M
   i1++; i2++;
367
   /* 3 */
368
326M
   c1 = block[i1]; c2 = block[i2];
369
326M
   if (c1 != c2) return (c1 > c2);
370
311M
   i1++; i2++;
371
   /* 4 */
372
311M
   c1 = block[i1]; c2 = block[i2];
373
311M
   if (c1 != c2) return (c1 > c2);
374
298M
   i1++; i2++;
375
   /* 5 */
376
298M
   c1 = block[i1]; c2 = block[i2];
377
298M
   if (c1 != c2) return (c1 > c2);
378
287M
   i1++; i2++;
379
   /* 6 */
380
287M
   c1 = block[i1]; c2 = block[i2];
381
287M
   if (c1 != c2) return (c1 > c2);
382
278M
   i1++; i2++;
383
   /* 7 */
384
278M
   c1 = block[i1]; c2 = block[i2];
385
278M
   if (c1 != c2) return (c1 > c2);
386
271M
   i1++; i2++;
387
   /* 8 */
388
271M
   c1 = block[i1]; c2 = block[i2];
389
271M
   if (c1 != c2) return (c1 > c2);
390
264M
   i1++; i2++;
391
   /* 9 */
392
264M
   c1 = block[i1]; c2 = block[i2];
393
264M
   if (c1 != c2) return (c1 > c2);
394
260M
   i1++; i2++;
395
   /* 10 */
396
260M
   c1 = block[i1]; c2 = block[i2];
397
260M
   if (c1 != c2) return (c1 > c2);
398
256M
   i1++; i2++;
399
   /* 11 */
400
256M
   c1 = block[i1]; c2 = block[i2];
401
256M
   if (c1 != c2) return (c1 > c2);
402
254M
   i1++; i2++;
403
   /* 12 */
404
254M
   c1 = block[i1]; c2 = block[i2];
405
254M
   if (c1 != c2) return (c1 > c2);
406
251M
   i1++; i2++;
407
408
251M
   k = nblock + 8;
409
410
8.40G
   do {
411
      /* 1 */
412
8.40G
      c1 = block[i1]; c2 = block[i2];
413
8.40G
      if (c1 != c2) return (c1 > c2);
414
8.39G
      s1 = quadrant[i1]; s2 = quadrant[i2];
415
8.39G
      if (s1 != s2) return (s1 > s2);
416
8.34G
      i1++; i2++;
417
      /* 2 */
418
8.34G
      c1 = block[i1]; c2 = block[i2];
419
8.34G
      if (c1 != c2) return (c1 > c2);
420
8.33G
      s1 = quadrant[i1]; s2 = quadrant[i2];
421
8.33G
      if (s1 != s2) return (s1 > s2);
422
8.30G
      i1++; i2++;
423
      /* 3 */
424
8.30G
      c1 = block[i1]; c2 = block[i2];
425
8.30G
      if (c1 != c2) return (c1 > c2);
426
8.29G
      s1 = quadrant[i1]; s2 = quadrant[i2];
427
8.29G
      if (s1 != s2) return (s1 > s2);
428
8.26G
      i1++; i2++;
429
      /* 4 */
430
8.26G
      c1 = block[i1]; c2 = block[i2];
431
8.26G
      if (c1 != c2) return (c1 > c2);
432
8.25G
      s1 = quadrant[i1]; s2 = quadrant[i2];
433
8.25G
      if (s1 != s2) return (s1 > s2);
434
8.23G
      i1++; i2++;
435
      /* 5 */
436
8.23G
      c1 = block[i1]; c2 = block[i2];
437
8.23G
      if (c1 != c2) return (c1 > c2);
438
8.22G
      s1 = quadrant[i1]; s2 = quadrant[i2];
439
8.22G
      if (s1 != s2) return (s1 > s2);
440
8.21G
      i1++; i2++;
441
      /* 6 */
442
8.21G
      c1 = block[i1]; c2 = block[i2];
443
8.21G
      if (c1 != c2) return (c1 > c2);
444
8.20G
      s1 = quadrant[i1]; s2 = quadrant[i2];
445
8.20G
      if (s1 != s2) return (s1 > s2);
446
8.19G
      i1++; i2++;
447
      /* 7 */
448
8.19G
      c1 = block[i1]; c2 = block[i2];
449
8.19G
      if (c1 != c2) return (c1 > c2);
450
8.18G
      s1 = quadrant[i1]; s2 = quadrant[i2];
451
8.18G
      if (s1 != s2) return (s1 > s2);
452
8.17G
      i1++; i2++;
453
      /* 8 */
454
8.17G
      c1 = block[i1]; c2 = block[i2];
455
8.17G
      if (c1 != c2) return (c1 > c2);
456
8.16G
      s1 = quadrant[i1]; s2 = quadrant[i2];
457
8.16G
      if (s1 != s2) return (s1 > s2);
458
8.15G
      i1++; i2++;
459
460
8.15G
      if (i1 >= nblock) i1 -= nblock;
461
8.15G
      if (i2 >= nblock) i2 -= nblock;
462
463
8.15G
      k -= 8;
464
8.15G
      (*budget)--;
465
8.15G
   }
466
8.15G
      while (k >= 0);
467
468
2.55k
   return False;
469
251M
}
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
36.0M
{
494
36.0M
   Int32 i, j, h, bigN, hp;
495
36.0M
   UInt32 v;
496
497
36.0M
   bigN = hi - lo + 1;
498
36.0M
   if (bigN < 2) return;
499
500
34.3M
   hp = 0;
501
87.8M
   while (incs[hp] < bigN) hp++;
502
34.3M
   hp--;
503
504
87.7M
   for (; hp >= 0; hp--) {
505
53.4M
      h = incs[hp];
506
507
53.4M
      i = lo + h;
508
178M
      while (True) {
509
510
         /*-- copy 1 --*/
511
178M
         if (i > hi) break;
512
165M
         v = ptr[i];
513
165M
         j = i;
514
267M
         while ( mainGtU ( 
515
267M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
516
267M
                 ) ) {
517
139M
            ptr[j] = ptr[j-h];
518
139M
            j = j - h;
519
139M
            if (j <= (lo + h - 1)) break;
520
139M
         }
521
165M
         ptr[j] = v;
522
165M
         i++;
523
524
         /*-- copy 2 --*/
525
165M
         if (i > hi) break;
526
141M
         v = ptr[i];
527
141M
         j = i;
528
256M
         while ( mainGtU ( 
529
256M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
530
256M
                 ) ) {
531
138M
            ptr[j] = ptr[j-h];
532
138M
            j = j - h;
533
138M
            if (j <= (lo + h - 1)) break;
534
138M
         }
535
141M
         ptr[j] = v;
536
141M
         i++;
537
538
         /*-- copy 3 --*/
539
141M
         if (i > hi) break;
540
125M
         v = ptr[i];
541
125M
         j = i;
542
243M
         while ( mainGtU ( 
543
243M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
544
243M
                 ) ) {
545
136M
            ptr[j] = ptr[j-h];
546
136M
            j = j - h;
547
136M
            if (j <= (lo + h - 1)) break;
548
136M
         }
549
125M
         ptr[j] = v;
550
125M
         i++;
551
552
125M
         if (*budget < 0) return;
553
125M
      }
554
53.4M
   }
555
34.3M
}
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
1.17G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
569
570
6.68M
#define mvswap(zzp1, zzp2, zzn)       \
571
6.68M
{                                     \
572
6.68M
   Int32 yyp1 = (zzp1);               \
573
6.68M
   Int32 yyp2 = (zzp2);               \
574
6.68M
   Int32 yyn  = (zzn);                \
575
60.9M
   while (yyn > 0) {                  \
576
54.2M
      mswap(ptr[yyp1], ptr[yyp2]);    \
577
54.2M
      yyp1++; yyp2++; yyn--;          \
578
54.2M
   }                                  \
579
6.68M
}
580
581
static 
582
__inline__
583
UChar mmed3 ( UChar a, UChar b, UChar c )
584
4.44M
{
585
4.44M
   UChar t;
586
4.44M
   if (a > b) { t = a; a = b; b = t; };
587
4.44M
   if (b > c) { 
588
1.82M
      b = c;
589
1.82M
      if (a > b) b = a;
590
1.82M
   }
591
4.44M
   return b;
592
4.44M
}
593
594
6.68M
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
595
596
40.5M
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
597
40.5M
                          stackHi[sp] = hz; \
598
40.5M
                          stackD [sp] = dz; \
599
40.5M
                          sp++; }
600
601
40.4M
#define mpop(lz,hz,dz) { sp--;             \
602
40.4M
                         lz = stackLo[sp]; \
603
40.4M
                         hz = stackHi[sp]; \
604
40.4M
                         dz = stackD [sp]; }
605
606
607
20.0M
#define mnextsize(az) (nextHi[az]-nextLo[az])
608
609
#define mnextswap(az,bz)                                        \
610
3.47M
   { Int32 tz;                                                  \
611
3.47M
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
612
3.47M
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
613
3.47M
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
614
615
616
80.9M
#define MAIN_QSORT_SMALL_THRESH 20
617
4.57M
#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
29.3M
{
630
29.3M
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
631
29.3M
   Int32 sp, lo, hi, d;
632
633
29.3M
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
634
29.3M
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
635
29.3M
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
636
637
29.3M
   Int32 nextLo[3];
638
29.3M
   Int32 nextHi[3];
639
29.3M
   Int32 nextD [3];
640
641
29.3M
   sp = 0;
642
29.3M
   mpush ( loSt, hiSt, dSt );
643
644
69.8M
   while (sp > 0) {
645
646
40.4M
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
647
648
40.4M
      mpop ( lo, hi, d );
649
40.4M
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
650
36.0M
          d > MAIN_QSORT_DEPTH_THRESH) {
651
36.0M
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
652
36.0M
         if (*budget < 0) return;
653
36.0M
         continue;
654
36.0M
      }
655
656
4.44M
      med = (Int32) 
657
4.44M
            mmed3 ( block[ptr[ lo         ]+d],
658
4.44M
                    block[ptr[ hi         ]+d],
659
4.44M
                    block[ptr[ (lo+hi)>>1 ]+d] );
660
661
4.44M
      unLo = ltLo = lo;
662
4.44M
      unHi = gtHi = hi;
663
664
34.5M
      while (True) {
665
802M
         while (True) {
666
802M
            if (unLo > unHi) break;
667
799M
            n = ((Int32)block[ptr[unLo]+d]) - med;
668
799M
            if (n == 0) { 
669
683M
               mswap(ptr[unLo], ptr[ltLo]); 
670
683M
               ltLo++; unLo++; continue; 
671
683M
            };
672
115M
            if (n >  0) break;
673
83.7M
            unLo++;
674
83.7M
         }
675
519M
         while (True) {
676
519M
            if (unLo > unHi) break;
677
514M
            n = ((Int32)block[ptr[unHi]+d]) - med;
678
514M
            if (n == 0) { 
679
404M
               mswap(ptr[unHi], ptr[gtHi]); 
680
404M
               gtHi--; unHi--; continue; 
681
404M
            };
682
110M
            if (n <  0) break;
683
80.5M
            unHi--;
684
80.5M
         }
685
34.5M
         if (unLo > unHi) break;
686
30.1M
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
687
30.1M
      }
688
689
4.44M
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
690
691
4.44M
      if (gtHi < ltLo) {
692
1.10M
         mpush(lo, hi, d+1 );
693
1.10M
         continue;
694
1.10M
      }
695
696
3.34M
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
697
3.34M
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
698
699
3.34M
      n = lo + unLo - ltLo - 1;
700
3.34M
      m = hi - (gtHi - unHi) + 1;
701
702
3.34M
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
703
3.34M
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
704
3.34M
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
705
706
3.34M
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
707
3.34M
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
708
3.34M
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
709
710
3.34M
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
711
3.34M
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
712
713
3.34M
      mpush (nextLo[0], nextHi[0], nextD[0]);
714
3.34M
      mpush (nextLo[1], nextHi[1], nextD[1]);
715
3.34M
      mpush (nextLo[2], nextHi[2], nextD[2]);
716
3.34M
   }
717
29.3M
}
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
19.7M
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
747
2.33G
#define SETMASK (1 << 21)
748
1.17G
#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
6.03k
{
759
6.03k
   Int32  i, j, k, ss, sb;
760
6.03k
   Int32  runningOrder[256];
761
6.03k
   Bool   bigDone[256];
762
6.03k
   Int32  copyStart[256];
763
6.03k
   Int32  copyEnd  [256];
764
6.03k
   UChar  c1;
765
6.03k
   Int32  numQSorted;
766
6.03k
   UInt16 s;
767
6.03k
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
768
769
   /*-- set up the 2-byte frequency table --*/
770
395M
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
771
772
6.03k
   j = block[0] << 8;
773
6.03k
   i = nblock-1;
774
259M
   for (; i >= 3; i -= 4) {
775
259M
      quadrant[i] = 0;
776
259M
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
777
259M
      ftab[j]++;
778
259M
      quadrant[i-1] = 0;
779
259M
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
780
259M
      ftab[j]++;
781
259M
      quadrant[i-2] = 0;
782
259M
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
783
259M
      ftab[j]++;
784
259M
      quadrant[i-3] = 0;
785
259M
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
786
259M
      ftab[j]++;
787
259M
   }
788
12.8k
   for (; i >= 0; i--) {
789
6.78k
      quadrant[i] = 0;
790
6.78k
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
791
6.78k
      ftab[j]++;
792
6.78k
   }
793
794
   /*-- (emphasises close relationship of block & quadrant) --*/
795
211k
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
796
205k
      block   [nblock+i] = block[i];
797
205k
      quadrant[nblock+i] = 0;
798
205k
   }
799
800
6.03k
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
801
802
   /*-- Complete the initial radix sort --*/
803
395M
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
804
805
6.03k
   s = block[0] << 8;
806
6.03k
   i = nblock-1;
807
259M
   for (; i >= 3; i -= 4) {
808
259M
      s = (s >> 8) | (block[i] << 8);
809
259M
      j = ftab[s] -1;
810
259M
      ftab[s] = j;
811
259M
      ptr[j] = i;
812
259M
      s = (s >> 8) | (block[i-1] << 8);
813
259M
      j = ftab[s] -1;
814
259M
      ftab[s] = j;
815
259M
      ptr[j] = i-1;
816
259M
      s = (s >> 8) | (block[i-2] << 8);
817
259M
      j = ftab[s] -1;
818
259M
      ftab[s] = j;
819
259M
      ptr[j] = i-2;
820
259M
      s = (s >> 8) | (block[i-3] << 8);
821
259M
      j = ftab[s] -1;
822
259M
      ftab[s] = j;
823
259M
      ptr[j] = i-3;
824
259M
   }
825
12.8k
   for (; i >= 0; i--) {
826
6.78k
      s = (s >> 8) | (block[i] << 8);
827
6.78k
      j = ftab[s] -1;
828
6.78k
      ftab[s] = j;
829
6.78k
      ptr[j] = i;
830
6.78k
   }
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.55M
   for (i = 0; i <= 255; i++) {
838
1.54M
      bigDone     [i] = False;
839
1.54M
      runningOrder[i] = i;
840
1.54M
   }
841
842
6.03k
   {
843
6.03k
      Int32 vv;
844
6.03k
      Int32 h = 1;
845
30.1k
      do h = 3 * h + 1; while (h <= 256);
846
30.1k
      do {
847
30.1k
         h = h / 3;
848
6.67M
         for (i = h; i <= 255; i++) {
849
6.64M
            vv = runningOrder[i];
850
6.64M
            j = i;
851
9.85M
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
852
3.58M
               runningOrder[j] = runningOrder[j-h];
853
3.58M
               j = j - h;
854
3.58M
               if (j <= (h - 1)) goto zero;
855
3.58M
            }
856
6.64M
            zero:
857
6.64M
            runningOrder[j] = vv;
858
6.64M
         }
859
30.1k
      } while (h != 1);
860
6.03k
   }
861
862
   /*--
863
      The main sorting loop.
864
   --*/
865
866
6.03k
   numQSorted = 0;
867
868
1.52M
   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.51M
      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
389M
      for (j = 0; j <= 255; j++) {
887
388M
         if (j != ss) {
888
386M
            sb = (ss << 8) + j;
889
386M
            if ( ! (ftab[sb] & SETMASK) ) {
890
194M
               Int32 lo = ftab[sb]   & CLEARMASK;
891
194M
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
892
194M
               if (hi > lo) {
893
29.3M
                  if (verb >= 4)
894
0
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
895
29.3M
                                "done %d   this %d\n",
896
29.3M
                                ss, j, numQSorted, hi - lo + 1 );
897
29.3M
                  mainQSort3 ( 
898
29.3M
                     ptr, block, quadrant, nblock, 
899
29.3M
                     lo, hi, BZ_N_RADIX, budget 
900
29.3M
                  );   
901
29.3M
                  numQSorted += (hi - lo + 1);
902
29.3M
                  if (*budget < 0) return;
903
29.3M
               }
904
194M
            }
905
386M
            ftab[sb] |= SETMASK;
906
386M
         }
907
388M
      }
908
909
1.51M
      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.51M
      {
919
389M
         for (j = 0; j <= 255; j++) {
920
388M
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
921
388M
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
922
388M
         }
923
257M
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
924
255M
            k = ptr[j]-1; if (k < 0) k += nblock;
925
255M
            c1 = block[k];
926
255M
            if (!bigDone[c1])
927
144M
               ptr[ copyStart[c1]++ ] = k;
928
255M
         }
929
272M
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
930
270M
            k = ptr[j]-1; if (k < 0) k += nblock;
931
270M
            c1 = block[k];
932
270M
            if (!bigDone[c1]) 
933
141M
               ptr[ copyEnd[c1]-- ] = k;
934
270M
         }
935
1.51M
      }
936
937
1.51M
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
938
1.51M
                || 
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.51M
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
944
1.51M
                1007 )
945
946
389M
      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.51M
      bigDone[ss] = True;
988
989
1.51M
      if (i < 255) {
990
1.51M
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
991
1.51M
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
992
1.51M
         Int32 shifts   = 0;
993
994
1.51M
         while ((bbSize >> shifts) > 65534) shifts++;
995
996
479M
         for (j = bbSize-1; j >= 0; j--) {
997
477M
            Int32 a2update     = ptr[bbStart + j];
998
477M
            UInt16 qVal        = (UInt16)(j >> shifts);
999
477M
            quadrant[a2update] = qVal;
1000
477M
            if (a2update < BZ_N_OVERSHOOT)
1001
95.5k
               quadrant[a2update + nblock] = qVal;
1002
477M
         }
1003
1.51M
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
1004
1.51M
      }
1005
1006
1.51M
   }
1007
1008
2.74k
   if (verb >= 4)
1009
0
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
1010
2.74k
                 nblock, numQSorted, nblock - numQSorted );
1011
2.74k
}
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
12.8k
{
1033
12.8k
   UInt32* ptr    = s->ptr; 
1034
12.8k
   UChar*  block  = s->block;
1035
12.8k
   UInt32* ftab   = s->ftab;
1036
12.8k
   Int32   nblock = s->nblock;
1037
12.8k
   Int32   verb   = s->verbosity;
1038
12.8k
   Int32   wfact  = s->workFactor;
1039
12.8k
   UInt16* quadrant;
1040
12.8k
   Int32   budget;
1041
12.8k
   Int32   budgetInit;
1042
12.8k
   Int32   i;
1043
1044
12.8k
   if (nblock < 10000) {
1045
6.82k
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1046
6.82k
   } 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
6.03k
      i = nblock+BZ_N_OVERSHOOT;
1053
6.03k
      if (i & 1) i++;
1054
6.03k
      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
6.03k
      if (wfact < 1  ) wfact = 1;
1064
6.03k
      if (wfact > 100) wfact = 100;
1065
6.03k
      budgetInit = nblock * ((wfact-1) / 3);
1066
6.03k
      budget = budgetInit;
1067
1068
6.03k
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
1069
6.03k
      if (verb >= 3) 
1070
0
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
1071
6.03k
                    budgetInit - budget,
1072
6.03k
                    nblock, 
1073
6.03k
                    (float)(budgetInit - budget) /
1074
6.03k
                    (float)(nblock==0 ? 1 : nblock) ); 
1075
6.03k
      if (budget < 0) {
1076
3.29k
         if (verb >= 2) 
1077
0
            VPrintf0 ( "    too repetitive; using fallback"
1078
3.29k
                       " sorting algorithm\n" );
1079
3.29k
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1080
3.29k
      }
1081
6.03k
   }
1082
1083
12.8k
   s->origPtr = -1;
1084
604M
   for (i = 0; i < s->nblock; i++)
1085
604M
      if (ptr[i] == 0)
1086
12.8k
         { s->origPtr = i; break; };
1087
1088
12.8k
   AssertH( s->origPtr != -1, 1003 );
1089
12.8k
}
1090
1091
1092
/*-------------------------------------------------------------*/
1093
/*--- end                                       blocksort.c ---*/
1094
/*-------------------------------------------------------------*/