libclamunrar/model.hpp
d39cb658
 #ifndef _RAR_PPMMODEL_
 #define _RAR_PPMMODEL_
 
 #include "coder.hpp"
 #include "suballoc.hpp"
 
 #ifdef ALLOW_MISALIGNED
 #pragma pack(1)
 #endif
 
 struct RARPPM_DEF
 {
   static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
     INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
 };
 
 struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
 { // SEE-contexts for PPM-contexts with masked symbols
   ushort Summ;
   byte Shift, Count;
   void init(int InitVal)
   {
     Summ=InitVal << (Shift=PERIOD_BITS-4);
     Count=4;
   }
   uint getMean()
   {
     uint RetVal=GET_SHORT16(Summ) >> Shift;
     Summ -= RetVal;
     return RetVal+(RetVal == 0);
   }
   void update()
   {
     if (Shift < PERIOD_BITS && --Count == 0)
     {
       Summ += Summ;
       Count=3 << Shift++;
     }
   }
 };
 
 
 class ModelPPM;
 struct RARPPM_CONTEXT;
 
 struct RARPPM_STATE
 {
   byte Symbol;
   byte Freq;
   RARPPM_CONTEXT* Successor;
 };
 
 
 struct RARPPM_CONTEXT : RARPPM_DEF
 {
     ushort NumStats;
 
     struct FreqData
     {
       ushort SummFreq;
       RARPPM_STATE RARPPM_PACK_ATTR * Stats;
     };
     
     union
     {
       FreqData U;
       RARPPM_STATE OneState;
     };
 
     RARPPM_CONTEXT* Suffix;
     inline void encodeBinSymbol(ModelPPM *Model,int symbol);  // MaxOrder:
     inline void encodeSymbol1(ModelPPM *Model,int symbol);    //  ABCD    context
     inline void encodeSymbol2(ModelPPM *Model,int symbol);    //   BCD    suffix
     inline void decodeBinSymbol(ModelPPM *Model);  //   BCDE   successor
     inline bool decodeSymbol1(ModelPPM *Model);    // other orders:
     inline bool decodeSymbol2(ModelPPM *Model);    //   BCD    context
     inline void update1(ModelPPM *Model,RARPPM_STATE* p); //    CD    suffix
     inline void update2(ModelPPM *Model,RARPPM_STATE* p); //   BCDE   successor
     void rescale(ModelPPM *Model);
     inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
     inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
 };
 
 #ifdef ALLOW_MISALIGNED
 #ifdef _AIX
 #pragma pack(pop)
 #else
 #pragma pack()
 #endif
 #endif
 
 class ModelPPM : RARPPM_DEF
 {
   private:
     friend struct RARPPM_CONTEXT;
     
     RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
     
     struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
     RARPPM_STATE* FoundState;      // found next state transition
     int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
     byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
     byte EscCount, PrevSuccess, HiBitsFlag;
     ushort BinSumm[128][64];               // binary SEE-contexts
 
     RangeCoder Coder;
     SubAllocator SubAlloc;
 
     void RestartModelRare();
     void StartModelRare(int MaxOrder);
     inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
 
     inline void UpdateModel();
     inline void ClearMask();
   public:
     ModelPPM();
     void CleanUp(); // reset PPM variables after data error
     bool DecodeInit(Unpack *UnpackRead,int &EscChar);
     int DecodeChar();
 };
 
 #endif