1 /****************************************************************************
2 * This file is part of PPMd project *
3 * Written and distributed to public domain by Dmitry Shkarin 1997, *
5 * Contents: model description and encoding/decoding routines *
6 ****************************************************************************/
8 inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
11 PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
15 pc->OneState=FirstState;
31 void ModelPPM::RestartModelRare()
34 memset(CharMask,0,sizeof(CharMask));
35 SubAlloc.InitSubAllocator();
36 InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
37 MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
40 MinContext->Suffix=NULL;
42 MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
43 FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
44 for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
46 MinContext->U.Stats[i].Symbol=i;
47 MinContext->U.Stats[i].Freq=1;
48 MinContext->U.Stats[i].Successor=NULL;
51 static const ushort InitBinEsc[]={
52 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
57 for (m=0;m < 64;m += 8)
58 BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
61 SEE2Cont[i][k].init(5*i+10);
65 void ModelPPM::StartModelRare(int MaxOrder)
72 memset(CharMask,0,sizeof(CharMask));
73 OrderFall=ModelPPM::MaxOrder;
74 MinContext=MaxContext;
75 while (MinContext->Suffix != NULL)
77 MinContext=MinContext->Suffix;
80 FoundState=MinContext->U.Stats;
81 MinContext=MaxContext;
86 ModelPPM::MaxOrder=MaxOrder;
90 memset(NS2BSIndx+2,2*2,9);
91 memset(NS2BSIndx+11,2*3,256-11);
94 for (m=i, k=Step=1;i < 256;i++)
103 memset(HB2Flag,0,0x40);
104 memset(HB2Flag+0x40,0x08,0x100-0x40);
105 DummySEE2Cont.Shift=PERIOD_BITS;
110 void PPM_CONTEXT::rescale(ModelPPM *Model)
112 int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
114 for (p=Model->FoundState;p != U.Stats;p--)
115 _PPMD_SWAP(p[0],p[-1]);
118 EscFreq=U.SummFreq-p->Freq;
119 Adder=(Model->OrderFall != 0);
120 U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
123 EscFreq -= (++p)->Freq;
124 U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
125 if (p[0].Freq > p[-1].Freq)
131 } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
140 } while ((--p)->Freq == 0);
142 if ((NumStats -= i) == 1)
147 tmp.Freq-=(tmp.Freq >> 1);
149 } while (EscFreq > 1);
150 Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
151 *(Model->FoundState=&OneState)=tmp; return;
154 U.SummFreq += (EscFreq -= (EscFreq >> 1));
155 int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
157 U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
158 Model->FoundState=U.Stats;
162 inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
168 PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
169 STATE * p, * ps[MAX_O], ** pps=ps;
185 if (pc->NumStats != 1)
187 if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
191 } while (p->Symbol != FoundState->Symbol);
196 if (p->Successor != UpBranch)
202 } while ( pc->Suffix );
206 UpState.Symbol=*(byte*) UpBranch;
207 UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
208 if (pc->NumStats != 1)
210 if ((byte*) pc <= SubAlloc.pText)
212 if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
216 } while (p->Symbol != UpState.Symbol);
218 uint s0=pc->U.SummFreq-pc->NumStats-cf;
219 UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
222 UpState.Freq=pc->OneState.Freq;
225 pc = pc->createChild(this,*--pps,UpState);
233 inline void ModelPPM::UpdateModel()
235 STATE fs = *FoundState, *p = NULL;
236 PPM_CONTEXT *pc, *Successor;
237 uint ns1, ns, cf, sf, s0;
238 if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
240 if (pc->NumStats != 1)
242 if ((p=pc->U.Stats)->Symbol != fs.Symbol)
247 } while (p->Symbol != fs.Symbol);
248 if (p[0].Freq >= p[-1].Freq)
250 _PPMD_SWAP(p[0],p[-1]);
254 if (p->Freq < MAX_FREQ-9)
263 p->Freq += (p->Freq < 32);
268 MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
273 *SubAlloc.pText++ = fs.Symbol;
274 Successor = (PPM_CONTEXT*) SubAlloc.pText;
275 if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
279 if ((byte*) fs.Successor <= SubAlloc.pText &&
280 (fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
284 Successor=fs.Successor;
285 SubAlloc.pText -= (MaxContext != MinContext);
290 FoundState->Successor=Successor;
291 fs.Successor=MinContext;
293 s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
294 for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
296 if ((ns1=pc->NumStats) != 1)
300 pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
304 pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
308 p=(STATE*) SubAlloc.AllocUnits(1);
313 if (p->Freq < MAX_FREQ/4-1)
316 p->Freq = MAX_FREQ-4;
317 pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
319 cf=2*fs.Freq*(pc->U.SummFreq+6);
320 sf=s0+pc->U.SummFreq;
323 cf=1+(cf > sf)+(cf >= 4*sf);
328 cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
329 pc->U.SummFreq += cf;
332 p->Successor=Successor;
333 p->Symbol = fs.Symbol;
337 MaxContext=MinContext=fs.Successor;
345 // Tabulated escapes for exponential symbol distribution
346 static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
347 #define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
351 inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
354 Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
355 ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
356 Model->NS2BSIndx[Suffix->NumStats-1]+
357 Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
358 ((Model->RunLength >> 26) & 0x20)];
359 if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
361 Model->FoundState=&rs;
362 rs.Freq += (rs.Freq < 128);
363 Model->Coder.SubRange.LowCount=0;
364 Model->Coder.SubRange.HighCount=bs;
365 bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
366 Model->PrevSuccess=1;
371 Model->Coder.SubRange.LowCount=bs;
372 bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
373 Model->Coder.SubRange.HighCount=BIN_SCALE;
374 Model->InitEsc=ExpEscape[bs >> 10];
376 Model->CharMask[rs.Symbol]=Model->EscCount;
377 Model->PrevSuccess=0;
378 Model->FoundState=NULL;
383 inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
385 (Model->FoundState=p)->Freq += 4;
387 if (p[0].Freq > p[-1].Freq)
389 _PPMD_SWAP(p[0],p[-1]);
390 Model->FoundState=--p;
391 if (p->Freq > MAX_FREQ)
399 inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
401 Model->Coder.SubRange.scale=U.SummFreq;
404 int count=Model->Coder.GetCurrentCount();
405 if ((uint)count>=Model->Coder.SubRange.scale)
407 if (count < (HiCnt=p->Freq))
409 Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
410 Model->RunLength += Model->PrevSuccess;
411 (Model->FoundState=p)->Freq=(HiCnt += 4);
413 if (HiCnt > MAX_FREQ)
415 Model->Coder.SubRange.LowCount=0;
419 if (Model->FoundState==NULL)
421 Model->PrevSuccess=0;
423 while ((HiCnt += (++p)->Freq) <= count)
426 Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
427 Model->Coder.SubRange.LowCount=HiCnt;
428 Model->CharMask[p->Symbol]=Model->EscCount;
429 i=(Model->NumMasked=NumStats)-1;
430 Model->FoundState=NULL;
433 Model->CharMask[(--p)->Symbol]=Model->EscCount;
435 Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
438 Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
444 inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
446 (Model->FoundState=p)->Freq += 4;
448 if (p->Freq > MAX_FREQ)
451 Model->RunLength=Model->InitRL;
455 inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
457 SEE2_CONTEXT* psee2c;
460 psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
461 (Diff < Suffix->NumStats-NumStats)+
462 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
464 Model->Coder.SubRange.scale=psee2c->getMean();
468 psee2c=&Model->DummySEE2Cont;
469 Model->Coder.SubRange.scale=1;
477 inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
479 int count, HiCnt, i=NumStats-Model->NumMasked;
480 SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
481 STATE* ps[256], ** pps=ps, * p=U.Stats-1;
488 } while (Model->CharMask[p->Symbol] == Model->EscCount);
492 Model->Coder.SubRange.scale += HiCnt;
493 count=Model->Coder.GetCurrentCount();
494 if ((uint)count>=Model->Coder.SubRange.scale)
500 while ((HiCnt += p->Freq) <= count)
502 Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
508 Model->Coder.SubRange.LowCount=HiCnt;
509 Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
510 i=NumStats-Model->NumMasked;
514 Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
516 psee2c->Summ += Model->Coder.SubRange.scale;
517 Model->NumMasked = NumStats;
523 inline void ModelPPM::ClearMask()
526 memset(CharMask,0,sizeof(CharMask));
532 bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
534 int MaxOrder=UnpackRead->GetChar();
535 bool Reset=(MaxOrder & 0x20);
539 MaxMB=UnpackRead->GetChar();
541 if (SubAlloc.GetAllocatedMemory()==0)
544 EscChar=UnpackRead->GetChar();
545 Coder.InitDecoder(UnpackRead);
548 MaxOrder=(MaxOrder & 0x1f)+1;
550 MaxOrder=16+(MaxOrder-16)*3;
553 SubAlloc.StopSubAllocator();
556 SubAlloc.StartSubAllocator(MaxMB+1);
557 StartModelRare(MaxOrder);
559 return(MinContext!=NULL);
563 int ModelPPM::DecodeChar()
565 if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
567 if (MinContext->NumStats != 1)
569 if (!MinContext->decodeSymbol1(this))
573 MinContext->decodeBinSymbol(this);
575 while ( !FoundState )
577 ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
581 MinContext=MinContext->Suffix;
582 if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
584 } while (MinContext->NumStats == NumMasked);
585 if (!MinContext->decodeSymbol2(this))
589 int Symbol=FoundState->Symbol;
590 if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
591 MinContext=MaxContext=FoundState->Successor;
598 ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);