Coverage Report

Created: 2026-01-20 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bzip2/blocksort.c
Line
Count
Source
1
2
/*-------------------------------------------------------------*/
3
/*--- Block sorting machinery                               ---*/
4
/*---                                           blocksort.c ---*/
5
/*-------------------------------------------------------------*/
6
7
/* ------------------------------------------------------------------
8
   This file is part of bzip2/libbzip2, a program and library for
9
   lossless, block-sorting data compression.
10
11
   bzip2/libbzip2 version 1.0.6 of 6 September 2010
12
   Copyright (C) 1996-2010 Julian Seward <jseward@acm.org>
13
14
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
15
   README file.
16
17
   This program is released under the terms of the license contained
18
   in the file LICENSE.
19
   ------------------------------------------------------------------ */
20
21
22
#include "bzlib_private.h"
23
24
/*---------------------------------------------*/
25
/*--- Fallback O(N log(N)^2) sorting        ---*/
26
/*--- algorithm, for repetitive blocks      ---*/
27
/*---------------------------------------------*/
28
29
/*---------------------------------------------*/
30
static 
31
__inline__
32
void fallbackSimpleSort ( UInt32* fmap, 
33
                          UInt32* eclass, 
34
                          Int32   lo, 
35
                          Int32   hi )
36
108M
{
37
108M
   Int32 i, j, tmp;
38
108M
   UInt32 ec_tmp;
39
40
108M
   if (lo == hi) return;
41
42
105M
   if (hi - lo > 3) {
43
95.8M
      for ( i = hi-4; i >= lo; i-- ) {
44
72.7M
         tmp = fmap[i];
45
72.7M
         ec_tmp = eclass[tmp];
46
95.0M
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
47
22.2M
            fmap[j-4] = fmap[j];
48
72.7M
         fmap[j-4] = tmp;
49
72.7M
      }
50
23.0M
   }
51
52
355M
   for ( i = hi-1; i >= lo; i-- ) {
53
249M
      tmp = fmap[i];
54
249M
      ec_tmp = eclass[tmp];
55
357M
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
56
108M
         fmap[j-1] = fmap[j];
57
249M
      fmap[j-1] = tmp;
58
249M
   }
59
105M
}
60
61
62
/*---------------------------------------------*/
63
#define fswap(zz1, zz2) \
64
1.22G
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
65
66
42.7M
#define fvswap(zzp1, zzp2, zzn)       \
67
42.7M
{                                     \
68
42.7M
   Int32 yyp1 = (zzp1);               \
69
42.7M
   Int32 yyp2 = (zzp2);               \
70
42.7M
   Int32 yyn  = (zzn);                \
71
229M
   while (yyn > 0) {                  \
72
186M
      fswap(fmap[yyp1], fmap[yyp2]);  \
73
186M
      yyp1++; yyp2++; yyn--;          \
74
186M
   }                                  \
75
42.7M
}
76
77
78
42.7M
#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
89.1M
{
98
89.1M
   Int32 unLo, unHi, ltLo, gtHi, n, m;
99
89.1M
   Int32 sp, lo, hi;
100
89.1M
   UInt32 med, r, r3;
101
89.1M
   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
102
89.1M
   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
103
104
89.1M
   r = 0;
105
106
89.1M
   sp = 0;
107
89.1M
   fpush ( loSt, hiSt );
108
109
220M
   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
108M
         fallbackSimpleSort ( fmap, eclass, lo, hi );
116
108M
         continue;
117
108M
      }
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
23.1M
      r = ((r * 7621) + 1) % 32768;
127
23.1M
      r3 = r % 3;
128
23.1M
      if (r3 == 0) med = eclass[fmap[lo]]; else
129
20.4M
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
130
7.72M
                   med = eclass[fmap[hi]];
131
132
23.1M
      unLo = ltLo = lo;
133
23.1M
      unHi = gtHi = hi;
