Coverage Report

Created: 2026-01-10 06:47

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
284M
{
37
284M
   Int32 i, j, tmp;
38
284M
   UInt32 ec_tmp;
39
40
284M
   if (lo == hi) return;
41
42
278M
   if (hi - lo > 3) {
43
182M
      for ( i = hi-4; i >= lo; i-- ) {
44
137M
         tmp = fmap[i];
45
137M
         ec_tmp = eclass[tmp];
46
192M
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
47
54.9M
            fmap[j-4] = fmap[j];
48
137M
         fmap[j-4] = tmp;
49
137M
      }
50
44.5M
   }
51
52
854M
   for ( i = hi-1; i >= lo; i-- ) {
53
576M
      tmp = fmap[i];
54
576M
      ec_tmp = eclass[tmp];
55
834M
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
56
257M
         fmap[j-1] = fmap[j];
57
576M
      fmap[j-1] = tmp;
58
576M
   }
59
278M
}
60
61
62
/*---------------------------------------------*/
63
#define fswap(zz1, zz2) \
64
5.55G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
65
66
119M
#define fvswap(zzp1, zzp2, zzn)       \
67
119M
{                                     \
68
119M
   Int32 yyp1 = (zzp1);               \
69
119M
   Int32 yyp2 = (zzp2);               \
70
119M
   Int32 yyn  = (zzn);                \
71
871M
   while (yyn > 0) {                  \
72
752M
      fswap(fmap[yyp1], fmap[yyp2]);  \
73
752M
      yyp1++; yyp2++; yyn--;          \
74
752M
   }                                  \
75
119M
}
76
77
78
119M
#define fmin(a,b) ((a) < (b)) ? (a) : (b)
79
80
346M
#define fpush(lz,hz) { stackLo[sp] = lz; \
81
346M
                       stackHi[sp] = hz; \
82
346M
                       sp++; }
83
84
346M
#define fpop(lz,hz) { sp--;              \
85
346M
                      lz = stackLo[sp];  \
86
346M
                      hz = stackHi[sp]; }
87
88
346M
#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
226M
{
98
226M
   Int32 unLo, unHi, ltLo, gtHi, n, m;
99
226M
   Int32 sp, lo, hi;
100
226M
   UInt32 med, r, r3;
101
226M
   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
102
226M
   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
103
104
226M
   r = 0;
105
106
226M
   sp = 0;
107
226M
   fpush ( loSt, hiSt );
108
109
572M
   while (sp > 0) {
110
111
346M
      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
112
113
346M
      fpop ( lo, hi );
114
346M
      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
115
284M
         fallbackSimpleSort ( fmap, eclass, lo, hi );
116
284M
         continue;
117
284M
      }
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
61.6M
      r = ((r * 7621) + 1) % 32768;
127
61.6M
      r3 = r % 3;
128
61.6M
      if (r3 == 0) med = eclass[fmap[lo]]; else
129
48.6M
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
130
20.2M
                   med = eclass[fmap[hi]];
131
132
61.6M
      unLo = ltLo = lo;
133
61.6M
      unHi = gtHi = hi;
134
135
616M
      while (1) {
136
4.68G
         while (1) {
137
4.68G
            if (unLo > unHi) break;
138
4.65G
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
139
4.65G
            if (n == 0) { 
140
2.19G
               fswap(fmap[unLo], fmap[ltLo]); 
141
2.19G
               ltLo++; unLo++; 
142
2.19G
               continue; 
143
2.45G
            };
144
2.45G
            if (n > 0) break;
145
1.87G
            unLo++;
146
1.87G
         }
147
4.52G
         while (1) {
148
4.52G
            if (unLo > unHi) break;
149
4.45G
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
150
4.45G
            if (n == 0) { 
151
2.05G
               fswap(fmap[unHi], fmap[gtHi]); 
152
2.05G
               gtHi--; unHi--; 
153
2.05G
               continue; 
154
2.40G
            };
155
2.40G
            if (n < 0) break;
156
1.85G
            unHi--;
157
1.85G
         }
158
616M
         if (unLo > unHi) break;
159
555M
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
160
555M
      }
161
162
61.6M
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
163
164
61.6M
      if (gtHi < ltLo) continue;
165
166
59.5M
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
167
59.5M
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
168
169
59.5M
      n = lo + unLo - ltLo - 1;
170
59.5M
      m = hi - (gtHi - unHi) + 1;
171
172
59.5M
      if (n - lo > hi - m) {
173
27.0M
         fpush ( lo, n );
174
27.0M
         fpush ( m, hi );
175
32.4M
      } else {
176
32.4M
         fpush ( m, hi );
177
32.4M
         fpush ( lo, n );
178
32.4M
      }
179
59.5M
   }
