Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

blocksort.c File Reference

#include "bzlib_private.h"

Go to the source code of this file.

Defines

#define fswap(zz1, zz2)   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
#define fvswap(zzp1, zzp2, zzn)
#define fmin(a, b)   ((a) < (b)) ? (a) : (b)
#define fpush(lz, hz)
#define fpop(lz, hz)
#define FALLBACK_QSORT_SMALL_THRESH   10
#define FALLBACK_QSORT_STACK_SIZE   100
#define SET_BH(zz)   bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
#define CLEAR_BH(zz)   bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
#define ISSET_BH(zz)   (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
#define WORD_BH(zz)   bhtab[(zz) >> 5]
#define UNALIGNED_BH(zz)   ((zz) & 0x01f)
#define mswap(zz1, zz2)   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
#define mvswap(zzp1, zzp2, zzn)
#define mmin(a, b)   ((a) < (b)) ? (a) : (b)
#define mpush(lz, hz, dz)
#define mpop(lz, hz, dz)
#define mnextsize(az)   (nextHi[az]-nextLo[az])
#define mnextswap(az, bz)
#define MAIN_QSORT_SMALL_THRESH   20
#define MAIN_QSORT_DEPTH_THRESH   (BZ_N_RADIX + BZ_N_QSORT)
#define MAIN_QSORT_STACK_SIZE   100
#define BIGFREQ(b)   (ftab[((b)+1) << 8] - ftab[(b) << 8])
#define SETMASK   (1 << 21)
#define CLEARMASK   (~(SETMASK))

Functions

__inline__ void fallbackSimpleSort (UInt32 *fmap, UInt32 *eclass, Int32 lo, Int32 hi)
void fallbackQSort3 (UInt32 *fmap, UInt32 *eclass, Int32 loSt, Int32 hiSt)
void fallbackSort (UInt32 *fmap, UInt32 *eclass, UInt32 *bhtab, Int32 nblock, Int32 verb)
__inline__ Bool mainGtU (UInt32 i1, UInt32 i2, UInt16 *block, UInt16 *quadrant, UInt32 nblock, Int32 *budget)
void mainSimpleSort (UInt32 *ptr, UInt16 *block, UInt16 *quadrant, Int32 nblock, Int32 lo, Int32 hi, Int32 d, Int32 *budget)
__inline__ UInt16 mmed3 (UInt16 a, UInt16 b, UInt16 c)
void mainQSort3 (UInt32 *ptr, UInt16 *block, UInt16 *quadrant, Int32 nblock, Int32 loSt, Int32 hiSt, Int32 dSt, Int32 *budget)
void mainSort (UInt32 *ptr, UInt16 *block, UInt16 *quadrant, UInt32 *ftab, Int32 nblock, Int32 verb, Int32 *budget)
void blockSort (EState *s)

Variables

Int32 incs [14]


Define Documentation

#define BIGFREQ b       (ftab[((b)+1) << 8] - ftab[(b) << 8])
 

Definition at line 736 of file blocksort.c.

Referenced by mainSort().

#define CLEARMASK   (~(SETMASK))
 

Definition at line 738 of file blocksort.c.

#define CLEAR_BH zz       bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
 

Definition at line 246 of file blocksort.c.

Referenced by fallbackSort().

#define FALLBACK_QSORT_SMALL_THRESH   10
 

Definition at line 128 of file blocksort.c.

#define FALLBACK_QSORT_STACK_SIZE   100
 

Definition at line 129 of file blocksort.c.

#define ISSET_BH zz       (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
 

Definition at line 247 of file blocksort.c.

Referenced by fallbackSort().

#define MAIN_QSORT_DEPTH_THRESH   (BZ_N_RADIX + BZ_N_QSORT)
 

Definition at line 607 of file blocksort.c.

#define MAIN_QSORT_SMALL_THRESH   20
 

Definition at line 606 of file blocksort.c.

#define MAIN_QSORT_STACK_SIZE   100
 

Definition at line 608 of file blocksort.c.

#define SETMASK   (1 << 21)
 

Definition at line 737 of file blocksort.c.

#define SET_BH zz       bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
 

Definition at line 245 of file blocksort.c.

Referenced by fallbackSort().

#define UNALIGNED_BH zz       ((zz) & 0x01f)
 

Definition at line 249 of file blocksort.c.

Referenced by fallbackSort().

#define WORD_BH zz       bhtab[(zz) >> 5]
 

Definition at line 248 of file blocksort.c.

