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

0001 /* Ppmd7Dec.c -- PPMdH Decoder
0002 2010-03-12 : Igor Pavlov : Public domain
0003 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
0004 
0005 #include "Precomp.h"
0006 
0007 #include "Ppmd7.h"
0008 
0009 #define kTopValue (1 << 24)
0010 
0011 Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
0012 {
0013   unsigned i;
0014   p->Code = 0;
0015   p->Range = 0xFFFFFFFF;
0016   if (p->Stream->Read((void *)p->Stream) != 0)
0017     return False;
0018   for (i = 0; i < 4; i++)
0019     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
0020   return (p->Code < 0xFFFFFFFF);
0021 }
0022 
0023 static UInt32 Range_GetThreshold(void *pp, UInt32 total)
0024 {
0025   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
0026   return (p->Code) / (p->Range /= total);
0027 }
0028 
0029 static void Range_Normalize(CPpmd7z_RangeDec *p)
0030 {
0031   if (p->Range < kTopValue)
0032   {
0033     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
0034     p->Range <<= 8;
0035     if (p->Range < kTopValue)
0036     {
0037       p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
0038       p->Range <<= 8;
0039     }
0040   }
0041 }
0042 
0043 static void Range_Decode(void *pp, UInt32 start, UInt32 size)
0044 {
0045   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
0046   p->Code -= start * p->Range;
0047   p->Range *= size;
0048   Range_Normalize(p);
0049 }
0050 
0051 static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
0052 {
0053   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
0054   UInt32 newBound = (p->Range >> 14) * size0;
0055   UInt32 symbol;
0056   if (p->Code < newBound)
0057   {
0058     symbol = 0;
0059     p->Range = newBound;
0060   }
0061   else
0062   {
0063     symbol = 1;
0064     p->Code -= newBound;
0065     p->Range -= newBound;
0066   }
0067   Range_Normalize(p);
0068   return symbol;
0069 }
0070 
0071 void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
0072 {
0073   p->p.GetThreshold = Range_GetThreshold;
0074   p->p.Decode = Range_Decode;
0075   p->p.DecodeBit = Range_DecodeBit;
0076 }
0077 
0078 
0079 #define MASK(sym) ((signed char *)charMask)[sym]
0080 
0081 int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
0082 {
0083   size_t charMask[256 / sizeof(size_t)];
0084   if (p->MinContext->NumStats != 1)
0085   {
0086     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
0087     unsigned i;
0088     UInt32 count, hiCnt;
0089     if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
0090     {
0091       Byte symbol;
0092       rc->Decode(rc, 0, s->Freq);
0093       p->FoundState = s;
0094       symbol = s->Symbol;
0095       Ppmd7_Update1_0(p);
0096       return symbol;
0097     }
0098     p->PrevSuccess = 0;
0099     i = p->MinContext->NumStats - 1;
0100     do
0101     {
0102       if ((hiCnt += (++s)->Freq) > count)
0103       {
0104         Byte symbol;
0105         rc->Decode(rc, hiCnt - s->Freq, s->Freq);
0106         p->FoundState = s;
0107         symbol = s->Symbol;
0108         Ppmd7_Update1(p);
0109         return symbol;
0110       }
0111     }
0112     while (--i);
0113     if (count >= p->MinContext->SummFreq)
0114       return -2;
0115     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
0116     rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
0117     PPMD_SetAllBitsIn256Bytes(charMask);
0118     MASK(s->Symbol) = 0;
0119     i = p->MinContext->NumStats - 1;
0120     do { MASK((--s)->Symbol) = 0; } while (--i);
0121   }
0122   else
0123   {
0124     UInt16 *prob = Ppmd7_GetBinSumm(p);
0125     if (rc->DecodeBit(rc, *prob) == 0)
0126     {
0127       Byte symbol;
0128       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
0129       symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
0130       Ppmd7_UpdateBin(p);
0131       return symbol;
0132     }
0133     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
0134     p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
0135     PPMD_SetAllBitsIn256Bytes(charMask);
0136     MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
0137     p->PrevSuccess = 0;
0138   }
0139   for (;;)
0140   {
0141     CPpmd_State *ps[256], *s;
0142     UInt32 freqSum, count, hiCnt;
0143     CPpmd_See *see;
0144     unsigned i, num, numMasked = p->MinContext->NumStats;
0145     do
0146     {
0147       p->OrderFall++;
0148       if (!p->MinContext->Suffix)
0149         return -1;
0150       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
0151     }
0152     while (p->MinContext->NumStats == numMasked);
0153     hiCnt = 0;
0154     s = Ppmd7_GetStats(p, p->MinContext);
0155     i = 0;
0156     num = p->MinContext->NumStats - numMasked;
0157     do
0158     {
0159       int k = (int)(MASK(s->Symbol));
0160       hiCnt += (s->Freq & k);
0161       ps[i] = s++;
0162       i -= k;
0163     }
0164     while (i != num);
0165     
0166     see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
0167     freqSum += hiCnt;
0168     count = rc->GetThreshold(rc, freqSum);
0169     
0170     if (count < hiCnt)
0171     {
0172       Byte symbol;
0173       CPpmd_State **pps = ps;
0174       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
0175       s = *pps;
0176       rc->Decode(rc, hiCnt - s->Freq, s->Freq);
0177       Ppmd_See_Update(see);
0178       p->FoundState = s;
0179       symbol = s->Symbol;
0180       Ppmd7_Update2(p);
0181       return symbol;
0182     }
0183     if (count >= freqSum)
0184       return -2;
0185     rc->Decode(rc, hiCnt, freqSum - hiCnt);
0186     see->Summ = (UInt16)(see->Summ + freqSum);
0187     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
0188   }
0189 }