180
226M
}
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
603M
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31))
206
273k
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31))
207
10.3G
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31)))
208
202M
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
209
1.15G
#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
8.56k
{
218
8.56k
   Int32 ftab[257];
219
8.56k
   Int32 ftabCopy[256];
220
8.56k
   Int32 H, i, j, k, l, r, cc, cc1;
221
8.56k
   Int32 nNotDone;
222
8.56k
   Int32 nBhtab;
223
8.56k
   UChar* eclass8 = (UChar*)eclass;
224
225
   /*--
226
      Initial 1-char radix sort to generate
227
      initial fmap and initial BH bits.
228
   --*/
229
8.56k
   if (verb >= 4)
230
0
      VPrintf0 ( "        bucket sorting ...\n" );
231
2.20M
   for (i = 0; i < 257;    i++) ftab[i] = 0;
232
376M
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
233
2.20M
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
234
2.20M
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
235
236
376M
   for (i = 0; i < nblock; i++) {
237
376M
      j = eclass8[i];
238
376M
      k = ftab[j] - 1;
239
376M
      ftab[j] = k;
240
376M
      fmap[k] = i;
241
376M
   }
242
243
8.56k
   nBhtab = 2 + (nblock / 32);
244
11.7M
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
245
2.20M
   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
282k
   for (i = 0; i < 32; i++) { 
255
273k
      SET_BH(nblock + 2*i);
256
273k
      CLEAR_BH(nblock + 2*i + 1);
257
273k
   }
258
259
   /*-- the log(N) loop --*/
260
8.56k
   H = 1;
261
73.6k
   while (1) {
262
263
73.6k
      if (verb >= 4) 
264
0
         VPrintf1 ( "        depth %6d has ", H );
265
266
73.6k
      j = 0;
267
6.47G
      for (i = 0; i < nblock; i++) {
268
6.47G
         if (ISSET_BH(i)) j = i;
269
6.47G
         k = fmap[i] - H; if (k < 0) k += nblock;
270
6.47G
         eclass[k] = j;
271
6.47G
      }
272
273
73.6k
      nNotDone = 0;
274
73.6k
      r = -1;
275
226M
      while (1) {
276
277
   /*-- find the next non-singleton bucket --*/
278
226M
         k = r + 1;
279
876M
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
280
226M
         if (ISSET_BH(k)) {
281
50.4M
            while (WORD_BH(k) == 0xffffffff) k += 32;
282
167M
            while (ISSET_BH(k)) k++;
283
24.9M
         }
284
226M
         l = k - 1;
285
226M
         if (l >= nblock) break;
286
688M
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
287
226M
         if (!ISSET_BH(k)) {
288
152M
            while (WORD_BH(k) == 0x00000000) k += 32;
289
134M
            while (!ISSET_BH(k)) k++;
290
18.1M
         }
291
226M
         r = k - 1;
292
226M
         if (r >= nblock) break;
293
294
         /*-- now [l, r] bracket current bucket --*/
295
226M
         if (r > l) {
296
226M
            nNotDone += (r - l + 1);
297
226M
            fallbackQSort3 ( fmap, eclass, l, r );
298
299
            /*-- scan bucket and generate header bits-- */
300
226M
            cc = -1;
301
5.32G
            for (i = l; i <= r; i++) {
302
5.09G
               cc1 = eclass[fmap[i]];
303
5.09G
               if (cc != cc1) { SET_BH(i); cc = cc1; };
304
5.09G
            }
305
226M
         }
306
226M
      }
307
308
73.6k
      if (verb >= 4) 
309
0
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
310
311
73.6k
      H *= 2;
312
73.6k
      if (H > nblock || nNotDone == 0) break;
313
73.6k
   }
314
315
   /*-- 
316
      Reconstruct the original block in
317
      eclass8 [0 .. nblock-1], since the
318
      previous phase destroyed it.
319
   --*/
320
8.56k
   if (verb >= 4)
321
0
      VPrintf0 ( "        reconstructing block ...\n" );
322
8.56k
   j = 0;
323
376M
   for (i = 0; i < nblock; i++) {
324
378M
      while (ftabCopy[j] == 0) j++;
325
376M
      ftabCopy[j]--;
326
376M
      eclass8[fmap[i]] = (UChar)j;
327
376M
   }
328
8.56k
   AssertH ( j < 256, 1005 );
329
8.56k
}
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
636M
{
354
636M
   Int32  k;
355
636M
   UChar  c1, c2;
356
636M
   UInt16 s1, s2;
357
358
636M
   AssertD ( i1 != i2, "mainGtU" );
359
   /* 1 */
360
636M
   c1 = block[i1]; c2 = block[i2];
361
636M
   if (c1 != c2) return (c1 > c2);
362
385M
   i1++; i2++;
363
   /* 2 */
364
385M
   c1 = block[i1]; c2 = block[i2];
365
385M
   if (c1 != c2) return (c1 > c2);
366
354M
   i1++; i2++;
367
   /* 3 */
368
354M
   c1 = block[i1]; c2 = block[i2];
369
354M
   if (c1 != c2) return (c1 > c2);
370
341M
   i1++; i2++;
371
   /* 4 */
372
341M
   c1 = block[i1]; c2 = block[i2];
373
341M
   if (c1 != c2) return (c1 > c2);
374
331M
   i1++; i2++;
375
   /* 5 */
376
331M
   c1 = block[i1]; c2 = block[i2];
377
331M
   if (c1 != c2) return (c1 > c2);
378
323M
   i1++; i2++;
379
   /* 6 */
380
323M
   c1 = block[i1]; c2 = block[i2];
381
323M
   if (c1 != c2) return (c1 > c2);
382
317M
   i1++; i2++;
383
   /* 7 */
384
317M
   c1 = block[i1]; c2 = block[i2];
385
317M
   if (c1 != c2) return (c1 > c2);
386
312M
   i1++; i2++;
387
   /* 8 */
388
312M
   c1 = block[i1]; c2 = block[i2];
389
312M
   if (c1 != c2) return (c1 > c2);
390
307M
   i1++; i2++;
391
   /* 9 */
392
307M
   c1 = block[i1]; c2 = block[i2];
393
307M
   if (c1 != c2) return (c1 > c2);
394
304M
   i1++; i2++;
395
   /* 10 */
396
304M
   c1 = block[i1]; c2 = block[i2];
397
304M
   if (c1 != c2) return (c1 > c2);
398
301M
   i1++; i2++;
399
   /* 11 */
400
301M
   c1 = block[i1]; c2 = block[i2];
401
301M
   if (c1 != c2) return (c1 > c2);
402
299M
   i1++; i2++;
403
   /* 12 */
404
299M
   c1 = block[i1]; c2 = block[i2];
405
299M
   if (c1 != c2) return (c1 > c2);
406
296M
   i1++; i2++;
407
408
296M
   k = nblock + 8;
409
410
6.44G
   do {
411
      /* 1 */
412
6.44G
      c1 = block[i1]; c2 = block[i2];
413
6.44G
      if (c1 != c2) return (c1 > c2);
414
6.43G
      s1 = quadrant[i1]; s2 = quadrant[i2];
415
6.43G
      if (s1 != s2) return (s1 > s2);
416
6.38G
      i1++; i2++;
417
      /* 2 */
418
6.38G
      c1 = block[i1]; c2 = block[i2];
419
6.38G
      if (c1 != c2) return (c1 > c2);
420
6.37G
      s1 = quadrant[i1]; s2 = quadrant[i2];
421
6.37G
      if (s1 != s2) return (s1 > s2);
422
6.33G
      i1++; i2++;
423
      /* 3 */
424
6.33G
      c1 = block[i1]; c2 = block[i2];
425
6.33G
      if (c1 != c2) return (c1 > c2);
426
6.32G
      s1 = quadrant[i1]; s2 = quadrant[i2];
427
6.32G
      if (s1 != s2) return (s1 > s2);
428
6.29G
      i1++; i2++;
429
      /* 4 */
430
6.29G
      c1 = block[i1]; c2 = block[i2];
431
6.29G
      if (c1 != c2) return (c1 > c2);
432
6.28G
      s1 = quadrant[i1]; s2 = quadrant[i2];
433
6.28G
      if (s1 != s2) return (s1 > s2);
434
6.25G
      i1++; i2++;
435
      /* 5 */
436
6.25G
      c1 = block[i1]; c2 = block[i2];
437
6.25G
      if (c1 != c2) return (c1 > c2);
438
6.24G
      s1 = quadrant[i1]; s2 = quadrant[i2];
439
6.24G
      if (s1 != s2) return (s1 > s2);
440
6.22G
      i1++; i2++;
441
      /* 6 */
442
6.22G
      c1 = block[i1]; c2 = block[i2];
443
6.22G
      if (c1 != c2) return (c1 > c2);
444
6.21G
      s1 = quadrant[i1]; s2 = quadrant[i2];
445
6.21G
      if (s1 != s2) return (s1 > s2);
446
6.19G
      i1++; i2++;
447
      /* 7 */
448
6.19G
      c1 = block[i1]; c2 = block[i2];
449
6.19G
      if (c1 != c2) return (c1 > c2);
450
6.18G
      s1 = quadrant[i1]; s2 = quadrant[i2];
451
6.18G
      if (s1 != s2) return (s1 > s2);
452
6.17G
      i1++; i2++;
453
      /* 8 */
454
6.17G
      c1 = block[i1]; c2 = block[i2];
455
6.17G
      if (c1 != c2) return (c1 > c2);
456
6.16G
      s1 = quadrant[i1]; s2 = quadrant[i2];
457
6.16G
      if (s1 != s2) return (s1 > s2);
458
6.15G
      i1++; i2++;
459
460
6.15G
      if (i1 >= nblock) i1 -= nblock;
461
6.15G
      if (i2 >= nblock) i2 -= nblock;
462
463
6.15G
      k -= 8;
464
6.15G
      (*budget)--;
465
6.15G
   }
466
6.15G
      while (k >= 0);
467
468
1.91k
   return False;
469
296M
}
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
25.4M
{
494
25.4M
   Int32 i, j, h, bigN, hp;
495
25.4M
   UInt32 v;
496
497
25.4M
   bigN = hi - lo + 1;
498
25.4M
   if (bigN < 2) return;
499
500
24.1M
   hp = 0;
501
61.2M
   while (incs[hp] < bigN) hp++;
502
24.1M
   hp--;
503
504
61.2M
   for (; hp >= 0; hp--) {
505
37.1M
      h = incs[hp];
506
507
37.1M
      i = lo + h;
508
136M
      while (True) {
509
510
         /*-- copy 1 --*/
511
136M
         if (i > hi) break;
512
126M
         v = ptr[i];
513
126M
         j = i;
514
220M
         while ( mainGtU ( 
515
220M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
516
220M
                 ) ) {
517
120M
            ptr[j] = ptr[j-h];
518
120M
            j = j - h;
519
120M
            if (j <= (lo + h - 1)) break;
520
120M
         }
521
126M
         ptr[j] = v;
522
126M
         i++;
523
524
         /*-- copy 2 --*/
525
126M
         if (i > hi) break;
526
110M
         v = ptr[i];
527
110M
         j = i;
528
212M
         while ( mainGtU ( 
529
212M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
530
212M
                 ) ) {
531
119M
            ptr[j] = ptr[j-h];
532
119M
            j = j - h;
533
119M
            if (j <= (lo + h - 1)) break;
534
119M
         }
535
110M
         ptr[j] = v;
536
110M
         i++;
537
538
         /*-- copy 3 --*/
539
110M
         if (i > hi) break;
540
99.0M
         v = ptr[i];
541
99.0M
         j = i;
542
203M
         while ( mainGtU ( 
543
203M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
544
203M
                 ) ) {
545
117M
            ptr[j] = ptr[j-h];
546
117M
            j = j - h;
547
117M
            if (j <= (lo + h - 1)) break;
548
117M
         }
549
99.0M
         ptr[j] = v;
550
99.0M
         i++;
551
552
99.0M
         if (*budget < 0) return;
553
99.0M
      }
554
37.1M
   }
555
24.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
986M
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
569
570
5.42M
#define mvswap(zzp1, zzp2, zzn)       \
571
5.42M
{                                     \
572
5.42M
   Int32 yyp1 = (zzp1);               \
573
5.42M
   Int32 yyp2 = (zzp2);               \
574
5.42M
   Int32 yyn  = (zzn);                \
575
54.5M
   while (yyn > 0) {                  \
576
49.1M
      mswap(ptr[yyp1], ptr[yyp2]);    \
577
49.1M
      yyp1++; yyp2++; yyn--;          \
578
49.1M
   }                                  \
579
5.42M
}
580
581
static 
582
__inline__
583
UChar mmed3 ( UChar a, UChar b, UChar c )
584
3.92M
{
585
3.92M
   UChar t;
586
3.92M
   if (a > b) { t = a; a = b; b = t; };
587
3.92M
   if (b > c) { 
588
1.42M
      b = c;
589
1.42M
      if (a > b) b = a;
590
1.42M
   }
591
3.92M
   return b;
592
3.92M
}
593
594
5.42M
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
595
596
29.3M
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
597
29.3M
                          stackHi[sp] = hz; \
598
29.3M
                          stackD [sp] = dz; \
599
29.3M
                          sp++; }
