Coverage Report

Created: 2025-11-24 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bzip2/blocksort.c
Line
Count
Source
1
2
/*-------------------------------------------------------------*/
3
/*--- Block sorting machinery                               ---*/
4
/*---                                           blocksort.c ---*/
5
/*-------------------------------------------------------------*/
6
7
/* ------------------------------------------------------------------
8
   This file is part of bzip2/libbzip2, a program and library for
9
   lossless, block-sorting data compression.
10
11
   bzip2/libbzip2 version 1.0.8 of 13 July 2019
12
   Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
13
14
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
15
   README file.
16
17
   This program is released under the terms of the license contained
18
   in the file LICENSE.
19
   ------------------------------------------------------------------ */
20
21
22
#include "bzlib_private.h"
23
24
/*---------------------------------------------*/
25
/*--- Fallback O(N log(N)^2) sorting        ---*/
26
/*--- algorithm, for repetitive blocks      ---*/
27
/*---------------------------------------------*/
28
29
/*---------------------------------------------*/
30
static 
31
__inline__
32
void fallbackSimpleSort ( UInt32* fmap, 
33
                          UInt32* eclass, 
34
                          Int32   lo, 
35
                          Int32   hi )
36
92.2M
{
37
92.2M
   Int32 i, j, tmp;
38
92.2M
   UInt32 ec_tmp;
39
40
92.2M
   if (lo == hi) return;
41
42
90.5M
   if (hi - lo > 3) {
43
54.0M
      for ( i = hi-4; i >= lo; i-- ) {
44
40.7M
         tmp = fmap[i];
45
40.7M
         ec_tmp = eclass[tmp];
46
56.8M
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
47
16.0M
            fmap[j-4] = fmap[j];
48
40.7M
         fmap[j-4] = tmp;
49
40.7M
      }
50
13.3M
   }
51
52
273M
   for ( i = hi-1; i >= lo; i-- ) {
53
182M
      tmp = fmap[i];
54
182M
      ec_tmp = eclass[tmp];
55
258M
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
56
76.2M
         fmap[j-1] = fmap[j];
57
182M
      fmap[j-1] = tmp;
58
182M
   }
59
90.5M
}
60
61
62
/*---------------------------------------------*/
63
#define fswap(zz1, zz2) \
64
1.70G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
65
66
34.7M
#define fvswap(zzp1, zzp2, zzn)       \
67
34.7M
{                                     \
68
34.7M
   Int32 yyp1 = (zzp1);               \
69
34.7M
   Int32 yyp2 = (zzp2);               \
70
34.7M
   Int32 yyn  = (zzn);                \
71
260M
   while (yyn > 0) {                  \
72
225M
      fswap(fmap[yyp1], fmap[yyp2]);  \
73
225M
      yyp1++; yyp2++; yyn--;          \
74
225M
   }                                  \
75
34.7M
}
76
77
78
34.7M
#define fmin(a,b) ((a) < (b)) ? (a) : (b)
79
80
110M
#define fpush(lz,hz) { stackLo[sp] = lz; \
81
110M
                       stackHi[sp] = hz; \
82
110M
                       sp++; }
83
84
110M
#define fpop(lz,hz) { sp--;              \
85
110M
                      lz = stackLo[sp];  \
86
110M
                      hz = stackHi[sp]; }
87
88
110M
#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
75.4M
{
98
75.4M
   Int32 unLo, unHi, ltLo, gtHi, n, m;
99
75.4M
   Int32 sp, lo, hi;
100
75.4M
   UInt32 med, r, r3;
101
75.4M
   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
102
75.4M
   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
103
104
75.4M
   r = 0;
105
106
75.4M
   sp = 0;
107
75.4M
   fpush ( loSt, hiSt );
108
109
185M
   while (sp > 0) {
110
111
110M
      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
112
113
110M
      fpop ( lo, hi );
114
110M
      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
115
92.2M
         fallbackSimpleSort ( fmap, eclass, lo, hi );
116
92.2M
         continue;
117
92.2M
      }
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
17.9M
      r = ((r * 7621) + 1) % 32768;
127
17.9M
      r3 = r % 3;
128
17.9M
      if (r3 == 0) med = eclass[fmap[lo]]; else
129
14.2M
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
130
6.08M
                   med = eclass[fmap[hi]];
131
132
17.9M
      unLo = ltLo = lo;
133
17.9M
      unHi = gtHi = hi;
134
135
187M
      while (1) {
136
1.47G
         while (1) {
137
1.47G
            if (unLo > unHi) break;
138
1.46G
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
139
1.46G
            if (n == 0) { 
140
713M
               fswap(fmap[unLo], fmap[ltLo]); 
141
713M
               ltLo++; unLo++; 
142
713M
               continue; 
143
752M
            };
144
752M
            if (n > 0) break;
145
573M
            unLo++;
146
573M
         }
147
1.35G
         while (1) {
148
1.35G
            if (unLo > unHi) break;
149
1.33G
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
150
1.33G
            if (n == 0) { 
151
596M
               fswap(fmap[unHi], fmap[gtHi]); 
152
596M
               gtHi--; unHi--; 
153
596M
               continue; 
154
736M
            };
155
736M
            if (n < 0) break;
156
567M
            unHi--;
157
567M
         }
158
187M
         if (unLo > unHi) break;
159
169M
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
160
169M
      }
161
162
17.9M
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
163
164
17.9M
      if (gtHi < ltLo) continue;
165
166
17.3M
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
167
17.3M
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
168
169
17.3M
      n = lo + unLo - ltLo - 1;
170
17.3M
      m = hi - (gtHi - unHi) + 1;
171
172
17.3M
      if (n - lo > hi - m) {
173
7.88M
         fpush ( lo, n );
174
7.88M
         fpush ( m, hi );
175
9.49M
      } else {
176
9.49M
         fpush ( m, hi );
177
9.49M
         fpush ( lo, n );
178
9.49M
      }
179
17.3M
   }
180
75.4M
}
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
186M
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31))
206
74.7k
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31))
207
3.22G
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31)))
208
61.9M
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
209
364M
#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
2.33k
{
218
2.33k
   Int32 ftab[257];
219
2.33k
   Int32 ftabCopy[256];
220
2.33k
   Int32 H, i, j, k, l, r, cc, cc1;
221
2.33k
   Int32 nNotDone;
222
2.33k
   Int32 nBhtab;
223
2.33k
   UChar* eclass8 = (UChar*)eclass;
224
225
   /*--
226
      Initial 1-char radix sort to generate
227
      initial fmap and initial BH bits.
228
   --*/
229
2.33k
   if (verb >= 4)
230
0
      VPrintf0 ( "        bucket sorting ...\n" );
231
602k
   for (i = 0; i < 257;    i++) ftab[i] = 0;
232
111M
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
233
600k
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
234
600k
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
235
236
111M
   for (i = 0; i < nblock; i++) {
237
111M
      j = eclass8[i];
238
111M
      k = ftab[j] - 1;
239
111M
      ftab[j] = k;
240
111M
      fmap[k] = i;
241
111M
   }
242
243
2.33k
   nBhtab = 2 + (nblock / 32);
244
3.47M
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
245
600k
   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
77.1k
   for (i = 0; i < 32; i++) { 
255
74.7k
      SET_BH(nblock + 2*i);
256
74.7k
      CLEAR_BH(nblock + 2*i + 1);
257
74.7k
   }
258
259
   /*-- the log(N) loop --*/
260
2.33k
   H = 1;
261
20.0k
   while (1) {
262
263
20.0k
      if (verb >= 4) 
264
0
         VPrintf1 ( "        depth %6d has ", H );
265
266
20.0k
      j = 0;
267
1.97G
      for (i = 0; i < nblock; i++) {
268
1.97G
         if (ISSET_BH(i)) j = i;
269
1.97G
         k = fmap[i] - H; if (k < 0) k += nblock;
270
1.97G
         eclass[k] = j;
271
1.97G
      }
272
273
20.0k
      nNotDone = 0;
274
20.0k
      r = -1;
275
75.4M
      while (1) {
276
277
   /*-- find the next non-singleton bucket --*/
278
75.4M
         k = r + 1;
279
279M
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
280
75.4M
         if (ISSET_BH(k)) {
281
14.8M
            while (WORD_BH(k) == 0xffffffff) k += 32;
282
49.9M
            while (ISSET_BH(k)) k++;
283
7.76M
         }
284
75.4M
         l = k - 1;
285
75.4M
         if (l >= nblock) break;
286
222M
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
287
75.4M
         if (!ISSET_BH(k)) {
288
47.0M
            while (WORD_BH(k) == 0x00000000) k += 32;
289
39.2M
            while (!ISSET_BH(k)) k++;
290
5.66M
         }
291
75.4M
         r = k - 1;
292
75.4M
         if (r >= nblock) break;
293
294
         /*-- now [l, r] bracket current bucket --*/
295
75.4M
         if (r > l) {
296
75.4M
            nNotDone += (r - l + 1);
297
75.4M
            fallbackQSort3 ( fmap, eclass, l, r );
298
299
            /*-- scan bucket and generate header bits-- */
300
75.4M
            cc = -1;
301
1.65G
            for (i = l; i <= r; i++) {
302
1.57G
               cc1 = eclass[fmap[i]];
303
1.57G
               if (cc != cc1) { SET_BH(i); cc = cc1; };
304
1.57G
            }
305
75.4M
         }
306
75.4M
      }
307
308
20.0k
      if (verb >= 4) 
309
0
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
310
311
20.0k
      H *= 2;
312
20.0k
      if (H > nblock || nNotDone == 0) break;
313
20.0k
   }
314
315
   /*-- 
316
      Reconstruct the original block in
317
      eclass8 [0 .. nblock-1], since the
318
      previous phase destroyed it.
319
   --*/
320
2.33k
   if (verb >= 4)
321
0
      VPrintf0 ( "        reconstructing block ...\n" );
322
2.33k
   j = 0;
323
111M
   for (i = 0; i < nblock; i++) {
324
111M
      while (ftabCopy[j] == 0) j++;
325
111M
      ftabCopy[j]--;
326
111M
      eclass8[fmap[i]] = (UChar)j;
327
111M
   }
328
2.33k
   AssertH ( j < 256, 1005 );
329
2.33k
}
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
165M
{
354
165M
   Int32  k;
355
165M
   UChar  c1, c2;
356
165M
   UInt16 s1, s2;
357
358
165M
   AssertD ( i1 != i2, "mainGtU" );
359
   /* 1 */
360
165M
   c1 = block[i1]; c2 = block[i2];
361
165M
   if (c1 != c2) return (c1 > c2);
362
88.1M
   i1++; i2++;
363
   /* 2 */
364
88.1M
   c1 = block[i1]; c2 = block[i2];
365
88.1M
   if (c1 != c2) return (c1 > c2);
366
76.8M
   i1++; i2++;
367
   /* 3 */
368
76.8M
   c1 = block[i1]; c2 = block[i2];
369
76.8M
   if (c1 != c2) return (c1 > c2);
370
72.1M
   i1++; i2++;
371
   /* 4 */
372
72.1M
   c1 = block[i1]; c2 = block[i2];
373
72.1M
   if (c1 != c2) return (c1 > c2);
374
69.5M
   i1++; i2++;
375
   /* 5 */
376
69.5M
   c1 = block[i1]; c2 = block[i2];
377
69.5M
   if (c1 != c2) return (c1 > c2);
378
67.8M
   i1++; i2++;
379
   /* 6 */
380
67.8M
   c1 = block[i1]; c2 = block[i2];
381
67.8M
   if (c1 != c2) return (c1 > c2);
382
66.5M
   i1++; i2++;
383
   /* 7 */
384
66.5M
   c1 = block[i1]; c2 = block[i2];
385
66.5M
   if (c1 != c2) return (c1 > c2);
386
65.5M
   i1++; i2++;
387
   /* 8 */
388
65.5M
   c1 = block[i1]; c2 = block[i2];
389
65.5M
   if (c1 != c2) return (c1 > c2);
390
64.5M
   i1++; i2++;
391
   /* 9 */
392
64.5M
   c1 = block[i1]; c2 = block[i2];
393
64.5M
   if (c1 != c2) return (c1 > c2);
394
63.7M
   i1++; i2++;
395
   /* 10 */
396
63.7M
   c1 = block[i1]; c2 = block[i2];
397
63.7M
   if (c1 != c2) return (c1 > c2);
398
63.0M
   i1++; i2++;
399
   /* 11 */
400
63.0M
   c1 = block[i1]; c2 = block[i2];
401
63.0M
   if (c1 != c2) return (c1 > c2);
402
62.4M
   i1++; i2++;
403
   /* 12 */
404
62.4M
   c1 = block[i1]; c2 = block[i2];
405
62.4M
   if (c1 != c2) return (c1 > c2);
406
61.9M
   i1++; i2++;
407
408
61.9M
   k = nblock + 8;
409
410
1.19G
   do {
411
      /* 1 */
412
1.19G
      c1 = block[i1]; c2 = block[i2];
413
1.19G
      if (c1 != c2) return (c1 > c2);
414
1.19G
      s1 = quadrant[i1]; s2 = quadrant[i2];
415
1.19G
      if (s1 != s2) return (s1 > s2);
416
1.18G
      i1++; i2++;
417
      /* 2 */
418
1.18G
      c1 = block[i1]; c2 = block[i2];
419
1.18G
      if (c1 != c2) return (c1 > c2);
420
1.17G
      s1 = quadrant[i1]; s2 = quadrant[i2];
421
1.17G
      if (s1 != s2) return (s1 > s2);
422
1.16G
      i1++; i2++;
423
      /* 3 */
424
1.16G
      c1 = block[i1]; c2 = block[i2];
425
1.16G
      if (c1 != c2) return (c1 > c2);
426
1.16G
      s1 = quadrant[i1]; s2 = quadrant[i2];
427
1.16G
      if (s1 != s2) return (s1 > s2);
428
1.16G
      i1++; i2++;
429
      /* 4 */
430
1.16G
      c1 = block[i1]; c2 = block[i2];
431
1.16G
      if (c1 != c2) return (c1 > c2);
432
1.15G
      s1 = quadrant[i1]; s2 = quadrant[i2];
433
1.15G
      if (s1 != s2) return (s1 > s2);
434
1.15G
      i1++; i2++;
435
      /* 5 */
436
1.15G
      c1 = block[i1]; c2 = block[i2];
437
1.15G
      if (c1 != c2) return (c1 > c2);
438
1.15G
      s1 = quadrant[i1]; s2 = quadrant[i2];
439
1.15G
      if (s1 != s2) return (s1 > s2);
440
1.14G
      i1++; i2++;
441
      /* 6 */
442
1.14G
      c1 = block[i1]; c2 = block[i2];
443
1.14G
      if (c1 != c2) return (c1 > c2);
444
1.14G
      s1 = quadrant[i1]; s2 = quadrant[i2];
445
1.14G
      if (s1 != s2) return (s1 > s2);
446
1.14G
      i1++; i2++;
447
      /* 7 */
448
1.14G
      c1 = block[i1]; c2 = block[i2];
449
1.14G
      if (c1 != c2) return (c1 > c2);
450
1.14G
      s1 = quadrant[i1]; s2 = quadrant[i2];
451
1.14G
      if (s1 != s2) return (s1 > s2);
452
1.13G
      i1++; i2++;
453
      /* 8 */
454
1.13G
      c1 = block[i1]; c2 = block[i2];
455
1.13G
      if (c1 != c2) return (c1 > c2);
456
1.13G
      s1 = quadrant[i1]; s2 = quadrant[i2];
457
1.13G
      if (s1 != s2) return (s1 > s2);
458
1.13G
      i1++; i2++;
459
460
1.13G
      if (i1 >= nblock) i1 -= nblock;
461
1.13G
      if (i2 >= nblock) i2 -= nblock;
462
463
1.13G
      k -= 8;
464
1.13G
      (*budget)--;
465
1.13G
   }
466
1.13G
      while (k >= 0);
467
468
481
   return False;
469
61.9M
}
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
5.35M
{
494
5.35M
   Int32 i, j, h, bigN, hp;
495
5.35M
   UInt32 v;
496
497
5.35M
   bigN = hi - lo + 1;
498
5.35M
   if (bigN < 2) return;
499
500
4.97M
   hp = 0;
501
13.9M
   while (incs[hp] < bigN) hp++;
502
4.97M
   hp--;
503
504
13.9M
   for (; hp >= 0; hp--) {
505
8.98M
      h = incs[hp];
506
507
8.98M
      i = lo + h;
508
35.1M
      while (True) {
509
510
         /*-- copy 1 --*/
511
35.1M
         if (i > hi) break;
512
32.5M
         v = ptr[i];
513
32.5M
         j = i;
514
56.8M
         while ( mainGtU ( 
515
56.8M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
516
56.8M
                 ) ) {
517
31.1M
            ptr[j] = ptr[j-h];
518
31.1M
            j = j - h;
519
31.1M
            if (j <= (lo + h - 1)) break;
520
31.1M
         }
521
32.5M
         ptr[j] = v;
522
32.5M
         i++;
523
524
         /*-- copy 2 --*/
525
32.5M
         if (i > hi) break;
526
28.8M
         v = ptr[i];
527
28.8M
         j = i;
528
55.1M
         while ( mainGtU ( 
529
55.1M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
530
55.1M
                 ) ) {
531
31.0M
            ptr[j] = ptr[j-h];
532
31.0M
            j = j - h;
533
31.0M
            if (j <= (lo + h - 1)) break;
534
31.0M
         }
535
28.8M
         ptr[j] = v;
536
28.8M
         i++;
537
538
         /*-- copy 3 --*/
539
28.8M
         if (i > hi) break;
540
26.1M
         v = ptr[i];
541
26.1M
         j = i;
542
53.3M
         while ( mainGtU ( 
543
53.3M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
544
53.3M
                 ) ) {
545
31.0M
            ptr[j] = ptr[j-h];
546
31.0M
            j = j - h;
547
31.0M
            if (j <= (lo + h - 1)) break;
548
31.0M
         }
549
26.1M
         ptr[j] = v;
550
26.1M
         i++;
551
552
26.1M
         if (*budget < 0) return;
553
26.1M
      }
554
8.98M
   }
555
4.97M
}
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
259M
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
569
570
1.95M
#define mvswap(zzp1, zzp2, zzn)       \
571
1.95M
{                                     \
572
1.95M
   Int32 yyp1 = (zzp1);               \
573
1.95M
   Int32 yyp2 = (zzp2);               \
574
1.95M
   Int32 yyn  = (zzn);                \
575
17.8M
   while (yyn > 0) {                  \
576
15.9M
      mswap(ptr[yyp1], ptr[yyp2]);    \
577
15.9M
      yyp1++; yyp2++; yyn--;          \
578
15.9M
   }                                  \
579
1.95M
}
580
581
static 
582
__inline__
583
UChar mmed3 ( UChar a, UChar b, UChar c )
584
1.22M
{
585
1.22M
   UChar t;
586
1.22M
   if (a > b) { t = a; a = b; b = t; };
587
1.22M
   if (b > c) { 
588
535k
      b = c;
589
535k
      if (a > b) b = a;
590
535k
   }
591
1.22M
   return b;
592
1.22M
}
593
594
1.95M
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
595
596
6.58M
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
597
6.58M
                          stackHi[sp] = hz; \
598
6.58M
                          stackD [sp] = dz; \
599
6.58M
                          sp++; }
600
601
6.58M
#define mpop(lz,hz,dz) { sp--;             \
602
6.58M
                         lz = stackLo[sp]; \
603
6.58M
                         hz = stackHi[sp]; \
604
6.58M
                         dz = stackD [sp]; }
605
606
607
5.85M
#define mnextsize(az) (nextHi[az]-nextLo[az])
608
609
#define mnextswap(az,bz)                                        \
610
1.02M
   { Int32 tz;                                                  \
611
1.02M
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
612
1.02M
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
613
1.02M
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
614
615
616
13.1M
#define MAIN_QSORT_SMALL_THRESH 20
617
1.25M
#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
618
#define MAIN_QSORT_STACK_SIZE 100
619
620
static
621
void mainQSort3 ( UInt32* ptr,
622
                  UChar*  block,
623
                  UInt16* quadrant,
624
                  Int32   nblock,
625
                  Int32   loSt, 
626
                  Int32   hiSt, 
627
                  Int32   dSt,
628
                  Int32*  budget )
629
3.40M
{
630
3.40M
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
631
3.40M
   Int32 sp, lo, hi, d;
632
633
3.40M
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
634
3.40M
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
635
3.40M
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
636
637
3.40M
   Int32 nextLo[3];
638
3.40M
   Int32 nextHi[3];
639
3.40M
   Int32 nextD [3];
640
641
3.40M
   sp = 0;
642
3.40M
   mpush ( loSt, hiSt, dSt );
643
644
9.98M
   while (sp > 0) {
645
646
6.58M
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
647
648
6.58M
      mpop ( lo, hi, d );
649
6.58M
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
650
5.35M
          d > MAIN_QSORT_DEPTH_THRESH) {
651
5.35M
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
652
5.35M
         if (*budget < 0) return;
653
5.35M
         continue;
654
5.35M
      }
655
656
1.22M
      med = (Int32) 
657
1.22M
            mmed3 ( block[ptr[ lo         ]+d],
658
1.22M
                    block[ptr[ hi         ]+d],
659
1.22M
                    block[ptr[ (lo+hi)>>1 ]+d] );
660
661
1.22M
      unLo = ltLo = lo;
662
1.22M
      unHi = gtHi = hi;
663
664
11.8M
      while (True) {
665
188M
         while (True) {
666
188M
            if (unLo > unHi) break;
667
187M
            n = ((Int32)block[ptr[unLo]+d]) - med;
668
187M
            if (n == 0) { 
669
150M
               mswap(ptr[unLo], ptr[ltLo]); 
670
150M
               ltLo++; unLo++; continue; 
671
150M
            };
672
37.4M
            if (n >  0) break;
673
26.3M
            unLo++;
674
26.3M
         }
675
117M
         while (True) {
676
117M
            if (unLo > unHi) break;
677
116M
            n = ((Int32)block[ptr[unHi]+d]) - med;
678
116M
            if (n == 0) { 
679
82.5M
               mswap(ptr[unHi], ptr[gtHi]); 
680
82.5M
               gtHi--; unHi--; continue; 
681
82.5M
            };
682
34.0M
            if (n <  0) break;
683
23.4M
            unHi--;
684
23.4M
         }
685
11.8M
         if (unLo > unHi) break;
686
10.6M
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
687
10.6M
      }
688
689
1.22M
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
690
691
1.22M
      if (gtHi < ltLo) {
692
254k
         mpush(lo, hi, d+1 );
693
254k
         continue;
694
254k
      }
695
696
975k
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
697
975k
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
698
699
975k
      n = lo + unLo - ltLo - 1;
700
975k
      m = hi - (gtHi - unHi) + 1;
701
702
975k
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
703
975k
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
704
975k
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
705
706
975k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
707
975k
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
708
975k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
709
710
975k
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
711
975k
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
712
713
975k
      mpush (nextLo[0], nextHi[0], nextD[0]);
714
975k
      mpush (nextLo[1], nextHi[1], nextD[1]);
715
975k
      mpush (nextLo[2], nextHi[2], nextD[2]);
716
975k
   }
717
3.40M
}
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
3.39M
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
747
423M
#define SETMASK (1 << 21)
748
212M
#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
1.10k
{
759
1.10k
   Int32  i, j, k, ss, sb;
760
1.10k
   Int32  runningOrder[256];
761
1.10k
   Bool   bigDone[256];
762
1.10k
   Int32  copyStart[256];
763
1.10k
   Int32  copyEnd  [256];
764
1.10k
   UChar  c1;
765
1.10k
   Int32  numQSorted;
766
1.10k
   UInt16 s;
767
1.10k
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
768
769
   /*-- set up the 2-byte frequency table --*/
770
72.1M
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
771
772
1.10k
   j = block[0] << 8;
773
1.10k
   i = nblock-1;
774
51.3M
   for (; i >= 3; i -= 4) {
775
51.3M
      quadrant[i] = 0;
776
51.3M
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
777
51.3M
      ftab[j]++;
778
51.3M
      quadrant[i-1] = 0;
779
51.3M
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
780
51.3M
      ftab[j]++;
781
51.3M
      quadrant[i-2] = 0;
782
51.3M
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
783
51.3M
      ftab[j]++;
784
51.3M
      quadrant[i-3] = 0;
785
51.3M
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
786
51.3M
      ftab[j]++;
787
51.3M
   }
788
2.24k
   for (; i >= 0; i--) {
789
1.14k
      quadrant[i] = 0;
790
1.14k
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
791
1.14k
      ftab[j]++;
792
1.14k
   }
793
794
   /*-- (emphasises close relationship of block & quadrant) --*/
795
38.5k
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
796
37.4k
      block   [nblock+i] = block[i];
797
37.4k
      quadrant[nblock+i] = 0;
798
37.4k
   }
799
800
1.10k
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
801
802
   /*-- Complete the initial radix sort --*/
803
72.1M
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
804
805
1.10k
   s = block[0] << 8;
806
1.10k
   i = nblock-1;
807
51.3M
   for (; i >= 3; i -= 4) {
808
51.3M
      s = (s >> 8) | (block[i] << 8);
809
51.3M
      j = ftab[s] -1;
810
51.3M
      ftab[s] = j;
811
51.3M
      ptr[j] = i;
812
51.3M
      s = (s >> 8) | (block[i-1] << 8);
813
51.3M
      j = ftab[s] -1;
814
51.3M
      ftab[s] = j;
815
51.3M
      ptr[j] = i-1;
816
51.3M
      s = (s >> 8) | (block[i-2] << 8);
817
51.3M
      j = ftab[s] -1;
818
51.3M
      ftab[s] = j;
819
51.3M
      ptr[j] = i-2;
820
51.3M
      s = (s >> 8) | (block[i-3] << 8);
821
51.3M
      j = ftab[s] -1;
822
51.3M
      ftab[s] = j;
823
51.3M
      ptr[j] = i-3;
824
51.3M
   }
825
2.24k
   for (; i >= 0; i--) {
826
1.14k
      s = (s >> 8) | (block[i] << 8);
827
1.14k
      j = ftab[s] -1;
828
1.14k
      ftab[s] = j;
829
1.14k
      ptr[j] = i;
830
1.14k
   }
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
282k
   for (i = 0; i <= 255; i++) {
838
281k
      bigDone     [i] = False;
839
281k
      runningOrder[i] = i;
840
281k
   }
841
842
1.10k
   {
843
1.10k
      Int32 vv;
844
1.10k
      Int32 h = 1;
845
5.50k
      do h = 3 * h + 1; while (h <= 256);
846
5.50k
      do {
847
5.50k
         h = h / 3;
848
1.21M
         for (i = h; i <= 255; i++) {
849
1.21M
            vv = runningOrder[i];
850
1.21M
            j = i;
851
1.69M
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
852
543k
               runningOrder[j] = runningOrder[j-h];
853
543k
               j = j - h;
854
543k
               if (j <= (h - 1)) goto zero;
855
543k
            }
856
1.21M
            zero:
857
1.21M
            runningOrder[j] = vv;
858
1.21M
         }
859
5.50k
      } while (h != 1);
860
1.10k
   }
861
862
   /*--
863
      The main sorting loop.
864
   --*/
865
866
1.10k
   numQSorted = 0;
867
868
276k
   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
275k
      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
70.7M
      for (j = 0; j <= 255; j++) {
887
70.4M
         if (j != ss) {
888
70.1M
            sb = (ss << 8) + j;
889
70.1M
            if ( ! (ftab[sb] & SETMASK) ) {
890
35.3M
               Int32 lo = ftab[sb]   & CLEARMASK;
891
35.3M
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
892
35.3M
               if (hi > lo) {
893
3.40M
                  if (verb >= 4)
894
0
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
895
3.40M
                                "done %d   this %d\n",
896
3.40M
                                ss, j, numQSorted, hi - lo + 1 );
897
3.40M
                  mainQSort3 ( 
898
3.40M
                     ptr, block, quadrant, nblock, 
899
3.40M
                     lo, hi, BZ_N_RADIX, budget 
900
3.40M
                  );   
901
3.40M
                  numQSorted += (hi - lo + 1);
902
3.40M
                  if (*budget < 0) return;
903
3.40M
               }
904
35.3M
            }
905
70.1M
            ftab[sb] |= SETMASK;
906
70.1M
         }