134
135
117M
      while (1) {
136
1.18G
         while (1) {
137
1.18G
            if (unLo > unHi) break;
138
1.16G
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
139
1.16G
            if (n == 0) { 
140
751M
               fswap(fmap[unLo], fmap[ltLo]); 
141
751M
               ltLo++; unLo++; 
142
751M
               continue; 
143
751M
            };
144
416M
            if (n > 0) break;
145
311M
            unLo++;
146
311M
         }
147
623M
         while (1) {
148
623M
            if (unLo > unHi) break;
149
600M
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
150
600M
            if (n == 0) { 
151
191M
               fswap(fmap[unHi], fmap[gtHi]); 
152
191M
               gtHi--; unHi--; 
153
191M
               continue; 
154
408M
            };
155
408M
            if (n < 0) break;
156
314M
            unHi--;
157
314M
         }
158
117M
         if (unLo > unHi) break;
159
94.3M
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
160
94.3M
      }
161
162
23.1M
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
163
164
23.1M
      if (gtHi < ltLo) continue;
165
166
21.3M
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
167
21.3M
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
168
169
21.3M
      n = lo + unLo - ltLo - 1;
170
21.3M
      m = hi - (gtHi - unHi) + 1;
171
172
21.3M
      if (n - lo > hi - m) {
173
10.6M
         fpush ( lo, n );
174
10.6M
         fpush ( m, hi );
175
10.6M
      } else {
176
10.6M
         fpush ( m, hi );
177
10.6M
         fpush ( lo, n );
178
10.6M
      }
179
21.3M
   }
