Files
easy7zip/CPP/7zip/Compress/PpmdDecode.h
Igor Pavlov 829409452d 9.04 beta
2016-05-28 00:15:59 +01:00

156 lines
4.2 KiB
C++
Executable File

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