1 #ifndef _RAR_PPMMODEL_
2 #define _RAR_PPMMODEL_
3 
4 #include "rartypes.hpp"
5 #include "rardefs.hpp"
6 #include "coder.hpp"
7 #include "suballoc.hpp"
8 
9 class Unpack;
10 
11 const int MAX_O=64;                   /* maximum allowed model order */
12 
13 const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
14           INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
15 
16 #ifndef STRICT_ALIGNMENT_REQUIRED
17 #pragma pack(1)
18 #endif
19 
20 struct SEE2_CONTEXT
21 { // SEE-contexts for PPM-contexts with masked symbols
22   ushort Summ;
23   byte Shift, Count;
initSEE2_CONTEXT24   void init(int InitVal)
25   {
26     Summ=InitVal << (Shift=PERIOD_BITS-4);
27     Count=4;
28   }
getMeanSEE2_CONTEXT29   uint getMean()
30   {
31     uint RetVal=SHORT16(Summ) >> Shift;
32     Summ -= RetVal;
33     return RetVal+(RetVal == 0);
34   }
updateSEE2_CONTEXT35   void update()
36   {
37     if (Shift < PERIOD_BITS && --Count == 0)
38     {
39       Summ += Summ;
40       Count=3 << Shift++;
41     }
42   }
43 };
44 
45 
46 class ModelPPM;
47 struct PPM_CONTEXT;
48 
49 struct STATE
50 {
51   byte Symbol;
52   byte Freq;
53   PPM_CONTEXT* Successor;
54 };
55 
56 struct FreqData
57 {
58   ushort SummFreq;
59   STATE _PACK_ATTR * Stats;
60 };
61 
62 struct PPM_CONTEXT
63 {
64     ushort NumStats;
65     union
66     {
67       FreqData U;
68       STATE OneState;
69     };
70 
71     PPM_CONTEXT* Suffix;
72     inline void encodeBinSymbol(ModelPPM *Model,int symbol);  // MaxOrder:
73     inline void encodeSymbol1(ModelPPM *Model,int symbol);    //  ABCD    context
74     inline void encodeSymbol2(ModelPPM *Model,int symbol);    //   BCD    suffix
75     inline void decodeBinSymbol(ModelPPM *Model);  //   BCDE   successor
76     inline bool decodeSymbol1(ModelPPM *Model);    // other orders:
77     inline bool decodeSymbol2(ModelPPM *Model);    //   BCD    context
78     inline void update1(ModelPPM *Model,STATE* p); //    CD    suffix
79     inline void update2(ModelPPM *Model,STATE* p); //   BCDE   successor
80     void rescale(ModelPPM *Model);
81     inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
82     inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
83 };
84 
85 #ifndef STRICT_ALIGNMENT_REQUIRED
86 #ifdef _AIX
87 #pragma pack(pop)
88 #else
89 #pragma pack()
90 #endif
91 #endif
92 
93 const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
94 const uint FIXED_UNIT_SIZE=12;
95 
96 /*
97 inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
98         NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
99 inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
100 */
101 
102 template <class T>
_PPMD_SWAP(T & t1,T & t2)103 inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
104 
105 
106 class ModelPPM
107 {
108   private:
109     friend struct PPM_CONTEXT;
110 
111     SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
112 
113     struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
114     STATE* FoundState;      // found next state transition
115     int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
116     byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
117     byte EscCount, PrevSuccess, HiBitsFlag;
118     ushort BinSumm[128][64];               // binary SEE-contexts
119 
120     RangeCoder Coder;
121     SubAllocator SubAlloc;
122 
123     void RestartModelRare();
124     void StartModelRare(int MaxOrder);
125     inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
126 
127     inline void UpdateModel();
128     inline void ClearMask();
129   public:
130     ModelPPM();
131     ModelPPM(const ModelPPM &copy);
132     const ModelPPM& operator=(const ModelPPM &src);
133     void CleanUp(); // reset PPM variables after data error
134     bool DecodeInit(Unpack *UnpackRead,int &EscChar);
135     int DecodeChar();
136 };
137 
138 #endif
139