Referenced by fallbackSort().

#define fmin a,
b       ((a) < (b)) ? (a) : (b)
 

Definition at line 118 of file blocksort.c.

Referenced by fallbackQSort3().

#define fpop lz,
hz   
 

Value:

{ sp--;              \
                      lz = stackLo[sp];  \
                      hz = stackHi[sp]; }

Definition at line 124 of file blocksort.c.

Referenced by fallbackQSort3().

#define fpush lz,
hz   
 

Value:

{ stackLo[sp] = lz; \
                       stackHi[sp] = hz; \
                       sp++; }

Definition at line 120 of file blocksort.c.

Referenced by fallbackQSort3().

#define fswap zz1,
zz2       { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
 

Definition at line 103 of file blocksort.c.

Referenced by fallbackQSort3().

#define fvswap zzp1,
zzp2,
zzn   
 

Value:

{                                     \
   Int32 yyp1 = (zzp1);               \
   Int32 yyp2 = (zzp2);               \
   Int32 yyn  = (zzn);                \
   while (yyn > 0) {                  \
      fswap(fmap[yyp1], fmap[yyp2]);  \
      yyp1++; yyp2++; yyn--;          \
   }                                  \
}

Definition at line 106 of file blocksort.c.

Referenced by fallbackQSort3().

#define mmin a,
b       ((a) < (b)) ? (a) : (b)
 

Definition at line 584 of file blocksort.c.

Referenced by mainQSort3().

#define mnextsize az       (nextHi[az]-nextLo[az])
 

Definition at line 597 of file blocksort.c.

Referenced by mainQSort3().

#define mnextswap az,
bz   
 

Value:

{ Int32 tz;                                                  \
     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }

Definition at line 599 of file blocksort.c.

Referenced by mainQSort3().

#define mpop lz,
hz,
dz   
 

Value:

{ sp--;             \
                         lz = stackLo[sp]; \
                         hz = stackHi[sp]; \
                         dz = stackD [sp]; }

Definition at line 591 of file blocksort.c.

Referenced by mainQSort3().

#define mpush lz,
hz,
dz   
 

Value:

{ stackLo[sp] = lz; \
                          stackHi[sp] = hz; \
                          stackD [sp] = dz; \
                          sp++; }

Definition at line 586 of file blocksort.c.

Referenced by mainQSort3().

#define mswap zz1,
zz2       { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
 

Definition at line 557 of file blocksort.c.

Referenced by mainQSort3().

#define mvswap zzp1,
zzp2,
zzn   
 

Value:

{                                     \
   Int32 yyp1 = (zzp1);               \
   Int32 yyp2 = (zzp2);               \
   Int32 yyn  = (zzn);                \
   while (yyn > 0) {                  \
      mswap(ptr[yyp1], ptr[yyp2]);    \
      yyp1++; yyp2++; yyn--;          \
   }                                  \
}

Definition at line 560 of file blocksort.c.

Referenced by mainQSort3().


Function Documentation

void blockSort EState   s
 

Definition at line 1017 of file blocksort.c.

01018 {
01019    UInt32* ptr    = s->ptr; 
01020    UInt16* block  = s->block;
01021    UInt32* ftab   = s->ftab;
01022    Int32   nblock = s->nblock;
01023    Int32   verb   = s->verbosity;
01024    Int32   wfact  = s->workFactor;
01025    UInt16* quadrant;
01026    Int32   budget;
01027    Int32   budgetInit;
01028    Int32   i;
01029 
01030    if (nblock < 10000) {
01031       for (i = 0; i < nblock; i++) block[i] <<= 8;
01032       fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
01033    } else {
01034       quadrant = &(block[nblock+BZ_N_OVERSHOOT]);
01035 
01036       /* (wfact-1) / 3 puts the default-factor-30
01037          transition point at very roughly the same place as 
01038          with v0.1 and v0.9.0.  
01039          Not that it particularly matters any more, since the
01040          resulting compressed stream is now the same regardless
01041          of whether or not we use the main sort or fallback sort.
01042       */
01043       if (wfact < 1  ) wfact = 1;
01044       if (wfact > 100) wfact = 100;
01045       budgetInit = nblock * ((wfact-1) / 3);
01046       budget = budgetInit;
01047 
01048       mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
01049       if (verb >= 3) 
01050          VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
01051                     budgetInit - budget,
01052                     nblock, 
01053                     (float)(budgetInit - budget) /
01054                     (float)(nblock==0 ? 1 : nblock) ); 
01055       if (budget < 0) {
01056          if (verb >= 2) 
01057             VPrintf0 ( "    too repetitive; using fallback"
01058                        " sorting algorithm\n" );
01059          fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
01060       }
01061    }
01062 
01063    s->origPtr = -1;
01064    for (i = 0; i < s->nblock; i++)
01065       if (ptr[i] == 0)
01066          { s->origPtr = i; break; };
01067 
01068    AssertH( s->origPtr != -1, 1003 );
01069 }

void fallbackQSort3 UInt32   fmap,
UInt32   eclass,
Int32    loSt,
Int32    hiSt
[static]
 

Definition at line 133 of file blocksort.c.

Referenced by fallbackSort().

00137 {
00138    Int32 unLo, unHi, ltLo, gtHi, n, m;
00139    Int32 sp, lo, hi;
00140    UInt32 med, r, r3;
00141    Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
00142    Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
00143 
00144    r = 0;
00145 
00146    sp = 0;
00147    fpush ( loSt, hiSt );
00148 
00149    while (sp > 0) {
00150 
00151       AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 );
00152 
00153       fpop ( lo, hi );
00154       if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
00155          fallbackSimpleSort ( fmap, eclass, lo, hi );
00156          continue;
00157       }
00158 
00159       /* Random partitioning.  Median of 3 sometimes fails to
00160          avoid bad cases.  Median of 9 seems to help but 
00161          looks rather expensive.  This too seems to work but
00162          is cheaper.  Guidance for the magic constants 
00163          7621 and 32768 is taken from Sedgewick's algorithms
00164          book, chapter 35.
00165       */
00166       r = ((r * 7621) + 1) % 32768;
00167       r3 = r % 3;
00168       if (r3 == 0) med = eclass[fmap[lo]]; else
00169       if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
00170                    med = eclass[fmap[hi]];
00171 
00172       unLo = ltLo = lo;
00173       unHi = gtHi = hi;
00174 
00175       while (1) {
00176          while (1) {
00177             if (unLo > unHi) break;
00178             n = (Int32)eclass[fmap[unLo]] - (Int32)med;
00179             if (n == 0) { 
00180                fswap(fmap[unLo], fmap[ltLo]); 
00181                ltLo++; unLo++; 
00182                continue; 
00183             };
00184             if (n > 0) break;
00185             unLo++;
00186          }
00187          while (1) {
00188             if (unLo > unHi) break;
00189             n = eclass[fmap[unHi]] - med;
00190             if (n == 0) { 
00191                fswap(fmap[unHi], fmap[gtHi]); 
00192                gtHi--; unHi--; 
00193                continue; 
00194             };
00195             if (n < 0) break;
00196             unHi--;
00197          }
00198          if (unLo > unHi) break;
00199          fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
00200       }
00201 
00202       AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
00203 
00204       if (gtHi < ltLo) continue;
00205 
00206       n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
00207       m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
00208 
00209       n = lo + unLo - ltLo - 1;
00210       m = hi - (gtHi - unHi) + 1;
00211 
00212       if (n - lo > hi - m) {
00213          fpush ( lo, n );
00214          fpush ( m, hi );
00215       } else {
00216          fpush ( m, hi );
00217          fpush ( lo, n );
00218       }
00219    }
00220 }

