• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Ppmd7Dec.c -- PPMdH Decoder
2 2010-03-12 : Igor Pavlov : Public domain
3 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4 
5 #include "Precomp.h"
6 
7 #include "Ppmd7.h"
8 
9 #define kTopValue (1 << 24)
10 
Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec * p)11 Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
12 {
13   unsigned i;
14   p->Code = 0;
15   p->Range = 0xFFFFFFFF;
16   if (p->Stream->Read((void *)p->Stream) != 0)
17     return False;
18   for (i = 0; i < 4; i++)
19     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
20   return (p->Code < 0xFFFFFFFF);
21 }
22 
Range_GetThreshold(void * pp,UInt32 total)23 static UInt32 Range_GetThreshold(void *pp, UInt32 total)
24 {
25   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
26   return (p->Code) / (p->Range /= total);
27 }
28 
Range_Normalize(CPpmd7z_RangeDec * p)29 static void Range_Normalize(CPpmd7z_RangeDec *p)
30 {
31   if (p->Range < kTopValue)
32   {
33     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
34     p->Range <<= 8;
35     if (p->Range < kTopValue)
36     {
37       p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
38       p->Range <<= 8;
39     }
40   }
41 }
42 
Range_Decode(void * pp,UInt32 start,UInt32 size)43 static void Range_Decode(void *pp, UInt32 start, UInt32 size)
44 {
45   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
46   p->Code -= start * p->Range;
47   p->Range *= size;
48   Range_Normalize(p);
49 }
50 
Range_DecodeBit(void * pp,UInt32 size0)51 static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
52 {
53   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
54   UInt32 newBound = (p->Range >> 14) * size0;
55   UInt32 symbol;
56   if (p->Code < newBound)
57   {
58     symbol = 0;
59     p->Range = newBound;
60   }
61   else
62   {
63     symbol = 1;
64     p->Code -= newBound;
65     p->Range -= newBound;
66   }
67   Range_Normalize(p);
68   return symbol;
69 }
70 
Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec * p)71 void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
72 {
73   p->p.GetThreshold = Range_GetThreshold;
74   p->p.Decode = Range_Decode;
75   p->p.DecodeBit = Range_DecodeBit;
76 }
77 
78 
79 #define MASK(sym) ((signed char *)charMask)[sym]
80 
Ppmd7_DecodeSymbol(CPpmd7 * p,IPpmd7_RangeDec * rc)81 int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
82 {
83   size_t charMask[256 / sizeof(size_t)];
84   if (p->MinContext->NumStats != 1)
85   {
86     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
87     unsigned i;
88     UInt32 count, hiCnt;
89     if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
90     {
91       Byte symbol;
92       rc->Decode(rc, 0, s->Freq);
93       p->FoundState = s;
94       symbol = s->Symbol;
95       Ppmd7_Update1_0(p);
96       return symbol;
97     }
98     p->PrevSuccess = 0;
99     i = p->MinContext->NumStats - 1;
100     do
101     {
102       if ((hiCnt += (++s)->Freq) > count)
103       {
104         Byte symbol;
105         rc->Decode(rc, hiCnt - s->Freq, s->Freq);
106         p->FoundState = s;
107         symbol = s->Symbol;
108         Ppmd7_Update1(p);
109         return symbol;
110       }
111     }
112     while (--i);
113     if (count >= p->MinContext->SummFreq)
114       return -2;
115     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
116     rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
117     PPMD_SetAllBitsIn256Bytes(charMask);
118     MASK(s->Symbol) = 0;
119     i = p->MinContext->NumStats - 1;
120     do { MASK((--s)->Symbol) = 0; } while (--i);
121   }
122   else
123   {
124     UInt16 *prob = Ppmd7_GetBinSumm(p);
125     if (rc->DecodeBit(rc, *prob) == 0)
126     {
127       Byte symbol;
128       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
129       symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
130       Ppmd7_UpdateBin(p);
131       return symbol;
132     }
133     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
134     p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
135     PPMD_SetAllBitsIn256Bytes(charMask);
136     MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
137     p->PrevSuccess = 0;
138   }
139   for (;;)
140   {
141     CPpmd_State *ps[256], *s;
142     UInt32 freqSum, count, hiCnt;
143     CPpmd_See *see;
144     unsigned i, num, numMasked = p->MinContext->NumStats;
145     do
146     {
147       p->OrderFall++;
148       if (!p->MinContext->Suffix)
149         return -1;
150       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
151     }
152     while (p->MinContext->NumStats == numMasked);
153     hiCnt = 0;
154     s = Ppmd7_GetStats(p, p->MinContext);
155     i = 0;
156     num = p->MinContext->NumStats - numMasked;
157     do
158     {
159       int k = (int)(MASK(s->Symbol));
160       hiCnt += (s->Freq & k);
161       ps[i] = s++;
162       i -= k;
163     }
164     while (i != num);
165 
166     see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
167     freqSum += hiCnt;
168     count = rc->GetThreshold(rc, freqSum);
169 
170     if (count < hiCnt)
171     {
172       Byte symbol;
173       CPpmd_State **pps = ps;
174       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
175       s = *pps;
176       rc->Decode(rc, hiCnt - s->Freq, s->Freq);
177       Ppmd_See_Update(see);
178       p->FoundState = s;
179       symbol = s->Symbol;
180       Ppmd7_Update2(p);
181       return symbol;
182     }
183     if (count >= freqSum)
184       return -2;
185     rc->Decode(rc, hiCnt, freqSum - hiCnt);
186     see->Summ = (UInt16)(see->Summ + freqSum);
187     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
188   }
189 }
190