Subversion Repositories nw_plus

Rev

Details | Last modification | View Log | RSS feed

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