__inline__ void fallbackSimpleSort UInt32   fmap,
UInt32   eclass,
Int32    lo,
Int32    hi
[static]
 

Definition at line 72 of file blocksort.c.

Referenced by fallbackQSort3().

00076 {
00077    Int32 i, j, tmp;
00078    UInt32 ec_tmp;
00079 
00080    if (lo == hi) return;
00081 
00082    if (hi - lo > 3) {
00083       for ( i = hi-4; i >= lo; i-- ) {
00084          tmp = fmap[i];
00085          ec_tmp = eclass[tmp];
00086          for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
00087             fmap[j-4] = fmap[j];
00088          fmap[j-4] = tmp;
00089       }
00090    }
00091 
00092    for ( i = hi-1; i >= lo; i-- ) {
00093       tmp = fmap[i];
00094       ec_tmp = eclass[tmp];
00095       for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
00096          fmap[j-1] = fmap[j];
00097       fmap[j-1] = tmp;
00098    }
00099 }

void fallbackSort UInt32   fmap,
UInt32   eclass,
UInt32   bhtab,
Int32    nblock,
Int32    verb
[static]
 

Definition at line 252 of file blocksort.c.

Referenced by blockSort().

00257 {
00258    Int32 ftab[257];
00259    Int32 ftabCopy[256];
00260    Int32 H, i, j, k, l, r, cc, cc1;
00261    Int32 nNotDone;
00262    Int32 nBhtab;
00263    UInt16* eclass16 = (UInt16*)eclass;
00264 
00265    /*--
00266       Initial 1-char radix sort to generate
00267       initial fmap and initial BH bits.
00268    --*/
00269    if (verb >= 4)
00270       VPrintf0 ( "        bucket sorting ...\n" );
00271    for (i = 0; i < 257;    i++) ftab[i] = 0;
00272    for (i = 0; i < nblock; i++) ftab[eclass16[i] >> 8]++;
00273    for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
00274    for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
00275 
00276    for (i = 0; i < nblock; i++) {
00277       j = eclass16[i] >> 8;
00278       k = ftab[j] - 1;
00279       ftab[j] = k;
00280       fmap[k] = i;
00281    }
00282 
00283    nBhtab = 2 + (nblock / 32);
00284    for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
00285    for (i = 0; i < 256; i++) SET_BH(ftab[i]);
00286 
00287    /*--
00288       Inductively refine the buckets.  Kind-of an
00289       "exponential radix sort" (!), inspired by the
00290       Manber-Myers suffix array construction algorithm.
00291    --*/
00292 
00293    /*-- set sentinel bits for block-end detection --*/
00294    for (i = 0; i < 32; i++) { 
00295       SET_BH(nblock + 2*i);
00296       CLEAR_BH(nblock + 2*i + 1);
00297    }
00298 
00299    /*-- the log(N) loop --*/
00300    H = 1;
00301    while (1) {
00302 
00303       if (verb >= 4) 
00304          VPrintf1 ( "        depth %6d has ", H );
00305 
00306       j = 0;
00307       for (i = 0; i < nblock; i++) {
00308          if (ISSET_BH(i)) j = i;
00309          k = fmap[i] - H; if (k < 0) k += nblock;
00310          eclass[k] = j;
00311       }
00312 
00313       nNotDone = 0;
00314       r = -1;
00315       while (1) {
00316 
00317          /*-- find the next non-singleton bucket --*/
00318          k = r + 1;
00319          while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
00320          if (ISSET_BH(k)) {
00321             while (WORD_BH(k) == 0xffffffff) k += 32;
00322             while (ISSET_BH(k)) k++;
00323          }
00324          l = k - 1;
00325          if (l >= nblock) break;
00326          while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
00327          if (!ISSET_BH(k)) {
00328             while (WORD_BH(k) == 0x00000000) k += 32;
00329             while (!ISSET_BH(k)) k++;
00330          }
00331          r = k - 1;
00332          if (r >= nblock) break;
00333 
00334          /*-- now [l, r] bracket current bucket --*/
00335          if (r > l) {
00336             nNotDone += (r - l + 1);
00337             fallbackQSort3 ( fmap, eclass, l, r );
00338 
00339             /*-- scan bucket and generate header bits-- */
00340             cc = -1;
00341             for (i = l; i <= r; i++) {
00342                cc1 = eclass[fmap[i]];
00343                if (cc != cc1) { SET_BH(i); cc = cc1; };
00344             }
00345          }
00346       }
00347 
00348       if (verb >= 4) 
00349          VPrintf1 ( "%6d unresolved strings\n", nNotDone );
00350 
00351       H *= 2;
00352       if (H > nblock || nNotDone == 0) break;
00353    }
00354 
00355    /*-- 
00356       Reconstruct the original block in
00357       eclass16 [0 .. nblock-1] [15:8], since the
00358       previous phase destroyed it.
00359    --*/
00360    if (verb >= 4)
00361       VPrintf0 ( "        reconstructing block ...\n" );
00362    j = 0;
00363    for (i = 0; i < nblock; i++) {
00364       while (ftabCopy[j] == 0) j++;
00365       ftabCopy[j]--;
00366       eclass16[fmap[i]] = j << 8;
00367    }
00368    AssertH ( j < 256, 1005 );
00369 }

__inline__ Bool mainGtU UInt32    i1,
UInt32    i2,
UInt16   block,
UInt16   quadrant,
UInt32    nblock,
Int32   budget
[static]
 

Definition at line 387 of file blocksort.c.

Referenced by mainSimpleSort().

00393 {
00394    Int32 k;
00395    UInt16 s1, s2;
00396 
00397    AssertD ( i1 != i2, "mainGtU" );
00398 
00399    s1 = block[i1]; s2 = block[i2];
00400    if (s1 != s2) return (s1 > s2);
00401    i1 += 2; i2 += 2;
00402 
00403    s1 = block[i1]; s2 = block[i2];
00404    if (s1 != s2) return (s1 > s2);
00405    i1 += 2; i2 += 2;
00406 
00407    s1 = block[i1]; s2 = block[i2];
00408    if (s1 != s2) return (s1 > s2);
00409    i1 += 2; i2 += 2;
00410 
00411    s1 = block[i1]; s2 = block[i2];
00412    if (s1 != s2) return (s1 > s2);
00413    i1 += 2; i2 += 2;
00414 
00415    s1 = block[i1]; s2 = block[i2];
00416    if (s1 != s2) return (s1 > s2);
00417    i1 += 2; i2 += 2;
00418 
00419    s1 = block[i1]; s2 = block[i2];
00420    if (s1 != s2) return (s1 > s2);
00421    i1 += 2; i2 += 2;
00422 
00423    k = nblock + 8;
00424 
00425    do {
00426 
00427       s1 = block[i1]; s2 = block[i2];
00428       if (s1 != s2) return (s1 > s2);
00429       s1 = quadrant[i1]; s2 = quadrant[i2];
00430       if (s1 != s2) return (s1 > s2);
00431       i1 += 2; i2 += 2;
00432 
00433       s1 = block[i1]; s2 = block[i2];
00434       if (s1 != s2) return (s1 > s2);
00435       s1 = quadrant[i1]; s2 = quadrant[i2];
00436       if (s1 != s2) return (s1 > s2);
00437       i1 += 2; i2 += 2;
00438 
00439       s1 = block[i1]; s2 = block[i2];
00440       if (s1 != s2) return (s1 > s2);
00441       s1 = quadrant[i1]; s2 = quadrant[i2];
00442       if (s1 != s2) return (s1 > s2);
00443       i1 += 2; i2 += 2;
00444 
00445       s1 = block[i1]; s2 = block[i2];
00446       if (s1 != s2) return (s1 > s2);
00447       s1 = quadrant[i1]; s2 = quadrant[i2];
00448       if (s1 != s2) return (s1 > s2);
00449       i1 += 2; i2 += 2;
00450 
00451       if (i1 >= nblock) i1 -= nblock;
00452       if (i2 >= nblock) i2 -= nblock;
00453 
00454       k -= 8;
00455       (*budget)--;
00456    }
00457       while (k >= 0);
00458 
00459    return False;
00460 }

