Coverage Report

Created: 2026-09-14 07:37

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
127M
{
37
127M
   Int32 i, j, tmp;
38
127M
   UInt32 ec_tmp;
39
40
127M
   if (lo == hi) return;
41
42
123M
   if (hi - lo > 3) {
43
106M
      for ( i = hi-4; i >= lo; i-- ) {
44
80.1M
         tmp = fmap[i];
45
80.1M
         ec_tmp = eclass[tmp];
46
107M
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
47
27.3M
            fmap[j-4] = fmap[j];
48
80.1M
         fmap[j-4] = tmp;
49
80.1M
      }
50
26.5M
   }
51
52
409M
   for ( i = hi-1; i >= lo; i-- ) {
53
286M
      tmp = fmap[i];
54
286M
      ec_tmp = eclass[tmp];
55
422M
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
56
136M
         fmap[j-1] = fmap[j];
57
286M
      fmap[j-1] = tmp;
58
286M
   }
59
123M
}
60
61
62
/*---------------------------------------------*/
63
#define fswap(zz1, zz2) \
64
1.57G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
65
66
55.0M
#define fvswap(zzp1, zzp2, zzn)       \
67
55.0M
{                                     \
68
55.0M
   Int32 yyp1 = (zzp1);               \
69
55.0M
   Int32 yyp2 = (zzp2);               \
70
55.0M
   Int32 yyn  = (zzn);                \
71
307M
   while (yyn > 0) {                  \
72
252M
      fswap(fmap[yyp1], fmap[yyp2]);  \
73
252M
      yyp1++; yyp2++; yyn--;          \
74
252M
   }                                  \
75
55.0M
}
76
77
78
55.0M
#define fmin(a,b) ((a) < (b)) ? (a) : (b)
79
80
158M
#define fpush(lz,hz) { stackLo[sp] = lz; \
81
158M
                       stackHi[sp] = hz; \
82
158M
                       sp++; }
83
84
158M
#define fpop(lz,hz) { sp--;              \
85
158M
                      lz = stackLo[sp];  \
86
158M
                      hz = stackHi[sp]; }
87
88
158M
#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
261M
   while (sp > 0) {
110
111
158M
      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
112
113
158M
      fpop ( lo, hi );
114
158M
      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
115
127M
         fallbackSimpleSort ( fmap, eclass, lo, hi );
116
127M
         continue;
117
127M
      }
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
30.4M
      r = ((r * 7621) + 1) % 32768;
127
30.4M
      r3 = r % 3;
128
30.4M
      if (r3 == 0) med = eclass[fmap[lo]]; else
129
27.3M
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
130
9.96M
                   med = eclass[fmap[hi]];
131
132
30.4M
      unLo = ltLo = lo;
133
30.4M
      unHi = gtHi = hi;
134
135
153M
      while (1) {
136
1.43G
         while (1) {
137
1.43G
            if (unLo > unHi) break;
138
1.41G
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
139
1.41G
            if (n == 0) { 
140
875M
               fswap(fmap[unLo], fmap[ltLo]); 
141
875M
               ltLo++; unLo++; 
142
875M
               continue; 
143
875M
            };
144
540M
            if (n > 0) break;
145
403M
            unLo++;
146
403M
         }
147
885M
         while (1) {
148
885M
            if (unLo > unHi) break;
149
855M
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
150
855M
            if (n == 0) { 
151
325M
               fswap(fmap[unHi], fmap[gtHi]); 
152
325M
               gtHi--; unHi--; 
153
325M
               continue; 
154
530M
            };
155
530M
            if (n < 0) break;
156
407M
            unHi--;
157
407M
         }
158
153M
         if (unLo > unHi) break;
159
122M
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
160
122M
      }
161
162
30.4M
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
163
164
30.4M
      if (gtHi < ltLo) continue;
165
166
27.5M
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
167
27.5M
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
168
169
27.5M
      n = lo + unLo - ltLo - 1;
170
27.5M
      m = hi - (gtHi - unHi) + 1;
171
172
27.5M
      if (n - lo > hi - m) {
173
13.6M
         fpush ( lo, n );
174
13.6M
         fpush ( m, hi );
175
13.8M
      } else {
176
13.8M
         fpush ( m, hi );
177
13.8M
         fpush ( lo, n );
178
13.8M
      }
