LCOV - code coverage report
Current view: top level - ballet/bzip2 - blocksort.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 639 0.0 %
Date: 2026-06-30 05:50:37 Functions: 0 9 0.0 %

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

Generated by: LCOV version 1.14