180
89.1M
}
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
257M
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31))
206
2.71M
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31))
207
3.39G
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31)))
208
55.2M
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
209
495M
#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
84.7k
{
218
84.7k
   Int32 ftab[257];
219
84.7k
   Int32 ftabCopy[256];
220
84.7k
   Int32 H, i, j, k, l, r, cc, cc1;
221
84.7k
   Int32 nNotDone;
222
84.7k
   Int32 nBhtab;
223
84.7k
   UChar* eclass8 = (UChar*)eclass;
224
225
   /*--
226
      Initial 1-char radix sort to generate
227
      initial fmap and initial BH bits.
228
   --*/
229
84.7k
   if (verb >= 4)
230
0
      VPrintf0 ( "        bucket sorting ...\n" );
231
21.8M
   for (i = 0; i < 257;    i++) ftab[i] = 0;
232
150M
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
233
21.7M
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
234
21.7M
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
235
236
150M
   for (i = 0; i < nblock; i++) {
237
150M
      j = eclass8[i];
238
150M
      k = ftab[j] - 1;
239
150M
      ftab[j] = k;
240
150M
      fmap[k] = i;
241
150M
   }
242
243
84.7k
   nBhtab = 2 + (nblock / 32);
244
4.91M
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
245
21.7M
   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
246
247
   /*--
248
      Inductively refine the buckets.  Kind-of an
249
      "exponential radix sort" (!), inspired by the
250
      Manber-Myers suffix array construction algorithm.
251
   --*/
252
253
   /*-- set sentinel bits for block-end detection --*/
254
2.79M
   for (i = 0; i < 32; i++) { 
255
2.71M
      SET_BH(nblock + 2*i);
256
2.71M
      CLEAR_BH(nblock + 2*i + 1);
257
2.71M
   }
258
259
   /*-- the log(N) loop --*/
260
84.7k
   H = 1;
261
514k
   while (1) {
262
263
514k
      if (verb >= 4) 
264
0
         VPrintf1 ( "        depth %6d has ", H );
265
266
514k
      j = 0;
267
1.75G
      for (i = 0; i < nblock; i++) {
268
1.75G
         if (ISSET_BH(i)) j = i;
269
1.75G
         k = fmap[i] - H; if (k < 0) k += nblock;
270
1.75G
         eclass[k] = j;
271
1.75G
      }
272
273
514k
      nNotDone = 0;
274
514k
      r = -1;
275
89.6M
      while (1) {
276
277
   /*-- find the next non-singleton bucket --*/
278
89.6M
         k = r + 1;
279
318M
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
280
89.6M
         if (ISSET_BH(k)) {
281
17.6M
            while (WORD_BH(k) == 0xffffffff) k += 32;
282
65.9M
            while (ISSET_BH(k)) k++;
283
9.38M
         }
284
89.6M
         l = k - 1;
285
89.6M
         if (l >= nblock) break;
286
335M
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
287
89.1M
         if (!ISSET_BH(k)) {
288
37.5M
            while (WORD_BH(k) == 0x00000000) k += 32;
289
85.7M
            while (!ISSET_BH(k)) k++;
290
10.0M
         }
291
89.1M
         r = k - 1;
292
89.1M
         if (r >= nblock) break;
293
294
         /*-- now [l, r] bracket current bucket --*/
295
89.1M
         if (r > l) {
296
89.1M
            nNotDone += (r - l + 1);
297
89.1M
            fallbackQSort3 ( fmap, eclass, l, r );
298
299
            /*-- scan bucket and generate header bits-- */
300
89.1M
            cc = -1;
301
1.38G
            for (i = l; i <= r; i++) {
302
1.29G
               cc1 = eclass[fmap[i]];
303
1.29G
               if (cc != cc1) { SET_BH(i); cc = cc1; };
304
1.29G
            }
305
89.1M
         }
306
89.1M
      }
307
308
514k
      if (verb >= 4) 
309
0
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
310
311
514k
      H *= 2;
312
514k
      if (H > nblock || nNotDone == 0) break;
313
514k
   }
314
315
   /*-- 
316
      Reconstruct the original block in
317
      eclass8 [0 .. nblock-1], since the
318
      previous phase destroyed it.
319
   --*/
320
84.7k
   if (verb >= 4)
321
0
      VPrintf0 ( "        reconstructing block ...\n" );
322
84.7k
   j = 0;
323
150M
   for (i = 0; i < nblock; i++) {
324
165M
      while (ftabCopy[j] == 0) j++;
325
150M
      ftabCopy[j]--;
326
150M
      eclass8[fmap[i]] = (UChar)j;
327
150M
   }
328
84.7k
   AssertH ( j < 256, 1005 );
329
84.7k
}
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
102M
{
354
102M
   Int32  k;
355
102M
   UChar  c1, c2;
356
102M
   UInt16 s1, s2;
357
358
102M
   AssertD ( i1 != i2, "mainGtU" );
359
   /* 1 */
360
102M
   c1 = block[i1]; c2 = block[i2];
361
102M
   if (c1 != c2) return (c1 > c2);
362
100M
   i1++; i2++;
363
   /* 2 */
364
100M
   c1 = block[i1]; c2 = block[i2];
365
100M
   if (c1 != c2) return (c1 > c2);
366
98.5M
   i1++; i2++;
367
   /* 3 */
368
98.5M
   c1 = block[i1]; c2 = block[i2];
369
98.5M
   if (c1 != c2) return (c1 > c2);
370
97.3M
   i1++; i2++;
371
   /* 4 */
372
97.3M
   c1 = block[i1]; c2 = block[i2];
373
97.3M
   if (c1 != c2) return (c1 > c2);
374
95.9M
   i1++; i2++;
375
   /* 5 */
376
95.9M
   c1 = block[i1]; c2 = block[i2];
377
95.9M
   if (c1 != c2) return (c1 > c2);
378
94.6M
   i1++; i2++;
379
   /* 6 */
380
94.6M
   c1 = block[i1]; c2 = block[i2];
381
94.6M
   if (c1 != c2) return (c1 > c2);
382
93.2M
   i1++; i2++;
383
   /* 7 */
384
93.2M
   c1 = block[i1]; c2 = block[i2];
385
93.2M
   if (c1 != c2) return (c1 > c2);
386
91.6M
   i1++; i2++;
387
   /* 8 */
388
91.6M
   c1 = block[i1]; c2 = block[i2];
389
91.6M
   if (c1 != c2) return (c1 > c2);
390
90.3M
   i1++; i2++;
391
   /* 9 */
392
90.3M
   c1 = block[i1]; c2 = block[i2];
393
90.3M
   if (c1 != c2) return (c1 > c2);
394
89.2M
   i1++; i2++;
395
   /* 10 */
396
89.2M
   c1 = block[i1]; c2 = block[i2];
397
89.2M
   if (c1 != c2) return (c1 > c2);
398
88.0M
   i1++; i2++;
399
   /* 11 */
400
88.0M
   c1 = block[i1]; c2 = block[i2];
401
88.0M
   if (c1 != c2) return (c1 > c2);
402
87.0M
   i1++; i2++;
403
   /* 12 */
404
87.0M
   c1 = block[i1]; c2 = block[i2];
405
87.0M
   if (c1 != c2) return (c1 > c2);
406
86.0M
   i1++; i2++;
407
408
86.0M
   k = nblock + 8;
409
410
783M
   do {
411
      /* 1 */
412
783M
      c1 = block[i1]; c2 = block[i2];
413
783M
      if (c1 != c2) return (c1 > c2);
414
780M
      s1 = quadrant[i1]; s2 = quadrant[i2];
415
780M
      if (s1 != s2) return (s1 > s2);
416
769M
      i1++; i2++;
417
      /* 2 */
418
769M
      c1 = block[i1]; c2 = block[i2];
419
769M
      if (c1 != c2) return (c1 > c2);
420
765M
      s1 = quadrant[i1]; s2 = quadrant[i2];
421
765M
      if (s1 != s2) return (s1 > s2);
422
753M
      i1++; i2++;
423
      /* 3 */
424
753M
      c1 = block[i1]; c2 = block[i2];
425
753M
      if (c1 != c2) return (c1 > c2);
426
749M
      s1 = quadrant[i1]; s2 = quadrant[i2];
427
749M
      if (s1 != s2) return (s1 > s2);
428
744M
      i1++; i2++;
429
      /* 4 */
430
744M
      c1 = block[i1]; c2 = block[i2];
431
744M
      if (c1 != c2) return (c1 > c2);
432
740M
      s1 = quadrant[i1]; s2 = quadrant[i2];
433
740M
      if (s1 != s2) return (s1 > s2);
434
735M
      i1++; i2++;
435
      /* 5 */
436
735M
      c1 = block[i1]; c2 = block[i2];
437
735M
      if (c1 != c2) return (c1 > c2);
438
732M
      s1 = quadrant[i1]; s2 = quadrant[i2];
439
732M
      if (s1 != s2) return (s1 > s2);
440
727M
      i1++; i2++;
441
      /* 6 */
442
727M
      c1 = block[i1]; c2 = block[i2];
443
727M
      if (c1 != c2) return (c1 > c2);
444
724M
      s1 = quadrant[i1]; s2 = quadrant[i2];
445
724M
      if (s1 != s2) return (s1 > s2);
446
717M
      i1++; i2++;
447
      /* 7 */
448
717M
      c1 = block[i1]; c2 = block[i2];
449
717M
      if (c1 != c2) return (c1 > c2);
450
713M
      s1 = quadrant[i1]; s2 = quadrant[i2];
451
713M
      if (s1 != s2) return (s1 > s2);
452
709M
      i1++; i2++;
453
      /* 8 */
454
709M
      c1 = block[i1]; c2 = block[i2];
455
709M
      if (c1 != c2) return (c1 > c2);
456
704M
      s1 = quadrant[i1]; s2 = quadrant[i2];
457
704M
      if (s1 != s2) return (s1 > s2);
458
697M
      i1++; i2++;
459
460
697M
      if (i1 >= nblock) i1 -= nblock;
461
697M
      if (i2 >= nblock) i2 -= nblock;
462
463
697M
      k -= 8;
464
697M
      (*budget)--;
465
697M
   }
466
697M
      while (k >= 0);
467
468
25.0k
   return False;
469
86.0M
}
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
947k
{
494
947k
   Int32 i, j, h, bigN, hp;
495
947k
   UInt32 v;
496
497
947k
   bigN = hi - lo + 1;
498
947k
   if (bigN < 2) return;
499
500
710k
   hp = 0;
501
2.03M
   while (incs[hp] < bigN) hp++;
502
710k
   hp--;
503
504
2.01M
   for (; hp >= 0; hp--) {
505
1.30M
      h = incs[hp];
506
507
1.30M
      i = lo + h;
508
17.1M
      while (True) {
509
510
         /*-- copy 1 --*/
511
17.1M
         if (i > hi) break;
512
16.8M
         v = ptr[i];
513
16.8M
         j = i;
514
34.5M
         while ( mainGtU ( 
515
34.5M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
516
34.5M
                 ) ) {
517
20.1M
            ptr[j] = ptr[j-h];
518
20.1M
            j = j - h;
519
20.1M
            if (j <= (lo + h - 1)) break;
520
20.1M
         }
521
16.8M
         ptr[j] = v;
522
16.8M
         i++;
523
524
         /*-- copy 2 --*/
525
16.8M
         if (i > hi) break;
526
16.3M
         v = ptr[i];
527
16.3M
         j = i;
528
34.2M
         while ( mainGtU ( 
529
34.2M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
530
34.2M
                 ) ) {
531
20.1M
            ptr[j] = ptr[j-h];
532
20.1M
            j = j - h;
533
20.1M
            if (j <= (lo + h - 1)) break;
534
20.1M
         }
535
16.3M
         ptr[j] = v;
536
16.3M
         i++;
537
538
         /*-- copy 3 --*/
539
16.3M
         if (i > hi) break;
540
15.8M
         v = ptr[i];
541
15.8M
         j = i;
542
33.9M
         while ( mainGtU ( 
543
33.9M
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
544
33.9M
                 ) ) {
545
20.1M
            ptr[j] = ptr[j-h];
546
20.1M
            j = j - h;
547
20.1M
            if (j <= (lo + h - 1)) break;
548
20.1M
         }
549
15.8M
         ptr[j] = v;
550
15.8M
         i++;
551
552
15.8M
         if (*budget < 0) return;
553
15.8M
      }
554
1.30M
   }
555
710k
}
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
219M
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
569
570
445k
#define mvswap(zzp1, zzp2, zzn)       \
571
445k
{                                     \
572
445k
   Int32 yyp1 = (zzp1);               \
573
445k
   Int32 yyp2 = (zzp2);               \
574
445k
   Int32 yyn  = (zzn);                \
575
9.05M
   while (yyn > 0) {                  \
576
8.61M
      mswap(ptr[yyp1], ptr[yyp2]);    \
577
8.61M
      yyp1++; yyp2++; yyn--;          \
578
8.61M
   }                                  \
579
445k
}
580
581
static 
582
__inline__
583
UChar mmed3 ( UChar a, UChar b, UChar c )
584
1.07M
{
585
1.07M
   UChar t;
586
1.07M
   if (a > b) { t = a; a = b; b = t; };
587
1.07M
   if (b > c) { 
588
45.3k
      b = c;
589
45.3k
      if (a > b) b = a;
590
45.3k
   }
591
1.07M
   return b;
592
1.07M
}
593
594
445k
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
595
596
2.01M
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
597
2.01M
                          stackHi[sp] = hz; \
