⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppmdcontext.h

📁 由7-zip提供的压缩、解压缩程序
💻 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=InitVal << (Shift=PERIOD_BITS-4); Count=4; }  unsigned int getMean()   {    unsigned int RetVal=(Summ >> Shift);            Summ -= RetVal;    return RetVal+(RetVal == 0);  }  void update()   {    if (Shift < PERIOD_BITS && --Count == 0)     {      Summ += Summ;                         Count = 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 = (MinContext->NumStats = 256) + 1;    FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);    MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);    for (RunLength = InitRL, PrevSuccess = i = 0; i < 256; i++)     {      PPM_CONTEXT::STATE &state = FoundState[i];      state.Symbol = 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] = 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 = this->MaxOrder;                       MinContext = MaxContext;        while (MinContext->Suffix != 0)         {          MinContext = GetContextNoCheck(MinContext->Suffix);            OrderFall--;        }        FoundState = GetState(MinContext->Stats);        MinContext = MaxContext;    }     else     {        this->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] = i;        for (m = i, k = Step = 1; i < 256; i++)         {            NS2Indx[i] =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 = 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;  }  void UpdateModel()  {    PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;    PPM_CONTEXT* pc, * Successor;    unsigned int ns1, ns, cf, sf, s0;    if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)     {        pc = GetContextNoCheck(MinContext->Suffix);              if (pc->NumStats != 1)         {            if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)             {                do { p++; } while (p->Symbol != fs.Symbol);                if (p[0].Freq >= p[-1].Freq)                 {                    _PPMD_SWAP(p[0],p[-1]);                     p--;                }            }            if (p->Freq < MAX_FREQ-9)             {                p->Freq += 2;                               pc->SummFreq += 2;            }        }         else         {            p = &(pc->oneState());                        p->Freq += (p->Freq < 32);        }    }    if ( !OrderFall )     {        MinContext = MaxContext = CreateSuccessors(true, p);        FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));        if (MinContext == 0)                            goto RESTART_MODEL;        return;    }    *SubAllocator.pText++ = fs.Symbol;                       Successor = (PPM_CONTEXT*) SubAllocator.pText;    if (SubAllocator.pText >= SubAllocator.UnitsStart)                      goto RESTART_MODEL;    if (fs.GetSuccessor() != 0)     {        if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)        {          PPM_CONTEXT* cs = CreateSuccessors(false, p);          fs.SetSuccessor(SubAllocator.GetOffset(cs));          if (cs == NULL)            goto RESTART_MODEL;        }        if ( !--OrderFall )         {            Successor = GetContext(fs.GetSuccessor());            SubAllocator.pText -= (MaxContext != MinContext);        }    }     else     {        FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));            fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));    }    s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);    for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))     {        if ((ns1 = pc->NumStats) != 1)         {            if ((ns1 & 1) == 0)             {                void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);                pc->Stats = SubAllocator.GetOffset(ppp);                if (!ppp)                             goto RESTART_MODEL;            }            pc->SummFreq += (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &                    (pc->SummFreq <= 8 * ns1));        }         else         {            p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);            if ( !p )                                     goto RESTART_MODEL;            *p = pc->oneState();                          pc->Stats = SubAllocator.GetOffsetNoCheck(p);            if (p->Freq < MAX_FREQ / 4 - 1)                   p->Freq += p->Freq;            else                                          p->Freq  = MAX_FREQ - 4;            pc->SummFreq = p->Freq + InitEsc + (ns > 3);        }        cf = 2 * fs.Freq * (pc->SummFreq+6);              sf = s0 + pc->SummFreq;        if (cf < 6 * sf)         {            cf = 1 + (cf > sf)+(cf >= 4 * sf);            pc->SummFreq += 3;        }         else         {            cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);            pc->SummFreq += cf;        }        p = GetState(pc->Stats) + ns1;                            p->SetSuccessor(SubAllocator.GetOffset(Successor));        p->Symbol = fs.Symbol;                      p->Freq = cf;        pc->NumStats = ++ns1;    }    MaxContext = MinContext = GetContext(fs.GetSuccessor());    return;RESTART_MODEL:    RestartModelRare();    EscCount = 0;                   PrintCount = 0xFF;  }  void ClearMask()  {    EscCount = 1;                                 memset(CharMask, 0, sizeof(CharMask));    // if (++PrintCount == 0)                      //   PrintInfo(DecodedFile,EncodedFile);  }  void update1(PPM_CONTEXT::STATE* p)  {    (FoundState = p)->Freq += 4;                  MinContext->SummFreq += 4;    if (p[0].Freq > p[-1].Freq)     {        _PPMD_SWAP(p[0],p[-1]);                     FoundState = --p;        if (p->Freq > MAX_FREQ)                       rescale();    }  }  void update2(PPM_CONTEXT::STATE* p)  {    (FoundState = p)->Freq += 4;    MinContext->SummFreq += 4;    if (p->Freq > MAX_FREQ)                       rescale();    EscCount++;                                 RunLength = InitRL;  }    SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)  {    SEE2_CONTEXT* psee2c;    if (MinContext->NumStats != 256)     {      psee2c = SEE2Cont[NS2Indx[Diff-1]] +         (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +        2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +         4 * (NumMasked > Diff) +         HiBitsFlag;      scale = psee2c->getMean();    }     else     {      psee2c = &DummySEE2Cont;                    scale = 1;    }    return psee2c;  }  void rescale()  {    int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;    PPM_CONTEXT::STATE* p1, * p;    PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);    for (p = FoundState; p != stats; p--)             _PPMD_SWAP(p[0], p[-1]);    stats->Freq += 4;                           MinContext->SummFreq += 4;    EscFreq = MinContext->SummFreq - p->Freq;                   Adder = (OrderFall != 0);    MinContext->SummFreq = (p->Freq = (p->Freq + Adder) >> 1);    do     {        EscFreq -= (++p)->Freq;        MinContext->SummFreq += (p->Freq = (p->Freq + Adder) >> 1);        if (p[0].Freq > p[-1].Freq)         {            PPM_CONTEXT::STATE tmp = *(p1 = p);            do             {               p1[0] = p1[-1];             }             while (--p1 != stats && tmp.Freq > p1[-1].Freq);            *p1 = tmp;        }    }     while ( --i );    if (p->Freq == 0)     {        do { i++; } while ((--p)->Freq == 0);        EscFreq += i;        if ((MinContext->NumStats -= i) == 1)         {            PPM_CONTEXT::STATE tmp = *stats;            do { tmp.Freq -= (tmp.Freq >> 1); EscFreq >>= 1; } while (EscFreq > 1);            SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);            *(FoundState = &MinContext->oneState()) = tmp;  return;        }    }    MinContext->SummFreq += (EscFreq -= (EscFreq >> 1));    int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;    if (n0 != n1)      MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));    FoundState = GetState(MinContext->Stats);  }  void NextContext()  {    PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());    if (!OrderFall && (Byte *)c > SubAllocator.pText)      MinContext = MaxContext = c;    else     {      UpdateModel();      if (EscCount == 0)                      ClearMask();    }  }};// Tabulated escapes for exponential symbol distributionconst Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))}}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -