Coverage Report

Created: 2025-08-11 08:01

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