XADMaster/PPMd/VariantI.c
2018-03-21 14:24:50 +02:00

868 lines
22 KiB
C

/*
* VariantI.c
*
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "VariantI.h"
#include <string.h>
#define UP_FREQ 5
#define O_BOUND 9
static void RestartModel(PPMdModelVariantI *self);
static void UpdateModel(PPMdModelVariantI *self,PPMdContext *mincontext);
static PPMdContext *CreateSuccessors(PPMdModelVariantI *self,bool skip,PPMdState *p1,PPMdContext *mincontext);
static PPMdContext *ReduceOrder(PPMdModelVariantI *self,PPMdState *state,PPMdContext *startcontext);
static void RestoreModel(PPMdModelVariantI *self,PPMdContext *currcontext,PPMdContext *mincontext,PPMdContext *FSuccessor);
static void ShrinkContext(PPMdContext *self,int newlastindex,bool scale,PPMdModelVariantI *model);
static PPMdContext *CutOffContext(PPMdContext *self,int order,PPMdModelVariantI *model);
static PPMdContext *RemoveBinConts(PPMdContext *self,int order,PPMdModelVariantI *model);
static void DecodeBinSymbolVariantI(PPMdContext *self,PPMdModelVariantI *model);
static void DecodeSymbol1VariantI(PPMdContext *self,PPMdModelVariantI *model);
static void DecodeSymbol2VariantI(PPMdContext *self,PPMdModelVariantI *model);
static void RescalePPMdContextVariantI(PPMdContext *self,PPMdModelVariantI *model);
void StartPPMdModelVariantI(PPMdModelVariantI *self,
PPMdReadFunction *readfunc,void *inputcontext,
PPMdSubAllocatorVariantI *alloc,int maxorder,int restoration)
{
InitializePPMdRangeCoder(&self->core.coder,readfunc,inputcontext,true,0x8000);
if(maxorder<2) // TODO: solid mode
{
memset(self->core.CharMask,0,sizeof(self->core.CharMask));
self->core.OrderFall=self->MaxOrder;
for(PPMdContext *pc=self->MaxContext;pc->Suffix;pc=PPMdContextSuffix(pc,&self->core))
self->core.OrderFall--;
return;
}
self->alloc=alloc;
self->core.alloc=&alloc->core;
self->core.RescalePPMdContext=(void *)RescalePPMdContextVariantI;
self->MaxOrder=maxorder;
self->MRMethod=restoration;
self->core.EscCount=1;
self->NS2BSIndx[0]=2*0;
self->NS2BSIndx[1]=2*1;
for(int i=2;i<11;i++) self->NS2BSIndx[i]=2*2;
for(int i=11;i<256;i++) self->NS2BSIndx[i]=2*3;
for(int i=0;i<UP_FREQ;i++) self->QTable[i]=i;
int m=UP_FREQ,k=1,step=1;
for(int i=UP_FREQ;i<260;i++)
{
self->QTable[i]=m;
if(!--k) { m++; step++; k=step; }
}
self->DummySEE2Cont.Summ=0xaf8f;
//self->DummySEE2Cont.Shift=0xac;
self->DummySEE2Cont.Count=0x84;
self->DummySEE2Cont.Shift=PERIOD_BITS;
self->endofstream=false;
RestartModel(self);
}
static void RestartModel(PPMdModelVariantI *self)
{
InitSubAllocator(self->core.alloc);
memset(self->core.CharMask,0,sizeof(self->core.CharMask));
self->core.PrevSuccess=0;
self->core.OrderFall=self->MaxOrder;
self->core.RunLength=self->core.InitRL=-((self->MaxOrder<12)?self->MaxOrder:12)-1;
self->MaxContext=NewPPMdContext(&self->core);
self->MaxContext->LastStateIndex=255;
self->MaxContext->SummFreq=257;
self->MaxContext->States=AllocUnits(self->core.alloc,256/2);
PPMdState *maxstates=PPMdContextStates(self->MaxContext,&self->core);
for(int i=0;i<256;i++)
{
maxstates[i].Symbol=i;
maxstates[i].Freq=1;
maxstates[i].Successor=0;
}
static const uint16_t InitBinEsc[8]={0x3cdd,0x1f3f,0x59bf,0x48f3,0x64a1,0x5abc,0x6632,0x6051};
int i=0;
for(int m=0;m<25;m++)
{
while(self->QTable[i]==m) i++;
for(int k=0;k<8;k++) self->BinSumm[m][k]=BIN_SCALE-InitBinEsc[k]/(i+1);
for(int k=8;k<64;k+=8) memcpy(&self->BinSumm[m][k],&self->BinSumm[m][0],8*sizeof(uint16_t));
}
i=0;
for(int m=0;m<24;m++)
{
while(self->QTable[i+3]==m+3) i++;
for(int k=0;k<32;k++) self->SEE2Cont[m][k]=MakeSEE2(2*i+5,7);
}
}
int NextPPMdVariantIByte(PPMdModelVariantI *self)
{
if(self->endofstream) return -1;
PPMdContext *mincontext=self->MaxContext;
if(mincontext->LastStateIndex!=0) DecodeSymbol1VariantI(mincontext,self);
else DecodeBinSymbolVariantI(mincontext,self);
while(!self->core.FoundState)
{
do
{
self->core.OrderFall++;
mincontext=PPMdContextSuffix(mincontext,&self->core);
if(!mincontext) { self->endofstream=true; return -1; }
}
while(mincontext->LastStateIndex==self->core.LastMaskIndex);
DecodeSymbol2VariantI(mincontext,self);
}
uint8_t byte=self->core.FoundState->Symbol;
if(self->core.OrderFall==0&&(uint8_t *)PPMdStateSuccessor(self->core.FoundState,&self->core)>=self->alloc->UnitsStart)
{
self->MaxContext=PPMdStateSuccessor(self->core.FoundState,&self->core);
//PrefetchData(MaxContext)
}
else
{
UpdateModel(self,mincontext);
//PrefetchData(MaxContext)
if(self->core.EscCount==0) ClearPPMdModelMask(&self->core);
}
return byte;
}
static void UpdateModel(PPMdModelVariantI *self,PPMdContext *mincontext)
{
PPMdState fs=*self->core.FoundState;
PPMdState *state=NULL;
PPMdContext *currcontext=self->MaxContext;
if(fs.Freq<MAX_FREQ/4&&mincontext->Suffix)
{
PPMdContext *context=PPMdContextSuffix(mincontext,&self->core);
if(context->LastStateIndex!=0)
{
state=PPMdContextStates(context,&self->core);
if(state->Symbol!=fs.Symbol)
{
do state++;
while(state->Symbol!=fs.Symbol);
if(state[0].Freq>=state[-1].Freq)
{
SWAP(state[0],state[-1]);
state--;
}
}
if(state->Freq<MAX_FREQ-9)
{
state->Freq+=2;
context->SummFreq+=2;
}
}
else
{
state=PPMdContextOneState(context);
if(state->Freq<32) state->Freq++;
}
}
if(self->core.OrderFall==0&&fs.Successor)
{
PPMdContext *newsuccessor=CreateSuccessors(self,true,state,mincontext);
SetPPMdStateSuccessorPointer(self->core.FoundState,newsuccessor,&self->core);
if(!newsuccessor) goto RESTART_MODEL;
self->MaxContext=newsuccessor;
return;
}
*self->alloc->pText++=fs.Symbol;
PPMdContext *Successor=(PPMdContext *)self->alloc->pText;
if(self->alloc->pText>=self->alloc->UnitsStart) goto RESTART_MODEL;
if(fs.Successor)
{
if((uint8_t *)PPMdStateSuccessor(&fs,&self->core)<self->alloc->UnitsStart)
{
SetPPMdStateSuccessorPointer(&fs,CreateSuccessors(self,false,state,mincontext),&self->core);
}
}
else
{
SetPPMdStateSuccessorPointer(&fs,ReduceOrder(self,state,mincontext),&self->core);
}
if(!fs.Successor) goto RESTART_MODEL;
if(--self->core.OrderFall==0)
{
Successor=PPMdStateSuccessor(&fs,&self->core);
if(self->MaxContext!=mincontext) self->alloc->pText--;
}
else if(self->MRMethod>MRM_FREEZE)
{
Successor=PPMdStateSuccessor(&fs,&self->core);
self->alloc->pText=self->alloc->HeapStart;
self->core.OrderFall=0;
}
int minnum=mincontext->LastStateIndex+1;
int s0=mincontext->SummFreq-minnum-(fs.Freq-1);
uint8_t flag=fs.Symbol>=0x40?8:0;
for(;currcontext!=mincontext;currcontext=PPMdContextSuffix(currcontext,&self->core))
{
int currnum=currcontext->LastStateIndex+1;
if(currnum!=1)
{
if((currnum&1)==0)
{
uint32_t states=ExpandUnits(self->core.alloc,currcontext->States,currnum>>1);
if(!states) goto RESTART_MODEL;
currcontext->States=states;
}
if(3*currnum-1<minnum) currcontext->SummFreq++;
}
else
{
PPMdState *states=OffsetToPointer(self->core.alloc,AllocUnits(self->core.alloc,1));
if(!states) goto RESTART_MODEL;
states[0]=*(PPMdContextOneState(currcontext));
SetPPMdContextStatesPointer(currcontext,states,&self->core);
if(states[0].Freq<MAX_FREQ/4-1) states[0].Freq*=2;
else states[0].Freq=MAX_FREQ-4;
currcontext->SummFreq=states[0].Freq+self->core.InitEsc+(minnum>3?1:0);
}
unsigned int cf=2*fs.Freq*(currcontext->SummFreq+6);
unsigned int sf=s0+currcontext->SummFreq;
unsigned int freq;
if(cf<6*sf)
{
if(cf>=4*sf) freq=3;
else if(cf>sf) freq=2;
else freq=1;
currcontext->SummFreq+=4;
}
else
{
if(cf>15*sf) freq=7;
else if(cf>12*sf) freq=6;
else if(cf>9*sf) freq=5;
else freq=4;
currcontext->SummFreq+=freq;
}
currcontext->LastStateIndex++;
PPMdState *currstates=PPMdContextStates(currcontext,&self->core);
PPMdState *new=&currstates[currcontext->LastStateIndex];
SetPPMdStateSuccessorPointer(new,Successor,&self->core);
new->Symbol=fs.Symbol;
new->Freq=freq;
currcontext->Flags|=flag;
}
self->MaxContext=PPMdStateSuccessor(&fs,&self->core);
return;
RESTART_MODEL:
RestoreModel(self,currcontext,mincontext,PPMdStateSuccessor(&fs,&self->core));
}
static PPMdContext *CreateSuccessors(PPMdModelVariantI *self,bool skip,PPMdState *state,PPMdContext *context)
{
PPMdContext *upbranch=PPMdStateSuccessor(self->core.FoundState,&self->core);
PPMdState *statelist[MAX_O];
uint8_t sym=self->core.FoundState->Symbol;
int n=0;
if(!skip)
{
statelist[n++]=self->core.FoundState;
if(!context->Suffix) goto skip;
}
if(state)
{
context=PPMdContextSuffix(context,&self->core);
if(PPMdStateSuccessor(state,&self->core)!=upbranch)
{
context=PPMdStateSuccessor(state,&self->core);
goto skip;
}
statelist[n++]=state;
if(!context->Suffix) goto skip;
}
do
{
context=PPMdContextSuffix(context,&self->core);
if(context->LastStateIndex!=0)
{
state=PPMdContextStates(context,&self->core);
while(state->Symbol!=sym) state++;
if(state->Freq<MAX_FREQ-9)
{
state->Freq++;
context->SummFreq++;
}
}
else
{
state=PPMdContextOneState(context);
state->Freq+=(!PPMdContextSuffix(context,&self->core)->LastStateIndex&(state->Freq<24));
}
if(PPMdStateSuccessor(state,&self->core)!=upbranch)
{
context=PPMdStateSuccessor(state,&self->core);
break;
}
statelist[n++]=state;
}
while(context->Suffix);
skip:
if(n==0) return context;
PPMdContext ct;
uint8_t newsym=*(uint8_t *)upbranch;
ct.LastStateIndex=0;
ct.Flags=0;
if(sym>=0x40) ct.Flags|=0x10;
if(newsym>=0x40) ct.Flags|=0x08;
PPMdState *onestate=PPMdContextOneState(&ct);
onestate->Symbol=newsym;
SetPPMdStateSuccessorPointer(onestate,(PPMdContext *)(((uint8_t *)upbranch)+1),&self->core);
if(context->LastStateIndex!=0)
{
state=PPMdContextStates(context,&self->core);
while(state->Symbol!=newsym) state++;
int cf=state->Freq-1;
int s0=context->SummFreq-context->LastStateIndex-cf;
if(2*cf<=s0)
{
if(5*cf>s0) onestate->Freq=2;
else onestate->Freq=1;
}
else onestate->Freq=1+((cf+2*s0-3)/s0);
}
else onestate->Freq=PPMdContextOneState(context)->Freq;
for(int i=n-1;i>=0;i--)
{
PPMdContext *newcontext=(PPMdContext *)OffsetToPointer(self->core.alloc,AllocContext(self->core.alloc));
if(!newcontext) return NULL;
memcpy(newcontext,&ct,8);
SetPPMdContextSuffixPointer(newcontext,context,&self->core);
SetPPMdStateSuccessorPointer(statelist[i],newcontext,&self->core);
context=newcontext;
}
return context;
}
static PPMdContext *ReduceOrder(PPMdModelVariantI *self,PPMdState *state,PPMdContext *startcontext)
{
PPMdState *statelist[MAX_O];
PPMdContext *context=startcontext,*upbranch=(PPMdContext *)self->alloc->pText;
uint8_t sym=self->core.FoundState->Symbol;
int n=0;
statelist[n++]=self->core.FoundState;
self->core.OrderFall++;
if(state)
{
context=PPMdContextSuffix(context,&self->core);
if(state->Successor) goto skip;
statelist[n++]=state;
self->core.OrderFall++;
}
for(;;)
{
if(!context->Suffix)
{
if(self->MRMethod>MRM_FREEZE)
{
for(int i=0;i<n;i++) SetPPMdStateSuccessorPointer(statelist[i],context,&self->core);
self->alloc->pText=self->alloc->HeapStart+1;
self->core.OrderFall=1;
}
else
{
for(int i=0;i<n;i++) SetPPMdStateSuccessorPointer(statelist[i],upbranch,&self->core);
}
return context;
}
context=PPMdContextSuffix(context,&self->core);
if(context->LastStateIndex)
{
state=PPMdContextStates(context,&self->core);
while(state->Symbol!=sym) state++;
if(state->Freq<MAX_FREQ-9)
{
state->Freq+=2;
context->SummFreq+=2;
}
}
else
{
state=PPMdContextOneState(context);
if(state->Freq<32) state->Freq++;
}
if(state->Successor) break;
statelist[n++]=state;
self->core.OrderFall++;
}
skip:
if(self->MRMethod>MRM_FREEZE)
{
PPMdContext *successor=PPMdStateSuccessor(state,&self->core);
for(int i=0;i<n;i++) SetPPMdStateSuccessorPointer(statelist[i],successor,&self->core);
self->alloc->pText=self->alloc->HeapStart+1;
self->core.OrderFall=1;
return successor;
}
else
{
for(int i=0;i<n;i++) SetPPMdStateSuccessorPointer(statelist[i],upbranch,&self->core);
}
if(PPMdStateSuccessor(state,&self->core)<=upbranch)
{
PPMdState *tmp=self->core.FoundState;
self->core.FoundState=state;
SetPPMdStateSuccessorPointer(state,CreateSuccessors(self,false,NULL,context),&self->core);
self->core.FoundState=tmp;
}
if(self->core.OrderFall==1&&startcontext==self->MaxContext)
{
self->core.FoundState->Successor=state->Successor;
self->alloc->pText--;
}
return PPMdStateSuccessor(state,&self->core);
}
static void RestoreModel(PPMdModelVariantI *self,PPMdContext *currcontext,PPMdContext *mincontext,PPMdContext *FSuccessor)
{
self->alloc->pText=self->alloc->HeapStart;
PPMdContext *context=self->MaxContext;
while(context!=currcontext)
{
if(context->LastStateIndex==1)
{
PPMdState state=*(PPMdContextStates(context,&self->core));
SpecialFreeUnitVariantI(self->alloc,context->States);
state.Freq=(state.Freq+11)>>3;
*(PPMdContextOneState(context))=state;
context->LastStateIndex=0;
context->Flags&=0x10;
if(state.Symbol>=0x40) context->Flags+=0x08;
}
else
{
ShrinkContext(context,context->LastStateIndex-1,false,self);
}
context=PPMdContextSuffix(context,&self->core);
}
while(context!=mincontext)
{
if(!context->LastStateIndex)
{
PPMdContextOneState(context)->Freq=(PPMdContextOneState(context)->Freq+1)>>1;
}
else
{
context->SummFreq+=4;
if(context->SummFreq>128+4*context->LastStateIndex)
ShrinkContext(context,context->LastStateIndex,true,self);
}
context=PPMdContextSuffix(context,&self->core);
}
if(self->MRMethod>MRM_FREEZE)
{
self->MaxContext=FSuccessor;
if(!(self->alloc->BList[1].Stamp&1)) self->alloc->GlueCount++;
}
else if(self->MRMethod==MRM_FREEZE)
{
while(self->MaxContext->Suffix) self->MaxContext=PPMdContextSuffix(self->MaxContext,&self->core);
RemoveBinConts(self->MaxContext,0,self);
self->MRMethod=self->MRMethod+1;
self->alloc->GlueCount=0;
self->core.OrderFall=self->MaxOrder;
}
else if(self->MRMethod==MRM_RESTART||GetUsedMemoryVariantI(self->alloc)<(self->alloc->SubAllocatorSize>>1))
{
RestartModel(self);
self->core.EscCount=0;
}
else
{
while(self->MaxContext->Suffix) self->MaxContext=PPMdContextSuffix(self->MaxContext,&self->core);
do
{
CutOffContext(self->MaxContext,0,self);
ExpandTextAreaVariantI(self->alloc);
} while(GetUsedMemoryVariantI(self->alloc)>3*(self->alloc->SubAllocatorSize>>2));
self->alloc->GlueCount=0;
self->core.OrderFall=self->MaxOrder;
}
}
static void ShrinkContext(PPMdContext *self,int newlastindex,bool scale,PPMdModelVariantI *model)
{
self->States=ShrinkUnits(model->core.alloc,self->States,(self->LastStateIndex+2)>>1,(newlastindex+2)>>1);
self->LastStateIndex=newlastindex;
if(scale) self->Flags&=0x14;
else self->Flags&=0x10;
PPMdState *states=PPMdContextStates(self,&model->core);
int escfreq=self->SummFreq;
self->SummFreq=0;
for(int i=0;i<=self->LastStateIndex;i++)
{
escfreq-=states[i].Freq;
if(scale) states[i].Freq=(states[i].Freq+1)>>1;
self->SummFreq+=states[i].Freq;
if(states[i].Symbol>=0x40) self->Flags|=0x08;
}
if(scale) escfreq=(escfreq+1)>>1;
self->SummFreq+=escfreq;
}
static PPMdContext *CutOffContext(PPMdContext *self,int order,PPMdModelVariantI *model)
{
if(self->LastStateIndex==0)
{
PPMdState *onestate=PPMdContextOneState(self);
if((uint8_t *)PPMdStateSuccessor(onestate,&model->core)>=model->alloc->UnitsStart)
{
if(order<model->MaxOrder)
{
//PrefetchData(p->Successor);
SetPPMdStateSuccessorPointer(onestate,
CutOffContext(PPMdStateSuccessor(onestate,&model->core),order+1,model),
&model->core);
}
else onestate->Successor=0;
if(!onestate->Successor&&order>O_BOUND)
{
SpecialFreeUnitVariantI(model->alloc,PointerToOffset(model->core.alloc,self));
return NULL;
}
return self;
}
else
{
SpecialFreeUnitVariantI(model->alloc,PointerToOffset(model->core.alloc,self));
return NULL;
}
}
//PrefetchData(self->States);
int oldnum=(self->LastStateIndex+2)>>1;
self->States=MoveUnitsUpVariantI(model->alloc,self->States,oldnum);
int n=self->LastStateIndex;
PPMdState *states=PPMdContextStates(self,&model->core);
for(int i=n;i>=0;i--)
{
if((uint8_t *)PPMdStateSuccessor(&states[i],&model->core)<model->alloc->UnitsStart)
{
states[i].Successor=0;
SWAP(states[i],states[n]);
n--;
}
else if(order<model->MaxOrder)
{
//PrefetchData(state->Successor);
SetPPMdStateSuccessorPointer(&states[i],
CutOffContext(PPMdStateSuccessor(&states[i],&model->core),order+1,model),
&model->core);
}
else states[i].Successor=0;
}
if(n!=self->LastStateIndex&&order)
{
if(n<0)
{
FreeUnits(model->core.alloc,self->States,oldnum);
SpecialFreeUnitVariantI(model->alloc,PointerToOffset(model->core.alloc,self));
return NULL;
}
else if(n==0)
{
PPMdState state=*(PPMdContextStates(self,&model->core));
FreeUnits(model->core.alloc,self->States,oldnum);
state.Freq=(state.Freq+11)>>3;
*(PPMdContextOneState(self))=state;
self->LastStateIndex=0;
self->Flags&=0x10;
if(state.Symbol>=0x40) self->Flags+=0x08;
}
else ShrinkContext(self,n,self->SummFreq>16*n,model);
}
return self;
}
static PPMdContext *RemoveBinConts(PPMdContext *self,int order,PPMdModelVariantI *model)
{
if(self->LastStateIndex==0)
{
PPMdState *state=PPMdContextOneState(self);
if((uint8_t *)PPMdStateSuccessor(state,&model->core)>=model->alloc->UnitsStart&&order<model->MaxOrder)
{
//PrefetchData(onestate->Successor);
SetPPMdStateSuccessorPointer(state,
RemoveBinConts(PPMdStateSuccessor(state,&model->core),order+1,model),
&model->core);
}
else state->Successor=0;
if(!state->Successor)
{
PPMdContext *suffix=PPMdContextSuffix(self,&model->core);
if(suffix->LastStateIndex==0||suffix->Flags==0xff)
{
FreeUnits(model->core.alloc,PointerToOffset(model->core.alloc,self),1);
return NULL;
}
}
return self;
}
//PrefetchData(self->States);
PPMdState *states=PPMdContextStates(self,&model->core);
for(int i=self->LastStateIndex;i>=0;i--)
{
if((uint8_t *)PPMdStateSuccessor(&states[i],&model->core)>=model->alloc->UnitsStart&&order<model->MaxOrder)
{
//PrefetchData(states[i].Successor);
SetPPMdStateSuccessorPointer(&states[i],
RemoveBinConts(PPMdStateSuccessor(&states[i],&model->core),order+1,model),
&model->core);
}
else states[i].Successor=0;
}
return self;
}
static void DecodeBinSymbolVariantI(PPMdContext *self,PPMdModelVariantI *model)
{
PPMdState *rs=PPMdContextOneState(self);
uint8_t index=model->NS2BSIndx[PPMdContextSuffix(self,&model->core)->LastStateIndex]+model->core.PrevSuccess+self->Flags;
uint16_t *bs=&model->BinSumm[model->QTable[rs->Freq-1]][index+((model->core.RunLength>>26)&0x20)];
PPMdDecodeBinSymbol(self,&model->core,bs,196,false);
}
static void DecodeSymbol1VariantI(PPMdContext *self,PPMdModelVariantI *model)
{
PPMdDecodeSymbol1(self,&model->core,true);
}
static void DecodeSymbol2VariantI(PPMdContext *self,PPMdModelVariantI *model)
{
SEE2Context *see;
//uint8_t *pb=(uint8_t *)PPMdContextStates(self);
//unsigned int t=2*self->LastStateIndex;
//PrefetchData(pb);
//PrefetchData(pb+t);
//PrefetchData(pb+2*t);
//PrefetchData(pb+3*t);
if(self->LastStateIndex!=255)
{
int n=PPMdContextSuffix(self,&model->core)->LastStateIndex;
see=&model->SEE2Cont[model->QTable[self->LastStateIndex+2]-3][
(self->SummFreq>11*(self->LastStateIndex+1)?1:0)
+(2*self->LastStateIndex<n+model->core.LastMaskIndex?2:0)
+self->Flags];
model->core.scale=GetSEE2Mean(see);
}
else
{
model->core.scale=1;
see=&model->DummySEE2Cont;
}
PPMdDecodeSymbol2(self,&model->core,see);
}
static void RescalePPMdContextVariantI(PPMdContext *self,PPMdModelVariantI *model)
{
PPMdState *states=PPMdContextStates(self,&model->core);
int n=self->LastStateIndex+1;
// Bump frequency of found state
model->core.FoundState->Freq+=4;
// Divide all frequencies and sort list
int escfreq=self->SummFreq+4;
int adder=(model->core.OrderFall!=0||model->MRMethod>MRM_FREEZE?1:0);
self->SummFreq=0;
for(int i=0;i<n;i++)
{
escfreq-=states[i].Freq;
states[i].Freq=(states[i].Freq+adder)>>1;
self->SummFreq+=states[i].Freq;
// Keep states sorted by decreasing frequency
if(i>0&&states[i].Freq>states[i-1].Freq)
{
// If not sorted, move current state upwards until list is sorted
PPMdState tmp=states[i];
int j=i-1;
while(j>0&&tmp.Freq>states[j-1].Freq) j--;
memmove(&states[j+1],&states[j],sizeof(PPMdState)*(i-j));
states[j]=tmp;
}
}
// TODO: add better sorting stage here.
// Drop states whose frequency has fallen to 0
if(states[n-1].Freq==0)
{
int numzeros=1;
while(numzeros<n&&states[n-1-numzeros].Freq==0) numzeros++;
escfreq+=numzeros;
self->LastStateIndex-=numzeros;
if(self->LastStateIndex==0)
{
PPMdState tmp=states[0];
tmp.Freq=(2*tmp.Freq+escfreq-1)/escfreq;
if(tmp.Freq>MAX_FREQ/3) tmp.Freq=MAX_FREQ/3;
FreeUnits(model->core.alloc,self->States,(n+1)>>1);
model->core.FoundState=PPMdContextOneState(self);
*model->core.FoundState=tmp;
self->Flags=(self->Flags&0x10)+0x08*(tmp.Symbol>=0x40);
return;
}
self->States=ShrinkUnits(model->core.alloc,self->States,(n+1)>>1,(self->LastStateIndex+2)>>1);
PPMdState *states=PPMdContextStates(self,&model->core);
self->Flags&=~0x08;
for(int i=0;i<=self->LastStateIndex;i++)
if(states[i].Symbol>=0x40) self->Flags|=0x08;
}
self->SummFreq+=(escfreq+1)>>1;
self->Flags|=0x04;
// The found state is the first one to breach the limit, thus it is the largest and also first
model->core.FoundState=PPMdContextStates(self,&model->core);
}