Coverage Report

Created: 2025-10-28 06:52

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