598
2.01M
                          stackD [sp] = dz; \
599
2.01M
                          sp++; }
600
601
2.01M
#define mpop(lz,hz,dz) { sp--;             \
602
2.01M
                         lz = stackLo[sp]; \
603
2.01M
                         hz = stackHi[sp]; \
604
2.01M
                         dz = stackD [sp]; }
605
606
607
1.33M
#define mnextsize(az) (nextHi[az]-nextLo[az])
608
609
#define mnextswap(az,bz)                                        \
610
471k
   { Int32 tz;                                                  \
611
471k
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
612
471k
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
613
471k
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
614
615
616
4.03M
#define MAIN_QSORT_SMALL_THRESH 20
617
1.17M
#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
503k
{
630
503k
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
631
503k
   Int32 sp, lo, hi, d;
632
633
503k
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
634
503k
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
635
503k
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
636
637
503k
   Int32 nextLo[3];
638
503k
   Int32 nextHi[3];
639
503k
   Int32 nextD [3];
640
641
503k
   sp = 0;
642
503k
   mpush ( loSt, hiSt, dSt );
643
644
2.51M
   while (sp > 0) {
645
646
2.01M
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
647
648
2.01M
      mpop ( lo, hi, d );
649
2.01M
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
650
1.17M
          d > MAIN_QSORT_DEPTH_THRESH) {
651
947k
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
652
947k
         if (*budget < 0) return;
653
942k
         continue;
654
947k
      }
655
656
1.07M
      med = (Int32) 
657
1.07M
            mmed3 ( block[ptr[ lo         ]+d],
658
1.07M
                    block[ptr[ hi         ]+d],
659
1.07M
                    block[ptr[ (lo+hi)>>1 ]+d] );
660
661
1.07M
      unLo = ltLo = lo;
662
1.07M
      unHi = gtHi = hi;
663
664
1.50M
      while (True) {
665
189M
         while (True) {
666
189M
            if (unLo > unHi) break;
667
188M
            n = ((Int32)block[ptr[unLo]+d]) - med;
668
188M
            if (n == 0) { 
669
183M
               mswap(ptr[unLo], ptr[ltLo]); 
670
183M
               ltLo++; unLo++; continue; 
671
183M
            };
672
5.86M
            if (n >  0) break;
673
5.33M
            unLo++;
674
5.33M
         }
675
33.4M
         while (True) {
676
33.4M
            if (unLo > unHi) break;
677
32.3M
            n = ((Int32)block[ptr[unHi]+d]) - med;
678
32.3M
            if (n == 0) { 
679
27.1M
               mswap(ptr[unHi], ptr[gtHi]); 
680
27.1M
               gtHi--; unHi--; continue; 
681
27.1M
            };
682
5.21M
            if (n <  0) break;
683
4.77M
            unHi--;
684
4.77M
         }
685
1.50M
         if (unLo > unHi) break;
686
435k
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
687
435k
      }
688
689
1.07M
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
690
691
1.07M
      if (gtHi < ltLo) {
692
847k
         mpush(lo, hi, d+1 );
693
847k
         continue;
694
847k
      }
695
696
222k
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
697
222k
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
698
699
222k
      n = lo + unLo - ltLo - 1;
700
222k
      m = hi - (gtHi - unHi) + 1;
701
702
222k
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
703
222k
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
704
222k
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
705
706
222k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
707
222k
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
708
222k
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
709
710
222k
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
711
222k
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
712
713
222k
      mpush (nextLo[0], nextHi[0], nextD[0]);
714
222k
      mpush (nextLo[1], nextHi[1], nextD[1]);
715
222k
      mpush (nextLo[2], nextHi[2], nextD[2]);
716
222k
   }
717
503k
}
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
20.7M
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
747
3.14G
#define SETMASK (1 << 21)
748
1.58G
#define CLEARMASK (~(SETMASK))
749
750
static
751
void mainSort ( UInt32* ptr, 
752
                UChar*  block,
753
                UInt16* quadrant, 
754
                UInt32* ftab,
755
                Int32   nblock,
756
                Int32   verb,
757
                Int32*  budget )
