Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/PpmdContext.h @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // PpmdContext.h2 // This code is based on Dmitry Shkarin's PPMdH code4 #ifndef __COMPRESS_PPMD_CONTEXT_H5 #define __COMPRESS_PPMD_CONTEXT_H7 #include "../../Common/Types.h"9 #include "PpmdSubAlloc.h"10 #include "RangeCoder.h"12 namespace NCompress {13 namespace NPpmd {15 const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,16 INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;18 struct SEE2_CONTEXT19 {20 // SEE-contexts for PPM-contexts with masked symbols21 UInt16 Summ;22 Byte Shift, Count;23 void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; }24 unsigned int getMean()25 {26 unsigned int RetVal=(Summ >> Shift);27 Summ = (UInt16)(Summ - RetVal);28 return RetVal+(RetVal == 0);29 }30 void update()31 {32 if (Shift < PERIOD_BITS && --Count == 0)33 {34 Summ <<= 1;35 Count = (Byte)(3 << Shift++);36 }37 }38 };40 struct PPM_CONTEXT41 {42 UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte)43 UInt16 SummFreq;45 struct STATE46 {47 Byte Symbol, Freq;48 UInt16 SuccessorLow;49 UInt16 SuccessorHigh;51 UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); }52 void SetSuccessor(UInt32 v)53 {54 SuccessorLow = (UInt16)(v & 0xFFFF);55 SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF);56 }57 };59 UInt32 Stats;60 UInt32 Suffix;62 PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState)63 {64 PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext();65 if (pc)66 {67 pc->NumStats = 1;68 pc->oneState() = FirstState;69 pc->Suffix = subAllocator.GetOffset(this);70 pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc));71 }72 return pc;73 }75 STATE& oneState() const { return (STATE&) SummFreq; }76 };78 /////////////////////////////////80 const UInt16 InitBinEsc[] =81 {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};83 struct CInfo84 {85 CSubAllocator SubAllocator;86 SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;87 PPM_CONTEXT * MinContext, * MaxContext;89 PPM_CONTEXT::STATE* FoundState; // found next state transition90 int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder;91 Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];92 Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag;93 UInt16 BinSumm[128][64]; // binary SEE-contexts95 UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates)96 {97 HiBitsFlag = HB2Flag[FoundState->Symbol];98 return BinSumm[rs.Freq - 1][99 PrevSuccess + NS2BSIndx[numStates - 1] +100 HiBitsFlag + 2 * HB2Flag[rs.Symbol] +101 ((RunLength >> 26) & 0x20)];102 }104 PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); }105 PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); }106 PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }107 PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); }109 void RestartModelRare()110 {111 int i, k, m;112 memset(CharMask,0,sizeof(CharMask));113 SubAllocator.InitSubAllocator();114 InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1;115 MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext();116 MinContext->Suffix = 0;117 OrderFall = MaxOrder;118 MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1);119 FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2);120 MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState);121 PrevSuccess = 0;122 for (RunLength = InitRL, i = 0; i < 256; i++)123 {124 PPM_CONTEXT::STATE &state = FoundState[i];125 state.Symbol = (Byte)i;126 state.Freq = 1;127 state.SetSuccessor(0);128 }129 for (i = 0; i < 128; i++)130 for (k = 0; k < 8; k++)131 for ( m=0; m < 64; m += 8)132 BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2));133 for (i = 0; i < 25; i++)134 for (k = 0; k < 16; k++)135 SEE2Cont[i][k].init(5*i+10);136 }138 void StartModelRare(int maxOrder)139 {140 int i, k, m ,Step;141 EscCount=PrintCount=1;142 if (maxOrder < 2)143 {144 memset(CharMask,0,sizeof(CharMask));145 OrderFall = MaxOrder;146 MinContext = MaxContext;147 while (MinContext->Suffix != 0)148 {149 MinContext = GetContextNoCheck(MinContext->Suffix);150 OrderFall--;151 }152 FoundState = GetState(MinContext->Stats);153 MinContext = MaxContext;154 }155 else156 {157 MaxOrder = maxOrder;158 RestartModelRare();159 NS2BSIndx[0] = 2 * 0;160 NS2BSIndx[1] = 2 * 1;161 memset(NS2BSIndx + 2, 2 * 2, 9);162 memset(NS2BSIndx + 11, 2 * 3, 256 - 11);163 for (i = 0; i < 3; i++)164 NS2Indx[i] = (Byte)i;165 for (m = i, k = Step = 1; i < 256; i++)166 {167 NS2Indx[i] = (Byte)m;168 if ( !--k )169 {170 k = ++Step;171 m++;172 }173 }174 memset(HB2Flag, 0, 0x40);175 memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40);176 DummySEE2Cont.Shift = PERIOD_BITS;177 }178 }180 PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1)181 {182 // static UpState declaration bypasses IntelC bug183 // static PPM_CONTEXT::STATE UpState;184 PPM_CONTEXT::STATE UpState;186 PPM_CONTEXT *pc = MinContext;187 PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor());188 PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps;189 if ( !skip )190 {191 *pps++ = FoundState;192 if ( !pc->Suffix )193 goto NO_LOOP;194 }195 if ( p1 )196 {197 p = p1;198 pc = GetContext(pc->Suffix);199 goto LOOP_ENTRY;200 }201 do202 {203 pc = GetContext(pc->Suffix);204 if (pc->NumStats != 1)205 {206 if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol)207 do { p++; } while (p->Symbol != FoundState->Symbol);208 }209 else210 p = &(pc->oneState());211 LOOP_ENTRY:212 if (GetContext(p->GetSuccessor()) != UpBranch)213 {214 pc = GetContext(p->GetSuccessor());215 break;216 }217 *pps++ = p;218 }219 while ( pc->Suffix );220 NO_LOOP:221 if (pps == ps)222 return pc;223 UpState.Symbol = *(Byte*) UpBranch;224 UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1);225 if (pc->NumStats != 1)226 {227 if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol)228 do { p++; } while (p->Symbol != UpState.Symbol);229 unsigned int cf = p->Freq-1;230 unsigned int s0 = pc->SummFreq - pc->NumStats - cf;231 UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) :232 ((2 * cf + 3 * s0 - 1) / (2 * s0))));233 }234 else235 UpState.Freq = pc->oneState().Freq;236 do237 {238 pc = pc->createChild(SubAllocator, *--pps, UpState);239 if ( !pc )240 return NULL;241 }242 while (pps != ps);243 return pc;244 }246 void UpdateModel()247 {248 PPM_CONTEXT::STATE fs = *FoundState, * p = NULL;249 PPM_CONTEXT* pc, * Successor;250 unsigned int ns1, ns, cf, sf, s0;251 if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0)252 {253 pc = GetContextNoCheck(MinContext->Suffix);255 if (pc->NumStats != 1)256 {257 if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol)258 {259 do { p++; } while (p->Symbol != fs.Symbol);260 if (p[0].Freq >= p[-1].Freq)261 {262 _PPMD_SWAP(p[0],p[-1]);263 p--;264 }265 }266 if (p->Freq < MAX_FREQ-9)267 {268 p->Freq += 2;269 pc->SummFreq += 2;270 }271 }272 else273 {274 p = &(pc->oneState());275 p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0));276 }277 }278 if ( !OrderFall )279 {280 MinContext = MaxContext = CreateSuccessors(true, p);281 FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext));282 if (MinContext == 0)283 goto RESTART_MODEL;284 return;285 }286 *SubAllocator.pText++ = fs.Symbol;287 Successor = (PPM_CONTEXT*) SubAllocator.pText;288 if (SubAllocator.pText >= SubAllocator.UnitsStart)289 goto RESTART_MODEL;290 if (fs.GetSuccessor() != 0)291 {292 if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText)293 {294 PPM_CONTEXT* cs = CreateSuccessors(false, p);295 fs.SetSuccessor(SubAllocator.GetOffset(cs));296 if (cs == NULL)297 goto RESTART_MODEL;298 }299 if ( !--OrderFall )300 {301 Successor = GetContext(fs.GetSuccessor());302 SubAllocator.pText -= (MaxContext != MinContext);303 }304 }305 else306 {307 FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor));308 fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext));309 }310 s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1);311 for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix))312 {313 if ((ns1 = pc->NumStats) != 1)314 {315 if ((ns1 & 1) == 0)316 {317 void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1);318 pc->Stats = SubAllocator.GetOffset(ppp);319 if (!ppp)320 goto RESTART_MODEL;321 }322 pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) &323 (pc->SummFreq <= 8 * ns1)));324 }325 else326 {327 p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1);328 if ( !p )329 goto RESTART_MODEL;330 *p = pc->oneState();331 pc->Stats = SubAllocator.GetOffsetNoCheck(p);332 if (p->Freq < MAX_FREQ / 4 - 1)333 p->Freq <<= 1;334 else335 p->Freq = MAX_FREQ - 4;336 pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3));337 }338 cf = 2 * fs.Freq * (pc->SummFreq+6);339 sf = s0 + pc->SummFreq;340 if (cf < 6 * sf)341 {342 cf = 1 + (cf > sf)+(cf >= 4 * sf);343 pc->SummFreq += 3;344 }345 else346 {347 cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);348 pc->SummFreq = (UInt16)(pc->SummFreq + cf);349 }350 p = GetState(pc->Stats) + ns1;351 p->SetSuccessor(SubAllocator.GetOffset(Successor));352 p->Symbol = fs.Symbol;353 p->Freq = (Byte)cf;354 pc->NumStats = (UInt16)++ns1;355 }356 MaxContext = MinContext = GetContext(fs.GetSuccessor());357 return;358 RESTART_MODEL:359 RestartModelRare();360 EscCount = 0;361 PrintCount = 0xFF;362 }364 void ClearMask()365 {366 EscCount = 1;367 memset(CharMask, 0, sizeof(CharMask));368 // if (++PrintCount == 0)369 // PrintInfo(DecodedFile,EncodedFile);370 }372 void update1(PPM_CONTEXT::STATE* p)373 {374 (FoundState = p)->Freq += 4;375 MinContext->SummFreq += 4;376 if (p[0].Freq > p[-1].Freq)377 {378 _PPMD_SWAP(p[0],p[-1]);379 FoundState = --p;380 if (p->Freq > MAX_FREQ)381 rescale();382 }383 }386 void update2(PPM_CONTEXT::STATE* p)387 {388 (FoundState = p)->Freq += 4;389 MinContext->SummFreq += 4;390 if (p->Freq > MAX_FREQ)391 rescale();392 EscCount++;393 RunLength = InitRL;394 }396 SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale)397 {398 SEE2_CONTEXT* psee2c;399 if (MinContext->NumStats != 256)400 {401 psee2c = SEE2Cont[NS2Indx[Diff-1]] +402 (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) +403 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) +404 4 * (NumMasked > Diff) +405 HiBitsFlag;406 scale = psee2c->getMean();407 }408 else409 {410 psee2c = &DummySEE2Cont;411 scale = 1;412 }413 return psee2c;414 }418 void rescale()419 {420 int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq;421 PPM_CONTEXT::STATE* p1, * p;422 PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats);423 for (p = FoundState; p != stats; p--)424 _PPMD_SWAP(p[0], p[-1]);425 stats->Freq += 4;426 MinContext->SummFreq += 4;427 EscFreq = MinContext->SummFreq - p->Freq;428 Adder = (OrderFall != 0);429 p->Freq = (Byte)((p->Freq + Adder) >> 1);430 MinContext->SummFreq = p->Freq;431 do432 {433 EscFreq -= (++p)->Freq;434 p->Freq = (Byte)((p->Freq + Adder) >> 1);435 MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq);436 if (p[0].Freq > p[-1].Freq)437 {438 PPM_CONTEXT::STATE tmp = *(p1 = p);439 do440 {441 p1[0] = p1[-1];442 }443 while (--p1 != stats && tmp.Freq > p1[-1].Freq);444 *p1 = tmp;445 }446 }447 while ( --i );448 if (p->Freq == 0)449 {450 do { i++; } while ((--p)->Freq == 0);451 EscFreq += i;452 MinContext->NumStats = (UInt16)(MinContext->NumStats - i);453 if (MinContext->NumStats == 1)454 {455 PPM_CONTEXT::STATE tmp = *stats;456 do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1);457 SubAllocator.FreeUnits(stats, (OldNS+1) >> 1);458 *(FoundState = &MinContext->oneState()) = tmp; return;459 }460 }461 EscFreq -= (EscFreq >> 1);462 MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq);463 int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1;464 if (n0 != n1)465 MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1));466 FoundState = GetState(MinContext->Stats);467 }469 void NextContext()470 {471 PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor());472 if (!OrderFall && (Byte *)c > SubAllocator.pText)473 MinContext = MaxContext = c;474 else475 {476 UpdateModel();477 if (EscCount == 0)478 ClearMask();479 }480 }481 };483 // Tabulated escapes for exponential symbol distribution484 const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };485 #define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))487 }}489 #endif