00001
00002
00003
00004
00005
00006
00007 #include <string.h>
00008 #include "PPMd.h"
00009 #pragma hdrstop
00010 #include "Coder.h"
00011 #include "SubAlloc.h"
00012
00013 enum { UP_FREQ=5, INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
00014 INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124, O_BOUND=9 };
00015
00016 #pragma pack(1)
00017 static struct SEE2_CONTEXT {
00018 WORD Summ;
00019 BYTE Shift, Count;
00020 void init(UINT InitVal) { Summ=InitVal << (Shift=PERIOD_BITS-4); Count=7; }
00021 UINT getMean() {
00022 UINT RetVal=(Summ >> Shift); Summ -= RetVal;
00023 return RetVal+(RetVal == 0);
00024 }
00025 void update() {
00026 if (Shift < PERIOD_BITS && --Count == 0) {
00027 Summ += Summ; Count=3 << Shift++;
00028 }
00029 }
00030 } _PACK_ATTR SEE2Cont[24][32], DummySEE2Cont;
00031 static struct PPM_CONTEXT {
00032 BYTE NumStats, Flags;
00033 WORD SummFreq;
00034 struct STATE {
00035 BYTE Symbol, Freq;
00036 PPM_CONTEXT* Successor;
00037 } _PACK_ATTR * Stats;
00038 PPM_CONTEXT* Suffix;
00039 inline void encodeBinSymbol(int symbol);
00040 inline void encodeSymbol1(int symbol);
00041 inline void encodeSymbol2(int symbol);
00042 inline void decodeBinSymbol();
00043 inline void decodeSymbol1();
00044 inline void decodeSymbol2();
00045 inline void update1(STATE* p);
00046 inline void update2(STATE* p);
00047 inline SEE2_CONTEXT* makeEscFreq2();
00048 void rescale();
00049 void refresh(int OldNU,BOOL Scale);
00050 PPM_CONTEXT* cutOff(int Order);
00051 PPM_CONTEXT* removeBinConts(int Order);
00052 STATE& oneState() const { return (STATE&) SummFreq; }
00053 } _PACK_ATTR* MaxContext;
00054 #pragma pack()
00055
00056 static BYTE NS2BSIndx[256], QTable[260];
00057 static PPM_CONTEXT::STATE* FoundState;
00058 static int InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
00059 static BYTE CharMask[256], NumMasked, PrevSuccess, EscCount, PrintCount;
00060 static WORD BinSumm[25][64];
00061 static MR_METHOD MRMethod;
00062
00063 inline void SWAP(PPM_CONTEXT::STATE& s1,PPM_CONTEXT::STATE& s2)
00064 {
00065
00066
00067
00068
00069
00070 PPM_CONTEXT::STATE t = s1;
00071 s1 = s2;
00072 s2 = t;
00073 }
00074 inline void StateCpy(PPM_CONTEXT::STATE& s1,const PPM_CONTEXT::STATE& s2)
00075 {
00076
00077 s1 = s2;
00078 }
00079 struct PPMD_STARTUP { inline PPMD_STARTUP(); } PPMd_StartUp;
00080 inline PPMD_STARTUP::PPMD_STARTUP()
00081 {
00082 UINT i, k, m, Step;
00083 for (i=0,k=1;i < N1 ;i++,k += 1) Indx2Units[i]=k;
00084 for (k++;i < N1+N2 ;i++,k += 2) Indx2Units[i]=k;
00085 for (k++;i < N1+N2+N3 ;i++,k += 3) Indx2Units[i]=k;
00086 for (k++;i < N1+N2+N3+N4;i++,k += 4) Indx2Units[i]=k;
00087 for (k=i=0;k < 128;k++) {
00088 i += (Indx2Units[i] < k+1); Units2Indx[k]=i;
00089 }
00090 NS2BSIndx[0]=2*0; NS2BSIndx[1]=2*1;
00091 memset(NS2BSIndx+2,2*2,9); memset(NS2BSIndx+11,2*3,256-11);
00092 for (i=0;i < UP_FREQ;i++) QTable[i]=i;
00093 for (m=i=UP_FREQ, k=Step=1;i < 260;i++) {
00094 QTable[i]=m;
00095 if ( !--k ) { k = ++Step; m++; }
00096 }
00097 (DWORD&) DummySEE2Cont=PPMdSignature;
00098 }
00099 static void _STDCALL StartModelRare(int MaxOrder,MR_METHOD MRMethod)
00100 {
00101 UINT i, k, m;
00102 memset(CharMask,0,sizeof(CharMask)); EscCount=PrintCount=1;
00103 if (MaxOrder < 2) {
00104 OrderFall=::MaxOrder;
00105 for (PPM_CONTEXT* pc=MaxContext;pc->Suffix != NULL;pc=pc->Suffix)
00106 OrderFall--;
00107 return;
00108 }
00109 OrderFall=::MaxOrder=MaxOrder; ::MRMethod=MRMethod;
00110 InitSubAllocator();
00111 RunLength=InitRL=-((MaxOrder < 12)?MaxOrder:12)-1;
00112 MaxContext = (PPM_CONTEXT*) AllocContext();
00113 MaxContext->Suffix=NULL;
00114 MaxContext->SummFreq=(MaxContext->NumStats=255)+2;
00115 MaxContext->Stats = (PPM_CONTEXT::STATE*) AllocUnits(256/2);
00116 for (PrevSuccess=i=0;i < 256;i++) {
00117 MaxContext->Stats[i].Symbol=i; MaxContext->Stats[i].Freq=1;
00118 MaxContext->Stats[i].Successor=NULL;
00119 }
00120 static const WORD InitBinEsc[]={0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051};
00121 for (i=m=0;m < 25;m++) {
00122 while (QTable[i] == m) i++;
00123 for (k=0;k < 8;k++)
00124 BinSumm[m][k]=BIN_SCALE-InitBinEsc[k]/(i+1);
00125 for (k=8;k < 64;k += 8)
00126 memcpy(BinSumm[m]+k,BinSumm[m],8*sizeof(WORD));
00127 }
00128 for (i=m=0;m < 24;m++) {
00129 while (QTable[i+3] == m+3) i++;
00130 SEE2Cont[m][0].init(2*i+5);
00131 for (k=1;k < 32;k++) SEE2Cont[m][k]=SEE2Cont[m][0];
00132 }
00133 }
00134 void PPM_CONTEXT::refresh(int OldNU,BOOL Scale)
00135 {
00136 int i=NumStats, EscFreq;
00137 STATE* p = Stats = (STATE*) ShrinkUnits(Stats,OldNU,(i+2) >> 1);
00138 Flags=(Flags & (0x10+0x04*Scale))+0x08*(p->Symbol >= 0x40);
00139 EscFreq=SummFreq-p->Freq;
00140 SummFreq = (p->Freq=(p->Freq+Scale) >> Scale);
00141 do {
00142 EscFreq -= (++p)->Freq;
00143 SummFreq += (p->Freq=(p->Freq+Scale) >> Scale);
00144 Flags |= 0x08*(p->Symbol >= 0x40);
00145 } while ( --i );
00146 SummFreq += (EscFreq=(EscFreq+Scale) >> Scale);
00147 }
00148 #define P_CALL(F) ( PrefetchData(p->Successor), \
00149 p->Successor=p->Successor->F(Order+1))
00150 PPM_CONTEXT* PPM_CONTEXT::cutOff(int Order)
00151 {
00152 int i, tmp;
00153 STATE* p;
00154 if ( !NumStats ) {
00155 if ((BYTE*) (p=&oneState())->Successor >= UnitsStart) {
00156 if (Order < MaxOrder) P_CALL(cutOff);
00157 else p->Successor=NULL;
00158 if (!p->Successor && Order > O_BOUND)
00159 goto REMOVE;
00160 return this;
00161 } else {
00162 REMOVE: SpecialFreeUnit(this); return NULL;
00163 }
00164 }
00165 PrefetchData(Stats);
00166 Stats = (STATE*) MoveUnitsUp(Stats,tmp=(NumStats+2) >> 1);
00167 for (p=Stats+(i=NumStats);p >= Stats;p--)
00168 if ((BYTE*) p->Successor < UnitsStart) {
00169 p->Successor=NULL; SWAP(*p,Stats[i--]);
00170 } else if (Order < MaxOrder) P_CALL(cutOff);
00171 else p->Successor=NULL;
00172 if (i != NumStats && Order) {
00173 NumStats=i; p=Stats;
00174 if (i < 0) { FreeUnits(p,tmp); goto REMOVE; }
00175 else if (i == 0) {
00176 Flags=(Flags & 0x10)+0x08*(p->Symbol >= 0x40);
00177 StateCpy(oneState(),*p); FreeUnits(p,tmp);
00178 oneState().Freq=(oneState().Freq+11) >> 3;
00179 } else refresh(tmp,SummFreq > 16*i);
00180 }
00181 return this;
00182 }
00183 PPM_CONTEXT* PPM_CONTEXT::removeBinConts(int Order)
00184 {
00185 STATE* p;
00186 if ( !NumStats ) {
00187 p=&oneState();
00188 if ((BYTE*) p->Successor >= UnitsStart && Order < MaxOrder)
00189 P_CALL(removeBinConts);
00190 else p->Successor=NULL;
00191 if (!p->Successor && (!Suffix->NumStats || Suffix->Flags == 0xFF)) {
00192 FreeUnits(this,1); return NULL;
00193 } else return this;
00194 }
00195 PrefetchData(Stats);
00196 for (p=Stats+NumStats;p >= Stats;p--)
00197 if ((BYTE*) p->Successor >= UnitsStart && Order < MaxOrder)
00198 P_CALL(removeBinConts);
00199 else p->Successor=NULL;
00200 return this;
00201 }
00202 static void RestoreModelRare(PPM_CONTEXT* pc1,PPM_CONTEXT* MinContext,
00203 PPM_CONTEXT* FSuccessor)
00204 {
00205 PPM_CONTEXT* pc;
00206 PPM_CONTEXT::STATE* p;
00207 for (pc=MaxContext, pText=HeapStart;pc != pc1;pc=pc->Suffix)
00208 if (--(pc->NumStats) == 0) {
00209 pc->Flags=(pc->Flags & 0x10)+0x08*(pc->Stats->Symbol >= 0x40);
00210 p=pc->Stats; StateCpy(pc->oneState(),*p);
00211 SpecialFreeUnit(p);
00212 pc->oneState().Freq=(pc->oneState().Freq+11) >> 3;
00213 } else
00214 pc->refresh((pc->NumStats+3) >> 1,FALSE);
00215 for ( ;pc != MinContext;pc=pc->Suffix)
00216 if ( !pc->NumStats )
00217 pc->oneState().Freq -= pc->oneState().Freq >> 1;
00218 else if ((pc->SummFreq += 4) > 128+4*pc->NumStats)
00219 pc->refresh((pc->NumStats+2) >> 1,TRUE);
00220 if (MRMethod > MRM_FREEZE) {
00221 MaxContext=FSuccessor; GlueCount += !(BList[1].Stamp & 1);
00222 } else if (MRMethod == MRM_FREEZE) {
00223 while ( MaxContext->Suffix ) MaxContext=MaxContext->Suffix;
00224 MaxContext->removeBinConts(0); MRMethod=MR_METHOD(MRMethod+1);
00225 GlueCount=0; OrderFall=MaxOrder;
00226 } else if (MRMethod == MRM_RESTART || GetUsedMemory() < (SubAllocatorSize >> 1)) {
00227 StartModelRare(MaxOrder,MRMethod);
00228 EscCount=0; PrintCount=0xFF;
00229 } else {
00230 while ( MaxContext->Suffix ) MaxContext=MaxContext->Suffix;
00231 do {
00232 MaxContext->cutOff(0); ExpandTextArea();
00233 } while (GetUsedMemory() > 3*(SubAllocatorSize >> 2));
00234 GlueCount=0; OrderFall=MaxOrder;
00235 }
00236 }
00237 static PPM_CONTEXT* _FASTCALL CreateSuccessors(BOOL Skip,PPM_CONTEXT::STATE* p,
00238 PPM_CONTEXT* pc);
00239 static PPM_CONTEXT* _FASTCALL ReduceOrder(PPM_CONTEXT::STATE* p,PPM_CONTEXT* pc)
00240 {
00241 PPM_CONTEXT::STATE* p1, * ps[MAX_O], ** pps=ps;
00242 PPM_CONTEXT* pc1=pc, * UpBranch = (PPM_CONTEXT*) pText;
00243 BYTE tmp, sym=FoundState->Symbol;
00244 *pps++ = FoundState; FoundState->Successor=UpBranch;
00245 OrderFall++;
00246 if ( p ) { pc=pc->Suffix; goto LOOP_ENTRY; }
00247 for ( ; ; ) {
00248 if ( !pc->Suffix ) {
00249 if (MRMethod > MRM_FREEZE) {
00250 FROZEN: do { (*--pps)->Successor = pc; } while (pps != ps);
00251 pText=HeapStart+1; OrderFall=1;
00252 }
00253 return pc;
00254 }
00255 pc=pc->Suffix;
00256 if ( pc->NumStats ) {
00257 if ((p=pc->Stats)->Symbol != sym)
00258 do { tmp=p[1].Symbol; p++; } while (tmp != sym);
00259 tmp=2*(p->Freq < MAX_FREQ-9);
00260 p->Freq += tmp; pc->SummFreq += tmp;
00261 } else { p=&(pc->oneState()); p->Freq += (p->Freq < 32); }
00262 LOOP_ENTRY:
00263 if ( p->Successor ) break;
00264 *pps++ = p; p->Successor=UpBranch;
00265 OrderFall++;
00266 }
00267 if (MRMethod > MRM_FREEZE) {
00268 pc = p->Successor; goto FROZEN;
00269 } else if (p->Successor <= UpBranch) {
00270 p1=FoundState; FoundState=p;
00271 p->Successor=CreateSuccessors(FALSE,NULL,pc);
00272 FoundState=p1;
00273 }
00274 if (OrderFall == 1 && pc1 == MaxContext) {
00275 FoundState->Successor=p->Successor; pText--;
00276 }
00277 return p->Successor;
00278 }
00279 void PPM_CONTEXT::rescale()
00280 {
00281 UINT OldNU, Adder, EscFreq, i=NumStats;
00282 STATE tmp, * p1, * p;
00283 for (p=FoundState;p != Stats;p--) SWAP(p[0],p[-1]);
00284 p->Freq += 4; SummFreq += 4;
00285 EscFreq=SummFreq-p->Freq;
00286 Adder=(OrderFall != 0 || MRMethod > MRM_FREEZE);
00287 SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
00288 do {
00289 EscFreq -= (++p)->Freq;
00290 SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
00291 if (p[0].Freq > p[-1].Freq) {
00292 StateCpy(tmp,*(p1=p));
00293 do StateCpy(p1[0],p1[-1]); while (tmp.Freq > (--p1)[-1].Freq);
00294 StateCpy(*p1,tmp);
00295 }
00296 } while ( --i );
00297 if (p->Freq == 0) {
00298 do { i++; } while ((--p)->Freq == 0);
00299 EscFreq += i; OldNU=(NumStats+2) >> 1;
00300 if ((NumStats -= i) == 0) {
00301 StateCpy(tmp,*Stats);
00302 tmp.Freq=(2*tmp.Freq+EscFreq-1)/EscFreq;
00303 if (tmp.Freq > MAX_FREQ/3) tmp.Freq=MAX_FREQ/3;
00304 FreeUnits(Stats,OldNU); StateCpy(oneState(),tmp);
00305 Flags=(Flags & 0x10)+0x08*(tmp.Symbol >= 0x40);
00306 FoundState=&oneState(); return;
00307 }
00308 Stats = (STATE*) ShrinkUnits(Stats,OldNU,(NumStats+2) >> 1);
00309 Flags &= ~0x08; i=NumStats;
00310 Flags |= 0x08*((p=Stats)->Symbol >= 0x40);
00311 do { Flags |= 0x08*((++p)->Symbol >= 0x40); } while ( --i );
00312 }
00313 SummFreq += (EscFreq -= (EscFreq >> 1));
00314 Flags |= 0x04; FoundState=Stats;
00315 }
00316 static PPM_CONTEXT* _FASTCALL CreateSuccessors(BOOL Skip,PPM_CONTEXT::STATE* p,
00317 PPM_CONTEXT* pc)
00318 {
00319 PPM_CONTEXT ct, * UpBranch=FoundState->Successor;
00320 PPM_CONTEXT::STATE* ps[MAX_O], ** pps=ps;
00321 UINT cf, s0;
00322 BYTE tmp, sym=FoundState->Symbol;
00323 if ( !Skip ) {
00324 *pps++ = FoundState;
00325 if ( !pc->Suffix ) goto NO_LOOP;
00326 }
00327 if ( p ) { pc=pc->Suffix; goto LOOP_ENTRY; }
00328 do {
00329 pc=pc->Suffix;
00330 if ( pc->NumStats ) {
00331 if ((p=pc->Stats)->Symbol != sym)
00332 do { tmp=p[1].Symbol; p++; } while (tmp != sym);
00333 tmp=(p->Freq < MAX_FREQ-9);
00334 p->Freq += tmp; pc->SummFreq += tmp;
00335 } else {
00336 p=&(pc->oneState());
00337 p->Freq += (!pc->Suffix->NumStats & (p->Freq < 24));
00338 }
00339 LOOP_ENTRY:
00340 if (p->Successor != UpBranch) {
00341 pc=p->Successor; break;
00342 }
00343 *pps++ = p;
00344 } while ( pc->Suffix );
00345 NO_LOOP:
00346 if (pps == ps) return pc;
00347 ct.NumStats=0; ct.Flags=0x10*(sym >= 0x40);
00348 ct.oneState().Symbol=sym=*(BYTE*) UpBranch;
00349 ct.oneState().Successor=(PPM_CONTEXT*) (((BYTE*) UpBranch)+1);
00350 ct.Flags |= 0x08*(sym >= 0x40);
00351 if ( pc->NumStats ) {
00352 if ((p=pc->Stats)->Symbol != sym)
00353 do { tmp=p[1].Symbol; p++; } while (tmp != sym);
00354 s0=pc->SummFreq-pc->NumStats-(cf=p->Freq-1);
00355 ct.oneState().Freq=1+((2*cf <= s0)?(5*cf > s0):((cf+2*s0-3)/s0));
00356 } else
00357 ct.oneState().Freq=pc->oneState().Freq;
00358 do {
00359 PPM_CONTEXT* pc1 = (PPM_CONTEXT*) AllocContext();
00360 if ( !pc1 ) return NULL;
00361 ((DWORD*) pc1)[0] = ((DWORD*) &ct)[0];
00362 ((DWORD*) pc1)[1] = ((DWORD*) &ct)[1];
00363 pc1->Suffix=pc; (*--pps)->Successor=pc=pc1;
00364 } while (pps != ps);
00365 return pc;
00366 }
00367 static inline void UpdateModel(PPM_CONTEXT* MinContext)
00368 {
00369 PPM_CONTEXT::STATE* p=NULL;
00370 PPM_CONTEXT* Successor, * FSuccessor, * pc, * pc1=MaxContext;
00371 UINT ns1, ns, cf, sf, s0, FFreq=FoundState->Freq;
00372 BYTE Flag, sym, FSymbol=FoundState->Symbol;
00373 FSuccessor=FoundState->Successor; pc=MinContext->Suffix;
00374 if (FFreq < MAX_FREQ/4 && pc) {
00375 if ( pc->NumStats ) {
00376 if ((p=pc->Stats)->Symbol != FSymbol) {
00377 do { sym=p[1].Symbol; p++; } while (sym != FSymbol);
00378 if (p[0].Freq >= p[-1].Freq) {
00379 SWAP(p[0],p[-1]); p--;
00380 }
00381 }
00382 cf=2*(p->Freq < MAX_FREQ-9);
00383 p->Freq += cf; pc->SummFreq += cf;
00384 } else { p=&(pc->oneState()); p->Freq += (p->Freq < 32); }
00385 }
00386 if (!OrderFall && FSuccessor) {
00387 FoundState->Successor=CreateSuccessors(TRUE,p,MinContext);
00388 if ( !FoundState->Successor ) goto RESTART_MODEL;
00389 MaxContext=FoundState->Successor; return;
00390 }
00391 *pText++ = FSymbol; Successor = (PPM_CONTEXT*) pText;
00392 if (pText >= UnitsStart) goto RESTART_MODEL;
00393 if ( FSuccessor ) {
00394 if ((BYTE*) FSuccessor < UnitsStart)
00395 FSuccessor=CreateSuccessors(FALSE,p,MinContext);
00396 } else
00397 FSuccessor=ReduceOrder(p,MinContext);
00398 if ( !FSuccessor ) goto RESTART_MODEL;
00399 if ( !--OrderFall ) {
00400 Successor=FSuccessor; pText -= (MaxContext != MinContext);
00401 } else if (MRMethod > MRM_FREEZE) {
00402 Successor=FSuccessor; pText=HeapStart;
00403 OrderFall=0;
00404 }
00405 s0=MinContext->SummFreq-(ns=MinContext->NumStats)-FFreq;
00406 for (Flag=0x08*(FSymbol >= 0x40);pc1 != MinContext;pc1=pc1->Suffix) {
00407 if ((ns1=pc1->NumStats) != 0) {
00408 if ((ns1 & 1) != 0) {
00409 p=(PPM_CONTEXT::STATE*) ExpandUnits(pc1->Stats,(ns1+1) >> 1);
00410 if ( !p ) goto RESTART_MODEL;
00411 pc1->Stats=p;
00412 }
00413 pc1->SummFreq += (3*ns1+1 < ns);
00414 } else {
00415 p=(PPM_CONTEXT::STATE*) AllocUnits(1);
00416 if ( !p ) goto RESTART_MODEL;
00417 StateCpy(*p,pc1->oneState()); pc1->Stats=p;
00418 if (p->Freq < MAX_FREQ/4-1) p->Freq += p->Freq;
00419 else p->Freq = MAX_FREQ-4;
00420 pc1->SummFreq=p->Freq+InitEsc+(ns > 2);
00421 }
00422 cf=2*FFreq*(pc1->SummFreq+6); sf=s0+pc1->SummFreq;
00423 if (cf < 6*sf) {
00424 cf=1+(cf > sf)+(cf >= 4*sf);
00425 pc1->SummFreq += 4;
00426 } else {
00427 cf=4+(cf > 9*sf)+(cf > 12*sf)+(cf > 15*sf);
00428 pc1->SummFreq += cf;
00429 }
00430 p=pc1->Stats+(++pc1->NumStats); p->Successor=Successor;
00431 p->Symbol = FSymbol; p->Freq = cf;
00432 pc1->Flags |= Flag;
00433 }
00434 MaxContext=FSuccessor; return;
00435 RESTART_MODEL:
00436 RestoreModelRare(pc1,MinContext,FSuccessor);
00437 }
00438
00439 static const BYTE ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
00440 #define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
00441 inline void PPM_CONTEXT::encodeBinSymbol(int symbol)
00442 {
00443 BYTE indx=NS2BSIndx[Suffix->NumStats]+PrevSuccess+Flags;
00444 STATE& rs=oneState();
00445 WORD& bs=BinSumm[QTable[rs.Freq-1]][indx+((RunLength >> 26) & 0x20)];
00446 if (rs.Symbol == symbol) {
00447 FoundState=&rs; rs.Freq += (rs.Freq < 196);
00448 SubRange.LowCount=0; SubRange.HighCount=bs;
00449 bs += INTERVAL-GET_MEAN(bs,PERIOD_BITS,2);
00450 PrevSuccess=1; RunLength++;
00451 } else {
00452 SubRange.LowCount=bs; bs -= GET_MEAN(bs,PERIOD_BITS,2);
00453 SubRange.HighCount=BIN_SCALE; InitEsc=ExpEscape[bs >> 10];
00454 CharMask[rs.Symbol]=EscCount;
00455 NumMasked=PrevSuccess=0; FoundState=NULL;
00456 }
00457 }
00458 inline void PPM_CONTEXT::decodeBinSymbol()
00459 {
00460 BYTE indx=NS2BSIndx[Suffix->NumStats]+PrevSuccess+Flags;
00461 STATE& rs=oneState();
00462 WORD& bs=BinSumm[QTable[rs.Freq-1]][indx+((RunLength >> 26) & 0x20)];
00463 if (ariGetCurrentShiftCount(TOT_BITS) < bs) {
00464 FoundState=&rs; rs.Freq += (rs.Freq < 196);
00465 SubRange.LowCount=0; SubRange.HighCount=bs;
00466 bs += INTERVAL-GET_MEAN(bs,PERIOD_BITS,2);
00467 PrevSuccess=1; RunLength++;
00468 } else {
00469 SubRange.LowCount=bs; bs -= GET_MEAN(bs,PERIOD_BITS,2);
00470 SubRange.HighCount=BIN_SCALE; InitEsc=ExpEscape[bs >> 10];
00471 CharMask[rs.Symbol]=EscCount;
00472 NumMasked=PrevSuccess=0; FoundState=NULL;
00473 }
00474 }
00475 inline void PPM_CONTEXT::update1(STATE* p)
00476 {
00477 (FoundState=p)->Freq += 4; SummFreq += 4;
00478 if (p[0].Freq > p[-1].Freq) {
00479 SWAP(p[0],p[-1]); FoundState=--p;
00480 if (p->Freq > MAX_FREQ) rescale();
00481 }
00482 }
00483 inline void PPM_CONTEXT::encodeSymbol1(int symbol)
00484 {
00485 UINT LoCnt, i=Stats->Symbol;
00486 STATE* p=Stats; SubRange.scale=SummFreq;
00487 if (i == symbol) {
00488 PrevSuccess=(2*(SubRange.HighCount=p->Freq) >= SubRange.scale);
00489 (FoundState=p)->Freq += 4; SummFreq += 4;
00490 RunLength += PrevSuccess;
00491 if (p->Freq > MAX_FREQ) rescale();
00492 SubRange.LowCount=0; return;
00493 }
00494 LoCnt=p->Freq;
00495 i=NumStats; PrevSuccess=0;
00496 while ((++p)->Symbol != symbol) {
00497 LoCnt += p->Freq;
00498 if (--i == 0) {
00499 if ( Suffix ) PrefetchData(Suffix);
00500 SubRange.LowCount=LoCnt; CharMask[p->Symbol]=EscCount;
00501 i=NumMasked=NumStats; FoundState=NULL;
00502 do { CharMask[(--p)->Symbol]=EscCount; } while ( --i );
00503 SubRange.HighCount=SubRange.scale;
00504 return;
00505 }
00506 }
00507 SubRange.HighCount=(SubRange.LowCount=LoCnt)+p->Freq;
00508 update1(p);
00509 }
00510 inline void PPM_CONTEXT::decodeSymbol1()
00511 {
00512 UINT i, count, HiCnt=Stats->Freq;
00513 STATE* p=Stats; SubRange.scale=SummFreq;
00514 if ((count=ariGetCurrentCount()) < HiCnt) {
00515 PrevSuccess=(2*(SubRange.HighCount=HiCnt) >= SubRange.scale);
00516 (FoundState=p)->Freq=(HiCnt += 4); SummFreq += 4;
00517 RunLength += PrevSuccess;
00518 if (HiCnt > MAX_FREQ) rescale();
00519 SubRange.LowCount=0; return;
00520 }
00521 i=NumStats; PrevSuccess=0;
00522 while ((HiCnt += (++p)->Freq) <= count)
00523 if (--i == 0) {
00524 if ( Suffix ) PrefetchData(Suffix);
00525 SubRange.LowCount=HiCnt; CharMask[p->Symbol]=EscCount;
00526 i=NumMasked=NumStats; FoundState=NULL;
00527 do { CharMask[(--p)->Symbol]=EscCount; } while ( --i );
00528 SubRange.HighCount=SubRange.scale;
00529 return;
00530 }
00531 SubRange.LowCount=(SubRange.HighCount=HiCnt)-p->Freq;
00532 update1(p);
00533 }
00534 inline void PPM_CONTEXT::update2(STATE* p)
00535 {
00536 (FoundState=p)->Freq += 4; SummFreq += 4;
00537 if (p->Freq > MAX_FREQ) rescale();
00538 EscCount++; RunLength=InitRL;
00539 }
00540 inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2()
00541 {
00542 BYTE* pb=(BYTE*) Stats; UINT t=2*NumStats;
00543 PrefetchData(pb); PrefetchData(pb+t);
00544 PrefetchData(pb += 2*t); PrefetchData(pb+t);
00545 SEE2_CONTEXT* psee2c;
00546 if (NumStats != 0xFF) {
00547 t=Suffix->NumStats;
00548 psee2c=SEE2Cont[QTable[NumStats+2]-3]+(SummFreq > 11*(NumStats+1));
00549 psee2c += 2*(2*NumStats < t+NumMasked)+Flags;
00550 SubRange.scale=psee2c->getMean();
00551 } else {
00552 psee2c=&DummySEE2Cont; SubRange.scale=1;
00553 }
00554 return psee2c;
00555 }
00556 inline void PPM_CONTEXT::encodeSymbol2(int symbol)
00557 {
00558 SEE2_CONTEXT* psee2c=makeEscFreq2();
00559 UINT Sym, LoCnt=0, i=NumStats-NumMasked;
00560 STATE* p1, * p=Stats-1;
00561 do {
00562 do { Sym=p[1].Symbol; p++; } while (CharMask[Sym] == EscCount);
00563 CharMask[Sym]=EscCount;
00564 if (Sym == symbol) goto SYMBOL_FOUND;
00565 LoCnt += p->Freq;
00566 } while ( --i );
00567 SubRange.HighCount=(SubRange.scale += (SubRange.LowCount=LoCnt));
00568 psee2c->Summ += SubRange.scale; NumMasked = NumStats;
00569 return;
00570 SYMBOL_FOUND:
00571 SubRange.LowCount=LoCnt; SubRange.HighCount=(LoCnt+=p->Freq);
00572 for (p1=p; --i ; ) {
00573 do { Sym=p1[1].Symbol; p1++; } while (CharMask[Sym] == EscCount);
00574 LoCnt += p1->Freq;
00575 }
00576 SubRange.scale += LoCnt;
00577 psee2c->update(); update2(p);
00578 }
00579 inline void PPM_CONTEXT::decodeSymbol2()
00580 {
00581 SEE2_CONTEXT* psee2c=makeEscFreq2();
00582 UINT Sym, count, HiCnt=0, i=NumStats-NumMasked;
00583 STATE* ps[256], ** pps=ps, * p=Stats-1;
00584 do {
00585 do { Sym=p[1].Symbol; p++; } while (CharMask[Sym] == EscCount);
00586 HiCnt += p->Freq; *pps++ = p;
00587 } while ( --i );
00588 SubRange.scale += HiCnt; count=ariGetCurrentCount();
00589 p=*(pps=ps);
00590 if (count < HiCnt) {
00591 HiCnt=0;
00592 while ((HiCnt += p->Freq) <= count) p=*++pps;
00593 SubRange.LowCount = (SubRange.HighCount=HiCnt)-p->Freq;
00594 psee2c->update(); update2(p);
00595 } else {
00596 SubRange.LowCount=HiCnt; SubRange.HighCount=SubRange.scale;
00597 i=NumStats-NumMasked; NumMasked = NumStats;
00598 do { CharMask[(*pps)->Symbol]=EscCount; pps++; } while ( --i );
00599 psee2c->Summ += SubRange.scale;
00600 }
00601 }
00602 inline void ClearMask(CInfo* EncodedFile, CInfo* DecodedFile)
00603 {
00604 EscCount=1; memset(CharMask,0,sizeof(CharMask));
00605
00606 }
00607 void _STDCALL EncodeFile(CSink* EncodedFile, CSource* DecodedFile,
00608 int MaxOrder,MR_METHOD MRMethod)
00609 {
00610 ariInitEncoder(); StartModelRare(MaxOrder,MRMethod);
00611 for (PPM_CONTEXT* MinContext; ; ) {
00612 BYTE ns=(MinContext=MaxContext)->NumStats;
00613 int c = _PPMD_E_GETC(DecodedFile);
00614 if ( ns ) {
00615 MinContext->encodeSymbol1(c); ariEncodeSymbol();
00616 } else {
00617 MinContext->encodeBinSymbol(c); ariShiftEncodeSymbol(TOT_BITS);
00618 }
00619 while ( !FoundState ) {
00620 ARI_ENC_NORMALIZE(EncodedFile);
00621 do {
00622 OrderFall++; MinContext=MinContext->Suffix;
00623 if ( !MinContext ) goto STOP_ENCODING;
00624 } while (MinContext->NumStats == NumMasked);
00625 MinContext->encodeSymbol2(c); ariEncodeSymbol();
00626 }
00627 if (!OrderFall && (BYTE*) FoundState->Successor >= UnitsStart)
00628 PrefetchData(MaxContext=FoundState->Successor);
00629 else {
00630 UpdateModel(MinContext); PrefetchData(MaxContext);
00631 if (EscCount == 0) ClearMask(EncodedFile,DecodedFile);
00632 }
00633 ARI_ENC_NORMALIZE(EncodedFile);
00634 }
00635 STOP_ENCODING:
00636 ARI_FLUSH_ENCODER(EncodedFile);
00637 }
00638 void _STDCALL DecodeFile(CSink* DecodedFile, CSource* EncodedFile,
00639 int MaxOrder,MR_METHOD MRMethod)
00640 {
00641 ARI_INIT_DECODER(EncodedFile); StartModelRare(MaxOrder,MRMethod);
00642 PPM_CONTEXT* MinContext=MaxContext;
00643 for (BYTE ns=MinContext->NumStats; ; ) {
00644 ( ns )?(MinContext->decodeSymbol1()):(MinContext->decodeBinSymbol());
00645 ariRemoveSubrange();
00646 while ( !FoundState ) {
00647 ARI_DEC_NORMALIZE(EncodedFile);
00648 do {
00649 OrderFall++; MinContext=MinContext->Suffix;
00650 if ( !MinContext ) goto STOP_DECODING;
00651 } while (MinContext->NumStats == NumMasked);
00652 MinContext->decodeSymbol2(); ariRemoveSubrange();
00653 }
00654 _PPMD_D_PUTC(FoundState->Symbol,DecodedFile);
00655 if (!OrderFall && (BYTE*) FoundState->Successor >= UnitsStart)
00656 PrefetchData(MaxContext=FoundState->Successor);
00657 else {
00658 UpdateModel(MinContext); PrefetchData(MaxContext);
00659 if (EscCount == 0) ClearMask(EncodedFile,DecodedFile);
00660 }
00661 ns=(MinContext=MaxContext)->NumStats;
00662 ARI_DEC_NORMALIZE(EncodedFile);
00663 }
00664 STOP_DECODING:
00665
00666 return;
00667 }
00668
00669
00670
00671 #include "PPMd.h"
00672 #include "CSource.h"
00673
00674 size_t UnPPM(bool extra, unsigned char* readbuffer, size_t reclen, unsigned char* buffer, size_t buffersize)
00675 {
00676 unsigned short order, mem, offset = 1;
00677 int type = 0;
00678 if (extra)
00679 {
00680 order = readbuffer[1];
00681 mem = readbuffer[0];
00682 type = order >> 6;
00683 order = (order & 63) + 2;
00684 offset = 2;
00685 }
00686 else
00687 {
00688 order = readbuffer[0];
00689 mem = order >> 4;
00690 order = (order & 15) + 2;
00691 }
00692 mem++;
00693
00694 StartSubAllocator(mem);
00695 CMemSink sink(buffer, buffersize);
00696 CMemSource source(readbuffer+offset, reclen-offset);
00697 DecodeFile(&sink,&source,order,(MR_METHOD)type);
00698 StopSubAllocator();
00699 return sink.size();
00700 }
00701
00702
00703 extern "C"
00704 {
00705
00706 size_t PluckerDecompress3(unsigned char* a, size_t b, unsigned char* c, size_t d)
00707 {
00708 return UnPPM(false, a, b, c, d);
00709 }
00710
00711 size_t PluckerDecompress4(unsigned char* a, size_t b, unsigned char* c, size_t d)
00712 {
00713 return UnPPM(true, a, b, c, d);
00714 }
00715
00716 size_t RebDecompress(unsigned char* a, size_t b, unsigned char* c, size_t d)
00717 {
00718 return UnPPM(true, a, b, c, d);
00719 }
00720
00721 }