aboutsummaryrefslogtreecommitdiff
path: root/lib/UnrarXLib/model.hpp
blob: bcaaa3661ccb02ac175a4b420d8169d44186b2a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef _RAR_PPMMODEL_
#define _RAR_PPMMODEL_

#include "coder.hpp"
#include "suballoc.hpp"

const int MAX_O=64;                   /* maximum allowed model order */

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;

#pragma pack(1)

struct SEE2_CONTEXT
{ // 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=SHORT16(Summ) >> Shift;
    Summ -= RetVal;
    return RetVal+(RetVal == 0);
  }
  void update()
  {
    if (Shift < PERIOD_BITS && --Count == 0)
    {
      Summ += Summ;
      Count=3 << Shift++;
    }
  }
} _PACK_ATTR;

class ModelPPM;
struct PPM_CONTEXT;

struct STATE
{
  byte Symbol;
  byte Freq;
  PPM_CONTEXT* Successor;
};

struct FreqData
{
  ushort SummFreq;
  STATE _PACK_ATTR * Stats;
};

struct PPM_CONTEXT 
{
    ushort NumStats;
    union
    {
      FreqData U;

      STATE OneState;
    };

    PPM_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,STATE* p); //    CD    suffix
    inline void update2(ModelPPM *Model,STATE* p); //   BCDE   successor
    void rescale(ModelPPM *Model);
    inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
    inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
};
#ifdef _AIX
#pragma pack(pop)
#else
#pragma pack()
#endif

const uint UNIT_SIZE=sizeof(PPM_CONTEXT);
const uint FIXED_UNIT_SIZE=12;

/*
inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
        NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
*/

template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }


class ModelPPM
{
  private:
    friend struct PPM_CONTEXT;
    
    SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
    
    struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
    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 PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);

    inline void UpdateModel();
    inline void ClearMask();
  public:
    ModelPPM();
    bool DecodeInit(Unpack *UnpackRead,int &EscChar);
    int DecodeChar();
};

#endif