void mainQSort3 UInt32   ptr,
UInt16   block,
UInt16   quadrant,
Int32    nblock,
Int32    loSt,
Int32    hiSt,
Int32    dSt,
Int32   budget
[static]
 

Definition at line 611 of file blocksort.c.

Referenced by mainSort().

00619 {
00620    Int32 unLo, unHi, ltLo, gtHi, n, m, med;
00621    Int32 sp, lo, hi, d;
00622 
00623    Int32 stackLo[MAIN_QSORT_STACK_SIZE];
00624    Int32 stackHi[MAIN_QSORT_STACK_SIZE];
00625    Int32 stackD [MAIN_QSORT_STACK_SIZE];
00626 
00627    Int32 nextLo[3];
00628    Int32 nextHi[3];
00629    Int32 nextD [3];
00630 
00631    sp = 0;
00632    mpush ( loSt, hiSt, dSt );
00633 
00634    while (sp > 0) {
00635 
00636       AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 );
00637 
00638       mpop ( lo, hi, d );
00639       if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
00640           d > MAIN_QSORT_DEPTH_THRESH) {
00641          mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
00642          if (*budget < 0) return;
00643          continue;
00644       }
00645 
00646       med = (Int32) 
00647             mmed3 ( block[ptr[ lo         ]+d],
00648                     block[ptr[ hi         ]+d],
00649                     block[ptr[ (lo+hi)>>1 ]+d] );
00650 
00651       unLo = ltLo = lo;
00652       unHi = gtHi = hi;
00653 
00654       while (True) {
00655          while (True) {
00656             if (unLo > unHi) break;
00657             n = ((Int32)block[ptr[unLo]+d]) - med;
00658             if (n == 0) { 
00659                mswap(ptr[unLo], ptr[ltLo]); 
00660                ltLo++; unLo++; continue; 
00661             };
00662             if (n >  0) break;
00663             unLo++;
00664          }
00665          while (True) {
00666             if (unLo > unHi) break;
00667             n = ((Int32)block[ptr[unHi]+d]) - med;
00668             if (n == 0) { 
00669                mswap(ptr[unHi], ptr[gtHi]); 
00670                gtHi--; unHi--; continue; 
00671             };
00672             if (n <  0) break;
00673             unHi--;
00674          }
00675          if (unLo > unHi) break;
00676          mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
00677       }
00678 
00679       AssertD ( unHi == unLo-1, "mainQSort3(2)" );
00680 
00681       if (gtHi < ltLo) {
00682          mpush(lo, hi, d+2 );
00683          continue;
00684       }
00685 
00686       n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
00687       m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
00688 
00689       n = lo + unLo - ltLo - 1;
00690       m = hi - (gtHi - unHi) + 1;
00691 
00692       nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
00693       nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
00694       nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+2;
00695 
00696       if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
00697       if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
00698       if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
00699 
00700       AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
00701       AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
00702 
00703       mpush (nextLo[0], nextHi[0], nextD[0]);
00704       mpush (nextLo[1], nextHi[1], nextD[1]);
00705       mpush (nextLo[2], nextHi[2], nextD[2]);
00706    }
00707 }

void mainSimpleSort UInt32   ptr,
UInt16   block,
UInt16   quadrant,
Int32    nblock,
Int32    lo,
Int32    hi,
Int32    d,
Int32   budget
[static]
 

Definition at line 475 of file blocksort.c.

Referenced by mainQSort3().

00483 {
00484    Int32 i, j, h, bigN, hp;
00485    UInt32 v;
00486 
00487    bigN = hi - lo + 1;
00488    if (bigN < 2) return;
00489 
00490    hp = 0;
00491    while (incs[hp] < bigN) hp++;
00492    hp--;
00493 
00494    for (; hp >= 0; hp--) {
00495       h = incs[hp];
00496 
00497       i = lo + h;
00498       while (True) {
00499 
00500          /*-- copy 1 --*/
00501          if (i > hi) break;
00502          v = ptr[i];
00503          j = i;
00504          while ( mainGtU ( 
00505                     ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
00506                  ) ) {
00507             ptr[j] = ptr[j-h];
00508             j = j - h;
00509             if (j <= (lo + h - 1)) break;
00510          }
00511          ptr[j] = v;
00512          i++;
00513 
00514          /*-- copy 2 --*/
00515          if (i > hi) break;
00516          v = ptr[i];
00517          j = i;
00518          while ( mainGtU ( 
00519                     ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
00520                  ) ) {
00521             ptr[j] = ptr[j-h];
00522             j = j - h;
00523             if (j <= (lo + h - 1)) break;
00524          }
00525          ptr[j] = v;
00526          i++;
00527 
00528          /*-- copy 3 --*/
00529          if (i > hi) break;
00530          v = ptr[i];
00531          j = i;
00532          while ( mainGtU ( 
00533                     ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
00534                  ) ) {
00535             ptr[j] = ptr[j-h];
00536             j = j - h;
00537             if (j <= (lo + h - 1)) break;
00538          }
00539          ptr[j] = v;
00540          i++;
00541 
00542          if (*budget < 0) return;
00543       }
00544    }
00545 }

void mainSort UInt32   ptr,
UInt16   block,
UInt16   quadrant,
UInt32   ftab,
Int32    nblock,
Int32    verb,
Int32   budget
[static]
 

Definition at line 741 of file blocksort.c.

Referenced by blockSort().