600
601
29.3M
#define mpop(lz,hz,dz) { sp--;             \
602
29.3M
                         lz = stackLo[sp]; \
603
29.3M
                         hz = stackHi[sp]; \
604
29.3M
                         dz = stackD [sp]; }
605
606
607
16.2M
#define mnextsize(az) (nextHi[az]-nextLo[az])
608
609
#define mnextswap(az,bz)                                        \
610
3.14M
   { Int32 tz;                                                  \
611
3.14M
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
612
3.14M
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
613
3.14M
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
614
615
616
58.6M
#define MAIN_QSORT_SMALL_THRESH 20
617
4.04M
#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
19.9M
{
630
19.9M
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
631
19.9M
   Int32 sp, lo, hi, d;
632
633
19.9M
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
634
19.9M
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
635
19.9M
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
636
637
19.9M
   Int32 nextLo[3];
638
19.9M
   Int32 nextHi[3];
639
19.9M
   Int32 nextD [3];
640
641
19.9M
   sp = 0;
642
19.9M
   mpush ( loSt, hiSt, dSt );
643
644
49.3M
   while (sp > 0) {
645
646
29.3M
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
647
648
29.3M
      mpop ( lo, hi, d );
649
29.3M
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
650
25.4M
          d > MAIN_QSORT_DEPTH_THRESH) {
651
25.4M
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
652
25.4M
         if (*budget < 0) return;
653
25.4M
         continue;
654
25.4M
      }
655
656
3.92M
      med = (Int32) 
657
3.92M
            mmed3 ( block[ptr[ lo         ]+d],
658
3.92M
                    block[ptr[ hi         ]+d],
659
3.92M
                    block[ptr[ (lo+hi)>>1 ]+d] );
660
661
3.92M
      unLo = ltLo = lo;
662
3.92M
      unHi = gtHi = hi;
663
664
29.1M
      while (True) {
665
699M
         while (True) {
666
699M
            if (unLo > unHi) break;
667
697M
            n = ((Int32)block[ptr[unLo]+d]) - med;
668
697M
            if (n == 0) { 
669
601M
               mswap(ptr[unLo], ptr[ltLo]); 
670
601M
               ltLo++; unLo++; continue; 
671
601M
            };
672
96.0M
            if (n >  0) break;
673
69.4M
            unLo++;
674
69.4M
         }
675
405M
         while (True) {
676
405M
            if (unLo > unHi) break;
677
401M
            n = ((Int32)block[ptr[unHi]+d]) - med;
678
401M
            if (n == 0) { 
679
311M
               mswap(ptr[unHi], ptr[gtHi]); 
680
311M
               gtHi--; unHi--; continue; 
681
311M
            };
682
90.8M
            if (n <  0) break;
683
65.6M
            unHi--;
684
65.6M
         }
685
29.1M
         if (unLo > unHi) break;
686
25.1M
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
687
25.1M
      }
688
689
3.92M
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
690
691
3.92M
      if (gtHi < ltLo) {
692
1.20M
         mpush(lo, hi, d+1 );
693
1.20M
         continue;
694
1.20M
      }
695
696
2.71M
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
697
2.71M
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
698
699
2.71M
      n = lo + unLo - ltLo - 1;
700
2.71M
      m = hi - (gtHi - unHi) + 1;
701
702
2.71M
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
703
2.71M
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
704
2.71M
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
705
706
2.71M
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
707
2.71M
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
708
2.71M
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
709
710
2.71M
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
711
2.71M
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
712
713
2.71M
      mpush (nextLo[0], nextHi[0], nextD[0]);
714
2.71M
      mpush (nextLo[1], nextHi[1], nextD[1]);
715
2.71M
      mpush (nextLo[2], nextHi[2], nextD[2]);
716
2.71M
   }
717
19.9M
}
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
15.6M
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
747
1.85G
#define SETMASK (1 << 21)
748
931M
#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
4.81k
{
759
4.81k
   Int32  i, j, k, ss, sb;
760
4.81k
   Int32  runningOrder[256];
761
4.81k
   Bool   bigDone[256];
762
4.81k
   Int32  copyStart[256];
763
4.81k
   Int32  copyEnd  [256];
764
4.81k
   UChar  c1;
765
4.81k
   Int32  numQSorted;
766
4.81k
   UInt16 s;
767
4.81k
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
768
769
   /*-- set up the 2-byte frequency table --*/
770
315M
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
771
772
4.81k
   j = block[0] << 8;
773
4.81k
   i = nblock-1;
774
183M
   for (; i >= 3; i -= 4) {
775
183M
      quadrant[i] = 0;
776
183M
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
777
183M
      ftab[j]++;
778
183M
      quadrant[i-1] = 0;
779
183M
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
780
183M
      ftab[j]++;
781
183M
      quadrant[i-2] = 0;
782
183M
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
783
183M
      ftab[j]++;
784
183M
      quadrant[i-3] = 0;
785
183M
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
786
183M
      ftab[j]++;
787
183M
   }
788
10.1k
   for (; i >= 0; i--) {
789
5.37k
      quadrant[i] = 0;
790
5.37k
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
791
5.37k
      ftab[j]++;
792
5.37k
   }
793
794
   /*-- (emphasises close relationship of block & quadrant) --*/
795
168k
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
796
163k
      block   [nblock+i] = block[i];
797
163k
      quadrant[nblock+i] = 0;
798
163k
   }
799
800
4.81k
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
801
802
   /*-- Complete the initial radix sort --*/
803
315M
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
804
805
4.81k
   s = block[0] << 8;
806
4.81k
   i = nblock-1;
807
183M
   for (; i >= 3; i -= 4) {
808
183M
      s = (s >> 8) | (block[i] << 8);
809
183M
      j = ftab[s] -1;
810
183M
      ftab[s] = j;
811
183M
      ptr[j] = i;
812
183M
      s = (s >> 8) | (block[i-1] << 8);
813
183M
      j = ftab[s] -1;
814
183M
      ftab[s] = j;
815
183M
      ptr[j] = i-1;
816
183M
      s = (s >> 8) | (block[i-2] << 8);
817
183M
      j = ftab[s] -1;
818
183M
      ftab[s] = j;
819
183M
      ptr[j] = i-2;
820
183M
      s = (s >> 8) | (block[i-3] << 8);
821
183M
      j = ftab[s] -1;
822
183M
      ftab[s] = j;
823
183M
      ptr[j] = i-3;
824
183M
   }
825
10.1k
   for (; i >= 0; i--) {
826
5.37k
      s = (s >> 8) | (block[i] << 8);
827
5.37k
      j = ftab[s] -1;
828
5.37k
      ftab[s] = j;
829
5.37k
      ptr[j] = i;
830
5.37k
   }