179
27.5M
   }
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
315M
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31))
206
3.59M
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31))
207
4.17G
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31)))
208
68.2M
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
209
619M
#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
112k
{
218
112k
   Int32 ftab[257];
219
112k
   Int32 ftabCopy[256];
220
112k
   Int32 H, i, j, k, l, r, cc, cc1;
221
112k
   Int32 nNotDone;
222
112k
   Int32 nBhtab;
223
112k
   UChar* eclass8 = (UChar*)eclass;
224
225
   /*--
226
      Initial 1-char radix sort to generate
227
      initial fmap and initial BH bits.
228
   --*/
229
112k
   if (verb >= 4)
230
0
      VPrintf0 ( "        bucket sorting ...\n" );
231
28.9M
   for (i = 0; i < 257;    i++) ftab[i] = 0;
232
186M
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
233
28.8M
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
234
28.8M
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
235
236
186M
   for (i = 0; i < nblock; i++) {
237
186M
      j = eclass8[i];
238
186M
      k = ftab[j] - 1;
239
186M
      ftab[j] = k;
240
186M
      fmap[k] = i;
241
186M
   }
242
243
112k
   nBhtab = 2 + (nblock / 32);
244
6.10M
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
245
28.8M
   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
3.70M
   for (i = 0; i < 32; i++) { 
255
3.59M
      SET_BH(nblock + 2*i);
256
3.59M
      CLEAR_BH(nblock + 2*i + 1);
257
3.59M
   }
258
259
   /*-- the log(N) loop --*/
260
112k
   H = 1;
261
658k
   while (1) {
262
263
658k
      if (verb >= 4) 
264
0
         VPrintf1 ( "        depth %6d has ", H );
265
266
658k
      j = 0;
267
2.16G
      for (i = 0; i < nblock; i++) {
268
2.16G
         if (ISSET_BH(i)) j = i;
269
2.16G
         k = fmap[i] - H; if (k < 0) k += nblock;
270
2.16G
         eclass[k] = j;
271
2.16G
      }
272
273
658k
      nNotDone = 0;
274
658k
      r = -1;
275
103M
      while (1) {
276
277
   /*-- find the next non-singleton bucket --*/
278
103M
         k = r + 1;
279
379M
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
280
103M
         if (ISSET_BH(k)) {
281
21.4M
            while (WORD_BH(k) == 0xffffffff) k += 32;
282
79.5M
            while (ISSET_BH(k)) k++;
283
11.3M
         }
284
103M
         l = k - 1;
285
103M
         if (l >= nblock) break;
286
421M
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
287
103M
         if (!ISSET_BH(k)) {
288
46.8M
            while (WORD_BH(k) == 0x00000000) k += 32;
289
123M
            while (!ISSET_BH(k)) k++;
290
13.2M
         }
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.70G
            for (i = l; i <= r; i++) {
302
1.60G
               cc1 = eclass[fmap[i]];
303
1.60G
               if (cc != cc1) { SET_BH(i); cc = cc1; };
304
1.60G
            }
305
103M
         }
306
103M
      }
307
308
658k
      if (verb >= 4) 
309
0
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
310
311
658k
      H *= 2;
312
658k
      if (H > nblock || nNotDone == 0) break;
313
658k
   }
314
315
   /*-- 
316
      Reconstruct the original block in
317
      eclass8 [0 .. nblock-1], since the
318
      previous phase destroyed it.
319
   --*/
320
112k
   if (verb >= 4)
321
0
      VPrintf0 ( "        reconstructing block ...\n" );
322
112k
   j = 0;
323
186M
   for (i = 0; i < nblock; i++) {
324
202M
      while (ftabCopy[j] == 0) j++;
325
186M
      ftabCopy[j]--;
326
186M
      eclass8[fmap[i]] = (UChar)j;
327
186M
   }
328
112k
   AssertH ( j < 256, 1005 );
