Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Model.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  *  This file is part of PPMd project                                       *
00003  *  Written and distributed to public domain by Dmitry Shkarin 1997,        *
00004  *  1999-2001                                                               *
00005  *  Contents: PPMII model description and encoding/decoding routines        *
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 { // SEE-contexts for PPM-contexts with masked symbols
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 {                 // Notes:
00032     BYTE NumStats, Flags;                   // 1. NumStats & NumMasked contain
00033     WORD SummFreq;                          //  number of symbols minus 1
00034     struct STATE {                          // 2. sizeof(WORD) > sizeof(BYTE)
00035         BYTE Symbol, Freq;                  // 3. contexts example:
00036         PPM_CONTEXT* Successor;             // MaxOrder:
00037     } _PACK_ATTR * Stats;                   //  ABCD    context
00038     PPM_CONTEXT* Suffix;                    //   BCD    suffix
00039     inline void encodeBinSymbol(int symbol);//   BCDE   successor
00040     inline void   encodeSymbol1(int symbol);// other orders:
00041     inline void   encodeSymbol2(int symbol);//   BCD    context
00042     inline void           decodeBinSymbol();//    CD    suffix
00043     inline void             decodeSymbol1();//   BCDE   successor
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];    // constants
00057 static PPM_CONTEXT::STATE* FoundState;      // found next state transition
00058 static int  InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
00059 static BYTE CharMask[256], NumMasked, PrevSuccess, EscCount, PrintCount;
00060 static WORD BinSumm[25][64];                // binary SEE-contexts
00061 static MR_METHOD MRMethod;
00062 
00063 inline void SWAP(PPM_CONTEXT::STATE& s1,PPM_CONTEXT::STATE& s2)
00064 {
00065   /*
00066     WORD t1=(WORD&) s1;                     PPM_CONTEXT* t2=s1.Successor;
00067     (WORD&) s1 = (WORD&) s2;                s1.Successor=s2.Successor;
00068     (WORD&) s2 = t1;                        s2.Successor=t2;
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   //    (WORD&) s1=(WORD&) s2;                  s1.Successor=s2.Successor;
00077   s1 = s2;
00078 }
00079 struct PPMD_STARTUP { inline PPMD_STARTUP(); } PPMd_StartUp;
00080 inline PPMD_STARTUP::PPMD_STARTUP()         // constants initialization
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) {                     // we are in solid mode
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 // Tabulated escapes for exponential symbol distribution
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     //    if (++PrintCount == 0)                  PrintInfo(DecodedFile,EncodedFile);
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);         //PrintInfo(DecodedFile,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     //    PrintInfo(DecodedFile,EncodedFile);
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   //  qDebug("Mem:%u Order:%u Type:%u\n", mem, order, type);
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 }

Generated on Sat Nov 5 16:16:55 2005 for OPIE by  doxygen 1.4.2