831
832
   /*--
833
      Now ftab contains the first loc of every small bucket.
834
      Calculate the running order, from smallest to largest
835
      big bucket.
836
   --*/
837
1.23M
   for (i = 0; i <= 255; i++) {
838
1.23M
      bigDone     [i] = False;
839
1.23M
      runningOrder[i] = i;
840
1.23M
   }
841
842
4.81k
   {
843
4.81k
      Int32 vv;
844
4.81k
      Int32 h = 1;
845
24.0k
      do h = 3 * h + 1; while (h <= 256);
846
24.0k
      do {
847
24.0k
         h = h / 3;
848
5.32M
         for (i = h; i <= 255; i++) {
849
5.30M
            vv = runningOrder[i];
850
5.30M
            j = i;
851
7.83M
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
852
2.81M
               runningOrder[j] = runningOrder[j-h];
853
2.81M
               j = j - h;
854
2.81M
               if (j <= (h - 1)) goto zero;
855
2.81M
            }
856
5.30M
            zero:
857
5.30M
            runningOrder[j] = vv;
858
5.30M
         }
859
24.0k
      } while (h != 1);
860
4.81k
   }
861
862
   /*--
863
      The main sorting loop.
864
   --*/
865
866
4.81k
   numQSorted = 0;
867
868
1.21M
   for (i = 0; i <= 255; i++) {
869
870
      /*--
871
         Process big buckets, starting with the least full.
872
         Basically this is a 3-step process in which we call
873
         mainQSort3 to sort the small buckets [ss, j], but
874
         also make a big effort to avoid the calls if we can.
875
      --*/
876
1.20M
      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
309M
      for (j = 0; j <= 255; j++) {
887
308M
         if (j != ss) {
888
307M
            sb = (ss << 8) + j;
889
307M
            if ( ! (ftab[sb] & SETMASK) ) {
890
154M
               Int32 lo = ftab[sb]   & CLEARMASK;
891
154M
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
892
154M
               if (hi > lo) {
893
19.9M
                  if (verb >= 4)
894
0
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
895
19.9M
                                "done %d   this %d\n",
896
19.9M
                                ss, j, numQSorted, hi - lo + 1 );
897
19.9M
                  mainQSort3 ( 
898
19.9M
                     ptr, block, quadrant, nblock, 
899
19.9M
                     lo, hi, BZ_N_RADIX, budget 
900
19.9M
                  );   
901
19.9M
                  numQSorted += (hi - lo + 1);
902
19.9M
                  if (*budget < 0) return;
903
19.9M
               }
904
154M
            }
905
307M
            ftab[sb] |= SETMASK;
906
307M
         }
907
308M
      }