329
112k
}
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
106M
{
354
106M
   Int32  k;
355
106M
   UChar  c1, c2;
356
106M
   UInt16 s1, s2;
357
358
106M
   AssertD ( i1 != i2, "mainGtU" );
359
   /* 1 */
360
106M
   c1 = block[i1]; c2 = block[i2];
361
106M
   if (c1 != c2) return (c1 > c2);
362
103M
   i1++; i2++;
363
   /* 2 */
364
103M
   c1 = block[i1]; c2 = block[i2];
365
103M
   if (c1 != c2) return (c1 > c2);
366
102M
   i1++; i2++;
367
   /* 3 */
368
102M
   c1 = block[i1]; c2 = block[i2];
369
102M
   if (c1 != c2) return (c1 > c2);
370
100M
   i1++; i2++;
371
   /* 4 */
372
100M
   c1 = block[i1]; c2 = block[i2];
373
100M
   if (c1 != c2) return (c1 > c2);
374
99.1M
   i1++; i2++;
375
   /* 5 */
376
99.1M
   c1 = block[i1]; c2 = block[i2];
377
99.1M
   if (c1 != c2) return (c1 > c2);
378
97.7M
   i1++; i2++;
379
   /* 6 */
380
97.7M
   c1 = block[i1]; c2 = block[i2];
381
97.7M
   if (c1 != c2) return (c1 > c2);
382
96.3M
   i1++; i2++;
383
   /* 7 */
384
96.3M
   c1 = block[i1]; c2 = block[i2];
385
96.3M
   if (c1 != c2) return (c1 > c2);
386
95.0M
   i1++; i2++;
387
   /* 8 */
388
95.0M
   c1 = block[i1]; c2 = block[i2];
389
95.0M
   if (c1 != c2) return (c1 > c2);
390
93.8M
   i1++; i2++;
391
   /* 9 */
392
93.8M
   c1 = block[i1]; c2 = block[i2];
393
93.8M
   if (c1 != c2) return (c1 > c2);
394
92.8M
   i1++; i2++;
395
   /* 10 */
396
92.8M
   c1 = block[i1]; c2 = block[i2];
397
92.8M
   if (c1 != c2) return (c1 > c2);
398
91.5M
   i1++; i2++;
399
   /* 11 */
400
91.5M
   c1 = block[i1]; c2 = block[i2];
401
91.5M
   if (c1 != c2) return (c1 > c2);
402
90.6M
   i1++; i2++;
403
   /* 12 */
404
90.6M
   c1 = block[i1]; c2 = block[i2];
405
90.6M
   if (c1 != c2) return (c1 > c2);
406
89.6M
   i1++; i2++;
407
408
89.6M
   k = nblock + 8;
409
410
962M
   do {
411
      /* 1 */
412
962M
      c1 = block[i1]; c2 = block[i2];
413
962M
      if (c1 != c2) return (c1 > c2);
414
957M
      s1 = quadrant[i1]; s2 = quadrant[i2];
415
957M
      if (s1 != s2) return (s1 > s2);
416
946M
      i1++; i2++;
417
      /* 2 */
418
946M
      c1 = block[i1]; c2 = block[i2];
419
946M
      if (c1 != c2) return (c1 > c2);
420
941M
      s1 = quadrant[i1]; s2 = quadrant[i2];
421
941M
      if (s1 != s2) return (s1 > s2);
422
930M
      i1++; i2++;
423
      /* 3 */
424
930M
      c1 = block[i1]; c2 = block[i2];
425
930M
      if (c1 != c2) return (c1 > c2);
426
926M
      s1 = quadrant[i1]; s2 = quadrant[i2];
427
926M
      if (s1 != s2) return (s1 > s2);
428
921M
      i1++; i2++;
429
      /* 4 */
430
921M
      c1 = block[i1]; c2 = block[i2];
431
921M
      if (c1 != c2) return (c1 > c2);
432
917M
      s1 = quadrant[i1]; s2 = quadrant[i2];
433
917M
      if (s1 != s2) return (s1 > s2);
434
912M
      i1++; i2++;
435
      /* 5 */
436
912M
      c1 = block[i1]; c2 = block[i2];
437
912M
      if (c1 != c2) return (c1 > c2);
438
908M
      s1 = quadrant[i1]; s2 = quadrant[i2];
439
908M
      if (s1 != s2) return (s1 > s2);
440
903M
      i1++; i2++;
441
      /* 6 */
442
903M
      c1 = block[i1]; c2 = block[i2];
443
903M
      if (c1 != c2) return (c1 > c2);
444
898M
      s1 = quadrant[i1]; s2 = quadrant[i2];
445
898M
      if (s1 != s2) return (s1 > s2);
446
890M
      i1++; i2++;
447
      /* 7 */
448
890M
      c1 = block[i1]; c2 = block[i2];
449
890M
      if (c1 != c2) return (c1 > c2);
450
887M
      s1 = quadrant[i1]; s2 = quadrant[i2];
451
887M
      if (s1 != s2) return (s1 > s2);
452
883M
      i1++; i2++;
453
      /* 8 */
454
883M
      c1 = block[i1]; c2 = block[i2];
455
883M
      if (c1 != c2) return (c1 > c2);
456
879M
      s1 = quadrant[i1]; s2 = quadrant[i2];
457
879M
      if (s1 != s2) return (s1 > s2);
458
872M
      i1++; i2++;
459
460
872M
      if (i1 >= nblock) i1 -= nblock;
461
872M
      if (i2 >= nblock) i2 -= nblock;
462
463
872M
      k -= 8;
464
872M
      (*budget)--;
465
872M
   }
466
872M
      while (k >= 0);
467
468
11.1k
   return False;
469
89.6M
}
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
981k
{
494
981k
   Int32 i, j, h, bigN, hp;
495
981k
   UInt32 v;
496
497
981k
   bigN = hi - lo + 1;
498
981k
   if (bigN < 2) return;
499
500
737k
   hp = 0;
501
2.09M
   while (incs[hp] < bigN) hp++;
502
737k
   hp--;
503
504
2.06M
   for (; hp >= 0; hp--) {
505
1.33M
      h = incs[hp];
506
507
1.33M
      i = lo + h;
508
18.1M
      while (True) {
509
510
         /*-- copy 1 --*/
511
18.1M
         if (i > hi) break;
512
17.7M
         v = ptr[i];
513
17.7M
         j = i;
514
35.8M
         while ( mainGtU ( 
515
35.8M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
516
35.8M
                 ) ) {
517
20.9M
            ptr[j] = ptr[j-h];
518
20.9M
            j = j - h;
519
20.9M
            if (j <= (lo + h - 1)) break;
520
20.9M
         }
521
17.7M
         ptr[j] = v;
522
17.7M
         i++;
523
524
         /*-- copy 2 --*/
525
17.7M
         if (i > hi) break;
526
17.1M
         v = ptr[i];
527
17.1M
         j = i;
528
35.6M
         while ( mainGtU ( 
529
35.6M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
530
35.6M
                 ) ) {
531
20.9M
            ptr[j] = ptr[j-h];
532
20.9M
            j = j - h;
533
20.9M
            if (j <= (lo + h - 1)) break;
534
20.9M
         }
535
17.1M
         ptr[j] = v;
536
17.1M
         i++;
537
538
         /*-- copy 3 --*/
539
17.1M
         if (i > hi) break;
540
16.7M
         v = ptr[i];
541
16.7M
         j = i;
542
35.3M
         while ( mainGtU ( 
543
35.3M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
544
35.3M
                 ) ) {
545
20.9M
            ptr[j] = ptr[j-h];
546
20.9M
            j = j - h;
547
20.9M
            if (j <= (lo + h - 1)) break;
548
20.9M
         }
549
16.7M
         ptr[j] = v;
550
16.7M
         i++;
551
552
16.7M
         if (*budget < 0) return;
553
16.7M
      }
554
1.33M
   }
555
737k
}
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
284M
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
569
570
483k
#define mvswap(zzp1, zzp2, zzn)       \
571
483k
{                                     \
572
483k
   Int32 yyp1 = (zzp1);               \
573
483k
   Int32 yyp2 = (zzp2);               \
574
483k
   Int32 yyn  = (zzn);                \
575
10.3M
   while (yyn > 0) {                  \
576
9.91M
      mswap(ptr[yyp1], ptr[yyp2]);    \
577
9.91M
      yyp1++; yyp2++; yyn--;          \
578
9.91M
   }                                  \
579
483k
}
580
581
static 
582
__inline__
583
UChar mmed3 ( UChar a, UChar b, UChar c )
584
1.14M
{
585
1.14M
   UChar t;
586
1.14M
   if (a > b) { t = a; a = b; b = t; };
587
1.14M
   if (b > c) { 
588
51.2k
      b = c;
589
51.2k
      if (a > b) b = a;
590
51.2k
   }
591
1.14M
   return b;
592
1.14M
}
593
594
483k
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
595
596
2.12M
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
597
2.12M
                          stackHi[sp] = hz; \
