mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 09:15:00 -06:00
143 lines
3.7 KiB
C++
Executable File
143 lines
3.7 KiB
C++
Executable File
// PpmdEncode.h
|
|
// 2009-05-30 : Igor Pavlov : Public domain
|
|
// This code is based on Dmitry Shkarin's PPMdH code (public domain)
|
|
|
|
#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
|