Coverage Report

Created: 2025-11-16 07:22

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