598
2.12M
                          stackD [sp] = dz; \
599
2.12M
                          sp++; }
600
601
2.12M
#define mpop(lz,hz,dz) { sp--;             \
602
2.12M
                         lz = stackLo[sp]; \
603
2.12M
                         hz = stackHi[sp]; \
604
2.12M
                         dz = stackD [sp]; }
605
606
607
1.45M
#define mnextsize(az) (nextHi[az]-nextLo[az])
608
609
#define mnextswap(az,bz)                                        \
610
522k
   { Int32 tz;                                                  \
611
522k
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
612
522k
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
613
522k
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
614
615
616
4.24M
#define MAIN_QSORT_SMALL_THRESH 20
617
1.25M
#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
499k
{
630
499k
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
631
499k
   Int32 sp, lo, hi, d;
632
633
499k
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
634
499k
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
635
499k
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
636
637
499k
   Int32 nextLo[3];
638
499k
   Int32 nextHi[3];
639
499k
   Int32 nextD [3];
640
641
499k
   sp = 0;
642
499k
   mpush ( loSt, hiSt, dSt );
643
644
2.61M
   while (sp > 0) {
645
646
2.12M
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
647
648
2.12M
      mpop ( lo, hi, d );
649
2.12M
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
650
1.25M
          d > MAIN_QSORT_DEPTH_THRESH) {
651
981k
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
652
981k
         if (*budget < 0) return;
653
974k
         continue;
654
981k
      }
655
656
1.14M
      med = (Int32) 
657
1.14M
            mmed3 ( block[ptr[ lo         ]+d],
658
1.14M
                    block[ptr[ hi         ]+d],
659
1.14M
                    block[ptr[ (lo+hi)>>1 ]+d] );
660
661
1.14M
      unLo = ltLo = lo;
662
1.14M
      unHi = gtHi = hi;
663
664
1.71M
      while (True) {
665
217M
         while (True) {
666
217M
            if (unLo > unHi) break;
667
216M
            n = ((Int32)block[ptr[unLo]+d]) - med;
668
216M
            if (n == 0) { 
669
210M
               mswap(ptr[unLo], ptr[ltLo]); 
670
210M
               ltLo++; unLo++; continue; 
671
210M
            };
672
6.24M
            if (n >  0) break;
673
5.57M
            unLo++;
674
5.57M
         }
675
70.8M
         while (True) {
676
70.8M
            if (unLo > unHi) break;
677
69.7M
            n = ((Int32)block[ptr[unHi]+d]) - med;
678
69.7M
            if (n == 0) { 
679
63.1M
               mswap(ptr[unHi], ptr[gtHi]); 
680
63.1M
               gtHi--; unHi--; continue; 
681
63.1M
            };
682
6.59M
            if (n <  0) break;
683
6.01M
            unHi--;
684
6.01M
         }
685
1.71M
         if (unLo > unHi) break;
686
575k
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
687
575k
      }
688
689
1.14M
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
690
691
1.14M
      if (gtHi < ltLo) {
692
901k
         mpush(lo, hi, d+1 );
693
901k
         continue;
694
901k
      }
695
696
241k
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
697
241k
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
698
699
241k
      n = lo + unLo - ltLo - 1;
700
241k
      m = hi - (gtHi - unHi) + 1;
701
702
241k
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
703
241k
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
704
241k
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
705
706
241k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
707
241k
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
708
241k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
709
710
241k
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
711
241k
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
712
713
241k
      mpush (nextLo[0], nextHi[0], nextD[0]);
714
241k
      mpush (nextLo[1], nextHi[1], nextD[1]);
715
241k
      mpush (nextLo[2], nextHi[2], nextD[2]);
716
241k
   }
717
499k
}
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.1M
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
747
3.58G
#define SETMASK (1 << 21)
748
1.80G
#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.21k
{
759
9.21k
   Int32  i, j, k, ss, sb;
760
9.21k
   Int32  runningOrder[256];
761
9.21k
   Bool   bigDone[256];
762
9.21k
   Int32  copyStart[256];
763
9.21k
   Int32  copyEnd  [256];
764
9.21k
   UChar  c1;
765
9.21k
   Int32  numQSorted;
766
9.21k
   UInt16 s;
767
9.21k
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
768
769
   /*-- set up the 2-byte frequency table --*/
770
604M
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
771
772
9.21k
   j = block[0] << 8;
773
9.21k
   i = nblock-1;
774
27.3M
   for (; i >= 3; i -= 4) {
775
27.3M
      quadrant[i] = 0;
776
27.3M
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
777
27.3M
      ftab[j]++;
778
27.3M
      quadrant[i-1] = 0;
779
27.3M
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
780
27.3M
      ftab[j]++;
781
27.3M
      quadrant[i-2] = 0;
782
27.3M
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
783
27.3M
      ftab[j]++;
784
27.3M
      quadrant[i-3] = 0;
785
27.3M
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
786
27.3M
      ftab[j]++;
787
27.3M
   }
788
19.4k
   for (; i >= 0; i--) {
789
10.2k
      quadrant[i] = 0;
790
10.2k
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
791
10.2k
      ftab[j]++;
792
10.2k
   }
793
794
   /*-- (emphasises close relationship of block & quadrant) --*/
795
322k
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
796
313k
      block   [nblock+i] = block[i];
797
313k
      quadrant[nblock+i] = 0;
798
313k
   }
799
800
9.21k
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
801
802
   /*-- Complete the initial radix sort --*/
803
604M
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
804
805
9.21k
   s = block[0] << 8;
806
9.21k
   i = nblock-1;
807
27.3M
   for (; i >= 3; i -= 4) {
808
27.3M
      s = (s >> 8) | (block[i] << 8);
809
27.3M
      j = ftab[s] -1;
810
27.3M
      ftab[s] = j;
811
27.3M
      ptr[j] = i;
812
27.3M
      s = (s >> 8) | (block[i-1] << 8);
813
27.3M
      j = ftab[s] -1;
814
27.3M
      ftab[s] = j;
815
27.3M
      ptr[j] = i-1;
816
27.3M
      s = (s >> 8) | (block[i-2] << 8);
817
27.3M
      j = ftab[s] -1;
818
27.3M
      ftab[s] = j;
819
27.3M
      ptr[j] = i-2;
820
27.3M
      s = (s >> 8) | (block[i-3] << 8);
821
27.3M
      j = ftab[s] -1;
822
27.3M
      ftab[s] = j;
823
27.3M
      ptr[j] = i-3;
824
27.3M
   }
825
19.4k
   for (; i >= 0; i--) {
826
10.2k
      s = (s >> 8) | (block[i] << 8);
827
10.2k
      j = ftab[s] -1;
828
10.2k
      ftab[s] = j;
829
10.2k
      ptr[j] = i;
830
10.2k
   }
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.36M
   for (i = 0; i <= 255; i++) {
838
2.35M
      bigDone     [i] = False;
839
2.35M
      runningOrder[i] = i;
840
2.35M
   }
841
842
9.21k
   {
843
9.21k
      Int32 vv;
844
9.21k
      Int32 h = 1;
845
46.0k
      do h = 3 * h + 1; while (h <= 256);
846
46.0k
      do {
847
46.0k
         h = h / 3;
848
10.1M
         for (i = h; i <= 255; i++) {
849
10.1M
            vv = runningOrder[i];
850
10.1M
            j = i;
851
11.5M
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
852
1.56M
               runningOrder[j] = runningOrder[j-h];
853
1.56M
               j = j - h;
854
1.56M
               if (j <= (h - 1)) goto zero;
855
1.56M
            }
856
10.1M
            zero:
857
10.1M
            runningOrder[j] = vv;
858
10.1M
         }
859
46.0k
      } while (h != 1);
860
9.21k
   }
861
862
   /*--
863
      The main sorting loop.
864
   --*/
865
866
9.21k
   numQSorted = 0;
867
868
2.33M
   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.33M
      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
598M
      for (j = 0; j <= 255; j++) {
887
595M
         if (j != ss) {
888
593M
            sb = (ss << 8) + j;
889
593M
            if ( ! (ftab[sb] & SETMASK) ) {
890
300M
               Int32 lo = ftab[sb]   & CLEARMASK;
891
300M
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
892
300M
               if (hi > lo) {
893
499k
                  if (verb >= 4)
894
0
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
895
499k
                                "done %d   this %d\n",
896
499k
                                ss, j, numQSorted, hi - lo + 1 );
897
499k
                  mainQSort3 ( 
898
499k
                     ptr, block, quadrant, nblock, 
899
499k
                     lo, hi, BZ_N_RADIX, budget 
900
499k
                  );   
901
499k
                  numQSorted += (hi - lo + 1);
902
499k
                  if (*budget < 0) return;
903
499k
               }
904
300M
            }
905
593M
            ftab[sb] |= SETMASK;
906
593M
         }
907
595M
      }
908
909
2.32M
      AssertH ( !bigDone[ss], 1006 );
910
911
      /*--
912
         Step 2:
913
         Now scan this big bucket [ss] so as to synthesise the
914
         sorted order for small buckets [t, ss] for all t,
915
         including, magically, the bucket [ss,ss] too.
916
         This will avoid doing Real Work in subsequent Step 1's.
917
      --*/
918
2.32M
      {
919
597M
         for (j = 0; j <= 255; j++) {
920
595M
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
921
595M
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
922
595M
         }
923
14.5M
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
924
12.1M
            k = ptr[j]-1; if (k < 0) k += nblock;
925
12.1M
            c1 = block[k];
926
12.1M
            if (!bigDone[c1])
927
7.23M
               ptr[ copyStart[c1]++ ] = k;
928
12.1M
         }
929
17.0M
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
930
14.7M
            k = ptr[j]-1; if (k < 0) k += nblock;
931
14.7M
            c1 = block[k];
932
14.7M
            if (!bigDone[c1]) 
933
9.09M
               ptr[ copyEnd[c1]-- ] = k;
934
14.7M
         }
935
2.32M
      }
936
937
2.32M
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
938
2.32M
                || 
939
                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
940
                   Necessity for this case is demonstrated by compressing 
941
                   a sequence of approximately 48.5 million of character 
942
                   251; 1.0.0/1.0.1 will then die here. */
943
2.32M
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
944
2.32M
                1007 )
945
946
597M
      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.32M
      bigDone[ss] = True;
988
989
2.32M
      if (i < 255) {
990
2.32M
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
991
2.32M
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
992
2.32M
         Int32 shifts   = 0;
993
994
2.32M
         while ((bbSize >> shifts) > 65534) shifts++;
995
996
20.9M
         for (j = bbSize-1; j >= 0; j--) {
997
18.6M
            Int32 a2update     = ptr[bbStart + j];
998
18.6M
            UInt16 qVal        = (UInt16)(j >> shifts);
999
18.6M
            quadrant[a2update] = qVal;
1000
18.6M
            if (a2update < BZ_N_OVERSHOOT)
1001
55.6k
               quadrant[a2update + nblock] = qVal;
1002
18.6M
         }
1003
2.32M
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
1004
2.32M
      }
1005
1006
2.32M
   }
1007
1008
2.04k
   if (verb >= 4)
1009
0
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
1010
2.04k
                 nblock, numQSorted, nblock - numQSorted );
1011
2.04k
}
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
114k
{
1033
114k
   UInt32* ptr    = s->ptr; 
1034
114k
   UChar*  block  = s->block;
1035
114k
   UInt32* ftab   = s->ftab;
1036
114k
   Int32   nblock = s->nblock;
1037
114k
   Int32   verb   = s->verbosity;
1038
114k
   Int32   wfact  = s->workFactor;
1039
114k
   UInt16* quadrant;
1040
114k
   Int32   budget;
1041
114k
   Int32   budgetInit;
1042
114k
   Int32   i;
1043
1044
114k
   if (nblock < 10000) {
1045
105k
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1046
105k
   } 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.21k
      i = nblock+BZ_N_OVERSHOOT;
1053
9.21k
      if (i & 1) i++;
1054
9.21k
      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.21k
      if (wfact < 1  ) wfact = 1;
1064
9.21k
      if (wfact > 100) wfact = 100;
1065
9.21k
      budgetInit = nblock * ((wfact-1) / 3);
1066
9.21k
      budget = budgetInit;
1067
1068
9.21k
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
1069
9.21k
      if (verb >= 3) 
1070
0
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
1071
9.21k
                    budgetInit - budget,
1072
9.21k
                    nblock, 
1073
9.21k
                    (float)(budgetInit - budget) /
1074
9.21k
                    (float)(nblock==0 ? 1 : nblock) ); 
1075
9.21k
      if (budget < 0) {
1076
7.17k
         if (verb >= 2) 
1077
0
            VPrintf0 ( "    too repetitive; using fallback"
1078
7.17k
                       " sorting algorithm\n" );
1079
7.17k
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1080
7.17k
      }
1081
9.21k
   }
1082
1083
114k
   s->origPtr = -1;
1084
100M
   for (i = 0; i < s->nblock; i++)
1085
100M
      if (ptr[i] == 0)
1086
114k
         { s->origPtr = i; break; };
1087
1088
114k
   AssertH( s->origPtr != -1, 1003 );
1089
114k
}
1090
1091
1092
/*-------------------------------------------------------------*/
1093
/*--- end                                       blocksort.c ---*/
1094
/*-------------------------------------------------------------*/