Coverage Report

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