diff src/win32/7zip/7z/CPP/7zip/Compress/PpmdContext.h @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/PpmdContext.h	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,489 @@
     1.4 +// PpmdContext.h
     1.5 +// This code is based on Dmitry Shkarin's PPMdH code
     1.6 +
     1.7 +#ifndef __COMPRESS_PPMD_CONTEXT_H
     1.8 +#define __COMPRESS_PPMD_CONTEXT_H
     1.9 +
    1.10 +#include "../../Common/Types.h"
    1.11 +
    1.12 +#include "PpmdSubAlloc.h"
    1.13 +#include "RangeCoder.h"
    1.14 +
    1.15 +namespace NCompress {
    1.16 +namespace NPpmd {
    1.17 +
    1.18 +const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
    1.19 +        INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
    1.20 +
    1.21 +struct SEE2_CONTEXT
    1.22 +{
    1.23 +  // SEE-contexts for PPM-contexts with masked symbols
    1.24 +  UInt16 Summ;
    1.25 +  Byte Shift, Count;
    1.26 +  void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }
    1.27 +  unsigned int getMean()
    1.28 +  {
    1.29 +    unsigned int RetVal=(Summ >> Shift);
    1.30 +    Summ = (UInt16)(Summ - RetVal);
    1.31 +    return RetVal+(RetVal == 0);
    1.32 +  }
    1.33 +  void update()
    1.34 +  {
    1.35 +    if (Shift < PERIOD_BITS && --Count == 0)
    1.36 +    {
    1.37 +      Summ <<= 1;
    1.38 +      Count = (Byte)(3 << Shift++);
    1.39 +    }
    1.40 +  }
    1.41 +};
    1.42 +
    1.43 +struct PPM_CONTEXT
    1.44 +{
    1.45 +  UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)
    1.46 +  UInt16 SummFreq;
    1.47 +  
    1.48 +  struct STATE
    1.49 +  {
    1.50 +    Byte Symbol, Freq;
    1.51 +    UInt16 SuccessorLow;
    1.52 +    UInt16 SuccessorHigh;
    1.53 +
    1.54 +    UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }
    1.55 +    void SetSuccessor(UInt32 v)
    1.56 +    {
    1.57 +      SuccessorLow = (UInt16)(v & 0xFFFF);
    1.58 +      SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);
    1.59 +    }
    1.60 +  };
    1.61 +  
    1.62 +  UInt32 Stats;
    1.63 +  UInt32 Suffix;
    1.64 +  
    1.65 +  PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
    1.66 +  {
    1.67 +    PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
    1.68 +    if (pc)
    1.69 +    {
    1.70 +      pc->NumStats = 1;
    1.71 +      pc->oneState() = FirstState;
    1.72 +      pc->Suffix = subAllocator.GetOffset(this);
    1.73 +      pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
    1.74 +    }
    1.75 +    return pc;
    1.76 +  }
    1.77 +
    1.78 +  STATE& oneState() const { return (STATE&) SummFreq; }
    1.79 +};
    1.80 +
    1.81 +/////////////////////////////////
    1.82 +
    1.83 +const UInt16 InitBinEsc[] =
    1.84 +  {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
    1.85 +
    1.86 +struct CInfo
    1.87 +{
    1.88 +  CSubAllocator SubAllocator;
    1.89 +  SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
    1.90 +  PPM_CONTEXT * MinContext, * MaxContext;
    1.91 +
    1.92 +  PPM_CONTEXT::STATE* FoundState;      // found next state transition
    1.93 +  int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
    1.94 +  Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
    1.95 +  Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
    1.96 +  UInt16 BinSumm[128][64];               // binary SEE-contexts
    1.97 +
    1.98 +  UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
    1.99 +  {
   1.100 +    HiBitsFlag = HB2Flag[FoundState->Symbol];
   1.101 +    return BinSumm[rs.Freq - 1][
   1.102 +         PrevSuccess + NS2BSIndx[numStates - 1] +
   1.103 +         HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
   1.104 +         ((RunLength >> 26) & 0x20)];
   1.105 +  }
   1.106 +
   1.107 +  PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }
   1.108 +  PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }
   1.109 +  PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
   1.110 +  PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
   1.111 +
   1.112 +  void RestartModelRare()
   1.113 +  {
   1.114 +    int i, k, m;
   1.115 +    memset(CharMask,0,sizeof(CharMask));
   1.116 +    SubAllocator.InitSubAllocator();
   1.117 +    InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
   1.118 +    MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
   1.119 +    MinContext->Suffix = 0;
   1.120 +    OrderFall = MaxOrder;
   1.121 +    MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);
   1.122 +    FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
   1.123 +    MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
   1.124 +    PrevSuccess = 0;
   1.125 +    for (RunLength = InitRL, i = 0; i < 256; i++)
   1.126 +    {
   1.127 +      PPM_CONTEXT::STATE &state = FoundState[i];
   1.128 +      state.Symbol = (Byte)i;
   1.129 +      state.Freq = 1;
   1.130 +      state.SetSuccessor(0);
   1.131 +    }
   1.132 +    for (i = 0; i < 128; i++)
   1.133 +        for (k = 0; k < 8; k++)
   1.134 +            for ( m=0; m < 64; m += 8)
   1.135 +                BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));
   1.136 +    for (i = 0; i < 25; i++)
   1.137 +        for (k = 0; k < 16; k++)
   1.138 +            SEE2Cont[i][k].init(5*i+10);
   1.139 +  }
   1.140 +
   1.141 +  void StartModelRare(int maxOrder)
   1.142 +  {
   1.143 +    int i, k, m ,Step;
   1.144 +    EscCount=PrintCount=1;
   1.145 +    if (maxOrder < 2)
   1.146 +    {
   1.147 +        memset(CharMask,0,sizeof(CharMask));
   1.148 +        OrderFall = MaxOrder;
   1.149 +        MinContext = MaxContext;
   1.150 +        while (MinContext->Suffix != 0)
   1.151 +        {
   1.152 +          MinContext = GetContextNoCheck(MinContext->Suffix);
   1.153 +          OrderFall--;
   1.154 +        }
   1.155 +        FoundState = GetState(MinContext->Stats);
   1.156 +        MinContext = MaxContext;
   1.157 +    }
   1.158 +    else
   1.159 +    {
   1.160 +        MaxOrder = maxOrder;
   1.161 +        RestartModelRare();
   1.162 +        NS2BSIndx[0] = 2 * 0;
   1.163 +        NS2BSIndx[1] = 2 * 1;
   1.164 +        memset(NS2BSIndx + 2, 2 * 2, 9);
   1.165 +        memset(NS2BSIndx + 11, 2 * 3, 256 - 11);
   1.166 +        for (i = 0; i < 3; i++)
   1.167 +          NS2Indx[i] = (Byte)i;
   1.168 +        for (m = i, k = Step = 1; i < 256; i++)
   1.169 +        {
   1.170 +            NS2Indx[i] = (Byte)m;
   1.171 +            if ( !--k )
   1.172 +            {
   1.173 +              k = ++Step;
   1.174 +              m++;
   1.175 +            }
   1.176 +        }
   1.177 +        memset(HB2Flag, 0, 0x40);
   1.178 +        memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);
   1.179 +        DummySEE2Cont.Shift = PERIOD_BITS;
   1.180 +    }
   1.181 +  }
   1.182 +
   1.183 +  PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
   1.184 +  {
   1.185 +    // static UpState declaration bypasses IntelC bug
   1.186 +    // static PPM_CONTEXT::STATE UpState;
   1.187 +    PPM_CONTEXT::STATE UpState;
   1.188 +
   1.189 +    PPM_CONTEXT *pc = MinContext;
   1.190 +    PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
   1.191 +    PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
   1.192 +    if ( !skip )
   1.193 +    {
   1.194 +        *pps++ = FoundState;
   1.195 +        if ( !pc->Suffix )
   1.196 +          goto NO_LOOP;
   1.197 +    }
   1.198 +    if ( p1 )
   1.199 +    {
   1.200 +        p = p1;
   1.201 +        pc = GetContext(pc->Suffix);
   1.202 +        goto LOOP_ENTRY;
   1.203 +    }
   1.204 +    do
   1.205 +    {
   1.206 +        pc = GetContext(pc->Suffix);
   1.207 +        if (pc->NumStats != 1)
   1.208 +        {
   1.209 +            if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
   1.210 +                do { p++; } while (p->Symbol != FoundState->Symbol);
   1.211 +        }
   1.212 +        else
   1.213 +          p = &(pc->oneState());
   1.214 +LOOP_ENTRY:
   1.215 +        if (GetContext(p->GetSuccessor()) != UpBranch)
   1.216 +        {
   1.217 +            pc = GetContext(p->GetSuccessor());
   1.218 +            break;
   1.219 +        }
   1.220 +        *pps++ = p;
   1.221 +    }
   1.222 +    while ( pc->Suffix );
   1.223 +NO_LOOP:
   1.224 +    if (pps == ps)
   1.225 +      return pc;
   1.226 +    UpState.Symbol = *(Byte*) UpBranch;
   1.227 +    UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
   1.228 +    if (pc->NumStats != 1)
   1.229 +    {
   1.230 +        if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)
   1.231 +                do { p++; } while (p->Symbol != UpState.Symbol);
   1.232 +        unsigned int cf = p->Freq-1;
   1.233 +        unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
   1.234 +        UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :
   1.235 +            ((2 * cf + 3 * s0 - 1) / (2 * s0))));
   1.236 +    }
   1.237 +    else
   1.238 +      UpState.Freq = pc->oneState().Freq;
   1.239 +    do
   1.240 +    {
   1.241 +        pc = pc->createChild(SubAllocator, *--pps, UpState);
   1.242 +        if ( !pc )
   1.243 +          return NULL;
   1.244 +    }
   1.245 +    while (pps != ps);
   1.246 +    return pc;
   1.247 +  }
   1.248 +
   1.249 +  void UpdateModel()
   1.250 +  {
   1.251 +    PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
   1.252 +    PPM_CONTEXT* pc, * Successor;
   1.253 +    unsigned int ns1, ns, cf, sf, s0;
   1.254 +    if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)
   1.255 +    {
   1.256 +        pc = GetContextNoCheck(MinContext->Suffix);
   1.257 +      
   1.258 +        if (pc->NumStats != 1)
   1.259 +        {
   1.260 +            if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)
   1.261 +            {
   1.262 +                do { p++; } while (p->Symbol != fs.Symbol);
   1.263 +                if (p[0].Freq >= p[-1].Freq)
   1.264 +                {
   1.265 +                    _PPMD_SWAP(p[0],p[-1]);
   1.266 +                    p--;
   1.267 +                }
   1.268 +            }
   1.269 +            if (p->Freq < MAX_FREQ-9)
   1.270 +            {
   1.271 +                p->Freq += 2;
   1.272 +                pc->SummFreq += 2;
   1.273 +            }
   1.274 +        }
   1.275 +        else
   1.276 +        {
   1.277 +            p = &(pc->oneState());
   1.278 +            p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0));
   1.279 +        }
   1.280 +    }
   1.281 +    if ( !OrderFall )
   1.282 +    {
   1.283 +        MinContext = MaxContext = CreateSuccessors(true, p);
   1.284 +        FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));
   1.285 +        if (MinContext == 0)
   1.286 +          goto RESTART_MODEL;
   1.287 +        return;
   1.288 +    }
   1.289 +    *SubAllocator.pText++ = fs.Symbol;
   1.290 +    Successor = (PPM_CONTEXT*) SubAllocator.pText;
   1.291 +    if (SubAllocator.pText >= SubAllocator.UnitsStart)
   1.292 +      goto RESTART_MODEL;
   1.293 +    if (fs.GetSuccessor() != 0)
   1.294 +    {
   1.295 +        if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)
   1.296 +        {
   1.297 +          PPM_CONTEXT* cs = CreateSuccessors(false, p);
   1.298 +          fs.SetSuccessor(SubAllocator.GetOffset(cs));
   1.299 +          if (cs == NULL)
   1.300 +            goto RESTART_MODEL;
   1.301 +        }
   1.302 +        if ( !--OrderFall )
   1.303 +        {
   1.304 +            Successor = GetContext(fs.GetSuccessor());
   1.305 +            SubAllocator.pText -= (MaxContext != MinContext);
   1.306 +        }
   1.307 +    }
   1.308 +    else
   1.309 +    {
   1.310 +        FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));
   1.311 +        fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));
   1.312 +    }
   1.313 +    s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);
   1.314 +    for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))
   1.315 +    {
   1.316 +        if ((ns1 = pc->NumStats) != 1)
   1.317 +        {
   1.318 +            if ((ns1 & 1) == 0)
   1.319 +            {
   1.320 +                void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);
   1.321 +                pc->Stats = SubAllocator.GetOffset(ppp);
   1.322 +                if (!ppp)
   1.323 +                  goto RESTART_MODEL;
   1.324 +            }
   1.325 +            pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &
   1.326 +                    (pc->SummFreq <= 8 * ns1)));
   1.327 +        }
   1.328 +        else
   1.329 +        {
   1.330 +            p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);
   1.331 +            if ( !p )
   1.332 +              goto RESTART_MODEL;
   1.333 +            *p = pc->oneState();
   1.334 +            pc->Stats = SubAllocator.GetOffsetNoCheck(p);
   1.335 +            if (p->Freq < MAX_FREQ / 4 - 1)
   1.336 +              p->Freq <<= 1;
   1.337 +            else
   1.338 +              p->Freq  = MAX_FREQ - 4;
   1.339 +            pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3));
   1.340 +        }
   1.341 +        cf = 2 * fs.Freq * (pc->SummFreq+6);
   1.342 +        sf = s0 + pc->SummFreq;
   1.343 +        if (cf < 6 * sf)
   1.344 +        {
   1.345 +            cf = 1 + (cf > sf)+(cf >= 4 * sf);
   1.346 +            pc->SummFreq += 3;
   1.347 +        }
   1.348 +        else
   1.349 +        {
   1.350 +            cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
   1.351 +            pc->SummFreq = (UInt16)(pc->SummFreq + cf);
   1.352 +        }
   1.353 +        p = GetState(pc->Stats) + ns1;
   1.354 +        p->SetSuccessor(SubAllocator.GetOffset(Successor));
   1.355 +        p->Symbol = fs.Symbol;
   1.356 +        p->Freq = (Byte)cf;
   1.357 +        pc->NumStats = (UInt16)++ns1;
   1.358 +    }
   1.359 +    MaxContext = MinContext = GetContext(fs.GetSuccessor());
   1.360 +    return;
   1.361 +RESTART_MODEL:
   1.362 +    RestartModelRare();
   1.363 +    EscCount = 0;
   1.364 +    PrintCount = 0xFF;
   1.365 +  }
   1.366 +
   1.367 +  void ClearMask()
   1.368 +  {
   1.369 +    EscCount = 1;
   1.370 +    memset(CharMask, 0, sizeof(CharMask));
   1.371 +    // if (++PrintCount == 0)
   1.372 +    //   PrintInfo(DecodedFile,EncodedFile);
   1.373 +  }
   1.374 +
   1.375 +  void update1(PPM_CONTEXT::STATE* p)
   1.376 +  {
   1.377 +    (FoundState = p)->Freq += 4;
   1.378 +    MinContext->SummFreq += 4;
   1.379 +    if (p[0].Freq > p[-1].Freq)
   1.380 +    {
   1.381 +        _PPMD_SWAP(p[0],p[-1]);
   1.382 +        FoundState = --p;
   1.383 +        if (p->Freq > MAX_FREQ)
   1.384 +          rescale();
   1.385 +    }
   1.386 +  }
   1.387 +
   1.388 +
   1.389 +  void update2(PPM_CONTEXT::STATE* p)
   1.390 +  {
   1.391 +    (FoundState = p)->Freq += 4;
   1.392 +    MinContext->SummFreq += 4;
   1.393 +    if (p->Freq > MAX_FREQ)
   1.394 +      rescale();
   1.395 +    EscCount++;
   1.396 +    RunLength = InitRL;
   1.397 +  }
   1.398 +  
   1.399 +  SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)
   1.400 +  {
   1.401 +    SEE2_CONTEXT* psee2c;
   1.402 +    if (MinContext->NumStats != 256)
   1.403 +    {
   1.404 +      psee2c = SEE2Cont[NS2Indx[Diff-1]] +
   1.405 +        (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +
   1.406 +        2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +
   1.407 +        4 * (NumMasked > Diff) +
   1.408 +        HiBitsFlag;
   1.409 +      scale = psee2c->getMean();
   1.410 +    }
   1.411 +    else
   1.412 +    {
   1.413 +      psee2c = &DummySEE2Cont;
   1.414 +      scale = 1;
   1.415 +    }
   1.416 +    return psee2c;
   1.417 +  }
   1.418 +
   1.419 +
   1.420 +
   1.421 +  void rescale()
   1.422 +  {
   1.423 +    int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;
   1.424 +    PPM_CONTEXT::STATE* p1, * p;
   1.425 +    PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);
   1.426 +    for (p = FoundState; p != stats; p--)
   1.427 +      _PPMD_SWAP(p[0], p[-1]);
   1.428 +    stats->Freq += 4;
   1.429 +    MinContext->SummFreq += 4;
   1.430 +    EscFreq = MinContext->SummFreq - p->Freq;
   1.431 +    Adder = (OrderFall != 0);
   1.432 +    p->Freq = (Byte)((p->Freq + Adder) >> 1);
   1.433 +    MinContext->SummFreq = p->Freq;
   1.434 +    do
   1.435 +    {
   1.436 +        EscFreq -= (++p)->Freq;
   1.437 +        p->Freq = (Byte)((p->Freq + Adder) >> 1);
   1.438 +        MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq);
   1.439 +        if (p[0].Freq > p[-1].Freq)
   1.440 +        {
   1.441 +            PPM_CONTEXT::STATE tmp = *(p1 = p);
   1.442 +            do
   1.443 +            {
   1.444 +              p1[0] = p1[-1];
   1.445 +            }
   1.446 +            while (--p1 != stats && tmp.Freq > p1[-1].Freq);
   1.447 +            *p1 = tmp;
   1.448 +        }
   1.449 +    }
   1.450 +    while ( --i );
   1.451 +    if (p->Freq == 0)
   1.452 +    {
   1.453 +        do { i++; } while ((--p)->Freq == 0);
   1.454 +        EscFreq += i;
   1.455 +        MinContext->NumStats = (UInt16)(MinContext->NumStats - i);
   1.456 +        if (MinContext->NumStats == 1)
   1.457 +        {
   1.458 +            PPM_CONTEXT::STATE tmp = *stats;
   1.459 +            do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1);
   1.460 +            SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);
   1.461 +            *(FoundState = &MinContext->oneState()) = tmp;  return;
   1.462 +        }
   1.463 +    }
   1.464 +    EscFreq -= (EscFreq >> 1);
   1.465 +    MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq);
   1.466 +    int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;
   1.467 +    if (n0 != n1)
   1.468 +      MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));
   1.469 +    FoundState = GetState(MinContext->Stats);
   1.470 +  }
   1.471 +
   1.472 +  void NextContext()
   1.473 +  {
   1.474 +    PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());
   1.475 +    if (!OrderFall && (Byte *)c > SubAllocator.pText)
   1.476 +      MinContext = MaxContext = c;
   1.477 +    else
   1.478 +    {
   1.479 +      UpdateModel();
   1.480 +      if (EscCount == 0)
   1.481 +        ClearMask();
   1.482 +    }
   1.483 +  }
   1.484 +};
   1.485 +
   1.486 +// Tabulated escapes for exponential symbol distribution
   1.487 +const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
   1.488 +#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
   1.489 +
   1.490 +}}
   1.491 +
   1.492 +#endif