758
8.09k
{
759
8.09k
   Int32  i, j, k, ss, sb;
760
8.09k
   Int32  runningOrder[256];
761
8.09k
   Bool   bigDone[256];
762
8.09k
   Int32  copyStart[256];
763
8.09k
   Int32  copyEnd  [256];
764
8.09k
   UChar  c1;
765
8.09k
   Int32  numQSorted;
766
8.09k
   UInt16 s;
767
8.09k
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
768
769
   /*-- set up the 2-byte frequency table --*/
770
530M
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
771
772
8.09k
   j = block[0] << 8;
773
8.09k
   i = nblock-1;
774
23.1M
   for (; i >= 3; i -= 4) {
775
23.1M
      quadrant[i] = 0;
776
23.1M
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
777
23.1M
      ftab[j]++;
778
23.1M
      quadrant[i-1] = 0;
779
23.1M
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
780
23.1M
      ftab[j]++;
781
23.1M
      quadrant[i-2] = 0;
782
23.1M
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
783
23.1M
      ftab[j]++;
784
23.1M
      quadrant[i-3] = 0;
785
23.1M
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
786
23.1M
      ftab[j]++;
787
23.1M
   }
788
18.0k
   for (; i >= 0; i--) {
789
9.97k
      quadrant[i] = 0;
790
9.97k
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
791
9.97k
      ftab[j]++;
792
9.97k
   }
793
794
   /*-- (emphasises close relationship of block & quadrant) --*/
795
283k
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
796
275k
      block   [nblock+i] = block[i];
797
275k
      quadrant[nblock+i] = 0;
798
275k
   }
