Blame blocksort.c

Packit 71fd91
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
/*--- Block sorting machinery                               ---*/
Packit 71fd91
/*---                                           blocksort.c ---*/
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* ------------------------------------------------------------------
Packit 71fd91
   This file is part of bzip2/libbzip2, a program and library for
Packit 71fd91
   lossless, block-sorting data compression.
Packit 71fd91
Packit 71fd91
   bzip2/libbzip2 version 1.0.6 of 6 September 2010
Packit 71fd91
   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Packit 71fd91
Packit 71fd91
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
Packit 71fd91
   README file.
Packit 71fd91
Packit 71fd91
   This program is released under the terms of the license contained
Packit 71fd91
   in the file LICENSE.
Packit 71fd91
   ------------------------------------------------------------------ */
Packit 71fd91
Packit 71fd91
Packit 71fd91
#include "bzlib_private.h"
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--- Fallback O(N log(N)^2) sorting        ---*/
Packit 71fd91
/*--- algorithm, for repetitive blocks      ---*/
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
__inline__
Packit 71fd91
void fallbackSimpleSort ( UInt32* fmap, 
Packit 71fd91
                          UInt32* eclass, 
Packit 71fd91
                          Int32   lo, 
Packit 71fd91
                          Int32   hi )
Packit 71fd91
{
Packit 71fd91
   Int32 i, j, tmp;
Packit 71fd91
   UInt32 ec_tmp;
Packit 71fd91
Packit 71fd91
   if (lo == hi) return;
Packit 71fd91
Packit 71fd91
   if (hi - lo > 3) {
Packit 71fd91
      for ( i = hi-4; i >= lo; i-- ) {
Packit 71fd91
         tmp = fmap[i];
Packit 71fd91
         ec_tmp = eclass[tmp];
Packit 71fd91
         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
Packit 71fd91
            fmap[j-4] = fmap[j];
Packit 71fd91
         fmap[j-4] = tmp;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   for ( i = hi-1; i >= lo; i-- ) {
Packit 71fd91
      tmp = fmap[i];
Packit 71fd91
      ec_tmp = eclass[tmp];
Packit 71fd91
      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
Packit 71fd91
         fmap[j-1] = fmap[j];
Packit 71fd91
      fmap[j-1] = tmp;
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
#define fswap(zz1, zz2) \
Packit 71fd91
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
Packit 71fd91
Packit 71fd91
#define fvswap(zzp1, zzp2, zzn)       \
Packit 71fd91
{                                     \
Packit 71fd91
   Int32 yyp1 = (zzp1);               \
Packit 71fd91
   Int32 yyp2 = (zzp2);               \
Packit 71fd91
   Int32 yyn  = (zzn);                \
Packit 71fd91
   while (yyn > 0) {                  \
Packit 71fd91
      fswap(fmap[yyp1], fmap[yyp2]);  \
Packit 71fd91
      yyp1++; yyp2++; yyn--;          \
Packit 71fd91
   }                                  \
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
#define fmin(a,b) ((a) < (b)) ? (a) : (b)
Packit 71fd91
Packit 71fd91
#define fpush(lz,hz) { stackLo[sp] = lz; \
Packit 71fd91
                       stackHi[sp] = hz; \
Packit 71fd91
                       sp++; }
Packit 71fd91
Packit 71fd91
#define fpop(lz,hz) { sp--;              \
Packit 71fd91
                      lz = stackLo[sp];  \
Packit 71fd91
                      hz = stackHi[sp]; }
Packit 71fd91
Packit 71fd91
#define FALLBACK_QSORT_SMALL_THRESH 10
Packit 71fd91
#define FALLBACK_QSORT_STACK_SIZE   100
Packit 71fd91
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void fallbackQSort3 ( UInt32* fmap, 
Packit 71fd91
                      UInt32* eclass,
Packit 71fd91
                      Int32   loSt, 
Packit 71fd91
                      Int32   hiSt )
Packit 71fd91
{
Packit 71fd91
   Int32 unLo, unHi, ltLo, gtHi, n, m;
Packit 71fd91
   Int32 sp, lo, hi;
Packit 71fd91
   UInt32 med, r, r3;
Packit 71fd91
   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
Packit 71fd91
   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
Packit 71fd91
Packit 71fd91
   r = 0;
Packit 71fd91
Packit 71fd91
   sp = 0;
Packit 71fd91
   fpush ( loSt, hiSt );
Packit 71fd91
Packit 71fd91
   while (sp > 0) {
Packit 71fd91
Packit 71fd91
      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
Packit 71fd91
Packit 71fd91
      fpop ( lo, hi );
Packit 71fd91
      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
Packit 71fd91
         fallbackSimpleSort ( fmap, eclass, lo, hi );
Packit 71fd91
         continue;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      /* Random partitioning.  Median of 3 sometimes fails to
Packit 71fd91
         avoid bad cases.  Median of 9 seems to help but 
Packit 71fd91
         looks rather expensive.  This too seems to work but
Packit 71fd91
         is cheaper.  Guidance for the magic constants 
Packit 71fd91
         7621 and 32768 is taken from Sedgewick's algorithms
Packit 71fd91
         book, chapter 35.
Packit 71fd91
      */
Packit 71fd91
      r = ((r * 7621) + 1) % 32768;
Packit 71fd91
      r3 = r % 3;
Packit 71fd91
      if (r3 == 0) med = eclass[fmap[lo]]; else
Packit 71fd91
      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
Packit 71fd91
                   med = eclass[fmap[hi]];
Packit 71fd91
Packit 71fd91
      unLo = ltLo = lo;
Packit 71fd91
      unHi = gtHi = hi;
Packit 71fd91
Packit 71fd91
      while (1) {
Packit 71fd91
         while (1) {
Packit 71fd91
            if (unLo > unHi) break;
Packit 71fd91
            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
Packit 71fd91
            if (n == 0) { 
Packit 71fd91
               fswap(fmap[unLo], fmap[ltLo]); 
Packit 71fd91
               ltLo++; unLo++; 
Packit 71fd91
               continue; 
Packit 71fd91
            };
Packit 71fd91
            if (n > 0) break;
Packit 71fd91
            unLo++;
Packit 71fd91
         }
Packit 71fd91
         while (1) {
Packit 71fd91
            if (unLo > unHi) break;
Packit 71fd91
            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
Packit 71fd91
            if (n == 0) { 
Packit 71fd91
               fswap(fmap[unHi], fmap[gtHi]); 
Packit 71fd91
               gtHi--; unHi--; 
Packit 71fd91
               continue; 
Packit 71fd91
            };
Packit 71fd91
            if (n < 0) break;
Packit 71fd91
            unHi--;
Packit 71fd91
         }
Packit 71fd91
         if (unLo > unHi) break;
Packit 71fd91
         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
Packit 71fd91
Packit 71fd91
      if (gtHi < ltLo) continue;
Packit 71fd91
Packit 71fd91
      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
Packit 71fd91
      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
Packit 71fd91
Packit 71fd91
      n = lo + unLo - ltLo - 1;
Packit 71fd91
      m = hi - (gtHi - unHi) + 1;
Packit 71fd91
Packit 71fd91
      if (n - lo > hi - m) {
Packit 71fd91
         fpush ( lo, n );
Packit 71fd91
         fpush ( m, hi );
Packit 71fd91
      } else {
Packit 71fd91
         fpush ( m, hi );
Packit 71fd91
         fpush ( lo, n );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#undef fmin
Packit 71fd91
#undef fpush
Packit 71fd91
#undef fpop
Packit 71fd91
#undef fswap
Packit 71fd91
#undef fvswap
Packit 71fd91
#undef FALLBACK_QSORT_SMALL_THRESH
Packit 71fd91
#undef FALLBACK_QSORT_STACK_SIZE
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/* Pre:
Packit 71fd91
      nblock > 0
Packit 71fd91
      eclass exists for [0 .. nblock-1]
Packit 71fd91
      ((UChar*)eclass) [0 .. nblock-1] holds block
Packit 71fd91
      ptr exists for [0 .. nblock-1]
Packit 71fd91
Packit 71fd91
   Post:
Packit 71fd91
      ((UChar*)eclass) [0 .. nblock-1] holds block
Packit 71fd91
      All other areas of eclass destroyed
Packit 71fd91
      fmap [0 .. nblock-1] holds sorted order
Packit 71fd91
      bhtab [ 0 .. 2+(nblock/32) ] destroyed
Packit 71fd91
*/
Packit 71fd91
Packit 71fd91
#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
Packit 71fd91
#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
Packit 71fd91
#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
Packit 71fd91
#define      WORD_BH(zz)  bhtab[(zz) >> 5]
Packit 71fd91
#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void fallbackSort ( UInt32* fmap, 
Packit 71fd91
                    UInt32* eclass, 
Packit 71fd91
                    UInt32* bhtab,
Packit 71fd91
                    Int32   nblock,
Packit 71fd91
                    Int32   verb )
Packit 71fd91
{
Packit 71fd91
   Int32 ftab[257];
Packit 71fd91
   Int32 ftabCopy[256];
Packit 71fd91
   Int32 H, i, j, k, l, r, cc, cc1;
Packit 71fd91
   Int32 nNotDone;
Packit 71fd91
   Int32 nBhtab;
Packit 71fd91
   UChar* eclass8 = (UChar*)eclass;
Packit 71fd91
Packit 71fd91
   /*--
Packit 71fd91
      Initial 1-char radix sort to generate
Packit 71fd91
      initial fmap and initial BH bits.
Packit 71fd91
   --*/
Packit 71fd91
   if (verb >= 4)
Packit 71fd91
      VPrintf0 ( "        bucket sorting ...\n" );
Packit 71fd91
   for (i = 0; i < 257;    i++) ftab[i] = 0;
Packit 71fd91
   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
Packit 71fd91
   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
Packit 71fd91
   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
Packit 71fd91
Packit 71fd91
   for (i = 0; i < nblock; i++) {
Packit 71fd91
      j = eclass8[i];
Packit 71fd91
      k = ftab[j] - 1;
Packit 71fd91
      ftab[j] = k;
Packit 71fd91
      fmap[k] = i;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   nBhtab = 2 + (nblock / 32);
Packit 71fd91
   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
Packit 71fd91
   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
Packit 71fd91
Packit 71fd91
   /*--
Packit 71fd91
      Inductively refine the buckets.  Kind-of an
Packit 71fd91
      "exponential radix sort" (!), inspired by the
Packit 71fd91
      Manber-Myers suffix array construction algorithm.
Packit 71fd91
   --*/
Packit 71fd91
Packit 71fd91
   /*-- set sentinel bits for block-end detection --*/
Packit 71fd91
   for (i = 0; i < 32; i++) { 
Packit 71fd91
      SET_BH(nblock + 2*i);
Packit 71fd91
      CLEAR_BH(nblock + 2*i + 1);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*-- the log(N) loop --*/
Packit 71fd91
   H = 1;
Packit 71fd91
   while (1) {
Packit 71fd91
Packit 71fd91
      if (verb >= 4) 
Packit 71fd91
         VPrintf1 ( "        depth %6d has ", H );
Packit 71fd91
Packit 71fd91
      j = 0;
Packit 71fd91
      for (i = 0; i < nblock; i++) {
Packit 71fd91
         if (ISSET_BH(i)) j = i;
Packit 71fd91
         k = fmap[i] - H; if (k < 0) k += nblock;
Packit 71fd91
         eclass[k] = j;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      nNotDone = 0;
Packit 71fd91
      r = -1;
Packit 71fd91
      while (1) {
Packit 71fd91
Packit 71fd91
	 /*-- find the next non-singleton bucket --*/
Packit 71fd91
         k = r + 1;
Packit 71fd91
         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
Packit 71fd91
         if (ISSET_BH(k)) {
Packit 71fd91
            while (WORD_BH(k) == 0xffffffff) k += 32;
Packit 71fd91
            while (ISSET_BH(k)) k++;
Packit 71fd91
         }
Packit 71fd91
         l = k - 1;
Packit 71fd91
         if (l >= nblock) break;
Packit 71fd91
         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
Packit 71fd91
         if (!ISSET_BH(k)) {
Packit 71fd91
            while (WORD_BH(k) == 0x00000000) k += 32;
Packit 71fd91
            while (!ISSET_BH(k)) k++;
Packit 71fd91
         }
Packit 71fd91
         r = k - 1;
Packit 71fd91
         if (r >= nblock) break;
Packit 71fd91
Packit 71fd91
         /*-- now [l, r] bracket current bucket --*/
Packit 71fd91
         if (r > l) {
Packit 71fd91
            nNotDone += (r - l + 1);
Packit 71fd91
            fallbackQSort3 ( fmap, eclass, l, r );
Packit 71fd91
Packit 71fd91
            /*-- scan bucket and generate header bits-- */
Packit 71fd91
            cc = -1;
Packit 71fd91
            for (i = l; i <= r; i++) {
Packit 71fd91
               cc1 = eclass[fmap[i]];
Packit 71fd91
               if (cc != cc1) { SET_BH(i); cc = cc1; };
Packit 71fd91
            }
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      if (verb >= 4) 
Packit 71fd91
         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
Packit 71fd91
Packit 71fd91
      H *= 2;
Packit 71fd91
      if (H > nblock || nNotDone == 0) break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*-- 
Packit 71fd91
      Reconstruct the original block in
Packit 71fd91
      eclass8 [0 .. nblock-1], since the
Packit 71fd91
      previous phase destroyed it.
Packit 71fd91
   --*/
Packit 71fd91
   if (verb >= 4)
Packit 71fd91
      VPrintf0 ( "        reconstructing block ...\n" );
Packit 71fd91
   j = 0;
Packit 71fd91
   for (i = 0; i < nblock; i++) {
Packit 71fd91
      while (ftabCopy[j] == 0) j++;
Packit 71fd91
      ftabCopy[j]--;
Packit 71fd91
      eclass8[fmap[i]] = (UChar)j;
Packit 71fd91
   }
Packit 71fd91
   AssertH ( j < 256, 1005 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#undef       SET_BH
Packit 71fd91
#undef     CLEAR_BH
Packit 71fd91
#undef     ISSET_BH
Packit 71fd91
#undef      WORD_BH
Packit 71fd91
#undef UNALIGNED_BH
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--- The main, O(N^2 log(N)) sorting       ---*/
Packit 71fd91
/*--- algorithm.  Faster for "normal"       ---*/
Packit 71fd91
/*--- non-repetitive blocks.                ---*/
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static
Packit 71fd91
__inline__
Packit 71fd91
Bool mainGtU ( UInt32  i1, 
Packit 71fd91
               UInt32  i2,
Packit 71fd91
               UChar*  block, 
Packit 71fd91
               UInt16* quadrant,
Packit 71fd91
               UInt32  nblock,
Packit 71fd91
               Int32*  budget )
Packit 71fd91
{
Packit 71fd91
   Int32  k;
Packit 71fd91
   UChar  c1, c2;
Packit 71fd91
   UInt16 s1, s2;
Packit 71fd91
Packit 71fd91
   AssertD ( i1 != i2, "mainGtU" );
Packit 71fd91
   /* 1 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 2 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 3 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 4 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 5 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 6 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 7 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 8 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 9 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 10 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 11 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
   /* 12 */
Packit 71fd91
   c1 = block[i1]; c2 = block[i2];
Packit 71fd91
   if (c1 != c2) return (c1 > c2);
Packit 71fd91
   i1++; i2++;
Packit 71fd91
Packit 71fd91
   k = nblock + 8;
Packit 71fd91
Packit 71fd91
   do {
Packit 71fd91
      /* 1 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 2 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 3 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 4 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 5 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 6 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 7 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
      /* 8 */
Packit 71fd91
      c1 = block[i1]; c2 = block[i2];
Packit 71fd91
      if (c1 != c2) return (c1 > c2);
Packit 71fd91
      s1 = quadrant[i1]; s2 = quadrant[i2];
Packit 71fd91
      if (s1 != s2) return (s1 > s2);
Packit 71fd91
      i1++; i2++;
Packit 71fd91
Packit 71fd91
      if (i1 >= nblock) i1 -= nblock;
Packit 71fd91
      if (i2 >= nblock) i2 -= nblock;
Packit 71fd91
Packit 71fd91
      k -= 8;
Packit 71fd91
      (*budget)--;
Packit 71fd91
   }
Packit 71fd91
      while (k >= 0);
Packit 71fd91
Packit 71fd91
   return False;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
   Knuth's increments seem to work better
Packit 71fd91
   than Incerpi-Sedgewick here.  Possibly
Packit 71fd91
   because the number of elems to sort is
Packit 71fd91
   usually small, typically <= 20.
Packit 71fd91
--*/
Packit 71fd91
static
Packit 71fd91
Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
Packit 71fd91
                   9841, 29524, 88573, 265720,
Packit 71fd91
                   797161, 2391484 };
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void mainSimpleSort ( UInt32* ptr,
Packit 71fd91
                      UChar*  block,
Packit 71fd91
                      UInt16* quadrant,
Packit 71fd91
                      Int32   nblock,
Packit 71fd91
                      Int32   lo, 
Packit 71fd91
                      Int32   hi, 
Packit 71fd91
                      Int32   d,
Packit 71fd91
                      Int32*  budget )
Packit 71fd91
{
Packit 71fd91
   Int32 i, j, h, bigN, hp;
Packit 71fd91
   UInt32 v;
Packit 71fd91
Packit 71fd91
   bigN = hi - lo + 1;
Packit 71fd91
   if (bigN < 2) return;
Packit 71fd91
Packit 71fd91
   hp = 0;
Packit 71fd91
   while (incs[hp] < bigN) hp++;
Packit 71fd91
   hp--;
Packit 71fd91
Packit 71fd91
   for (; hp >= 0; hp--) {
Packit 71fd91
      h = incs[hp];
Packit 71fd91
Packit 71fd91
      i = lo + h;
Packit 71fd91
      while (True) {
Packit 71fd91
Packit 71fd91
         /*-- copy 1 --*/
Packit 71fd91
         if (i > hi) break;
Packit 71fd91
         v = ptr[i];
Packit 71fd91
         j = i;
Packit 71fd91
         while ( mainGtU ( 
Packit 71fd91
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
Packit 71fd91
                 ) ) {
Packit 71fd91
            ptr[j] = ptr[j-h];
Packit 71fd91
            j = j - h;
Packit 71fd91
            if (j <= (lo + h - 1)) break;
Packit 71fd91
         }
Packit 71fd91
         ptr[j] = v;
Packit 71fd91
         i++;
Packit 71fd91
Packit 71fd91
         /*-- copy 2 --*/
Packit 71fd91
         if (i > hi) break;
Packit 71fd91
         v = ptr[i];
Packit 71fd91
         j = i;
Packit 71fd91
         while ( mainGtU ( 
Packit 71fd91
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
Packit 71fd91
                 ) ) {
Packit 71fd91
            ptr[j] = ptr[j-h];
Packit 71fd91
            j = j - h;
Packit 71fd91
            if (j <= (lo + h - 1)) break;
Packit 71fd91
         }
Packit 71fd91
         ptr[j] = v;
Packit 71fd91
         i++;
Packit 71fd91
Packit 71fd91
         /*-- copy 3 --*/
Packit 71fd91
         if (i > hi) break;
Packit 71fd91
         v = ptr[i];
Packit 71fd91
         j = i;
Packit 71fd91
         while ( mainGtU ( 
Packit 71fd91
                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
Packit 71fd91
                 ) ) {
Packit 71fd91
            ptr[j] = ptr[j-h];
Packit 71fd91
            j = j - h;
Packit 71fd91
            if (j <= (lo + h - 1)) break;
Packit 71fd91
         }
Packit 71fd91
         ptr[j] = v;
Packit 71fd91
         i++;
Packit 71fd91
Packit 71fd91
         if (*budget < 0) return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
   The following is an implementation of
Packit 71fd91
   an elegant 3-way quicksort for strings,
Packit 71fd91
   described in a paper "Fast Algorithms for
Packit 71fd91
   Sorting and Searching Strings", by Robert
Packit 71fd91
   Sedgewick and Jon L. Bentley.
Packit 71fd91
--*/
Packit 71fd91
Packit 71fd91
#define mswap(zz1, zz2) \
Packit 71fd91
   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
Packit 71fd91
Packit 71fd91
#define mvswap(zzp1, zzp2, zzn)       \
Packit 71fd91
{                                     \
Packit 71fd91
   Int32 yyp1 = (zzp1);               \
Packit 71fd91
   Int32 yyp2 = (zzp2);               \
Packit 71fd91
   Int32 yyn  = (zzn);                \
Packit 71fd91
   while (yyn > 0) {                  \
Packit 71fd91
      mswap(ptr[yyp1], ptr[yyp2]);    \
Packit 71fd91
      yyp1++; yyp2++; yyn--;          \
Packit 71fd91
   }                                  \
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
__inline__
Packit 71fd91
UChar mmed3 ( UChar a, UChar b, UChar c )
Packit 71fd91
{
Packit 71fd91
   UChar t;
Packit 71fd91
   if (a > b) { t = a; a = b; b = t; };
Packit 71fd91
   if (b > c) { 
Packit 71fd91
      b = c;
Packit 71fd91
      if (a > b) b = a;
Packit 71fd91
   }
Packit 71fd91
   return b;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#define mmin(a,b) ((a) < (b)) ? (a) : (b)
Packit 71fd91
Packit 71fd91
#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
Packit 71fd91
                          stackHi[sp] = hz; \
Packit 71fd91
                          stackD [sp] = dz; \
Packit 71fd91
                          sp++; }
Packit 71fd91
Packit 71fd91
#define mpop(lz,hz,dz) { sp--;             \
Packit 71fd91
                         lz = stackLo[sp]; \
Packit 71fd91
                         hz = stackHi[sp]; \
Packit 71fd91
                         dz = stackD [sp]; }
Packit 71fd91
Packit 71fd91
Packit 71fd91
#define mnextsize(az) (nextHi[az]-nextLo[az])
Packit 71fd91
Packit 71fd91
#define mnextswap(az,bz)                                        \
Packit 71fd91
   { Int32 tz;                                                  \
Packit 71fd91
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
Packit 71fd91
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
Packit 71fd91
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
Packit 71fd91
Packit 71fd91
Packit 71fd91
#define MAIN_QSORT_SMALL_THRESH 20
Packit 71fd91
#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
Packit 71fd91
#define MAIN_QSORT_STACK_SIZE 100
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void mainQSort3 ( UInt32* ptr,
Packit 71fd91
                  UChar*  block,
Packit 71fd91
                  UInt16* quadrant,
Packit 71fd91
                  Int32   nblock,
Packit 71fd91
                  Int32   loSt, 
Packit 71fd91
                  Int32   hiSt, 
Packit 71fd91
                  Int32   dSt,
Packit 71fd91
                  Int32*  budget )
Packit 71fd91
{
Packit 71fd91
   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
Packit 71fd91
   Int32 sp, lo, hi, d;
Packit 71fd91
Packit 71fd91
   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
Packit 71fd91
   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
Packit 71fd91
   Int32 stackD [MAIN_QSORT_STACK_SIZE];
Packit 71fd91
Packit 71fd91
   Int32 nextLo[3];
Packit 71fd91
   Int32 nextHi[3];
Packit 71fd91
   Int32 nextD [3];
Packit 71fd91
Packit 71fd91
   sp = 0;
Packit 71fd91
   mpush ( loSt, hiSt, dSt );
Packit 71fd91
Packit 71fd91
   while (sp > 0) {
Packit 71fd91
Packit 71fd91
      AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
Packit 71fd91
Packit 71fd91
      mpop ( lo, hi, d );
Packit 71fd91
      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
Packit 71fd91
          d > MAIN_QSORT_DEPTH_THRESH) {
Packit 71fd91
         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
Packit 71fd91
         if (*budget < 0) return;
Packit 71fd91
         continue;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      med = (Int32) 
Packit 71fd91
            mmed3 ( block[ptr[ lo         ]+d],
Packit 71fd91
                    block[ptr[ hi         ]+d],
Packit 71fd91
                    block[ptr[ (lo+hi)>>1 ]+d] );
Packit 71fd91
Packit 71fd91
      unLo = ltLo = lo;
Packit 71fd91
      unHi = gtHi = hi;
Packit 71fd91
Packit 71fd91
      while (True) {
Packit 71fd91
         while (True) {
Packit 71fd91
            if (unLo > unHi) break;
Packit 71fd91
            n = ((Int32)block[ptr[unLo]+d]) - med;
Packit 71fd91
            if (n == 0) { 
Packit 71fd91
               mswap(ptr[unLo], ptr[ltLo]); 
Packit 71fd91
               ltLo++; unLo++; continue; 
Packit 71fd91
            };
Packit 71fd91
            if (n >  0) break;
Packit 71fd91
            unLo++;
Packit 71fd91
         }
Packit 71fd91
         while (True) {
Packit 71fd91
            if (unLo > unHi) break;
Packit 71fd91
            n = ((Int32)block[ptr[unHi]+d]) - med;
Packit 71fd91
            if (n == 0) { 
Packit 71fd91
               mswap(ptr[unHi], ptr[gtHi]); 
Packit 71fd91
               gtHi--; unHi--; continue; 
Packit 71fd91
            };
Packit 71fd91
            if (n <  0) break;
Packit 71fd91
            unHi--;
Packit 71fd91
         }
Packit 71fd91
         if (unLo > unHi) break;
Packit 71fd91
         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
Packit 71fd91
Packit 71fd91
      if (gtHi < ltLo) {
Packit 71fd91
         mpush(lo, hi, d+1 );
Packit 71fd91
         continue;
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
Packit 71fd91
      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
Packit 71fd91
Packit 71fd91
      n = lo + unLo - ltLo - 1;
Packit 71fd91
      m = hi - (gtHi - unHi) + 1;
Packit 71fd91
Packit 71fd91
      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
Packit 71fd91
      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
Packit 71fd91
      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
Packit 71fd91
Packit 71fd91
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
Packit 71fd91
      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
Packit 71fd91
      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
Packit 71fd91
Packit 71fd91
      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
Packit 71fd91
      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
Packit 71fd91
Packit 71fd91
      mpush (nextLo[0], nextHi[0], nextD[0]);
Packit 71fd91
      mpush (nextLo[1], nextHi[1], nextD[1]);
Packit 71fd91
      mpush (nextLo[2], nextHi[2], nextD[2]);
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#undef mswap
Packit 71fd91
#undef mvswap
Packit 71fd91
#undef mpush
Packit 71fd91
#undef mpop
Packit 71fd91
#undef mmin
Packit 71fd91
#undef mnextsize
Packit 71fd91
#undef mnextswap
Packit 71fd91
#undef MAIN_QSORT_SMALL_THRESH
Packit 71fd91
#undef MAIN_QSORT_DEPTH_THRESH
Packit 71fd91
#undef MAIN_QSORT_STACK_SIZE
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/* Pre:
Packit 71fd91
      nblock > N_OVERSHOOT
Packit 71fd91
      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
Packit 71fd91
      ((UChar*)block32) [0 .. nblock-1] holds block
Packit 71fd91
      ptr exists for [0 .. nblock-1]
Packit 71fd91
Packit 71fd91
   Post:
Packit 71fd91
      ((UChar*)block32) [0 .. nblock-1] holds block
Packit 71fd91
      All other areas of block32 destroyed
Packit 71fd91
      ftab [0 .. 65536 ] destroyed
Packit 71fd91
      ptr [0 .. nblock-1] holds sorted order
Packit 71fd91
      if (*budget < 0), sorting was abandoned
Packit 71fd91
*/
Packit 71fd91
Packit 71fd91
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
Packit 71fd91
#define SETMASK (1 << 21)
Packit 71fd91
#define CLEARMASK (~(SETMASK))
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void mainSort ( UInt32* ptr, 
Packit 71fd91
                UChar*  block,
Packit 71fd91
                UInt16* quadrant, 
Packit 71fd91
                UInt32* ftab,
Packit 71fd91
                Int32   nblock,
Packit 71fd91
                Int32   verb,
Packit 71fd91
                Int32*  budget )
Packit 71fd91
{
Packit 71fd91
   Int32  i, j, k, ss, sb;
Packit 71fd91
   Int32  runningOrder[256];
Packit 71fd91
   Bool   bigDone[256];
Packit 71fd91
   Int32  copyStart[256];
Packit 71fd91
   Int32  copyEnd  [256];
Packit 71fd91
   UChar  c1;
Packit 71fd91
   Int32  numQSorted;
Packit 71fd91
   UInt16 s;
Packit 71fd91
   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
Packit 71fd91
Packit 71fd91
   /*-- set up the 2-byte frequency table --*/
Packit 71fd91
   for (i = 65536; i >= 0; i--) ftab[i] = 0;
Packit 71fd91
Packit 71fd91
   j = block[0] << 8;
Packit 71fd91
   i = nblock-1;
Packit 71fd91
   for (; i >= 3; i -= 4) {
Packit 71fd91
      quadrant[i] = 0;
Packit 71fd91
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
Packit 71fd91
      ftab[j]++;
Packit 71fd91
      quadrant[i-1] = 0;
Packit 71fd91
      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
Packit 71fd91
      ftab[j]++;
Packit 71fd91
      quadrant[i-2] = 0;
Packit 71fd91
      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
Packit 71fd91
      ftab[j]++;
Packit 71fd91
      quadrant[i-3] = 0;
Packit 71fd91
      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
Packit 71fd91
      ftab[j]++;
Packit 71fd91
   }
Packit 71fd91
   for (; i >= 0; i--) {
Packit 71fd91
      quadrant[i] = 0;
Packit 71fd91
      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
Packit 71fd91
      ftab[j]++;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*-- (emphasises close relationship of block & quadrant) --*/
Packit 71fd91
   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
Packit 71fd91
      block   [nblock+i] = block[i];
Packit 71fd91
      quadrant[nblock+i] = 0;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
Packit 71fd91
Packit 71fd91
   /*-- Complete the initial radix sort --*/
Packit 71fd91
   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
Packit 71fd91
Packit 71fd91
   s = block[0] << 8;
Packit 71fd91
   i = nblock-1;
Packit 71fd91
   for (; i >= 3; i -= 4) {
Packit 71fd91
      s = (s >> 8) | (block[i] << 8);
Packit 71fd91
      j = ftab[s] -1;
Packit 71fd91
      ftab[s] = j;
Packit 71fd91
      ptr[j] = i;
Packit 71fd91
      s = (s >> 8) | (block[i-1] << 8);
Packit 71fd91
      j = ftab[s] -1;
Packit 71fd91
      ftab[s] = j;
Packit 71fd91
      ptr[j] = i-1;
Packit 71fd91
      s = (s >> 8) | (block[i-2] << 8);
Packit 71fd91
      j = ftab[s] -1;
Packit 71fd91
      ftab[s] = j;
Packit 71fd91
      ptr[j] = i-2;
Packit 71fd91
      s = (s >> 8) | (block[i-3] << 8);
Packit 71fd91
      j = ftab[s] -1;
Packit 71fd91
      ftab[s] = j;
Packit 71fd91
      ptr[j] = i-3;
Packit 71fd91
   }
Packit 71fd91
   for (; i >= 0; i--) {
Packit 71fd91
      s = (s >> 8) | (block[i] << 8);
Packit 71fd91
      j = ftab[s] -1;
Packit 71fd91
      ftab[s] = j;
Packit 71fd91
      ptr[j] = i;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*--
Packit 71fd91
      Now ftab contains the first loc of every small bucket.
Packit 71fd91
      Calculate the running order, from smallest to largest
Packit 71fd91
      big bucket.
Packit 71fd91
   --*/
Packit 71fd91
   for (i = 0; i <= 255; i++) {
Packit 71fd91
      bigDone     [i] = False;
Packit 71fd91
      runningOrder[i] = i;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   {
Packit 71fd91
      Int32 vv;
Packit 71fd91
      Int32 h = 1;
Packit 71fd91
      do h = 3 * h + 1; while (h <= 256);
Packit 71fd91
      do {
Packit 71fd91
         h = h / 3;
Packit 71fd91
         for (i = h; i <= 255; i++) {
Packit 71fd91
            vv = runningOrder[i];
Packit 71fd91
            j = i;
Packit 71fd91
            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
Packit 71fd91
               runningOrder[j] = runningOrder[j-h];
Packit 71fd91
               j = j - h;
Packit 71fd91
               if (j <= (h - 1)) goto zero;
Packit 71fd91
            }
Packit 71fd91
            zero:
Packit 71fd91
            runningOrder[j] = vv;
Packit 71fd91
         }
Packit 71fd91
      } while (h != 1);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*--
Packit 71fd91
      The main sorting loop.
Packit 71fd91
   --*/
Packit 71fd91
Packit 71fd91
   numQSorted = 0;
Packit 71fd91
Packit 71fd91
   for (i = 0; i <= 255; i++) {
Packit 71fd91
Packit 71fd91
      /*--
Packit 71fd91
         Process big buckets, starting with the least full.
Packit 71fd91
         Basically this is a 3-step process in which we call
Packit 71fd91
         mainQSort3 to sort the small buckets [ss, j], but
Packit 71fd91
         also make a big effort to avoid the calls if we can.
Packit 71fd91
      --*/
Packit 71fd91
      ss = runningOrder[i];
Packit 71fd91
Packit 71fd91
      /*--
Packit 71fd91
         Step 1:
Packit 71fd91
         Complete the big bucket [ss] by quicksorting
Packit 71fd91
         any unsorted small buckets [ss, j], for j != ss.  
Packit 71fd91
         Hopefully previous pointer-scanning phases have already
Packit 71fd91
         completed many of the small buckets [ss, j], so
Packit 71fd91
         we don't have to sort them at all.
Packit 71fd91
      --*/
Packit 71fd91
      for (j = 0; j <= 255; j++) {
Packit 71fd91
         if (j != ss) {
Packit 71fd91
            sb = (ss << 8) + j;
Packit 71fd91
            if ( ! (ftab[sb] & SETMASK) ) {
Packit 71fd91
               Int32 lo = ftab[sb]   & CLEARMASK;
Packit 71fd91
               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
Packit 71fd91
               if (hi > lo) {
Packit 71fd91
                  if (verb >= 4)
Packit 71fd91
                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
Packit 71fd91
                                "done %d   this %d\n",
Packit 71fd91
                                ss, j, numQSorted, hi - lo + 1 );
Packit 71fd91
                  mainQSort3 ( 
Packit 71fd91
                     ptr, block, quadrant, nblock, 
Packit 71fd91
                     lo, hi, BZ_N_RADIX, budget 
Packit 71fd91
                  );   
Packit 71fd91
                  numQSorted += (hi - lo + 1);
Packit 71fd91
                  if (*budget < 0) return;
Packit 71fd91
               }
Packit 71fd91
            }
Packit 71fd91
            ftab[sb] |= SETMASK;
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertH ( !bigDone[ss], 1006 );
Packit 71fd91
Packit 71fd91
      /*--
Packit 71fd91
         Step 2:
Packit 71fd91
         Now scan this big bucket [ss] so as to synthesise the
Packit 71fd91
         sorted order for small buckets [t, ss] for all t,
Packit 71fd91
         including, magically, the bucket [ss,ss] too.
Packit 71fd91
         This will avoid doing Real Work in subsequent Step 1's.
Packit 71fd91
      --*/
Packit 71fd91
      {
Packit 71fd91
         for (j = 0; j <= 255; j++) {
Packit 71fd91
            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
Packit 71fd91
            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
Packit 71fd91
         }
Packit 71fd91
         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
Packit 71fd91
            k = ptr[j]-1; if (k < 0) k += nblock;
Packit 71fd91
            c1 = block[k];
Packit 71fd91
            if (!bigDone[c1])
Packit 71fd91
               ptr[ copyStart[c1]++ ] = k;
Packit 71fd91
         }
Packit 71fd91
         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
Packit 71fd91
            k = ptr[j]-1; if (k < 0) k += nblock;
Packit 71fd91
            c1 = block[k];
Packit 71fd91
            if (!bigDone[c1]) 
Packit 71fd91
               ptr[ copyEnd[c1]-- ] = k;
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
Packit 71fd91
                || 
Packit 71fd91
                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
Packit 71fd91
                   Necessity for this case is demonstrated by compressing 
Packit 71fd91
                   a sequence of approximately 48.5 million of character 
Packit 71fd91
                   251; 1.0.0/1.0.1 will then die here. */
Packit 71fd91
                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
Packit 71fd91
                1007 )
Packit 71fd91
Packit 71fd91
      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
Packit 71fd91
Packit 71fd91
      /*--
Packit 71fd91
         Step 3:
Packit 71fd91
         The [ss] big bucket is now done.  Record this fact,
Packit 71fd91
         and update the quadrant descriptors.  Remember to
Packit 71fd91
         update quadrants in the overshoot area too, if
Packit 71fd91
         necessary.  The "if (i < 255)" test merely skips
Packit 71fd91
         this updating for the last bucket processed, since
Packit 71fd91
         updating for the last bucket is pointless.
Packit 71fd91
Packit 71fd91
         The quadrant array provides a way to incrementally
Packit 71fd91
         cache sort orderings, as they appear, so as to 
Packit 71fd91
         make subsequent comparisons in fullGtU() complete
Packit 71fd91
         faster.  For repetitive blocks this makes a big
Packit 71fd91
         difference (but not big enough to be able to avoid
Packit 71fd91
         the fallback sorting mechanism, exponential radix sort).
Packit 71fd91
Packit 71fd91
         The precise meaning is: at all times:
Packit 71fd91
Packit 71fd91
            for 0 <= i < nblock and 0 <= j <= nblock
Packit 71fd91
Packit 71fd91
            if block[i] != block[j], 
Packit 71fd91
Packit 71fd91
               then the relative values of quadrant[i] and 
Packit 71fd91
                    quadrant[j] are meaningless.
Packit 71fd91
Packit 71fd91
               else {
Packit 71fd91
                  if quadrant[i] < quadrant[j]
Packit 71fd91
                     then the string starting at i lexicographically
Packit 71fd91
                     precedes the string starting at j
Packit 71fd91
Packit 71fd91
                  else if quadrant[i] > quadrant[j]
Packit 71fd91
                     then the string starting at j lexicographically
Packit 71fd91
                     precedes the string starting at i
Packit 71fd91
Packit 71fd91
                  else
Packit 71fd91
                     the relative ordering of the strings starting
Packit 71fd91
                     at i and j has not yet been determined.
Packit 71fd91
               }
Packit 71fd91
      --*/
Packit 71fd91
      bigDone[ss] = True;
Packit 71fd91
Packit 71fd91
      if (i < 255) {
Packit 71fd91
         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
Packit 71fd91
         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
Packit 71fd91
         Int32 shifts   = 0;
Packit 71fd91
Packit 71fd91
         while ((bbSize >> shifts) > 65534) shifts++;
Packit 71fd91
Packit 71fd91
         for (j = bbSize-1; j >= 0; j--) {
Packit 71fd91
            Int32 a2update     = ptr[bbStart + j];
Packit 71fd91
            UInt16 qVal        = (UInt16)(j >> shifts);
Packit 71fd91
            quadrant[a2update] = qVal;
Packit 71fd91
            if (a2update < BZ_N_OVERSHOOT)
Packit 71fd91
               quadrant[a2update + nblock] = qVal;
Packit 71fd91
         }
Packit 71fd91
         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verb >= 4)
Packit 71fd91
      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
Packit 71fd91
                 nblock, numQSorted, nblock - numQSorted );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#undef BIGFREQ
Packit 71fd91
#undef SETMASK
Packit 71fd91
#undef CLEARMASK
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/* Pre:
Packit 71fd91
      nblock > 0
Packit 71fd91
      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
Packit 71fd91
      ((UChar*)arr2)  [0 .. nblock-1] holds block
Packit 71fd91
      arr1 exists for [0 .. nblock-1]
Packit 71fd91
Packit 71fd91
   Post:
Packit 71fd91
      ((UChar*)arr2) [0 .. nblock-1] holds block
Packit 71fd91
      All other areas of block destroyed
Packit 71fd91
      ftab [ 0 .. 65536 ] destroyed
Packit 71fd91
      arr1 [0 .. nblock-1] holds sorted order
Packit 71fd91
*/
Packit 71fd91
void BZ2_blockSort ( EState* s )
Packit 71fd91
{
Packit 71fd91
   UInt32* ptr    = s->ptr; 
Packit 71fd91
   UChar*  block  = s->block;
Packit 71fd91
   UInt32* ftab   = s->ftab;
Packit 71fd91
   Int32   nblock = s->nblock;
Packit 71fd91
   Int32   verb   = s->verbosity;
Packit 71fd91
   Int32   wfact  = s->workFactor;
Packit 71fd91
   UInt16* quadrant;
Packit 71fd91
   Int32   budget;
Packit 71fd91
   Int32   budgetInit;
Packit 71fd91
   Int32   i;
Packit 71fd91
Packit 71fd91
   if (nblock < 10000) {
Packit 71fd91
      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
Packit 71fd91
   } else {
Packit 71fd91
      /* Calculate the location for quadrant, remembering to get
Packit 71fd91
         the alignment right.  Assumes that &(block[0]) is at least
Packit 71fd91
         2-byte aligned -- this should be ok since block is really
Packit 71fd91
         the first section of arr2.
Packit 71fd91
      */
Packit 71fd91
      i = nblock+BZ_N_OVERSHOOT;
Packit 71fd91
      if (i & 1) i++;
Packit 71fd91
      quadrant = (UInt16*)(&(block[i]));
Packit 71fd91
Packit 71fd91
      /* (wfact-1) / 3 puts the default-factor-30
Packit 71fd91
         transition point at very roughly the same place as 
Packit 71fd91
         with v0.1 and v0.9.0.  
Packit 71fd91
         Not that it particularly matters any more, since the
Packit 71fd91
         resulting compressed stream is now the same regardless
Packit 71fd91
         of whether or not we use the main sort or fallback sort.
Packit 71fd91
      */
Packit 71fd91
      if (wfact < 1  ) wfact = 1;
Packit 71fd91
      if (wfact > 100) wfact = 100;
Packit 71fd91
      budgetInit = nblock * ((wfact-1) / 3);
Packit 71fd91
      budget = budgetInit;
Packit 71fd91
Packit 71fd91
      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
Packit 71fd91
      if (verb >= 3) 
Packit 71fd91
         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
Packit 71fd91
                    budgetInit - budget,
Packit 71fd91
                    nblock, 
Packit 71fd91
                    (float)(budgetInit - budget) /
Packit 71fd91
                    (float)(nblock==0 ? 1 : nblock) ); 
Packit 71fd91
      if (budget < 0) {
Packit 71fd91
         if (verb >= 2) 
Packit 71fd91
            VPrintf0 ( "    too repetitive; using fallback"
Packit 71fd91
                       " sorting algorithm\n" );
Packit 71fd91
         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   s->origPtr = -1;
Packit 71fd91
   for (i = 0; i < s->nblock; i++)
Packit 71fd91
      if (ptr[i] == 0)
Packit 71fd91
         { s->origPtr = i; break; };
Packit 71fd91
Packit 71fd91
   AssertH( s->origPtr != -1, 1003 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
/*--- end                                       blocksort.c ---*/
Packit 71fd91
/*-------------------------------------------------------------*/