Coverage Report

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