799
800
8.09k
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
801
802
   /*-- Complete the initial radix sort --*/
803
530M
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
804
805
8.09k
   s = block[0] << 8;
806
8.09k
   i = nblock-1;
807
23.1M
   for (; i >= 3; i -= 4) {
808
23.1M
      s = (s >> 8) | (block[i] << 8);
809
23.1M
      j = ftab[s] -1;
810
23.1M
      ftab[s] = j;
811
23.1M
      ptr[j] = i;
812
23.1M
      s = (s >> 8) | (block[i-1] << 8);
813
23.1M
      j = ftab[s] -1;
814
23.1M
      ftab[s] = j;
815
23.1M
      ptr[j] = i-1;
816
23.1M
      s = (s >> 8) | (block[i-2] << 8);
817
23.1M
      j = ftab[s] -1;
818
23.1M
      ftab[s] = j;
819
23.1M
      ptr[j] = i-2;
820
23.1M
      s = (s >> 8) | (block[i-3] << 8);
821
23.1M
      j = ftab[s] -1;
822
23.1M
      ftab[s] = j;
823
23.1M
      ptr[j] = i-3;
824
23.1M
   }
825
18.0k
   for (; i >= 0; i--) {
826
9.97k
      s = (s >> 8) | (block[i] << 8);
827
9.97k
      j = ftab[s] -1;
828
9.97k
      ftab[s] = j;
829
9.97k
      ptr[j] = i;
830
9.97k
   }
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.07M
   for (i = 0; i <= 255; i++) {
838
2.07M
      bigDone     [i] = False;
839
2.07M
      runningOrder[i] = i;
840
2.07M
   }
