rlm@1: // PpmdDecode.h rlm@1: // This code is based on Dmitry Shkarin's PPMdH code rlm@1: rlm@1: #ifndef __COMPRESS_PPMD_DECODE_H rlm@1: #define __COMPRESS_PPMD_DECODE_H rlm@1: rlm@1: #include "PpmdContext.h" rlm@1: rlm@1: namespace NCompress { rlm@1: namespace NPpmd { rlm@1: rlm@1: class CRangeDecoderVirt rlm@1: { rlm@1: public: rlm@1: virtual UInt32 GetThreshold(UInt32 total) = 0; rlm@1: virtual void Decode(UInt32 start, UInt32 size) = 0; rlm@1: virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) = 0; rlm@1: }; rlm@1: rlm@1: typedef NRangeCoder::CDecoder CRangeDecoderMy; rlm@1: rlm@1: class CRangeDecoder:public CRangeDecoderVirt, public CRangeDecoderMy rlm@1: { rlm@1: UInt32 GetThreshold(UInt32 total) { return CRangeDecoderMy::GetThreshold(total); } rlm@1: void Decode(UInt32 start, UInt32 size) { CRangeDecoderMy::Decode(start, size); } rlm@1: UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { return CRangeDecoderMy::DecodeBit(size0, numTotalBits); } rlm@1: }; rlm@1: rlm@1: struct CDecodeInfo: public CInfo rlm@1: { rlm@1: void DecodeBinSymbol(CRangeDecoderVirt *rangeDecoder) rlm@1: { rlm@1: PPM_CONTEXT::STATE& rs = MinContext->oneState(); rlm@1: UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); rlm@1: if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0) rlm@1: { rlm@1: FoundState = &rs; rlm@1: rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0)); rlm@1: bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2)); rlm@1: PrevSuccess = 1; rlm@1: RunLength++; rlm@1: } rlm@1: else rlm@1: { rlm@1: bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2)); rlm@1: InitEsc = ExpEscape[bs >> 10]; rlm@1: NumMasked = 1; rlm@1: CharMask[rs.Symbol] = EscCount; rlm@1: PrevSuccess = 0; rlm@1: FoundState = NULL; rlm@1: } rlm@1: } rlm@1: rlm@1: void DecodeSymbol1(CRangeDecoderVirt *rangeDecoder) rlm@1: { rlm@1: PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); rlm@1: int i, count, hiCnt; rlm@1: if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq)) rlm@1: { rlm@1: PrevSuccess = (2 * hiCnt > MinContext->SummFreq); rlm@1: RunLength += PrevSuccess; rlm@1: rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq); rlm@1: (FoundState = p)->Freq = (Byte)(hiCnt += 4); rlm@1: MinContext->SummFreq += 4; rlm@1: if (hiCnt > MAX_FREQ) rlm@1: rescale(); rlm@1: return; rlm@1: } rlm@1: PrevSuccess = 0; rlm@1: i = MinContext->NumStats - 1; rlm@1: while ((hiCnt += (++p)->Freq) <= count) rlm@1: if (--i == 0) rlm@1: { rlm@1: HiBitsFlag = HB2Flag[FoundState->Symbol]; rlm@1: rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt); // , MinContext->SummFreq); rlm@1: CharMask[p->Symbol] = EscCount; rlm@1: i = (NumMasked = MinContext->NumStats)-1; rlm@1: FoundState = NULL; rlm@1: do { CharMask[(--p)->Symbol] = EscCount; } while ( --i ); rlm@1: return; rlm@1: } rlm@1: rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq); rlm@1: update1(p); rlm@1: } rlm@1: rlm@1: rlm@1: void DecodeSymbol2(CRangeDecoderVirt *rangeDecoder) rlm@1: { rlm@1: int count, hiCnt, i = MinContext->NumStats - NumMasked; rlm@1: UInt32 freqSum; rlm@1: SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum); rlm@1: PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1; rlm@1: hiCnt = 0; rlm@1: do rlm@1: { rlm@1: do { p++; } while (CharMask[p->Symbol] == EscCount); rlm@1: hiCnt += p->Freq; rlm@1: *pps++ = p; rlm@1: } rlm@1: while ( --i ); rlm@1: rlm@1: freqSum += hiCnt; rlm@1: count = rangeDecoder->GetThreshold(freqSum); rlm@1: rlm@1: p = *(pps = ps); rlm@1: if (count < hiCnt) rlm@1: { rlm@1: hiCnt = 0; rlm@1: while ((hiCnt += p->Freq) <= count) rlm@1: p=*++pps; rlm@1: rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum); rlm@1: rlm@1: psee2c->update(); rlm@1: update2(p); rlm@1: } rlm@1: else rlm@1: { rlm@1: rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum); rlm@1: rlm@1: i = MinContext->NumStats - NumMasked; rlm@1: pps--; rlm@1: do { CharMask[(*++pps)->Symbol] = EscCount; } while ( --i ); rlm@1: psee2c->Summ = (UInt16)(psee2c->Summ + freqSum); rlm@1: NumMasked = MinContext->NumStats; rlm@1: } rlm@1: } rlm@1: rlm@1: int DecodeSymbol(CRangeDecoderVirt *rangeDecoder) rlm@1: { rlm@1: if (MinContext->NumStats != 1) rlm@1: DecodeSymbol1(rangeDecoder); rlm@1: else rlm@1: DecodeBinSymbol(rangeDecoder); rlm@1: while ( !FoundState ) rlm@1: { rlm@1: do rlm@1: { rlm@1: OrderFall++; rlm@1: MinContext = GetContext(MinContext->Suffix); rlm@1: if (MinContext == 0) rlm@1: return -1; rlm@1: } rlm@1: while (MinContext->NumStats == NumMasked); rlm@1: DecodeSymbol2(rangeDecoder); rlm@1: } rlm@1: Byte symbol = FoundState->Symbol; rlm@1: NextContext(); rlm@1: return symbol; rlm@1: } rlm@1: }; rlm@1: rlm@1: }} rlm@1: rlm@1: #endif