907
70.4M
      }
908
909
275k
      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
275k
      {
919
70.7M
         for (j = 0; j <= 255; j++) {
920
70.4M
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
921
70.4M
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
922
70.4M
         }
923
44.5M
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
924
44.2M
            k = ptr[j]-1; if (k < 0) k += nblock;
925
44.2M
            c1 = block[k];
926
44.2M
            if (!bigDone[c1])
927
27.1M
               ptr[ copyStart[c1]++ ] = k;
928
44.2M
         }
929
57.7M
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
930
57.5M
            k = ptr[j]-1; if (k < 0) k += nblock;
931
57.5M
            c1 = block[k];
932
57.5M
            if (!bigDone[c1]) 
933
30.3M
               ptr[ copyEnd[c1]-- ] = k;
934
57.5M
         }
935
275k
      }
936
937
275k
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
938
275k
                || 
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
275k
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
944
275k
                1007 )
945
946
70.7M
      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
275k
      bigDone[ss] = True;
988
989
275k
      if (i < 255) {
990
274k
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
991
274k
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
992
274k
         Int32 shifts   = 0;
993
994
274k
         while ((bbSize >> shifts) > 65534) shifts++;
995
996
88.6M
         for (j = bbSize-1; j >= 0; j--) {
997
88.3M
            Int32 a2update     = ptr[bbStart + j];
998
88.3M
            UInt16 qVal        = (UInt16)(j >> shifts);
999
88.3M
            quadrant[a2update] = qVal;
1000
88.3M
            if (a2update < BZ_N_OVERSHOOT)
1001
14.2k
               quadrant[a2update + nblock] = qVal;
1002
88.3M
         }
1003
274k
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
1004
274k
      }
1005
1006
275k
   }
1007
1008
426
   if (verb >= 4)
1009
0
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
1010
426
                 nblock, numQSorted, nblock - numQSorted );
1011
426
}
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
2.76k
{
1033
2.76k
   UInt32* ptr    = s->ptr; 
1034
2.76k
   UChar*  block  = s->block;
1035
2.76k
   UInt32* ftab   = s->ftab;
1036
2.76k
   Int32   nblock = s->nblock;
1037
2.76k
   Int32   verb   = s->verbosity;
1038
2.76k
   Int32   wfact  = s->workFactor;
1039
2.76k
   UInt16* quadrant;
1040
2.76k
   Int32   budget;
1041
2.76k
   Int32   budgetInit;
1042
2.76k
   Int32   i;
1043
1044
2.76k
   if (nblock < 10000) {
1045
1.66k
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1046
1.66k
   } 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
1.10k
      i = nblock+BZ_N_OVERSHOOT;
1053
1.10k
      if (i & 1) i++;
1054
1.10k
      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
1.10k
      if (wfact < 1  ) wfact = 1;
1064
1.10k
      if (wfact > 100) wfact = 100;
1065
1.10k
      budgetInit = nblock * ((wfact-1) / 3);
1066
1.10k
      budget = budgetInit;
1067
1068
1.10k
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
1069
1.10k
      if (verb >= 3) 
1070
0
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
1071
1.10k
                    budgetInit - budget,
1072
1.10k
                    nblock, 
1073
1.10k
                    (float)(budgetInit - budget) /
1074
1.10k
                    (float)(nblock==0 ? 1 : nblock) ); 
1075
1.10k
      if (budget < 0) {
1076
675
         if (verb >= 2) 
1077
0
            VPrintf0 ( "    too repetitive; using fallback"
1078
675
                       " sorting algorithm\n" );
1079
675
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1080
675
      }
1081
1.10k
   }
1082
1083
2.76k
   s->origPtr = -1;
1084
121M
   for (i = 0; i < s->nblock; i++)
1085
121M
      if (ptr[i] == 0)
1086
2.76k
         { s->origPtr = i; break; };
1087
1088
2.76k
   AssertH( s->origPtr != -1, 1003 );
1089
2.76k
}
1090
1091
1092
/*-------------------------------------------------------------*/
1093
/*--- end                                       blocksort.c ---*/
1094
/*-------------------------------------------------------------*/