841
842
8.09k
   {
843
8.09k
      Int32 vv;
844
8.09k
      Int32 h = 1;
845
40.4k
      do h = 3 * h + 1; while (h <= 256);
846
40.4k
      do {
847
40.4k
         h = h / 3;
848
8.94M
         for (i = h; i <= 255; i++) {
849
8.90M
            vv = runningOrder[i];
850
8.90M
            j = i;
851
10.3M
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
852
1.61M
               runningOrder[j] = runningOrder[j-h];
853
1.61M
               j = j - h;
854
1.61M
               if (j <= (h - 1)) goto zero;
855
1.61M
            }
856
8.90M
            zero:
857
8.90M
            runningOrder[j] = vv;
858
8.90M
         }
859
40.4k
      } while (h != 1);
860
8.09k
   }
861
862
   /*--
863
      The main sorting loop.
864
   --*/
865
866
8.09k
   numQSorted = 0;
867
868
2.04M
   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.04M
      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
524M
      for (j = 0; j <= 255; j++) {
887
522M
         if (j != ss) {
888
520M
            sb = (ss << 8) + j;
889
520M
            if ( ! (ftab[sb] & SETMASK) ) {
890
264M
               Int32 lo = ftab[sb]   & CLEARMASK;
891
264M
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
892
264M
               if (hi > lo) {
893
503k
                  if (verb >= 4)
894
0
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
895
503k
                                "done %d   this %d\n",
896
503k
                                ss, j, numQSorted, hi - lo + 1 );
897
503k
                  mainQSort3 ( 
898
503k
                     ptr, block, quadrant, nblock, 
899
503k
                     lo, hi, BZ_N_RADIX, budget 
900
503k
                  );   
901
503k
                  numQSorted += (hi - lo + 1);
902
503k
                  if (*budget < 0) return;
903
503k
               }
904
264M
            }
905
520M
            ftab[sb] |= SETMASK;
906
520M
         }
907
522M
      }
908
909
2.03M
      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.03M
      {
919
524M
         for (j = 0; j <= 255; j++) {
920
522M
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
921
522M
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
922
522M
         }
923
15.4M
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
924
13.4M
            k = ptr[j]-1; if (k < 0) k += nblock;
925
13.4M
            c1 = block[k];
926
13.4M
            if (!bigDone[c1])
927
8.77M
               ptr[ copyStart[c1]++ ] = k;
928
13.4M
         }
929
19.3M
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
930
17.3M
            k = ptr[j]-1; if (k < 0) k += nblock;
931
17.3M
            c1 = block[k];
932
17.3M
            if (!bigDone[c1]) 