908
909
1.20M
      AssertH ( !bigDone[ss], 1006 );
910
911
      /*--
912
         Step 2:
913
         Now scan this big bucket [ss] so as to synthesise the
914
         sorted order for small buckets [t, ss] for all t,
915
         including, magically, the bucket [ss,ss] too.
916
         This will avoid doing Real Work in subsequent Step 1's.
917
      --*/
918
1.20M
      {
919
309M
         for (j = 0; j <= 255; j++) {
920
308M
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
921
308M
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
922
308M
         }
923
182M
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
924
180M
            k = ptr[j]-1; if (k < 0) k += nblock;
925
180M
            c1 = block[k];
926
180M
            if (!bigDone[c1])
927
104M
               ptr[ copyStart[c1]++ ] = k;
928
180M
         }
929
205M
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
930
204M
            k = ptr[j]-1; if (k < 0) k += nblock;
931
204M
            c1 = block[k];
932
204M
            if (!bigDone[c1]) 
933
108M
               ptr[ copyEnd[c1]-- ] = k;
934
204M
         }
935
1.20M
      }
936
937
1.20M
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
938
1.20M
                || 
939
                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
940
                   Necessity for this case is demonstrated by compressing 
941
                   a sequence of approximately 48.5 million of character 
942
                   251; 1.0.0/1.0.1 will then die here. */
943
1.20M
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
944
1.20M
                1007 )
945
946
309M
      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
947
948
      /*--
949
         Step 3:
950
         The [ss] big bucket is now done.  Record this fact,
951
         and update the quadrant descriptors.  Remember to
952
         update quadrants in the overshoot area too, if
953
         necessary.  The "if (i < 255)" test merely skips
954
         this updating for the last bucket processed, since
955
         updating for the last bucket is pointless.
956
957
         The quadrant array provides a way to incrementally
958
         cache sort orderings, as they appear, so as to 
959
         make subsequent comparisons in fullGtU() complete
960
         faster.  For repetitive blocks this makes a big
961
         difference (but not big enough to be able to avoid
962
         the fallback sorting mechanism, exponential radix sort).
963
964
         The precise meaning is: at all times:
965
966
            for 0 <= i < nblock and 0 <= j <= nblock
967
968
            if block[i] != block[j], 
969
970
               then the relative values of quadrant[i] and 
971
                    quadrant[j] are meaningless.
972
973
               else {
974
                  if quadrant[i] < quadrant[j]
975
                     then the string starting at i lexicographically
976
                     precedes the string starting at j
977
978
                  else if quadrant[i] > quadrant[j]
979
                     then the string starting at j lexicographically
980
                     precedes the string starting at i
981
982
                  else
983
                     the relative ordering of the strings starting
984
                     at i and j has not yet been determined.
985
               }
986
      --*/
