1370b324cSopenharmony_ci/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder
2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain
3370b324cSopenharmony_ciThis code is based on:
4370b324cSopenharmony_ci  PPMd var.H (2001): Dmitry Shkarin : Public domain */
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "Precomp.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#include "Ppmd7.h"
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#define kTopValue ((UInt32)1 << 24)
12370b324cSopenharmony_ci
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#define READ_BYTE(p) IByteIn_Read((p)->Stream)
15370b324cSopenharmony_ci
16370b324cSopenharmony_ciBoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p)
17370b324cSopenharmony_ci{
18370b324cSopenharmony_ci  unsigned i;
19370b324cSopenharmony_ci  p->Code = 0;
20370b324cSopenharmony_ci  p->Range = 0xFFFFFFFF;
21370b324cSopenharmony_ci  if (READ_BYTE(p) != 0)
22370b324cSopenharmony_ci    return False;
23370b324cSopenharmony_ci  for (i = 0; i < 4; i++)
24370b324cSopenharmony_ci    p->Code = (p->Code << 8) | READ_BYTE(p);
25370b324cSopenharmony_ci  return (p->Code < 0xFFFFFFFF);
26370b324cSopenharmony_ci}
27370b324cSopenharmony_ci
28370b324cSopenharmony_ci#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \
29370b324cSopenharmony_ci  { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8;
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci#define RC_NORM_1(p)  RC_NORM_BASE(p) }
32370b324cSopenharmony_ci#define RC_NORM(p)    RC_NORM_BASE(p) RC_NORM_BASE(p) }}
33370b324cSopenharmony_ci
34370b324cSopenharmony_ci// we must use only one type of Normalization from two: LOCAL or REMOTE
35370b324cSopenharmony_ci#define RC_NORM_LOCAL(p)    // RC_NORM(p)
36370b324cSopenharmony_ci#define RC_NORM_REMOTE(p)   RC_NORM(p)
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci#define R (&p->rc.dec)
39370b324cSopenharmony_ci
40370b324cSopenharmony_ciZ7_FORCE_INLINE
41370b324cSopenharmony_ci// Z7_NO_INLINE
42370b324cSopenharmony_cistatic void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
43370b324cSopenharmony_ci{
44370b324cSopenharmony_ci
45370b324cSopenharmony_ci
46370b324cSopenharmony_ci  R->Code -= start * R->Range;
47370b324cSopenharmony_ci  R->Range *= size;
48370b324cSopenharmony_ci  RC_NORM_LOCAL(R)
49370b324cSopenharmony_ci}
50370b324cSopenharmony_ci
51370b324cSopenharmony_ci#define RC_Decode(start, size)  Ppmd7z_RD_Decode(p, start, size);
52370b324cSopenharmony_ci#define RC_DecodeFinal(start, size)  RC_Decode(start, size)  RC_NORM_REMOTE(R)
53370b324cSopenharmony_ci#define RC_GetThreshold(total)  (R->Code / (R->Range /= (total)))
54370b324cSopenharmony_ci
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
57370b324cSopenharmony_ci// typedef CPpmd7_Context * CTX_PTR;
58370b324cSopenharmony_ci#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
59370b324cSopenharmony_civoid Ppmd7_UpdateModel(CPpmd7 *p);
60370b324cSopenharmony_ci
61370b324cSopenharmony_ci#define MASK(sym) ((unsigned char *)charMask)[sym]
62370b324cSopenharmony_ci// Z7_FORCE_INLINE
63370b324cSopenharmony_ci// static
64370b324cSopenharmony_ciint Ppmd7z_DecodeSymbol(CPpmd7 *p)
65370b324cSopenharmony_ci{
66370b324cSopenharmony_ci  size_t charMask[256 / sizeof(size_t)];
67370b324cSopenharmony_ci
68370b324cSopenharmony_ci  if (p->MinContext->NumStats != 1)
69370b324cSopenharmony_ci  {
70370b324cSopenharmony_ci    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
71370b324cSopenharmony_ci    unsigned i;
72370b324cSopenharmony_ci    UInt32 count, hiCnt;
73370b324cSopenharmony_ci    const UInt32 summFreq = p->MinContext->Union2.SummFreq;
74370b324cSopenharmony_ci
75370b324cSopenharmony_ci
76370b324cSopenharmony_ci
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci    count = RC_GetThreshold(summFreq);
79370b324cSopenharmony_ci    hiCnt = count;
80370b324cSopenharmony_ci
81370b324cSopenharmony_ci    if ((Int32)(count -= s->Freq) < 0)
82370b324cSopenharmony_ci    {
83370b324cSopenharmony_ci      Byte sym;
84370b324cSopenharmony_ci      RC_DecodeFinal(0, s->Freq)
85370b324cSopenharmony_ci      p->FoundState = s;
86370b324cSopenharmony_ci      sym = s->Symbol;
87370b324cSopenharmony_ci      Ppmd7_Update1_0(p);
88370b324cSopenharmony_ci      return sym;
89370b324cSopenharmony_ci    }
90370b324cSopenharmony_ci
91370b324cSopenharmony_ci    p->PrevSuccess = 0;
92370b324cSopenharmony_ci    i = (unsigned)p->MinContext->NumStats - 1;
93370b324cSopenharmony_ci
94370b324cSopenharmony_ci    do
95370b324cSopenharmony_ci    {
96370b324cSopenharmony_ci      if ((Int32)(count -= (++s)->Freq) < 0)
97370b324cSopenharmony_ci      {
98370b324cSopenharmony_ci        Byte sym;
99370b324cSopenharmony_ci        RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
100370b324cSopenharmony_ci        p->FoundState = s;
101370b324cSopenharmony_ci        sym = s->Symbol;
102370b324cSopenharmony_ci        Ppmd7_Update1(p);
103370b324cSopenharmony_ci        return sym;
104370b324cSopenharmony_ci      }
105370b324cSopenharmony_ci    }
106370b324cSopenharmony_ci    while (--i);
107370b324cSopenharmony_ci
108370b324cSopenharmony_ci    if (hiCnt >= summFreq)
109370b324cSopenharmony_ci      return PPMD7_SYM_ERROR;
110370b324cSopenharmony_ci
111370b324cSopenharmony_ci    hiCnt -= count;
112370b324cSopenharmony_ci    RC_Decode(hiCnt, summFreq - hiCnt)
113370b324cSopenharmony_ci
114370b324cSopenharmony_ci    p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);
115370b324cSopenharmony_ci    PPMD_SetAllBitsIn256Bytes(charMask)
116370b324cSopenharmony_ci    // i = p->MinContext->NumStats - 1;
117370b324cSopenharmony_ci    // do { MASK((--s)->Symbol) = 0; } while (--i);
118370b324cSopenharmony_ci    {
119370b324cSopenharmony_ci      CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);
120370b324cSopenharmony_ci      MASK(s->Symbol) = 0;
121370b324cSopenharmony_ci      do
122370b324cSopenharmony_ci      {
123370b324cSopenharmony_ci        unsigned sym0 = s2[0].Symbol;
124370b324cSopenharmony_ci        unsigned sym1 = s2[1].Symbol;
125370b324cSopenharmony_ci        s2 += 2;
126370b324cSopenharmony_ci        MASK(sym0) = 0;
127370b324cSopenharmony_ci        MASK(sym1) = 0;
128370b324cSopenharmony_ci      }
129370b324cSopenharmony_ci      while (s2 < s);
130370b324cSopenharmony_ci    }
131370b324cSopenharmony_ci  }
132370b324cSopenharmony_ci  else
133370b324cSopenharmony_ci  {
134370b324cSopenharmony_ci    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
135370b324cSopenharmony_ci    UInt16 *prob = Ppmd7_GetBinSumm(p);
136370b324cSopenharmony_ci    UInt32 pr = *prob;
137370b324cSopenharmony_ci    UInt32 size0 = (R->Range >> 14) * pr;
138370b324cSopenharmony_ci    pr = PPMD_UPDATE_PROB_1(pr);
139370b324cSopenharmony_ci
140370b324cSopenharmony_ci    if (R->Code < size0)
141370b324cSopenharmony_ci    {
142370b324cSopenharmony_ci      Byte sym;
143370b324cSopenharmony_ci      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
144370b324cSopenharmony_ci
145370b324cSopenharmony_ci      // RangeDec_DecodeBit0(size0);
146370b324cSopenharmony_ci      R->Range = size0;
147370b324cSopenharmony_ci      RC_NORM_1(R)
148370b324cSopenharmony_ci      /* we can use single byte normalization here because of
149370b324cSopenharmony_ci         (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */
150370b324cSopenharmony_ci
151370b324cSopenharmony_ci      // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
152370b324cSopenharmony_ci      // Ppmd7_UpdateBin(p);
153370b324cSopenharmony_ci      {
154370b324cSopenharmony_ci        unsigned freq = s->Freq;
155370b324cSopenharmony_ci        CPpmd7_Context *c = CTX(SUCCESSOR(s));
156370b324cSopenharmony_ci        sym = s->Symbol;
157370b324cSopenharmony_ci        p->FoundState = s;
158370b324cSopenharmony_ci        p->PrevSuccess = 1;
159370b324cSopenharmony_ci        p->RunLength++;
160370b324cSopenharmony_ci        s->Freq = (Byte)(freq + (freq < 128));
161370b324cSopenharmony_ci        // NextContext(p);
162370b324cSopenharmony_ci        if (p->OrderFall == 0 && (const Byte *)c > p->Text)
163370b324cSopenharmony_ci          p->MaxContext = p->MinContext = c;
164370b324cSopenharmony_ci        else
165370b324cSopenharmony_ci          Ppmd7_UpdateModel(p);
166370b324cSopenharmony_ci      }
167370b324cSopenharmony_ci      return sym;
168370b324cSopenharmony_ci    }
169370b324cSopenharmony_ci
170370b324cSopenharmony_ci    *prob = (UInt16)pr;
171370b324cSopenharmony_ci    p->InitEsc = p->ExpEscape[pr >> 10];
172370b324cSopenharmony_ci
173370b324cSopenharmony_ci    // RangeDec_DecodeBit1(size0);
174370b324cSopenharmony_ci
175370b324cSopenharmony_ci    R->Code -= size0;
176370b324cSopenharmony_ci    R->Range -= size0;
177370b324cSopenharmony_ci    RC_NORM_LOCAL(R)
178370b324cSopenharmony_ci
179370b324cSopenharmony_ci    PPMD_SetAllBitsIn256Bytes(charMask)
180370b324cSopenharmony_ci    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
181370b324cSopenharmony_ci    p->PrevSuccess = 0;
182370b324cSopenharmony_ci  }
183370b324cSopenharmony_ci
184370b324cSopenharmony_ci  for (;;)
185370b324cSopenharmony_ci  {
186370b324cSopenharmony_ci    CPpmd_State *s, *s2;
187370b324cSopenharmony_ci    UInt32 freqSum, count, hiCnt;
188370b324cSopenharmony_ci
189370b324cSopenharmony_ci    CPpmd_See *see;
190370b324cSopenharmony_ci    CPpmd7_Context *mc;
191370b324cSopenharmony_ci    unsigned numMasked;
192370b324cSopenharmony_ci    RC_NORM_REMOTE(R)
193370b324cSopenharmony_ci    mc = p->MinContext;
194370b324cSopenharmony_ci    numMasked = mc->NumStats;
195370b324cSopenharmony_ci
196370b324cSopenharmony_ci    do
197370b324cSopenharmony_ci    {
198370b324cSopenharmony_ci      p->OrderFall++;
199370b324cSopenharmony_ci      if (!mc->Suffix)
200370b324cSopenharmony_ci        return PPMD7_SYM_END;
201370b324cSopenharmony_ci      mc = Ppmd7_GetContext(p, mc->Suffix);
202370b324cSopenharmony_ci    }
203370b324cSopenharmony_ci    while (mc->NumStats == numMasked);
204370b324cSopenharmony_ci
205370b324cSopenharmony_ci    s = Ppmd7_GetStats(p, mc);
206370b324cSopenharmony_ci
207370b324cSopenharmony_ci    {
208370b324cSopenharmony_ci      unsigned num = mc->NumStats;
209370b324cSopenharmony_ci      unsigned num2 = num / 2;
210370b324cSopenharmony_ci
211370b324cSopenharmony_ci      num &= 1;
212370b324cSopenharmony_ci      hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num);
213370b324cSopenharmony_ci      s += num;
214370b324cSopenharmony_ci      p->MinContext = mc;
215370b324cSopenharmony_ci
216370b324cSopenharmony_ci      do
217370b324cSopenharmony_ci      {
218370b324cSopenharmony_ci        unsigned sym0 = s[0].Symbol;
219370b324cSopenharmony_ci        unsigned sym1 = s[1].Symbol;
220370b324cSopenharmony_ci        s += 2;
221370b324cSopenharmony_ci        hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0)));
222370b324cSopenharmony_ci        hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1)));
223370b324cSopenharmony_ci      }
224370b324cSopenharmony_ci      while (--num2);
225370b324cSopenharmony_ci    }
226370b324cSopenharmony_ci
227370b324cSopenharmony_ci    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
228370b324cSopenharmony_ci    freqSum += hiCnt;
229370b324cSopenharmony_ci
230370b324cSopenharmony_ci
231370b324cSopenharmony_ci
232370b324cSopenharmony_ci
233370b324cSopenharmony_ci    count = RC_GetThreshold(freqSum);
234370b324cSopenharmony_ci
235370b324cSopenharmony_ci    if (count < hiCnt)
236370b324cSopenharmony_ci    {
237370b324cSopenharmony_ci      Byte sym;
238370b324cSopenharmony_ci
239370b324cSopenharmony_ci      s = Ppmd7_GetStats(p, p->MinContext);
240370b324cSopenharmony_ci      hiCnt = count;
241370b324cSopenharmony_ci      // count -= s->Freq & (unsigned)(MASK(s->Symbol));
242370b324cSopenharmony_ci      // if ((Int32)count >= 0)
243370b324cSopenharmony_ci      {
244370b324cSopenharmony_ci        for (;;)
245370b324cSopenharmony_ci        {
246370b324cSopenharmony_ci          count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
247370b324cSopenharmony_ci          // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
248370b324cSopenharmony_ci        }
249370b324cSopenharmony_ci      }
250370b324cSopenharmony_ci      s--;
251370b324cSopenharmony_ci      RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
252370b324cSopenharmony_ci
253370b324cSopenharmony_ci      // new (see->Summ) value can overflow over 16-bits in some rare cases
254370b324cSopenharmony_ci      Ppmd_See_UPDATE(see)
255370b324cSopenharmony_ci      p->FoundState = s;
256370b324cSopenharmony_ci      sym = s->Symbol;
257370b324cSopenharmony_ci      Ppmd7_Update2(p);
258370b324cSopenharmony_ci      return sym;
259370b324cSopenharmony_ci    }
260370b324cSopenharmony_ci
261370b324cSopenharmony_ci    if (count >= freqSum)
262370b324cSopenharmony_ci      return PPMD7_SYM_ERROR;
263370b324cSopenharmony_ci
264370b324cSopenharmony_ci    RC_Decode(hiCnt, freqSum - hiCnt)
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci    // We increase (see->Summ) for sum of Freqs of all non_Masked symbols.
267370b324cSopenharmony_ci    // new (see->Summ) value can overflow over 16-bits in some rare cases
268370b324cSopenharmony_ci    see->Summ = (UInt16)(see->Summ + freqSum);
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci    s = Ppmd7_GetStats(p, p->MinContext);
271370b324cSopenharmony_ci    s2 = s + p->MinContext->NumStats;
272370b324cSopenharmony_ci    do
273370b324cSopenharmony_ci    {
274370b324cSopenharmony_ci      MASK(s->Symbol) = 0;
275370b324cSopenharmony_ci      s++;
276370b324cSopenharmony_ci    }
277370b324cSopenharmony_ci    while (s != s2);
278370b324cSopenharmony_ci  }
279370b324cSopenharmony_ci}
280370b324cSopenharmony_ci
281370b324cSopenharmony_ci/*
282370b324cSopenharmony_ciByte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim)
283370b324cSopenharmony_ci{
284370b324cSopenharmony_ci  int sym = 0;
285370b324cSopenharmony_ci  if (buf != lim)
286370b324cSopenharmony_ci  do
287370b324cSopenharmony_ci  {
288370b324cSopenharmony_ci    sym = Ppmd7z_DecodeSymbol(p);
289370b324cSopenharmony_ci    if (sym < 0)
290370b324cSopenharmony_ci      break;
291370b324cSopenharmony_ci    *buf = (Byte)sym;
292370b324cSopenharmony_ci  }
293370b324cSopenharmony_ci  while (++buf < lim);
294370b324cSopenharmony_ci  p->LastSymbol = sym;
295370b324cSopenharmony_ci  return buf;
296370b324cSopenharmony_ci}
297370b324cSopenharmony_ci*/
298370b324cSopenharmony_ci
299370b324cSopenharmony_ci#undef kTopValue
300370b324cSopenharmony_ci#undef READ_BYTE
301370b324cSopenharmony_ci#undef RC_NORM_BASE
302370b324cSopenharmony_ci#undef RC_NORM_1
303370b324cSopenharmony_ci#undef RC_NORM
304370b324cSopenharmony_ci#undef RC_NORM_LOCAL
305370b324cSopenharmony_ci#undef RC_NORM_REMOTE
306370b324cSopenharmony_ci#undef R
307370b324cSopenharmony_ci#undef RC_Decode
308370b324cSopenharmony_ci#undef RC_DecodeFinal
309370b324cSopenharmony_ci#undef RC_GetThreshold
310370b324cSopenharmony_ci#undef CTX
311370b324cSopenharmony_ci#undef SUCCESSOR
312370b324cSopenharmony_ci#undef MASK
313