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 }