933
10.3M
               ptr[ copyEnd[c1]-- ] = k;
934
17.3M
         }
935
2.03M
      }
936
937
2.03M
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
938
2.03M
                || 
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.03M
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
944
2.03M
                1007 )
945
946
524M
      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.03M
      bigDone[ss] = True;
988
989
2.03M
      if (i < 255) {
990
2.03M
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
991
2.03M
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
992
2.03M
         Int32 shifts   = 0;
993
994
2.03M
         while ((bbSize >> shifts) > 65534) shifts++;
995
996
22.2M
         for (j = bbSize-1; j >= 0; j--) {
997
20.2M
            Int32 a2update     = ptr[bbStart + j];
998
20.2M
            UInt16 qVal        = (UInt16)(j >> shifts);
999
20.2M
            quadrant[a2update] = qVal;
1000
20.2M
            if (a2update < BZ_N_OVERSHOOT)
1001
63.5k
               quadrant[a2update + nblock] = qVal;
1002
20.2M
         }
1003
2.03M
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
1004
2.03M
      }
1005
1006
2.03M
   }
1007
1008
2.46k
   if (verb >= 4)
1009
0
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
1010
2.46k
                 nblock, numQSorted, nblock - numQSorted );
1011
2.46k
}
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
87.2k
{
1033
87.2k
   UInt32* ptr    = s->ptr; 
1034
87.2k
   UChar*  block  = s->block;
1035
87.2k
   UInt32* ftab   = s->ftab;
1036
87.2k
   Int32   nblock = s->nblock;
1037
87.2k
   Int32   verb   = s->verbosity;
1038
87.2k
   Int32   wfact  = s->workFactor;
1039
87.2k
   UInt16* quadrant;
1040
87.2k
   Int32   budget;
1041
87.2k
   Int32   budgetInit;
1042
87.2k
   Int32   i;
1043
1044
87.2k
   if (nblock < 10000) {
1045
79.1k
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1046
79.1k
   } else {
1047
      /* Calculate the location for quadrant, remembering to get
1048
         the alignment right.  Assumes that &(block[0]) is at least
1049
         2-byte aligned -- this should be ok since block is really
1050
         the first section of arr2.
1051
      */
1052
8.09k
      i = nblock+BZ_N_OVERSHOOT;
1053
8.09k
      if (i & 1) i++;
1054
8.09k
      quadrant = (UInt16*)(&(block[i]));
1055
1056
      /* (wfact-1) / 3 puts the default-factor-30
1057
         transition point at very roughly the same place as 
1058
         with v0.1 and v0.9.0.  
1059
         Not that it particularly matters any more, since the
1060
         resulting compressed stream is now the same regardless
1061
         of whether or not we use the main sort or fallback sort.
1062
      */
1063
8.09k
      if (wfact < 1  ) wfact = 1;
1064
8.09k
      if (wfact > 100) wfact = 100;
1065
8.09k
      budgetInit = nblock * ((wfact-1) / 3);
1066
8.09k
      budget = budgetInit;
1067
1068
8.09k
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
1069
8.09k
      if (verb >= 3) 
1070
0
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
1071
8.09k
                    budgetInit - budget,
1072
8.09k
                    nblock, 
1073
8.09k
                    (float)(budgetInit - budget) /
1074
8.09k
                    (float)(nblock==0 ? 1 : nblock) ); 
1075
8.09k
      if (budget < 0) {
1076
5.63k
         if (verb >= 2) 
1077
0
            VPrintf0 ( "    too repetitive; using fallback"
1078
5.63k
                       " sorting algorithm\n" );
1079
5.63k
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
1080
5.63k
      }
1081
8.09k
   }
1082
1083
87.2k
   s->origPtr = -1;
1084
80.6M
   for (i = 0; i < s->nblock; i++)
1085
80.6M
      if (ptr[i] == 0)
1086
87.2k
         { s->origPtr = i; break; };
1087
1088
87.2k
   AssertH( s->origPtr != -1, 1003 );
1089
87.2k
}
1090
1091
1092
/*-------------------------------------------------------------*/
1093
/*--- end                                       blocksort.c ---*/
1094
/*-------------------------------------------------------------*/