File indexing completed on 2025-02-02 04:26:00

0001 /* Ppmd8Dec.c -- PPMdI Decoder
0002 2010-04-16 : Igor Pavlov : Public domain
0003 This code is based on:
0004   PPMd var.I (2002): Dmitry Shkarin : Public domain
0005   Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
0006 
0007 #include "Precomp.h"
0008 
0009 #include "Ppmd8.h"
0010 
0011 #define kTop (1 << 24)
0012 #define kBot (1 << 15)
0013 
0014 Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
0015 {
0016   unsigned i;
0017   p->Low = 0;
0018   p->Range = 0xFFFFFFFF;
0019   p->Code = 0;
0020   for (i = 0; i < 4; i++)
0021     p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
0022   return (p->Code < 0xFFFFFFFF);
0023 }
0024 
0025 static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
0026 {
0027   return p->Code / (p->Range /= total);
0028 }
0029 
0030 static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
0031 {
0032   start *= p->Range;
0033   p->Low += start;
0034   p->Code -= start;
0035   p->Range *= size;
0036 
0037   while ((p->Low ^ (p->Low + p->Range)) < kTop ||
0038       (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
0039   {
0040     p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
0041     p->Range <<= 8;
0042     p->Low <<= 8;
0043   }
0044 }
0045 
0046 #define MASK(sym) ((signed char *)charMask)[sym]
0047 
0048 int Ppmd8_DecodeSymbol(CPpmd8 *p)
0049 {
0050   size_t charMask[256 / sizeof(size_t)];
0051   if (p->MinContext->NumStats != 0)
0052   {
0053     CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
0054     unsigned i;
0055     UInt32 count, hiCnt;
0056     if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
0057     {
0058       Byte symbol;
0059       RangeDec_Decode(p, 0, s->Freq);
0060       p->FoundState = s;
0061       symbol = s->Symbol;
0062       Ppmd8_Update1_0(p);
0063       return symbol;
0064     }
0065     p->PrevSuccess = 0;
0066     i = p->MinContext->NumStats;
0067     do
0068     {
0069       if ((hiCnt += (++s)->Freq) > count)
0070       {
0071         Byte symbol;
0072         RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
0073         p->FoundState = s;
0074         symbol = s->Symbol;
0075         Ppmd8_Update1(p);
0076         return symbol;
0077       }
0078     }
0079     while (--i);
0080     if (count >= p->MinContext->SummFreq)
0081       return -2;
0082     RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
0083     PPMD_SetAllBitsIn256Bytes(charMask);
0084     MASK(s->Symbol) = 0;
0085     i = p->MinContext->NumStats;
0086     do { MASK((--s)->Symbol) = 0; } while (--i);
0087   }
0088   else
0089   {
0090     UInt16 *prob = Ppmd8_GetBinSumm(p);
0091     if (((p->Code / (p->Range >>= 14)) < *prob))
0092     {
0093       Byte symbol;
0094       RangeDec_Decode(p, 0, *prob);
0095       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
0096       symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
0097       Ppmd8_UpdateBin(p);
0098       return symbol;
0099     }
0100     RangeDec_Decode(p, *prob, (1 << 14) - *prob);
0101     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
0102     p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
0103     PPMD_SetAllBitsIn256Bytes(charMask);
0104     MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
0105     p->PrevSuccess = 0;
0106   }
0107   for (;;)
0108   {
0109     CPpmd_State *ps[256], *s;
0110     UInt32 freqSum, count, hiCnt;
0111     CPpmd_See *see;
0112     unsigned i, num, numMasked = p->MinContext->NumStats;
0113     do
0114     {
0115       p->OrderFall++;
0116       if (!p->MinContext->Suffix)
0117         return -1;
0118       p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
0119     }
0120     while (p->MinContext->NumStats == numMasked);
0121     hiCnt = 0;
0122     s = Ppmd8_GetStats(p, p->MinContext);
0123     i = 0;
0124     num = p->MinContext->NumStats - numMasked;
0125     do
0126     {
0127       int k = (int)(MASK(s->Symbol));
0128       hiCnt += (s->Freq & k);
0129       ps[i] = s++;
0130       i -= k;
0131     }
0132     while (i != num);
0133     
0134     see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
0135     freqSum += hiCnt;
0136     count = RangeDec_GetThreshold(p, freqSum);
0137     
0138     if (count < hiCnt)
0139     {
0140       Byte symbol;
0141       CPpmd_State **pps = ps;
0142       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
0143       s = *pps;
0144       RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
0145       Ppmd_See_Update(see);
0146       p->FoundState = s;
0147       symbol = s->Symbol;
0148       Ppmd8_Update2(p);
0149       return symbol;
0150     }
0151     if (count >= freqSum)
0152       return -2;
0153     RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
0154     see->Summ = (UInt16)(see->Summ + freqSum);
0155     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
0156   }
0157 }