Mercurial > vba-linux
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/PpmdContext.h Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,489 @@ 1.4 +// PpmdContext.h 1.5 +// This code is based on Dmitry Shkarin's PPMdH code 1.6 + 1.7 +#ifndef __COMPRESS_PPMD_CONTEXT_H 1.8 +#define __COMPRESS_PPMD_CONTEXT_H 1.9 + 1.10 +#include "../../Common/Types.h" 1.11 + 1.12 +#include "PpmdSubAlloc.h" 1.13 +#include "RangeCoder.h" 1.14 + 1.15 +namespace NCompress { 1.16 +namespace NPpmd { 1.17 + 1.18 +const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS, 1.19 + INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124; 1.20 + 1.21 +struct SEE2_CONTEXT 1.22 +{ 1.23 + // SEE-contexts for PPM-contexts with masked symbols 1.24 + UInt16 Summ; 1.25 + Byte Shift, Count; 1.26 + void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; } 1.27 + unsigned int getMean() 1.28 + { 1.29 + unsigned int RetVal=(Summ >> Shift); 1.30 + Summ = (UInt16)(Summ - RetVal); 1.31 + return RetVal+(RetVal == 0); 1.32 + } 1.33 + void update() 1.34 + { 1.35 + if (Shift < PERIOD_BITS && --Count == 0) 1.36 + { 1.37 + Summ <<= 1; 1.38 + Count = (Byte)(3 << Shift++); 1.39 + } 1.40 + } 1.41 +}; 1.42 + 1.43 +struct PPM_CONTEXT 1.44 +{ 1.45 + UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte) 1.46 + UInt16 SummFreq; 1.47 + 1.48 + struct STATE 1.49 + { 1.50 + Byte Symbol, Freq; 1.51 + UInt16 SuccessorLow; 1.52 + UInt16 SuccessorHigh; 1.53 + 1.54 + UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); } 1.55 + void SetSuccessor(UInt32 v) 1.56 + { 1.57 + SuccessorLow = (UInt16)(v & 0xFFFF); 1.58 + SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF); 1.59 + } 1.60 + }; 1.61 + 1.62 + UInt32 Stats; 1.63 + UInt32 Suffix; 1.64 + 1.65 + PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState) 1.66 + { 1.67 + PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext(); 1.68 + if (pc) 1.69 + { 1.70 + pc->NumStats = 1; 1.71 + pc->oneState() = FirstState; 1.72 + pc->Suffix = subAllocator.GetOffset(this); 1.73 + pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc)); 1.74 + } 1.75 + return pc; 1.76 + } 1.77 + 1.78 + STATE& oneState() const { return (STATE&) SummFreq; } 1.79 +}; 1.80 + 1.81 +///////////////////////////////// 1.82 + 1.83 +const UInt16 InitBinEsc[] = 1.84 + {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; 1.85 + 1.86 +struct CInfo 1.87 +{ 1.88 + CSubAllocator SubAllocator; 1.89 + SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont; 1.90 + PPM_CONTEXT * MinContext, * MaxContext; 1.91 + 1.92 + PPM_CONTEXT::STATE* FoundState; // found next state transition 1.93 + int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder; 1.94 + Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; 1.95 + Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag; 1.96 + UInt16 BinSumm[128][64]; // binary SEE-contexts 1.97 + 1.98 + UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates) 1.99 + { 1.100 + HiBitsFlag = HB2Flag[FoundState->Symbol]; 1.101 + return BinSumm[rs.Freq - 1][ 1.102 + PrevSuccess + NS2BSIndx[numStates - 1] + 1.103 + HiBitsFlag + 2 * HB2Flag[rs.Symbol] + 1.104 + ((RunLength >> 26) & 0x20)]; 1.105 + } 1.106 + 1.107 + PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); } 1.108 + PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); } 1.109 + PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } 1.110 + PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } 1.111 + 1.112 + void RestartModelRare() 1.113 + { 1.114 + int i, k, m; 1.115 + memset(CharMask,0,sizeof(CharMask)); 1.116 + SubAllocator.InitSubAllocator(); 1.117 + InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1; 1.118 + MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext(); 1.119 + MinContext->Suffix = 0; 1.120 + OrderFall = MaxOrder; 1.121 + MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1); 1.122 + FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2); 1.123 + MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState); 1.124 + PrevSuccess = 0; 1.125 + for (RunLength = InitRL, i = 0; i < 256; i++) 1.126 + { 1.127 + PPM_CONTEXT::STATE &state = FoundState[i]; 1.128 + state.Symbol = (Byte)i; 1.129 + state.Freq = 1; 1.130 + state.SetSuccessor(0); 1.131 + } 1.132 + for (i = 0; i < 128; i++) 1.133 + for (k = 0; k < 8; k++) 1.134 + for ( m=0; m < 64; m += 8) 1.135 + BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2)); 1.136 + for (i = 0; i < 25; i++) 1.137 + for (k = 0; k < 16; k++) 1.138 + SEE2Cont[i][k].init(5*i+10); 1.139 + } 1.140 + 1.141 + void StartModelRare(int maxOrder) 1.142 + { 1.143 + int i, k, m ,Step; 1.144 + EscCount=PrintCount=1; 1.145 + if (maxOrder < 2) 1.146 + { 1.147 + memset(CharMask,0,sizeof(CharMask)); 1.148 + OrderFall = MaxOrder; 1.149 + MinContext = MaxContext; 1.150 + while (MinContext->Suffix != 0) 1.151 + { 1.152 + MinContext = GetContextNoCheck(MinContext->Suffix); 1.153 + OrderFall--; 1.154 + } 1.155 + FoundState = GetState(MinContext->Stats); 1.156 + MinContext = MaxContext; 1.157 + } 1.158 + else 1.159 + { 1.160 + MaxOrder = maxOrder; 1.161 + RestartModelRare(); 1.162 + NS2BSIndx[0] = 2 * 0; 1.163 + NS2BSIndx[1] = 2 * 1; 1.164 + memset(NS2BSIndx + 2, 2 * 2, 9); 1.165 + memset(NS2BSIndx + 11, 2 * 3, 256 - 11); 1.166 + for (i = 0; i < 3; i++) 1.167 + NS2Indx[i] = (Byte)i; 1.168 + for (m = i, k = Step = 1; i < 256; i++) 1.169 + { 1.170 + NS2Indx[i] = (Byte)m; 1.171 + if ( !--k ) 1.172 + { 1.173 + k = ++Step; 1.174 + m++; 1.175 + } 1.176 + } 1.177 + memset(HB2Flag, 0, 0x40); 1.178 + memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40); 1.179 + DummySEE2Cont.Shift = PERIOD_BITS; 1.180 + } 1.181 + } 1.182 + 1.183 + PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1) 1.184 + { 1.185 + // static UpState declaration bypasses IntelC bug 1.186 + // static PPM_CONTEXT::STATE UpState; 1.187 + PPM_CONTEXT::STATE UpState; 1.188 + 1.189 + PPM_CONTEXT *pc = MinContext; 1.190 + PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor()); 1.191 + PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps; 1.192 + if ( !skip ) 1.193 + { 1.194 + *pps++ = FoundState; 1.195 + if ( !pc->Suffix ) 1.196 + goto NO_LOOP; 1.197 + } 1.198 + if ( p1 ) 1.199 + { 1.200 + p = p1; 1.201 + pc = GetContext(pc->Suffix); 1.202 + goto LOOP_ENTRY; 1.203 + } 1.204 + do 1.205 + { 1.206 + pc = GetContext(pc->Suffix); 1.207 + if (pc->NumStats != 1) 1.208 + { 1.209 + if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol) 1.210 + do { p++; } while (p->Symbol != FoundState->Symbol); 1.211 + } 1.212 + else 1.213 + p = &(pc->oneState()); 1.214 +LOOP_ENTRY: 1.215 + if (GetContext(p->GetSuccessor()) != UpBranch) 1.216 + { 1.217 + pc = GetContext(p->GetSuccessor()); 1.218 + break; 1.219 + } 1.220 + *pps++ = p; 1.221 + } 1.222 + while ( pc->Suffix ); 1.223 +NO_LOOP: 1.224 + if (pps == ps) 1.225 + return pc; 1.226 + UpState.Symbol = *(Byte*) UpBranch; 1.227 + UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1); 1.228 + if (pc->NumStats != 1) 1.229 + { 1.230 + if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol) 1.231 + do { p++; } while (p->Symbol != UpState.Symbol); 1.232 + unsigned int cf = p->Freq-1; 1.233 + unsigned int s0 = pc->SummFreq - pc->NumStats - cf; 1.234 + UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : 1.235 + ((2 * cf + 3 * s0 - 1) / (2 * s0)))); 1.236 + } 1.237 + else 1.238 + UpState.Freq = pc->oneState().Freq; 1.239 + do 1.240 + { 1.241 + pc = pc->createChild(SubAllocator, *--pps, UpState); 1.242 + if ( !pc ) 1.243 + return NULL; 1.244 + } 1.245 + while (pps != ps); 1.246 + return pc; 1.247 + } 1.248 + 1.249 + void UpdateModel() 1.250 + { 1.251 + PPM_CONTEXT::STATE fs = *FoundState, * p = NULL; 1.252 + PPM_CONTEXT* pc, * Successor; 1.253 + unsigned int ns1, ns, cf, sf, s0; 1.254 + if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0) 1.255 + { 1.256 + pc = GetContextNoCheck(MinContext->Suffix); 1.257 + 1.258 + if (pc->NumStats != 1) 1.259 + { 1.260 + if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol) 1.261 + { 1.262 + do { p++; } while (p->Symbol != fs.Symbol); 1.263 + if (p[0].Freq >= p[-1].Freq) 1.264 + { 1.265 + _PPMD_SWAP(p[0],p[-1]); 1.266 + p--; 1.267 + } 1.268 + } 1.269 + if (p->Freq < MAX_FREQ-9) 1.270 + { 1.271 + p->Freq += 2; 1.272 + pc->SummFreq += 2; 1.273 + } 1.274 + } 1.275 + else 1.276 + { 1.277 + p = &(pc->oneState()); 1.278 + p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0)); 1.279 + } 1.280 + } 1.281 + if ( !OrderFall ) 1.282 + { 1.283 + MinContext = MaxContext = CreateSuccessors(true, p); 1.284 + FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext)); 1.285 + if (MinContext == 0) 1.286 + goto RESTART_MODEL; 1.287 + return; 1.288 + } 1.289 + *SubAllocator.pText++ = fs.Symbol; 1.290 + Successor = (PPM_CONTEXT*) SubAllocator.pText; 1.291 + if (SubAllocator.pText >= SubAllocator.UnitsStart) 1.292 + goto RESTART_MODEL; 1.293 + if (fs.GetSuccessor() != 0) 1.294 + { 1.295 + if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText) 1.296 + { 1.297 + PPM_CONTEXT* cs = CreateSuccessors(false, p); 1.298 + fs.SetSuccessor(SubAllocator.GetOffset(cs)); 1.299 + if (cs == NULL) 1.300 + goto RESTART_MODEL; 1.301 + } 1.302 + if ( !--OrderFall ) 1.303 + { 1.304 + Successor = GetContext(fs.GetSuccessor()); 1.305 + SubAllocator.pText -= (MaxContext != MinContext); 1.306 + } 1.307 + } 1.308 + else 1.309 + { 1.310 + FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor)); 1.311 + fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext)); 1.312 + } 1.313 + s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1); 1.314 + for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix)) 1.315 + { 1.316 + if ((ns1 = pc->NumStats) != 1) 1.317 + { 1.318 + if ((ns1 & 1) == 0) 1.319 + { 1.320 + void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1); 1.321 + pc->Stats = SubAllocator.GetOffset(ppp); 1.322 + if (!ppp) 1.323 + goto RESTART_MODEL; 1.324 + } 1.325 + pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & 1.326 + (pc->SummFreq <= 8 * ns1))); 1.327 + } 1.328 + else 1.329 + { 1.330 + p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1); 1.331 + if ( !p ) 1.332 + goto RESTART_MODEL; 1.333 + *p = pc->oneState(); 1.334 + pc->Stats = SubAllocator.GetOffsetNoCheck(p); 1.335 + if (p->Freq < MAX_FREQ / 4 - 1) 1.336 + p->Freq <<= 1; 1.337 + else 1.338 + p->Freq = MAX_FREQ - 4; 1.339 + pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3)); 1.340 + } 1.341 + cf = 2 * fs.Freq * (pc->SummFreq+6); 1.342 + sf = s0 + pc->SummFreq; 1.343 + if (cf < 6 * sf) 1.344 + { 1.345 + cf = 1 + (cf > sf)+(cf >= 4 * sf); 1.346 + pc->SummFreq += 3; 1.347 + } 1.348 + else 1.349 + { 1.350 + cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); 1.351 + pc->SummFreq = (UInt16)(pc->SummFreq + cf); 1.352 + } 1.353 + p = GetState(pc->Stats) + ns1; 1.354 + p->SetSuccessor(SubAllocator.GetOffset(Successor)); 1.355 + p->Symbol = fs.Symbol; 1.356 + p->Freq = (Byte)cf; 1.357 + pc->NumStats = (UInt16)++ns1; 1.358 + } 1.359 + MaxContext = MinContext = GetContext(fs.GetSuccessor()); 1.360 + return; 1.361 +RESTART_MODEL: 1.362 + RestartModelRare(); 1.363 + EscCount = 0; 1.364 + PrintCount = 0xFF; 1.365 + } 1.366 + 1.367 + void ClearMask() 1.368 + { 1.369 + EscCount = 1; 1.370 + memset(CharMask, 0, sizeof(CharMask)); 1.371 + // if (++PrintCount == 0) 1.372 + // PrintInfo(DecodedFile,EncodedFile); 1.373 + } 1.374 + 1.375 + void update1(PPM_CONTEXT::STATE* p) 1.376 + { 1.377 + (FoundState = p)->Freq += 4; 1.378 + MinContext->SummFreq += 4; 1.379 + if (p[0].Freq > p[-1].Freq) 1.380 + { 1.381 + _PPMD_SWAP(p[0],p[-1]); 1.382 + FoundState = --p; 1.383 + if (p->Freq > MAX_FREQ) 1.384 + rescale(); 1.385 + } 1.386 + } 1.387 + 1.388 + 1.389 + void update2(PPM_CONTEXT::STATE* p) 1.390 + { 1.391 + (FoundState = p)->Freq += 4; 1.392 + MinContext->SummFreq += 4; 1.393 + if (p->Freq > MAX_FREQ) 1.394 + rescale(); 1.395 + EscCount++; 1.396 + RunLength = InitRL; 1.397 + } 1.398 + 1.399 + SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale) 1.400 + { 1.401 + SEE2_CONTEXT* psee2c; 1.402 + if (MinContext->NumStats != 256) 1.403 + { 1.404 + psee2c = SEE2Cont[NS2Indx[Diff-1]] + 1.405 + (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) + 1.406 + 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) + 1.407 + 4 * (NumMasked > Diff) + 1.408 + HiBitsFlag; 1.409 + scale = psee2c->getMean(); 1.410 + } 1.411 + else 1.412 + { 1.413 + psee2c = &DummySEE2Cont; 1.414 + scale = 1; 1.415 + } 1.416 + return psee2c; 1.417 + } 1.418 + 1.419 + 1.420 + 1.421 + void rescale() 1.422 + { 1.423 + int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq; 1.424 + PPM_CONTEXT::STATE* p1, * p; 1.425 + PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats); 1.426 + for (p = FoundState; p != stats; p--) 1.427 + _PPMD_SWAP(p[0], p[-1]); 1.428 + stats->Freq += 4; 1.429 + MinContext->SummFreq += 4; 1.430 + EscFreq = MinContext->SummFreq - p->Freq; 1.431 + Adder = (OrderFall != 0); 1.432 + p->Freq = (Byte)((p->Freq + Adder) >> 1); 1.433 + MinContext->SummFreq = p->Freq; 1.434 + do 1.435 + { 1.436 + EscFreq -= (++p)->Freq; 1.437 + p->Freq = (Byte)((p->Freq + Adder) >> 1); 1.438 + MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq); 1.439 + if (p[0].Freq > p[-1].Freq) 1.440 + { 1.441 + PPM_CONTEXT::STATE tmp = *(p1 = p); 1.442 + do 1.443 + { 1.444 + p1[0] = p1[-1]; 1.445 + } 1.446 + while (--p1 != stats && tmp.Freq > p1[-1].Freq); 1.447 + *p1 = tmp; 1.448 + } 1.449 + } 1.450 + while ( --i ); 1.451 + if (p->Freq == 0) 1.452 + { 1.453 + do { i++; } while ((--p)->Freq == 0); 1.454 + EscFreq += i; 1.455 + MinContext->NumStats = (UInt16)(MinContext->NumStats - i); 1.456 + if (MinContext->NumStats == 1) 1.457 + { 1.458 + PPM_CONTEXT::STATE tmp = *stats; 1.459 + do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1); 1.460 + SubAllocator.FreeUnits(stats, (OldNS+1) >> 1); 1.461 + *(FoundState = &MinContext->oneState()) = tmp; return; 1.462 + } 1.463 + } 1.464 + EscFreq -= (EscFreq >> 1); 1.465 + MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq); 1.466 + int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1; 1.467 + if (n0 != n1) 1.468 + MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1)); 1.469 + FoundState = GetState(MinContext->Stats); 1.470 + } 1.471 + 1.472 + void NextContext() 1.473 + { 1.474 + PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor()); 1.475 + if (!OrderFall && (Byte *)c > SubAllocator.pText) 1.476 + MinContext = MaxContext = c; 1.477 + else 1.478 + { 1.479 + UpdateModel(); 1.480 + if (EscCount == 0) 1.481 + ClearMask(); 1.482 + } 1.483 + } 1.484 +}; 1.485 + 1.486 +// Tabulated escapes for exponential symbol distribution 1.487 +const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 1.488 +#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT)) 1.489 + 1.490 +}} 1.491 + 1.492 +#endif