Coverage Report

Created: 2026-04-01 07:49

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