// PPMDEncode.h // This code is based on Dmitry Shkarin's PPMdH code #ifndef __COMPRESS_PPMD_ENCODE_H #define __COMPRESS_PPMD_ENCODE_H #include "PPMDContext.h" namespace NCompress { namespace NPPMD { struct CEncodeInfo: public CInfo { void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder) { PPM_CONTEXT::STATE& rs = MinContext->oneState(); UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); if (rs.Symbol == symbol) { FoundState = &rs; rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0)); rangeEncoder->EncodeBit(bs, TOT_BITS, 0); bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2)); PrevSuccess = 1; RunLength++; } else { rangeEncoder->EncodeBit(bs, TOT_BITS, 1); bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2)); InitEsc = ExpEscape[bs >> 10]; NumMasked = 1; CharMask[rs.Symbol] = EscCount; PrevSuccess = 0; FoundState = NULL; } } void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder) { PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); if (p->Symbol == symbol) { PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq); RunLength += PrevSuccess; rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq); (FoundState = p)->Freq += 4; MinContext->SummFreq += 4; if (p->Freq > MAX_FREQ) rescale(); return; } PrevSuccess = 0; int LoCnt = p->Freq, i = MinContext->NumStats - 1; while ((++p)->Symbol != symbol) { LoCnt += p->Freq; if (--i == 0) { HiBitsFlag = HB2Flag[FoundState->Symbol]; CharMask[p->Symbol] = EscCount; i=(NumMasked = MinContext->NumStats)-1; FoundState = NULL; do { CharMask[(--p)->Symbol] = EscCount; } while ( --i ); rangeEncoder->Encode(LoCnt, MinContext->SummFreq - LoCnt, MinContext->SummFreq); return; } } rangeEncoder->Encode(LoCnt, p->Freq, MinContext->SummFreq); update1(p); } void EncodeSymbol2(int symbol, NRangeCoder::CEncoder *rangeEncoder) { int hiCnt, i = MinContext->NumStats - NumMasked; UInt32 scale; SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale); PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1; hiCnt = 0; do { do { p++; } while (CharMask[p->Symbol] == EscCount); hiCnt += p->Freq; if (p->Symbol == symbol) goto SYMBOL_FOUND; CharMask[p->Symbol] = EscCount; } while ( --i ); rangeEncoder->Encode(hiCnt, scale, hiCnt + scale); scale += hiCnt; psee2c->Summ = (UInt16)(psee2c->Summ + scale); NumMasked = MinContext->NumStats; return; SYMBOL_FOUND: UInt32 highCount = hiCnt; UInt32 lowCount = highCount - p->Freq; if ( --i ) { PPM_CONTEXT::STATE* p1 = p; do { do { p1++; } while (CharMask[p1->Symbol] == EscCount); hiCnt += p1->Freq; } while ( --i ); } // SubRange.scale += hiCnt; scale += hiCnt; rangeEncoder->Encode(lowCount, highCount - lowCount, scale); psee2c->update(); update2(p); } void EncodeSymbol(int c, NRangeCoder::CEncoder *rangeEncoder) { if (MinContext->NumStats != 1) EncodeSymbol1(c, rangeEncoder); else EncodeBinSymbol(c, rangeEncoder); while ( !FoundState ) { do { OrderFall++; MinContext = GetContext(MinContext->Suffix); if (MinContext == 0) return; // S_OK; } while (MinContext->NumStats == NumMasked); EncodeSymbol2(c, rangeEncoder); } NextContext(); } }; }} #endif