summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-reader/Model.cpp
Side-by-side diff
Diffstat (limited to 'noncore/apps/opie-reader/Model.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-reader/Model.cpp721
1 files changed, 721 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/Model.cpp b/noncore/apps/opie-reader/Model.cpp
new file mode 100644
index 0000000..6b61fa0
--- a/dev/null
+++ b/noncore/apps/opie-reader/Model.cpp
@@ -0,0 +1,721 @@
+/****************************************************************************
+ * This file is part of PPMd project *
+ * Written and distributed to public domain by Dmitry Shkarin 1997, *
+ * 1999-2001 *
+ * Contents: PPMII model description and encoding/decoding routines *
+ ****************************************************************************/
+#include <string.h>
+#include "PPMd.h"
+#pragma hdrstop
+#include "Coder.h"
+#include "SubAlloc.h"
+
+enum { UP_FREQ=5, INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
+ INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124, O_BOUND=9 };
+
+#pragma pack(1)
+static struct SEE2_CONTEXT { // SEE-contexts for PPM-contexts with masked symbols
+ WORD Summ;
+ BYTE Shift, Count;
+ void init(UINT InitVal) { Summ=InitVal << (Shift=PERIOD_BITS-4); Count=7; }
+ UINT getMean() {
+ UINT RetVal=(Summ >> Shift); Summ -= RetVal;
+ return RetVal+(RetVal == 0);
+ }
+ void update() {
+ if (Shift < PERIOD_BITS && --Count == 0) {
+ Summ += Summ; Count=3 << Shift++;
+ }
+ }
+} _PACK_ATTR SEE2Cont[24][32], DummySEE2Cont;
+static struct PPM_CONTEXT { // Notes:
+ BYTE NumStats, Flags; // 1. NumStats & NumMasked contain
+ WORD SummFreq; // number of symbols minus 1
+ struct STATE { // 2. sizeof(WORD) > sizeof(BYTE)
+ BYTE Symbol, Freq; // 3. contexts example:
+ PPM_CONTEXT* Successor; // MaxOrder:
+ } _PACK_ATTR * Stats; // ABCD context
+ PPM_CONTEXT* Suffix; // BCD suffix
+ inline void encodeBinSymbol(int symbol);// BCDE successor
+ inline void encodeSymbol1(int symbol);// other orders:
+ inline void encodeSymbol2(int symbol);// BCD context
+ inline void decodeBinSymbol();// CD suffix
+ inline void decodeSymbol1();// BCDE successor
+ inline void decodeSymbol2();
+ inline void update1(STATE* p);
+ inline void update2(STATE* p);
+ inline SEE2_CONTEXT* makeEscFreq2();
+ void rescale();
+ void refresh(int OldNU,BOOL Scale);
+ PPM_CONTEXT* cutOff(int Order);
+ PPM_CONTEXT* removeBinConts(int Order);
+ STATE& oneState() const { return (STATE&) SummFreq; }
+} _PACK_ATTR* MaxContext;
+#pragma pack()
+
+static BYTE NS2BSIndx[256], QTable[260]; // constants
+static PPM_CONTEXT::STATE* FoundState; // found next state transition
+static int InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
+static BYTE CharMask[256], NumMasked, PrevSuccess, EscCount, PrintCount;
+static WORD BinSumm[25][64]; // binary SEE-contexts
+static MR_METHOD MRMethod;
+
+inline void SWAP(PPM_CONTEXT::STATE& s1,PPM_CONTEXT::STATE& s2)
+{
+ /*
+ WORD t1=(WORD&) s1; PPM_CONTEXT* t2=s1.Successor;
+ (WORD&) s1 = (WORD&) s2; s1.Successor=s2.Successor;
+ (WORD&) s2 = t1; s2.Successor=t2;
+ */
+ PPM_CONTEXT::STATE t = s1;
+ s1 = s2;
+ s2 = t;
+}
+inline void StateCpy(PPM_CONTEXT::STATE& s1,const PPM_CONTEXT::STATE& s2)
+{
+ // (WORD&) s1=(WORD&) s2; s1.Successor=s2.Successor;
+ s1 = s2;
+}
+struct PPMD_STARTUP { inline PPMD_STARTUP(); } PPMd_StartUp;
+inline PPMD_STARTUP::PPMD_STARTUP() // constants initialization
+{
+ UINT i, k, m, Step;
+ for (i=0,k=1;i < N1 ;i++,k += 1) Indx2Units[i]=k;
+ for (k++;i < N1+N2 ;i++,k += 2) Indx2Units[i]=k;
+ for (k++;i < N1+N2+N3 ;i++,k += 3) Indx2Units[i]=k;
+ for (k++;i < N1+N2+N3+N4;i++,k += 4) Indx2Units[i]=k;
+ for (k=i=0;k < 128;k++) {
+ i += (Indx2Units[i] < k+1); Units2Indx[k]=i;
+ }
+ NS2BSIndx[0]=2*0; NS2BSIndx[1]=2*1;
+ memset(NS2BSIndx+2,2*2,9); memset(NS2BSIndx+11,2*3,256-11);
+ for (i=0;i < UP_FREQ;i++) QTable[i]=i;
+ for (m=i=UP_FREQ, k=Step=1;i < 260;i++) {
+ QTable[i]=m;
+ if ( !--k ) { k = ++Step; m++; }
+ }
+ (DWORD&) DummySEE2Cont=PPMdSignature;
+}
+static void _STDCALL StartModelRare(int MaxOrder,MR_METHOD MRMethod)
+{
+ UINT i, k, m;
+ memset(CharMask,0,sizeof(CharMask)); EscCount=PrintCount=1;
+ if (MaxOrder < 2) { // we are in solid mode
+ OrderFall=::MaxOrder;
+ for (PPM_CONTEXT* pc=MaxContext;pc->Suffix != NULL;pc=pc->Suffix)
+ OrderFall--;
+ return;
+ }
+ OrderFall=::MaxOrder=MaxOrder; ::MRMethod=MRMethod;
+ InitSubAllocator();
+ RunLength=InitRL=-((MaxOrder < 12)?MaxOrder:12)-1;
+ MaxContext = (PPM_CONTEXT*) AllocContext();
+ MaxContext->Suffix=NULL;
+ MaxContext->SummFreq=(MaxContext->NumStats=255)+2;
+ MaxContext->Stats = (PPM_CONTEXT::STATE*) AllocUnits(256/2);
+ for (PrevSuccess=i=0;i < 256;i++) {
+ MaxContext->Stats[i].Symbol=i; MaxContext->Stats[i].Freq=1;
+ MaxContext->Stats[i].Successor=NULL;
+ }
+static const WORD InitBinEsc[]={0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051};
+ for (i=m=0;m < 25;m++) {
+ while (QTable[i] == m) i++;
+ for (k=0;k < 8;k++)
+ BinSumm[m][k]=BIN_SCALE-InitBinEsc[k]/(i+1);
+ for (k=8;k < 64;k += 8)
+ memcpy(BinSumm[m]+k,BinSumm[m],8*sizeof(WORD));
+ }
+ for (i=m=0;m < 24;m++) {
+ while (QTable[i+3] == m+3) i++;
+ SEE2Cont[m][0].init(2*i+5);
+ for (k=1;k < 32;k++) SEE2Cont[m][k]=SEE2Cont[m][0];
+ }
+}
+void PPM_CONTEXT::refresh(int OldNU,BOOL Scale)
+{
+ int i=NumStats, EscFreq;
+ STATE* p = Stats = (STATE*) ShrinkUnits(Stats,OldNU,(i+2) >> 1);
+ Flags=(Flags & (0x10+0x04*Scale))+0x08*(p->Symbol >= 0x40);
+ EscFreq=SummFreq-p->Freq;
+ SummFreq = (p->Freq=(p->Freq+Scale) >> Scale);
+ do {
+ EscFreq -= (++p)->Freq;
+ SummFreq += (p->Freq=(p->Freq+Scale) >> Scale);
+ Flags |= 0x08*(p->Symbol >= 0x40);
+ } while ( --i );
+ SummFreq += (EscFreq=(EscFreq+Scale) >> Scale);
+}
+#define P_CALL(F) ( PrefetchData(p->Successor), \
+ p->Successor=p->Successor->F(Order+1))
+PPM_CONTEXT* PPM_CONTEXT::cutOff(int Order)
+{
+ int i, tmp;
+ STATE* p;
+ if ( !NumStats ) {
+ if ((BYTE*) (p=&oneState())->Successor >= UnitsStart) {
+ if (Order < MaxOrder) P_CALL(cutOff);
+ else p->Successor=NULL;
+ if (!p->Successor && Order > O_BOUND)
+ goto REMOVE;
+ return this;
+ } else {
+REMOVE: SpecialFreeUnit(this); return NULL;
+ }
+ }
+ PrefetchData(Stats);
+ Stats = (STATE*) MoveUnitsUp(Stats,tmp=(NumStats+2) >> 1);
+ for (p=Stats+(i=NumStats);p >= Stats;p--)
+ if ((BYTE*) p->Successor < UnitsStart) {
+ p->Successor=NULL; SWAP(*p,Stats[i--]);
+ } else if (Order < MaxOrder) P_CALL(cutOff);
+ else p->Successor=NULL;
+ if (i != NumStats && Order) {
+ NumStats=i; p=Stats;
+ if (i < 0) { FreeUnits(p,tmp); goto REMOVE; }
+ else if (i == 0) {
+ Flags=(Flags & 0x10)+0x08*(p->Symbol >= 0x40);
+ StateCpy(oneState(),*p); FreeUnits(p,tmp);
+ oneState().Freq=(oneState().Freq+11) >> 3;
+ } else refresh(tmp,SummFreq > 16*i);
+ }
+ return this;
+}
+PPM_CONTEXT* PPM_CONTEXT::removeBinConts(int Order)
+{
+ STATE* p;
+ if ( !NumStats ) {
+ p=&oneState();
+ if ((BYTE*) p->Successor >= UnitsStart && Order < MaxOrder)
+ P_CALL(removeBinConts);
+ else p->Successor=NULL;
+ if (!p->Successor && (!Suffix->NumStats || Suffix->Flags == 0xFF)) {
+ FreeUnits(this,1); return NULL;
+ } else return this;
+ }
+ PrefetchData(Stats);
+ for (p=Stats+NumStats;p >= Stats;p--)
+ if ((BYTE*) p->Successor >= UnitsStart && Order < MaxOrder)
+ P_CALL(removeBinConts);
+ else p->Successor=NULL;
+ return this;
+}
+static void RestoreModelRare(PPM_CONTEXT* pc1,PPM_CONTEXT* MinContext,
+ PPM_CONTEXT* FSuccessor)
+{
+ PPM_CONTEXT* pc;
+ PPM_CONTEXT::STATE* p;
+ for (pc=MaxContext, pText=HeapStart;pc != pc1;pc=pc->Suffix)
+ if (--(pc->NumStats) == 0) {
+ pc->Flags=(pc->Flags & 0x10)+0x08*(pc->Stats->Symbol >= 0x40);
+ p=pc->Stats; StateCpy(pc->oneState(),*p);
+ SpecialFreeUnit(p);
+ pc->oneState().Freq=(pc->oneState().Freq+11) >> 3;
+ } else
+ pc->refresh((pc->NumStats+3) >> 1,FALSE);
+ for ( ;pc != MinContext;pc=pc->Suffix)
+ if ( !pc->NumStats )
+ pc->oneState().Freq -= pc->oneState().Freq >> 1;
+ else if ((pc->SummFreq += 4) > 128+4*pc->NumStats)
+ pc->refresh((pc->NumStats+2) >> 1,TRUE);
+ if (MRMethod > MRM_FREEZE) {
+ MaxContext=FSuccessor; GlueCount += !(BList[1].Stamp & 1);
+ } else if (MRMethod == MRM_FREEZE) {
+ while ( MaxContext->Suffix ) MaxContext=MaxContext->Suffix;
+ MaxContext->removeBinConts(0); MRMethod=MR_METHOD(MRMethod+1);
+ GlueCount=0; OrderFall=MaxOrder;
+ } else if (MRMethod == MRM_RESTART || GetUsedMemory() < (SubAllocatorSize >> 1)) {
+ StartModelRare(MaxOrder,MRMethod);
+ EscCount=0; PrintCount=0xFF;
+ } else {
+ while ( MaxContext->Suffix ) MaxContext=MaxContext->Suffix;
+ do {
+ MaxContext->cutOff(0); ExpandTextArea();
+ } while (GetUsedMemory() > 3*(SubAllocatorSize >> 2));
+ GlueCount=0; OrderFall=MaxOrder;
+ }
+}
+static PPM_CONTEXT* _FASTCALL CreateSuccessors(BOOL Skip,PPM_CONTEXT::STATE* p,
+ PPM_CONTEXT* pc);
+static PPM_CONTEXT* _FASTCALL ReduceOrder(PPM_CONTEXT::STATE* p,PPM_CONTEXT* pc)
+{
+ PPM_CONTEXT::STATE* p1, * ps[MAX_O], ** pps=ps;
+ PPM_CONTEXT* pc1=pc, * UpBranch = (PPM_CONTEXT*) pText;
+ BYTE tmp, sym=FoundState->Symbol;
+ *pps++ = FoundState; FoundState->Successor=UpBranch;
+ OrderFall++;
+ if ( p ) { pc=pc->Suffix; goto LOOP_ENTRY; }
+ for ( ; ; ) {
+ if ( !pc->Suffix ) {
+ if (MRMethod > MRM_FREEZE) {
+FROZEN: do { (*--pps)->Successor = pc; } while (pps != ps);
+ pText=HeapStart+1; OrderFall=1;
+ }
+ return pc;
+ }
+ pc=pc->Suffix;
+ if ( pc->NumStats ) {
+ if ((p=pc->Stats)->Symbol != sym)
+ do { tmp=p[1].Symbol; p++; } while (tmp != sym);
+ tmp=2*(p->Freq < MAX_FREQ-9);
+ p->Freq += tmp; pc->SummFreq += tmp;
+ } else { p=&(pc->oneState()); p->Freq += (p->Freq < 32); }
+LOOP_ENTRY:
+ if ( p->Successor ) break;
+ *pps++ = p; p->Successor=UpBranch;
+ OrderFall++;
+ }
+ if (MRMethod > MRM_FREEZE) {
+ pc = p->Successor; goto FROZEN;
+ } else if (p->Successor <= UpBranch) {
+ p1=FoundState; FoundState=p;
+ p->Successor=CreateSuccessors(FALSE,NULL,pc);
+ FoundState=p1;
+ }
+ if (OrderFall == 1 && pc1 == MaxContext) {
+ FoundState->Successor=p->Successor; pText--;
+ }
+ return p->Successor;
+}
+void PPM_CONTEXT::rescale()
+{
+ UINT OldNU, Adder, EscFreq, i=NumStats;
+ STATE tmp, * p1, * p;
+ for (p=FoundState;p != Stats;p--) SWAP(p[0],p[-1]);
+ p->Freq += 4; SummFreq += 4;
+ EscFreq=SummFreq-p->Freq;
+ Adder=(OrderFall != 0 || MRMethod > MRM_FREEZE);
+ SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
+ do {
+ EscFreq -= (++p)->Freq;
+ SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
+ if (p[0].Freq > p[-1].Freq) {
+ StateCpy(tmp,*(p1=p));
+ do StateCpy(p1[0],p1[-1]); while (tmp.Freq > (--p1)[-1].Freq);
+ StateCpy(*p1,tmp);
+ }
+ } while ( --i );
+ if (p->Freq == 0) {
+ do { i++; } while ((--p)->Freq == 0);
+ EscFreq += i; OldNU=(NumStats+2) >> 1;
+ if ((NumStats -= i) == 0) {
+ StateCpy(tmp,*Stats);
+ tmp.Freq=(2*tmp.Freq+EscFreq-1)/EscFreq;
+ if (tmp.Freq > MAX_FREQ/3) tmp.Freq=MAX_FREQ/3;
+ FreeUnits(Stats,OldNU); StateCpy(oneState(),tmp);
+ Flags=(Flags & 0x10)+0x08*(tmp.Symbol >= 0x40);
+ FoundState=&oneState(); return;
+ }
+ Stats = (STATE*) ShrinkUnits(Stats,OldNU,(NumStats+2) >> 1);
+ Flags &= ~0x08; i=NumStats;
+ Flags |= 0x08*((p=Stats)->Symbol >= 0x40);
+ do { Flags |= 0x08*((++p)->Symbol >= 0x40); } while ( --i );
+ }
+ SummFreq += (EscFreq -= (EscFreq >> 1));
+ Flags |= 0x04; FoundState=Stats;
+}
+static PPM_CONTEXT* _FASTCALL CreateSuccessors(BOOL Skip,PPM_CONTEXT::STATE* p,
+ PPM_CONTEXT* pc)
+{
+ PPM_CONTEXT ct, * UpBranch=FoundState->Successor;
+ PPM_CONTEXT::STATE* ps[MAX_O], ** pps=ps;
+ UINT cf, s0;
+ BYTE tmp, sym=FoundState->Symbol;
+ if ( !Skip ) {
+ *pps++ = FoundState;
+ if ( !pc->Suffix ) goto NO_LOOP;
+ }
+ if ( p ) { pc=pc->Suffix; goto LOOP_ENTRY; }
+ do {
+ pc=pc->Suffix;
+ if ( pc->NumStats ) {
+ if ((p=pc->Stats)->Symbol != sym)
+ do { tmp=p[1].Symbol; p++; } while (tmp != sym);
+ tmp=(p->Freq < MAX_FREQ-9);
+ p->Freq += tmp; pc->SummFreq += tmp;
+ } else {
+ p=&(pc->oneState());
+ p->Freq += (!pc->Suffix->NumStats & (p->Freq < 24));
+ }
+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(CInfo* EncodedFile, CInfo* DecodedFile)
+{
+ EscCount=1; memset(CharMask,0,sizeof(CharMask));
+ // if (++PrintCount == 0) PrintInfo(DecodedFile,EncodedFile);
+}
+void _STDCALL EncodeFile(CSink* EncodedFile, CSource* 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(CSink* DecodedFile, CSource* 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);
+ return;
+}
+
+
+
+#include "PPMd.h"
+#include "CSource.h"
+
+size_t UnPPM(bool extra, unsigned char* readbuffer, size_t reclen, unsigned char* buffer, size_t buffersize)
+{
+ unsigned short order, mem, offset = 1;
+ int type = 0;
+ if (extra)
+ {
+ order = readbuffer[1];
+ mem = readbuffer[0];
+ type = order >> 6;
+ order = (order & 63) + 2;
+ offset = 2;
+ }
+ else
+ {
+ order = readbuffer[0];
+ mem = order >> 4;
+ order = (order & 15) + 2;
+ }
+ mem++;
+ // qDebug("Mem:%u Order:%u Type:%u\n", mem, order, type);
+ StartSubAllocator(mem);
+ CMemSink sink(buffer, buffersize);
+ CMemSource source(readbuffer+offset, reclen-offset);
+ DecodeFile(&sink,&source,order,(MR_METHOD)type);
+ StopSubAllocator();
+ return sink.size();
+}
+
+
+extern "C"
+{
+
+size_t PluckerDecompress3(unsigned char* a, size_t b, unsigned char* c, size_t d)
+{
+ return UnPPM(false, a, b, c, d);
+}
+
+size_t PluckerDecompress4(unsigned char* a, size_t b, unsigned char* c, size_t d)
+{
+ return UnPPM(true, a, b, c, d);
+}
+
+size_t RebDecompress(unsigned char* a, size_t b, unsigned char* c, size_t d)
+{
+ return UnPPM(true, a, b, c, d);
+}
+
+}