📄 model.cpp
字号:
}
LOOP_ENTRY:
if (p->Successor != UpBranch) {
pc=p->Successor; break;
}
*pps++ = p;
} while ( pc->Suffix );
NO_LOOP:
if (pps == ps) return pc;
ct.NumStats=0; ct.Flags=0x10*(sym >= 0x40);
ct.oneState().Symbol=sym=*(BYTE*) UpBranch;
ct.oneState().Successor=(PPM_CONTEXT*) (((BYTE*) UpBranch)+1);
ct.Flags |= 0x08*(sym >= 0x40);
if ( pc->NumStats ) {
if ((p=pc->Stats)->Symbol != sym)
do { tmp=p[1].Symbol; p++; } while (tmp != sym);
s0=pc->SummFreq-pc->NumStats-(cf=p->Freq-1);
ct.oneState().Freq=1+((2*cf <= s0)?(5*cf > s0):((cf+2*s0-3)/s0));
} else
ct.oneState().Freq=pc->oneState().Freq;
do {
PPM_CONTEXT* pc1 = (PPM_CONTEXT*) AllocContext();
if ( !pc1 ) return NULL;
((DWORD*) pc1)[0] = ((DWORD*) &ct)[0];
((DWORD*) pc1)[1] = ((DWORD*) &ct)[1];
pc1->Suffix=pc; (*--pps)->Successor=pc=pc1;
} while (pps != ps);
return pc;
}
static inline void UpdateModel(PPM_CONTEXT* MinContext)
{
PPM_CONTEXT::STATE* p=NULL;
PPM_CONTEXT* Successor, * FSuccessor, * pc, * pc1=MaxContext;
UINT ns1, ns, cf, sf, s0, FFreq=FoundState->Freq;
BYTE Flag, sym, FSymbol=FoundState->Symbol;
FSuccessor=FoundState->Successor; pc=MinContext->Suffix;
if (FFreq < MAX_FREQ/4 && pc) {
if ( pc->NumStats ) {
if ((p=pc->Stats)->Symbol != FSymbol) {
do { sym=p[1].Symbol; p++; } while (sym != FSymbol);
if (p[0].Freq >= p[-1].Freq) {
SWAP(p[0],p[-1]); p--;
}
}
cf=2*(p->Freq < MAX_FREQ-9);
p->Freq += cf; pc->SummFreq += cf;
} else { p=&(pc->oneState()); p->Freq += (p->Freq < 32); }
}
if (!OrderFall && FSuccessor) {
FoundState->Successor=CreateSuccessors(TRUE,p,MinContext);
if ( !FoundState->Successor ) goto RESTART_MODEL;
MaxContext=FoundState->Successor; return;
}
*pText++ = FSymbol; Successor = (PPM_CONTEXT*) pText;
if (pText >= UnitsStart) goto RESTART_MODEL;
if ( FSuccessor ) {
if ((BYTE*) FSuccessor < UnitsStart)
FSuccessor=CreateSuccessors(FALSE,p,MinContext);
} else
FSuccessor=ReduceOrder(p,MinContext);
if ( !FSuccessor ) goto RESTART_MODEL;
if ( !--OrderFall ) {
Successor=FSuccessor; pText -= (MaxContext != MinContext);
} else if (MRMethod > MRM_FREEZE) {
Successor=FSuccessor; pText=HeapStart;
OrderFall=0;
}
s0=MinContext->SummFreq-(ns=MinContext->NumStats)-FFreq;
for (Flag=0x08*(FSymbol >= 0x40);pc1 != MinContext;pc1=pc1->Suffix) {
if ((ns1=pc1->NumStats) != 0) {
if ((ns1 & 1) != 0) {
p=(PPM_CONTEXT::STATE*) ExpandUnits(pc1->Stats,(ns1+1) >> 1);
if ( !p ) goto RESTART_MODEL;
pc1->Stats=p;
}
pc1->SummFreq += (3*ns1+1 < ns);
} else {
p=(PPM_CONTEXT::STATE*) AllocUnits(1);
if ( !p ) goto RESTART_MODEL;
StateCpy(*p,pc1->oneState()); pc1->Stats=p;
if (p->Freq < MAX_FREQ/4-1) p->Freq += p->Freq;
else p->Freq = MAX_FREQ-4;
pc1->SummFreq=p->Freq+InitEsc+(ns > 2);
}
cf=2*FFreq*(pc1->SummFreq+6); sf=s0+pc1->SummFreq;
if (cf < 6*sf) {
cf=1+(cf > sf)+(cf >= 4*sf);
pc1->SummFreq += 4;
} else {
cf=4+(cf > 9*sf)+(cf > 12*sf)+(cf > 15*sf);
pc1->SummFreq += cf;
}
p=pc1->Stats+(++pc1->NumStats); p->Successor=Successor;
p->Symbol = FSymbol; p->Freq = cf;
pc1->Flags |= Flag;
}
MaxContext=FSuccessor; return;
RESTART_MODEL:
RestoreModelRare(pc1,MinContext,FSuccessor);
}
// Tabulated escapes for exponential symbol distribution
static const BYTE ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
inline void PPM_CONTEXT::encodeBinSymbol(int symbol)
{
BYTE indx=NS2BSIndx[Suffix->NumStats]+PrevSuccess+Flags;
STATE& rs=oneState();
WORD& bs=BinSumm[QTable[rs.Freq-1]][indx+((RunLength >> 26) & 0x20)];
if (rs.Symbol == symbol) {
FoundState=&rs; rs.Freq += (rs.Freq < 196);
SubRange.LowCount=0; SubRange.HighCount=bs;
bs += INTERVAL-GET_MEAN(bs,PERIOD_BITS,2);
PrevSuccess=1; RunLength++;
} else {
SubRange.LowCount=bs; bs -= GET_MEAN(bs,PERIOD_BITS,2);
SubRange.HighCount=BIN_SCALE; InitEsc=ExpEscape[bs >> 10];
CharMask[rs.Symbol]=EscCount;
NumMasked=PrevSuccess=0; FoundState=NULL;
}
}
inline void PPM_CONTEXT::decodeBinSymbol()
{
BYTE indx=NS2BSIndx[Suffix->NumStats]+PrevSuccess+Flags;
STATE& rs=oneState();
WORD& bs=BinSumm[QTable[rs.Freq-1]][indx+((RunLength >> 26) & 0x20)];
if (ariGetCurrentShiftCount(TOT_BITS) < bs) {
FoundState=&rs; rs.Freq += (rs.Freq < 196);
SubRange.LowCount=0; SubRange.HighCount=bs;
bs += INTERVAL-GET_MEAN(bs,PERIOD_BITS,2);
PrevSuccess=1; RunLength++;
} else {
SubRange.LowCount=bs; bs -= GET_MEAN(bs,PERIOD_BITS,2);
SubRange.HighCount=BIN_SCALE; InitEsc=ExpEscape[bs >> 10];
CharMask[rs.Symbol]=EscCount;
NumMasked=PrevSuccess=0; FoundState=NULL;
}
}
inline void PPM_CONTEXT::update1(STATE* p)
{
(FoundState=p)->Freq += 4; SummFreq += 4;
if (p[0].Freq > p[-1].Freq) {
SWAP(p[0],p[-1]); FoundState=--p;
if (p->Freq > MAX_FREQ) rescale();
}
}
inline void PPM_CONTEXT::encodeSymbol1(int symbol)
{
UINT LoCnt, i=Stats->Symbol;
STATE* p=Stats; SubRange.scale=SummFreq;
if (i == symbol) {
PrevSuccess=(2*(SubRange.HighCount=p->Freq) >= SubRange.scale);
(FoundState=p)->Freq += 4; SummFreq += 4;
RunLength += PrevSuccess;
if (p->Freq > MAX_FREQ) rescale();
SubRange.LowCount=0; return;
}
LoCnt=p->Freq;
i=NumStats; PrevSuccess=0;
while ((++p)->Symbol != symbol) {
LoCnt += p->Freq;
if (--i == 0) {
if ( Suffix ) PrefetchData(Suffix);
SubRange.LowCount=LoCnt; CharMask[p->Symbol]=EscCount;
i=NumMasked=NumStats; FoundState=NULL;
do { CharMask[(--p)->Symbol]=EscCount; } while ( --i );
SubRange.HighCount=SubRange.scale;
return;
}
}
SubRange.HighCount=(SubRange.LowCount=LoCnt)+p->Freq;
update1(p);
}
inline void PPM_CONTEXT::decodeSymbol1()
{
UINT i, count, HiCnt=Stats->Freq;
STATE* p=Stats; SubRange.scale=SummFreq;
if ((count=ariGetCurrentCount()) < HiCnt) {
PrevSuccess=(2*(SubRange.HighCount=HiCnt) >= SubRange.scale);
(FoundState=p)->Freq=(HiCnt += 4); SummFreq += 4;
RunLength += PrevSuccess;
if (HiCnt > MAX_FREQ) rescale();
SubRange.LowCount=0; return;
}
i=NumStats; PrevSuccess=0;
while ((HiCnt += (++p)->Freq) <= count)
if (--i == 0) {
if ( Suffix ) PrefetchData(Suffix);
SubRange.LowCount=HiCnt; CharMask[p->Symbol]=EscCount;
i=NumMasked=NumStats; FoundState=NULL;
do { CharMask[(--p)->Symbol]=EscCount; } while ( --i );
SubRange.HighCount=SubRange.scale;
return;
}
SubRange.LowCount=(SubRange.HighCount=HiCnt)-p->Freq;
update1(p);
}
inline void PPM_CONTEXT::update2(STATE* p)
{
(FoundState=p)->Freq += 4; SummFreq += 4;
if (p->Freq > MAX_FREQ) rescale();
EscCount++; RunLength=InitRL;
}
inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2()
{
BYTE* pb=(BYTE*) Stats; UINT t=2*NumStats;
PrefetchData(pb); PrefetchData(pb+t);
PrefetchData(pb += 2*t); PrefetchData(pb+t);
SEE2_CONTEXT* psee2c;
if (NumStats != 0xFF) {
t=Suffix->NumStats;
psee2c=SEE2Cont[QTable[NumStats+2]-3]+(SummFreq > 11*(NumStats+1));
psee2c += 2*(2*NumStats < t+NumMasked)+Flags;
SubRange.scale=psee2c->getMean();
} else {
psee2c=&DummySEE2Cont; SubRange.scale=1;
}
return psee2c;
}
inline void PPM_CONTEXT::encodeSymbol2(int symbol)
{
SEE2_CONTEXT* psee2c=makeEscFreq2();
UINT Sym, LoCnt=0, i=NumStats-NumMasked;
STATE* p1, * p=Stats-1;
do {
do { Sym=p[1].Symbol; p++; } while (CharMask[Sym] == EscCount);
CharMask[Sym]=EscCount;
if (Sym == symbol) goto SYMBOL_FOUND;
LoCnt += p->Freq;
} while ( --i );
SubRange.HighCount=(SubRange.scale += (SubRange.LowCount=LoCnt));
psee2c->Summ += SubRange.scale; NumMasked = NumStats;
return;
SYMBOL_FOUND:
SubRange.LowCount=LoCnt; SubRange.HighCount=(LoCnt+=p->Freq);
for (p1=p; --i ; ) {
do { Sym=p1[1].Symbol; p1++; } while (CharMask[Sym] == EscCount);
LoCnt += p1->Freq;
}
SubRange.scale += LoCnt;
psee2c->update(); update2(p);
}
inline void PPM_CONTEXT::decodeSymbol2()
{
SEE2_CONTEXT* psee2c=makeEscFreq2();
UINT Sym, count, HiCnt=0, i=NumStats-NumMasked;
STATE* ps[256], ** pps=ps, * p=Stats-1;
do {
do { Sym=p[1].Symbol; p++; } while (CharMask[Sym] == EscCount);
HiCnt += p->Freq; *pps++ = p;
} while ( --i );
SubRange.scale += HiCnt; count=ariGetCurrentCount();
p=*(pps=ps);
if (count < HiCnt) {
HiCnt=0;
while ((HiCnt += p->Freq) <= count) p=*++pps;
SubRange.LowCount = (SubRange.HighCount=HiCnt)-p->Freq;
psee2c->update(); update2(p);
} else {
SubRange.LowCount=HiCnt; SubRange.HighCount=SubRange.scale;
i=NumStats-NumMasked; NumMasked = NumStats;
do { CharMask[(*pps)->Symbol]=EscCount; pps++; } while ( --i );
psee2c->Summ += SubRange.scale;
}
}
inline void ClearMask(_PPMD_FILE* EncodedFile,_PPMD_FILE* DecodedFile)
{
EscCount=1; memset(CharMask,0,sizeof(CharMask));
if (++PrintCount == 0) PrintInfo(DecodedFile,EncodedFile);
}
void _STDCALL EncodeFile(_PPMD_FILE* EncodedFile,_PPMD_FILE* DecodedFile,
int MaxOrder,MR_METHOD MRMethod)
{
ariInitEncoder(); StartModelRare(MaxOrder,MRMethod);
for (PPM_CONTEXT* MinContext; ; ) {
BYTE ns=(MinContext=MaxContext)->NumStats;
int c = _PPMD_E_GETC(DecodedFile);
if ( ns ) {
MinContext->encodeSymbol1(c); ariEncodeSymbol();
} else {
MinContext->encodeBinSymbol(c); ariShiftEncodeSymbol(TOT_BITS);
}
while ( !FoundState ) {
ARI_ENC_NORMALIZE(EncodedFile);
do {
OrderFall++; MinContext=MinContext->Suffix;
if ( !MinContext ) goto STOP_ENCODING;
} while (MinContext->NumStats == NumMasked);
MinContext->encodeSymbol2(c); ariEncodeSymbol();
}
if (!OrderFall && (BYTE*) FoundState->Successor >= UnitsStart)
PrefetchData(MaxContext=FoundState->Successor);
else {
UpdateModel(MinContext); PrefetchData(MaxContext);
if (EscCount == 0) ClearMask(EncodedFile,DecodedFile);
}
ARI_ENC_NORMALIZE(EncodedFile);
}
STOP_ENCODING:
ARI_FLUSH_ENCODER(EncodedFile); PrintInfo(DecodedFile,EncodedFile);
}
void _STDCALL DecodeFile(_PPMD_FILE* DecodedFile,_PPMD_FILE* EncodedFile,
int MaxOrder,MR_METHOD MRMethod)
{
ARI_INIT_DECODER(EncodedFile); StartModelRare(MaxOrder,MRMethod);
PPM_CONTEXT* MinContext=MaxContext;
for (BYTE ns=MinContext->NumStats; ; ) {
( ns )?(MinContext->decodeSymbol1()):(MinContext->decodeBinSymbol());
ariRemoveSubrange();
while ( !FoundState ) {
ARI_DEC_NORMALIZE(EncodedFile);
do {
OrderFall++; MinContext=MinContext->Suffix;
if ( !MinContext ) goto STOP_DECODING;
} while (MinContext->NumStats == NumMasked);
MinContext->decodeSymbol2(); ariRemoveSubrange();
}
_PPMD_D_PUTC(FoundState->Symbol,DecodedFile);
if (!OrderFall && (BYTE*) FoundState->Successor >= UnitsStart)
PrefetchData(MaxContext=FoundState->Successor);
else {
UpdateModel(MinContext); PrefetchData(MaxContext);
if (EscCount == 0) ClearMask(EncodedFile,DecodedFile);
}
ns=(MinContext=MaxContext)->NumStats;
ARI_DEC_NORMALIZE(EncodedFile);
}
STOP_DECODING:
PrintInfo(DecodedFile,EncodedFile);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -