annotate 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
rev   line source
rlm@1 1 // PpmdContext.h
rlm@1 2 // This code is based on Dmitry Shkarin's PPMdH code
rlm@1 3
rlm@1 4 #ifndef __COMPRESS_PPMD_CONTEXT_H
rlm@1 5 #define __COMPRESS_PPMD_CONTEXT_H
rlm@1 6
rlm@1 7 #include "../../Common/Types.h"
rlm@1 8
rlm@1 9 #include "PpmdSubAlloc.h"
rlm@1 10 #include "RangeCoder.h"
rlm@1 11
rlm@1 12 namespace NCompress {
rlm@1 13 namespace NPpmd {
rlm@1 14
rlm@1 15 const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
rlm@1 16 INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
rlm@1 17
rlm@1 18 struct SEE2_CONTEXT
rlm@1 19 {
rlm@1 20 // SEE-contexts for PPM-contexts with masked symbols
rlm@1 21 UInt16 Summ;
rlm@1 22 Byte Shift, Count;
rlm@1 23 void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }
rlm@1 24 unsigned int getMean()
rlm@1 25 {
rlm@1 26 unsigned int RetVal=(Summ >> Shift);
rlm@1 27 Summ = (UInt16)(Summ - RetVal);
rlm@1 28 return RetVal+(RetVal == 0);
rlm@1 29 }
rlm@1 30 void update()
rlm@1 31 {
rlm@1 32 if (Shift < PERIOD_BITS && --Count == 0)
rlm@1 33 {
rlm@1 34 Summ <<= 1;
rlm@1 35 Count = (Byte)(3 << Shift++);
rlm@1 36 }
rlm@1 37 }
rlm@1 38 };
rlm@1 39
rlm@1 40 struct PPM_CONTEXT
rlm@1 41 {
rlm@1 42 UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)
rlm@1 43 UInt16 SummFreq;
rlm@1 44
rlm@1 45 struct STATE
rlm@1 46 {
rlm@1 47 Byte Symbol, Freq;
rlm@1 48 UInt16 SuccessorLow;
rlm@1 49 UInt16 SuccessorHigh;
rlm@1 50
rlm@1 51 UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }
rlm@1 52 void SetSuccessor(UInt32 v)
rlm@1 53 {
rlm@1 54 SuccessorLow = (UInt16)(v & 0xFFFF);
rlm@1 55 SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);
rlm@1 56 }
rlm@1 57 };
rlm@1 58
rlm@1 59 UInt32 Stats;
rlm@1 60 UInt32 Suffix;
rlm@1 61
rlm@1 62 PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
rlm@1 63 {
rlm@1 64 PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
rlm@1 65 if (pc)
rlm@1 66 {
rlm@1 67 pc->NumStats = 1;
rlm@1 68 pc->oneState() = FirstState;
rlm@1 69 pc->Suffix = subAllocator.GetOffset(this);
rlm@1 70 pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
rlm@1 71 }
rlm@1 72 return pc;
rlm@1 73 }
rlm@1 74
rlm@1 75 STATE& oneState() const { return (STATE&) SummFreq; }
rlm@1 76 };
rlm@1 77
rlm@1 78 /////////////////////////////////
rlm@1 79
rlm@1 80 const UInt16 InitBinEsc[] =
rlm@1 81 {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
rlm@1 82
rlm@1 83 struct CInfo
rlm@1 84 {
rlm@1 85 CSubAllocator SubAllocator;
rlm@1 86 SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
rlm@1 87 PPM_CONTEXT * MinContext, * MaxContext;
rlm@1 88
rlm@1 89 PPM_CONTEXT::STATE* FoundState; // found next state transition
rlm@1 90 int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
rlm@1 91 Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
rlm@1 92 Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
rlm@1 93 UInt16 BinSumm[128][64]; // binary SEE-contexts
rlm@1 94
rlm@1 95 UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
rlm@1 96 {
rlm@1 97 HiBitsFlag = HB2Flag[FoundState->Symbol];
rlm@1 98 return BinSumm[rs.Freq - 1][
rlm@1 99 PrevSuccess + NS2BSIndx[numStates - 1] +
rlm@1 100 HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
rlm@1 101 ((RunLength >> 26) & 0x20)];
rlm@1 102 }
rlm@1 103
rlm@1 104 PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }
rlm@1 105 PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }
rlm@1 106 PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
rlm@1 107 PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
rlm@1 108
rlm@1 109 void RestartModelRare()
rlm@1 110 {
rlm@1 111 int i, k, m;
rlm@1 112 memset(CharMask,0,sizeof(CharMask));
rlm@1 113 SubAllocator.InitSubAllocator();
rlm@1 114 InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
rlm@1 115 MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
rlm@1 116 MinContext->Suffix = 0;
rlm@1 117 OrderFall = MaxOrder;
rlm@1 118 MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);
rlm@1 119 FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
rlm@1 120 MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
rlm@1 121 PrevSuccess = 0;
rlm@1 122 for (RunLength = InitRL, i = 0; i < 256; i++)
rlm@1 123 {
rlm@1 124 PPM_CONTEXT::STATE &state = FoundState[i];
rlm@1 125 state.Symbol = (Byte)i;
rlm@1 126 state.Freq = 1;
rlm@1 127 state.SetSuccessor(0);
rlm@1 128 }
rlm@1 129 for (i = 0; i < 128; i++)
rlm@1 130 for (k = 0; k < 8; k++)
rlm@1 131 for ( m=0; m < 64; m += 8)
rlm@1 132 BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));
rlm@1 133 for (i = 0; i < 25; i++)
rlm@1 134 for (k = 0; k < 16; k++)
rlm@1 135 SEE2Cont[i][k].init(5*i+10);
rlm@1 136 }
rlm@1 137
rlm@1 138 void StartModelRare(int maxOrder)
rlm@1 139 {
rlm@1 140 int i, k, m ,Step;
rlm@1 141 EscCount=PrintCount=1;
rlm@1 142 if (maxOrder < 2)
rlm@1 143 {
rlm@1 144 memset(CharMask,0,sizeof(CharMask));
rlm@1 145 OrderFall = MaxOrder;
rlm@1 146 MinContext = MaxContext;
rlm@1 147 while (MinContext->Suffix != 0)
rlm@1 148 {
rlm@1 149 MinContext = GetContextNoCheck(MinContext->Suffix);
rlm@1 150 OrderFall--;
rlm@1 151 }
rlm@1 152 FoundState = GetState(MinContext->Stats);
rlm@1 153 MinContext = MaxContext;
rlm@1 154 }
rlm@1 155 else
rlm@1 156 {
rlm@1 157 MaxOrder = maxOrder;
rlm@1 158 RestartModelRare();
rlm@1 159 NS2BSIndx[0] = 2 * 0;
rlm@1 160 NS2BSIndx[1] = 2 * 1;
rlm@1 161 memset(NS2BSIndx + 2, 2 * 2, 9);
rlm@1 162 memset(NS2BSIndx + 11, 2 * 3, 256 - 11);
rlm@1 163 for (i = 0; i < 3; i++)
rlm@1 164 NS2Indx[i] = (Byte)i;
rlm@1 165 for (m = i, k = Step = 1; i < 256; i++)
rlm@1 166 {
rlm@1 167 NS2Indx[i] = (Byte)m;
rlm@1 168 if ( !--k )
rlm@1 169 {
rlm@1 170 k = ++Step;
rlm@1 171 m++;
rlm@1 172 }
rlm@1 173 }
rlm@1 174 memset(HB2Flag, 0, 0x40);
rlm@1 175 memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);
rlm@1 176 DummySEE2Cont.Shift = PERIOD_BITS;
rlm@1 177 }
rlm@1 178 }
rlm@1 179
rlm@1 180 PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
rlm@1 181 {
rlm@1 182 // static UpState declaration bypasses IntelC bug
rlm@1 183 // static PPM_CONTEXT::STATE UpState;
rlm@1 184 PPM_CONTEXT::STATE UpState;
rlm@1 185
rlm@1 186 PPM_CONTEXT *pc = MinContext;
rlm@1 187 PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
rlm@1 188 PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
rlm@1 189 if ( !skip )
rlm@1 190 {
rlm@1 191 *pps++ = FoundState;
rlm@1 192 if ( !pc->Suffix )
rlm@1 193 goto NO_LOOP;
rlm@1 194 }
rlm@1 195 if ( p1 )
rlm@1 196 {
rlm@1 197 p = p1;
rlm@1 198 pc = GetContext(pc->Suffix);
rlm@1 199 goto LOOP_ENTRY;
rlm@1 200 }
rlm@1 201 do
rlm@1 202 {
rlm@1 203 pc = GetContext(pc->Suffix);
rlm@1 204 if (pc->NumStats != 1)
rlm@1 205 {
rlm@1 206 if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
rlm@1 207 do { p++; } while (p->Symbol != FoundState->Symbol);
rlm@1 208 }
rlm@1 209 else
rlm@1 210 p = &(pc->oneState());
rlm@1 211 LOOP_ENTRY:
rlm@1 212 if (GetContext(p->GetSuccessor()) != UpBranch)
rlm@1 213 {
rlm@1 214 pc = GetContext(p->GetSuccessor());
rlm@1 215 break;
rlm@1 216 }
rlm@1 217 *pps++ = p;
rlm@1 218 }
rlm@1 219 while ( pc->Suffix );
rlm@1 220 NO_LOOP:
rlm@1 221 if (pps == ps)
rlm@1 222 return pc;
rlm@1 223 UpState.Symbol = *(Byte*) UpBranch;
rlm@1 224 UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
rlm@1 225 if (pc->NumStats != 1)
rlm@1 226 {
rlm@1 227 if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)
rlm@1 228 do { p++; } while (p->Symbol != UpState.Symbol);
rlm@1 229 unsigned int cf = p->Freq-1;
rlm@1 230 unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
rlm@1 231 UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :
rlm@1 232 ((2 * cf + 3 * s0 - 1) / (2 * s0))));
rlm@1 233 }
rlm@1 234 else
rlm@1 235 UpState.Freq = pc->oneState().Freq;
rlm@1 236 do
rlm@1 237 {
rlm@1 238 pc = pc->createChild(SubAllocator, *--pps, UpState);
rlm@1 239 if ( !pc )
rlm@1 240 return NULL;
rlm@1 241 }
rlm@1 242 while (pps != ps);
rlm@1 243 return pc;
rlm@1 244 }
rlm@1 245
rlm@1 246 void UpdateModel()
rlm@1 247 {
rlm@1 248 PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;
rlm@1 249 PPM_CONTEXT* pc, * Successor;
rlm@1 250 unsigned int ns1, ns, cf, sf, s0;
rlm@1 251 if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)
rlm@1 252 {
rlm@1 253 pc = GetContextNoCheck(MinContext->Suffix);
rlm@1 254
rlm@1 255 if (pc->NumStats != 1)
rlm@1 256 {
rlm@1 257 if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)
rlm@1 258 {
rlm@1 259 do { p++; } while (p->Symbol != fs.Symbol);
rlm@1 260 if (p[0].Freq >= p[-1].Freq)
rlm@1 261 {
rlm@1 262 _PPMD_SWAP(p[0],p[-1]);
rlm@1 263 p--;
rlm@1 264 }
rlm@1 265 }
rlm@1 266 if (p->Freq < MAX_FREQ-9)
rlm@1 267 {
rlm@1 268 p->Freq += 2;
rlm@1 269 pc->SummFreq += 2;
rlm@1 270 }
rlm@1 271 }
rlm@1 272 else
rlm@1 273 {
rlm@1 274 p = &(pc->oneState());
rlm@1 275 p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0));
rlm@1 276 }
rlm@1 277 }
rlm@1 278 if ( !OrderFall )
rlm@1 279 {
rlm@1 280 MinContext = MaxContext = CreateSuccessors(true, p);
rlm@1 281 FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));
rlm@1 282 if (MinContext == 0)
rlm@1 283 goto RESTART_MODEL;
rlm@1 284 return;
rlm@1 285 }
rlm@1 286 *SubAllocator.pText++ = fs.Symbol;
rlm@1 287 Successor = (PPM_CONTEXT*) SubAllocator.pText;
rlm@1 288 if (SubAllocator.pText >= SubAllocator.UnitsStart)
rlm@1 289 goto RESTART_MODEL;
rlm@1 290 if (fs.GetSuccessor() != 0)
rlm@1 291 {
rlm@1 292 if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)
rlm@1 293 {
rlm@1 294 PPM_CONTEXT* cs = CreateSuccessors(false, p);
rlm@1 295 fs.SetSuccessor(SubAllocator.GetOffset(cs));
rlm@1 296 if (cs == NULL)
rlm@1 297 goto RESTART_MODEL;
rlm@1 298 }
rlm@1 299 if ( !--OrderFall )
rlm@1 300 {
rlm@1 301 Successor = GetContext(fs.GetSuccessor());
rlm@1 302 SubAllocator.pText -= (MaxContext != MinContext);
rlm@1 303 }
rlm@1 304 }
rlm@1 305 else
rlm@1 306 {
rlm@1 307 FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));
rlm@1 308 fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));
rlm@1 309 }
rlm@1 310 s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);
rlm@1 311 for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))
rlm@1 312 {
rlm@1 313 if ((ns1 = pc->NumStats) != 1)
rlm@1 314 {
rlm@1 315 if ((ns1 & 1) == 0)
rlm@1 316 {
rlm@1 317 void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);
rlm@1 318 pc->Stats = SubAllocator.GetOffset(ppp);
rlm@1 319 if (!ppp)
rlm@1 320 goto RESTART_MODEL;
rlm@1 321 }
rlm@1 322 pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &
rlm@1 323 (pc->SummFreq <= 8 * ns1)));
rlm@1 324 }
rlm@1 325 else
rlm@1 326 {
rlm@1 327 p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);
rlm@1 328 if ( !p )
rlm@1 329 goto RESTART_MODEL;
rlm@1 330 *p = pc->oneState();
rlm@1 331 pc->Stats = SubAllocator.GetOffsetNoCheck(p);
rlm@1 332 if (p->Freq < MAX_FREQ / 4 - 1)
rlm@1 333 p->Freq <<= 1;
rlm@1 334 else
rlm@1 335 p->Freq = MAX_FREQ - 4;
rlm@1 336 pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3));
rlm@1 337 }
rlm@1 338 cf = 2 * fs.Freq * (pc->SummFreq+6);
rlm@1 339 sf = s0 + pc->SummFreq;
rlm@1 340 if (cf < 6 * sf)
rlm@1 341 {
rlm@1 342 cf = 1 + (cf > sf)+(cf >= 4 * sf);
rlm@1 343 pc->SummFreq += 3;
rlm@1 344 }
rlm@1 345 else
rlm@1 346 {
rlm@1 347 cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
rlm@1 348 pc->SummFreq = (UInt16)(pc->SummFreq + cf);
rlm@1 349 }
rlm@1 350 p = GetState(pc->Stats) + ns1;
rlm@1 351 p->SetSuccessor(SubAllocator.GetOffset(Successor));
rlm@1 352 p->Symbol = fs.Symbol;
rlm@1 353 p->Freq = (Byte)cf;
rlm@1 354 pc->NumStats = (UInt16)++ns1;
rlm@1 355 }
rlm@1 356 MaxContext = MinContext = GetContext(fs.GetSuccessor());
rlm@1 357 return;
rlm@1 358 RESTART_MODEL:
rlm@1 359 RestartModelRare();
rlm@1 360 EscCount = 0;
rlm@1 361 PrintCount = 0xFF;
rlm@1 362 }
rlm@1 363
rlm@1 364 void ClearMask()
rlm@1 365 {
rlm@1 366 EscCount = 1;
rlm@1 367 memset(CharMask, 0, sizeof(CharMask));
rlm@1 368 // if (++PrintCount == 0)
rlm@1 369 // PrintInfo(DecodedFile,EncodedFile);
rlm@1 370 }
rlm@1 371
rlm@1 372 void update1(PPM_CONTEXT::STATE* p)
rlm@1 373 {
rlm@1 374 (FoundState = p)->Freq += 4;
rlm@1 375 MinContext->SummFreq += 4;
rlm@1 376 if (p[0].Freq > p[-1].Freq)
rlm@1 377 {
rlm@1 378 _PPMD_SWAP(p[0],p[-1]);
rlm@1 379 FoundState = --p;
rlm@1 380 if (p->Freq > MAX_FREQ)
rlm@1 381 rescale();
rlm@1 382 }
rlm@1 383 }
rlm@1 384
rlm@1 385
rlm@1 386 void update2(PPM_CONTEXT::STATE* p)
rlm@1 387 {
rlm@1 388 (FoundState = p)->Freq += 4;
rlm@1 389 MinContext->SummFreq += 4;
rlm@1 390 if (p->Freq > MAX_FREQ)
rlm@1 391 rescale();
rlm@1 392 EscCount++;
rlm@1 393 RunLength = InitRL;
rlm@1 394 }
rlm@1 395
rlm@1 396 SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)
rlm@1 397 {
rlm@1 398 SEE2_CONTEXT* psee2c;
rlm@1 399 if (MinContext->NumStats != 256)
rlm@1 400 {
rlm@1 401 psee2c = SEE2Cont[NS2Indx[Diff-1]] +
rlm@1 402 (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +
rlm@1 403 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +
rlm@1 404 4 * (NumMasked > Diff) +
rlm@1 405 HiBitsFlag;
rlm@1 406 scale = psee2c->getMean();
rlm@1 407 }
rlm@1 408 else
rlm@1 409 {
rlm@1 410 psee2c = &DummySEE2Cont;
rlm@1 411 scale = 1;
rlm@1 412 }
rlm@1 413 return psee2c;
rlm@1 414 }
rlm@1 415
rlm@1 416
rlm@1 417
rlm@1 418 void rescale()
rlm@1 419 {
rlm@1 420 int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;
rlm@1 421 PPM_CONTEXT::STATE* p1, * p;
rlm@1 422 PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);
rlm@1 423 for (p = FoundState; p != stats; p--)
rlm@1 424 _PPMD_SWAP(p[0], p[-1]);
rlm@1 425 stats->Freq += 4;
rlm@1 426 MinContext->SummFreq += 4;
rlm@1 427 EscFreq = MinContext->SummFreq - p->Freq;
rlm@1 428 Adder = (OrderFall != 0);
rlm@1 429 p->Freq = (Byte)((p->Freq + Adder) >> 1);
rlm@1 430 MinContext->SummFreq = p->Freq;
rlm@1 431 do
rlm@1 432 {
rlm@1 433 EscFreq -= (++p)->Freq;
rlm@1 434 p->Freq = (Byte)((p->Freq + Adder) >> 1);
rlm@1 435 MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq);
rlm@1 436 if (p[0].Freq > p[-1].Freq)
rlm@1 437 {
rlm@1 438 PPM_CONTEXT::STATE tmp = *(p1 = p);
rlm@1 439 do
rlm@1 440 {
rlm@1 441 p1[0] = p1[-1];
rlm@1 442 }
rlm@1 443 while (--p1 != stats && tmp.Freq > p1[-1].Freq);
rlm@1 444 *p1 = tmp;
rlm@1 445 }
rlm@1 446 }
rlm@1 447 while ( --i );
rlm@1 448 if (p->Freq == 0)
rlm@1 449 {
rlm@1 450 do { i++; } while ((--p)->Freq == 0);
rlm@1 451 EscFreq += i;
rlm@1 452 MinContext->NumStats = (UInt16)(MinContext->NumStats - i);
rlm@1 453 if (MinContext->NumStats == 1)
rlm@1 454 {
rlm@1 455 PPM_CONTEXT::STATE tmp = *stats;
rlm@1 456 do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1);
rlm@1 457 SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);
rlm@1 458 *(FoundState = &MinContext->oneState()) = tmp; return;
rlm@1 459 }
rlm@1 460 }
rlm@1 461 EscFreq -= (EscFreq >> 1);
rlm@1 462 MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq);
rlm@1 463 int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;
rlm@1 464 if (n0 != n1)
rlm@1 465 MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));
rlm@1 466 FoundState = GetState(MinContext->Stats);
rlm@1 467 }
rlm@1 468
rlm@1 469 void NextContext()
rlm@1 470 {
rlm@1 471 PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());
rlm@1 472 if (!OrderFall && (Byte *)c > SubAllocator.pText)
rlm@1 473 MinContext = MaxContext = c;
rlm@1 474 else
rlm@1 475 {
rlm@1 476 UpdateModel();
rlm@1 477 if (EscCount == 0)
rlm@1 478 ClearMask();
rlm@1 479 }
rlm@1 480 }
rlm@1 481 };
rlm@1 482
rlm@1 483 // Tabulated escapes for exponential symbol distribution
rlm@1 484 const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
rlm@1 485 #define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
rlm@1 486
rlm@1 487 }}
rlm@1 488
rlm@1 489 #endif