Coverage Report

Created: 2026-10-17 06:26

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