📄 ppmdcontext.h
字号:
// Compress/PPMD/Context.h
// This code is based on Dmitry Shkarin's PPMdH code
#ifndef __COMPRESS_PPMD_CONTEXT_H
#define __COMPRESS_PPMD_CONTEXT_H
#include "../../../Common/Types.h"
#include "../RangeCoder/RangeCoder.h"
#include "PPMDSubAlloc.h"
namespace NCompress {
namespace NPPMD {
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
struct SEE2_CONTEXT
{
// SEE-contexts for PPM-contexts with masked symbols
UInt16 Summ;
Byte Shift, Count;
void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }
unsigned int getMean()
{
unsigned int RetVal=(Summ >> Shift);
Summ = (UInt16)(Summ - RetVal);
return RetVal+(RetVal == 0);
}
void update()
{
if (Shift < PERIOD_BITS && --Count == 0)
{
Summ <<= 1;
Count = (Byte)(3 << Shift++);
}
}
};
struct PPM_CONTEXT
{
UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)
UInt16 SummFreq;
struct STATE
{
Byte Symbol, Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }
void SetSuccessor(UInt32 v)
{
SuccessorLow = (UInt16)(v & 0xFFFF);
SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);
}
};
UInt32 Stats;
UInt32 Suffix;
PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)
{
PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();
if (pc)
{
pc->NumStats = 1;
pc->oneState() = FirstState;
pc->Suffix = subAllocator.GetOffset(this);
pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));
}
return pc;
}
STATE& oneState() const { return (STATE&) SummFreq; }
};
/////////////////////////////////
const UInt16 InitBinEsc[] =
{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
struct CInfo
{
CSubAllocator SubAllocator;
SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
PPM_CONTEXT * MinContext, * MaxContext;
PPM_CONTEXT::STATE* FoundState; // found next state transition
int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;
Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;
UInt16 BinSumm[128][64]; // binary SEE-contexts
UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)
{
HiBitsFlag = HB2Flag[FoundState->Symbol];
return BinSumm[rs.Freq - 1][
PrevSuccess + NS2BSIndx[numStates - 1] +
HiBitsFlag + 2 * HB2Flag[rs.Symbol] +
((RunLength >> 26) & 0x20)];
}
PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }
PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }
void RestartModelRare()
{
int i, k, m;
memset(CharMask,0,sizeof(CharMask));
SubAllocator.InitSubAllocator();
InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;
MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();
MinContext->Suffix = 0;
OrderFall = MaxOrder;
MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);
FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);
MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);
PrevSuccess = 0;
for (RunLength = InitRL, i = 0; i < 256; i++)
{
PPM_CONTEXT::STATE &state = FoundState[i];
state.Symbol = (Byte)i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
for ( m=0; m < 64; m += 8)
BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
SEE2Cont[i][k].init(5*i+10);
}
void StartModelRare(int maxOrder)
{
int i, k, m ,Step;
EscCount=PrintCount=1;
if (maxOrder < 2)
{
memset(CharMask,0,sizeof(CharMask));
OrderFall = MaxOrder;
MinContext = MaxContext;
while (MinContext->Suffix != 0)
{
MinContext = GetContextNoCheck(MinContext->Suffix);
OrderFall--;
}
FoundState = GetState(MinContext->Stats);
MinContext = MaxContext;
}
else
{
MaxOrder = maxOrder;
RestartModelRare();
NS2BSIndx[0] = 2 * 0;
NS2BSIndx[1] = 2 * 1;
memset(NS2BSIndx + 2, 2 * 2, 9);
memset(NS2BSIndx + 11, 2 * 3, 256 - 11);
for (i = 0; i < 3; i++)
NS2Indx[i] = (Byte)i;
for (m = i, k = Step = 1; i < 256; i++)
{
NS2Indx[i] = (Byte)m;
if ( !--k )
{
k = ++Step;
m++;
}
}
memset(HB2Flag, 0, 0x40);
memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);
DummySEE2Cont.Shift = PERIOD_BITS;
}
}
PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)
{
// static UpState declaration bypasses IntelC bug
// static PPM_CONTEXT::STATE UpState;
PPM_CONTEXT::STATE UpState;
PPM_CONTEXT *pc = MinContext;
PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());
PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;
if ( !skip )
{
*pps++ = FoundState;
if ( !pc->Suffix )
goto NO_LOOP;
}
if ( p1 )
{
p = p1;
pc = GetContext(pc->Suffix);
goto LOOP_ENTRY;
}
do
{
pc = GetContext(pc->Suffix);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)
do { p++; } while (p->Symbol != FoundState->Symbol);
}
else
p = &(pc->oneState());
LOOP_ENTRY:
if (GetContext(p->GetSuccessor()) != UpBranch)
{
pc = GetContext(p->GetSuccessor());
break;
}
*pps++ = p;
}
while ( pc->Suffix );
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol = *(Byte*) UpBranch;
UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);
if (pc->NumStats != 1)
{
if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)
do { p++; } while (p->Symbol != UpState.Symbol);
unsigned int cf = p->Freq-1;
unsigned int s0 = pc->SummFreq - pc->NumStats - cf;
UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :
((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
else
UpState.Freq = pc->oneState().Freq;
do
{
pc = pc->createChild(SubAllocator, *--pps, UpState);
if ( !pc )
return NULL;
}
while (pps != ps);
return pc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -