Coverage Report

Created: 2026-05-24 07:45

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