987
1.20M
      bigDone[ss] = True;
988
989
1.20M
      if (i < 255) {
990
1.20M
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
991
1.20M
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
992
1.20M
         Int32 shifts   = 0;
993
994
1.20M
         while ((bbSize >> shifts) > 65534) shifts++;
995
996
342M
         for (j = bbSize-1; j >= 0; j--) {
997
341M
            Int32 a2update     = ptr[bbStart + j];
998
341M
            UInt16 qVal        = (UInt16)(j >> shifts);
999
341M
            quadrant[a2update] = qVal;
1000
341M
            if (a2update < BZ_N_OVERSHOOT)
1001
72.9k
               quadrant[a2update + nblock] = qVal;
1002
341M
         }
1003
1.20M
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
1004
1.20M
      }
1005
1006
1.20M
   }
1007
1008
2.21k
   if (verb >= 4)
1009
0
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
1010
2.21k
                 nblock, numQSorted, nblock - numQSorted );
1011
2.21k
}
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
10.7k
{
1033
10.7k
   UInt32* ptr    = s->ptr; 
1034
10.7k
   UChar*  block  = s->block;
1035
10.7k
   UInt32* ftab   = s->ftab;
1036
10.7k
   Int32   nblock = s->nblock;
1037
10.7k
   Int32   verb   = s->verbosity;
1038
10.7k
   Int32   wfact  = s->workFactor;
1039
10.7k
   UInt16* quadrant;
1040
10.7k
   Int32   budget;
1041
10.7k
   Int32   budgetInit;
1042
10.7k
   Int32   i;
1043
1044
10.7k
   if (nblock < 10000) {
1045
5.96k
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1046
5.96k
   } 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
4.81k
      i = nblock+BZ_N_OVERSHOOT;
1053
4.81k
      if (i & 1) i++;
1054
4.81k
      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
4.81k
      if (wfact < 1  ) wfact = 1;
1064
4.81k
      if (wfact > 100) wfact = 100;
1065
4.81k
      budgetInit = nblock * ((wfact-1) / 3);
1066
4.81k
      budget = budgetInit;
1067
1068
4.81k
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
1069
4.81k
      if (verb >= 3) 
1070
0
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
1071
4.81k
                    budgetInit - budget,
1072
4.81k
                    nblock, 
1073
4.81k
                    (float)(budgetInit - budget) /
1074
4.81k
                    (float)(nblock==0 ? 1 : nblock) ); 
1075
4.81k
      if (budget < 0) {
1076
2.60k
         if (verb >= 2) 
1077
0
            VPrintf0 ( "    too repetitive; using fallback"
1078
2.60k
                       " sorting algorithm\n" );
1079
2.60k
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1080
2.60k
      }
1081
4.81k
   }
1082
1083
10.7k
   s->origPtr = -1;
1084
408M
   for (i = 0; i < s->nblock; i++)
1085
408M
      if (ptr[i] == 0)
1086
10.7k
         { s->origPtr = i; break; };
1087
1088
10.7k
   AssertH( s->origPtr != -1, 1003 );
1089
10.7k
}
1090
1091
1092
/*-------------------------------------------------------------*/
1093
/*--- end                                       blocksort.c ---*/
1094
/*-------------------------------------------------------------*/