00748 {
00749    Int32  i, j, k, m, ss, sb;
00750    Int32  runningOrder[256];
00751    Int32  copy[256];
00752    Bool   bigDone[256];
00753    UChar  c1;
00754    Int32  numQSorted;
00755    Int32  biggestSoFar;
00756    UInt16 s;
00757 
00758    if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
00759 
00760    /*-- Stripe the block data into 16 bits, and at the
00761         same time set up the 2-byte frequency table 
00762    --*/
00763    for (i = 65536; i >= 0; i--) ftab[i] = 0;
00764 
00765    s = block[0];
00766    for (i = 1; i < nblock; i++) {
00767       quadrant[i] = 0;
00768       s = (s << 8) | block[i];
00769       block[i-1] = s;
00770       ftab[s]++;      
00771    }
00772    quadrant[0] = 0;
00773    s = (s << 8) | (block[0] >> 8);
00774    block[nblock-1] = s;
00775    ftab[s]++;
00776 
00777    /*-- (emphasises close relationship of block & quadrant) --*/
00778    for (i = 0; i < BZ_N_OVERSHOOT; i++) {
00779       block   [nblock+i] = block[i];
00780       quadrant[nblock+i] = 0;
00781    }
00782 
00783    if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
00784 
00785    /*-- Complete the initial radix sort --*/
00786    for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
00787 
00788    for (i = 0; i < nblock; i++) {
00789       s = block[i];
00790       j = ftab[s] - 1;
00791       ftab[s] = j;
00792       ptr[j] = i;
00793    }
00794 
00795    /*--
00796       Now ftab contains the first loc of every small bucket.
00797       Calculate the running order, from smallest to largest
00798       big bucket.
00799    --*/
00800    for (i = 0; i <= 255; i++) {
00801       bigDone     [i] = False;
00802       runningOrder[i] = i;
00803    }
00804 
00805    {
00806       Int32 vv;
00807       Int32 h = 1;
00808       do h = 3 * h + 1; while (h <= 256);
00809       do 
00810                 {
00811 //                      printf("h=%lu\n",h);
00812          h = h / 3;
00813          for (i = h; i <= 255; i++) 
00814                         {
00815 //                              printf("i=%lu\n",i);
00816             vv = runningOrder[i];
00817             j = i;
00818             while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
00819 //                                              printf("j=%lu\n",j);
00820                                                 j-=h;
00821                runningOrder[j+h] = runningOrder[j];
00822 //                                      printf("j-h=%lu\n",j-h);
00823 //               j = j - h;
00824 
00825 //                                      printf("j=%lu\n",j);
00826                if (j <= (h - 1)) goto zero;
00827             }
00828             zero:
00829             runningOrder[j] = vv;
00830          }
00831       } while (h != 1);
00832    }
00833 
00834    /*--
00835       The main sorting loop.
00836    --*/
00837 
00838    biggestSoFar = numQSorted = 0;
00839 
00840    for (i = 0; i <= 255; i++) {
00841 
00842       /*--
00843          Process big buckets, starting with the least full.
00844          Basically this is a 4-step process in which we call
00845          mainQSort3 to sort the small buckets [ss, j], but
00846          also make a big effort to avoid the calls if we can.
00847       --*/
00848       ss = runningOrder[i];
00849 
00850       /*--
00851          Step 1:
00852          Complete the big bucket [ss] by quicksorting
00853          any unsorted small buckets [ss, j], for j != ss.  
00854          Hopefully previous pointer-scanning phases have already
00855          completed many of the small buckets [ss, j], so
00856          we don't have to sort them at all.
00857       --*/
00858       for (j = 0; j <= 255; j++) {
00859          if (j != ss) {
00860             sb = (ss << 8) + j;
00861             if ( ! (ftab[sb] & SETMASK) ) {
00862                Int32 lo = ftab[sb]   & CLEARMASK;
00863                Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
00864                if (hi > lo) {
00865                   if (verb >= 4)
00866                      VPrintf4 ( "        qsort [0x%x, 0x%x]   "
00867                                 "done %d   this %d\n",
00868                                 ss, j, numQSorted, hi - lo + 1 );
00869                   mainQSort3 ( 
00870                      ptr, block, quadrant, nblock, 
00871                      lo, hi, BZ_N_RADIX, budget 
00872                   );   
00873                   numQSorted += (hi - lo + 1);
00874                   if (*budget < 0) return;
00875                }
00876             }
00877             ftab[sb] |= SETMASK;
00878          }
00879       }
00880 
00881       /*--
00882          Step 2:
00883          Deal specially with case [ss, ss].  This establishes the
00884          sorted order for [ss, ss] without any comparisons.  
00885          A clever trick, cryptically described as steps Q6b and Q6c
00886          in SRC-124 (aka BW94).  Compared to bzip2, this makes it
00887          practical not to use a preliminary run-length coder.
00888       --*/
00889       {
00890          Int32 put0, get0, put1, get1;
00891          Int32 sbn = (ss << 8) + ss;
00892          Int32 lo = ftab[sbn] & CLEARMASK;
00893          Int32 hi = (ftab[sbn+1] & CLEARMASK) - 1;
00894          UChar ssc = (UChar)ss;
00895          put0 = lo;
00896          get0 = ftab[ss << 8] & CLEARMASK;
00897          put1 = hi;
00898          get1 = (ftab[(ss+1) << 8] & CLEARMASK) - 1;
00899          while (get0 < put0) {
00900             j = ptr[get0]-1; if (j < 0) j += nblock;
00901             c1 = (UChar)(block[j] >> 8);
00902             if (c1 == ssc) { ptr[put0] = j; put0++; };
00903             get0++;
00904          }
00905          while (get1 > put1) {
00906             j = ptr[get1]-1; if (j < 0) j += nblock;
00907             c1 = (UChar)(block[j] >> 8);
00908             if (c1 == ssc) { ptr[put1] = j; put1--; };
00909             get1--;
00910          }
00911          ftab[sbn] |= SETMASK;
00912       }
00913 
00914       /*--
00915          Step 3:
00916          The [ss] big bucket is now done.  Record this fact,
00917          and update the quadrant descriptors.  Remember to
00918          update quadrants in the overshoot area too, if
00919          necessary.  The "if (i < 255)" test merely skips
00920          this updating for the last bucket processed, since
00921          updating for the last bucket is pointless.
00922 
00923          The quadrant array provides a way to incrementally
00924          cache sort orderings, as they appear, so as to 
00925          make subsequent comparisons in fullGtU() complete
00926          faster.  For repetitive blocks this makes a big
00927          difference (but not big enough to be able to avoid
00928          the fallback sorting mechanism, exponential radix sort).
00929 
00930          The precise meaning is: at all times:
00931 
00932             for 0 <= i < nblock and 0 <= j <= nblock
00933 
00934             if block[i] != block[j], 
00935 
00936                then the relative values of quadrant[i] and 
00937                     quadrant[j] are meaningless.
00938 
00939                else {
00940                   if quadrant[i] < quadrant[j]
00941                      then the string starting at i lexicographically
00942                      precedes the string starting at j
00943 
00944                   else if quadrant[i] > quadrant[j]
00945                      then the string starting at j lexicographically
00946                      precedes the string starting at i
00947 
00948                   else
00949                      the relative ordering of the strings starting
00950                      at i and j has not yet been determined.
00951                }
00952       --*/
00953       bigDone[ss] = True;
00954 
00955       if (i < 255) {
00956          Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
00957          Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
00958          Int32 shifts   = 0;
00959 
00960          while ((bbSize >> shifts) > 65534) shifts++;
00961 
00962          for (j = 0; j < bbSize; j++) {
00963             Int32 a2update     = ptr[bbStart + j];
00964             UInt16 qVal        = (UInt16)(j >> shifts);
00965             quadrant[a2update] = qVal;
00966             if (a2update < BZ_N_OVERSHOOT)
00967                quadrant[a2update + nblock] = qVal;
00968          }
00969          AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
00970       }
00971 
00972       /*--
00973          Step 4:
00974          Now scan this big bucket [ss] so as to synthesise the
00975          sorted order for small buckets [t, ss] for all t != ss.
00976          This will avoid doing Real Work in subsequent Step 1's.
00977       --*/
00978       for (j = 0; j <= 255; j++)
00979          copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
00980 
00981       m = ftab[(ss+1) << 8] & CLEARMASK;
00982       for (j = ftab[ss << 8] & CLEARMASK; j < m; j++) {
00983          k = ptr[j] - 1; if (k < 0) k += nblock;
00984          c1 = (UChar)(block[k] >> 8);
00985          if ( ! bigDone[c1] ) {
00986             ptr[copy[c1]] = k;
00987             copy[c1] ++;
00988          }
00989       }
00990 
00991       for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
00992    }
00993 
00994    if (verb >= 4)
00995       VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
00996                  nblock, numQSorted, nblock - numQSorted );
00997 }

__inline__ UInt16 mmed3 UInt16    a,
UInt16    b,
UInt16    c
[static]
 

Definition at line 574 of file blocksort.c.

Referenced by mainQSort3().

00575 {
00576    UInt16 t;
00577    if (a > b) { t = a; a = b; b = t; };
00578    if (b > c) { t = b; b = c; c = t; };
00579    if (a > b)          b = a;
00580    return b;
00581 }


Variable Documentation

Int32 incs[14]
 

Initial value:

 { 1, 4, 13, 40, 121, 364, 1093, 3280,
                   9841, 29524, 88573, 265720,
                   797161, 2391484 }

Definition at line 470 of file blocksort.c.


Generated on Sat Oct 13 16:08:43 2001 for XMILL by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001