public static void Ppmd7_UpdateBin(CPpmd7 p) { p.FoundState->Freq = (byte)(p.FoundState->Freq + (p.FoundState->Freq < 128 ? 1 : 0)); p.PrevSuccess = 1; p.RunLength++; NextContext(p); }
private static void *RemoveNode(CPpmd7 p, uint indx) { CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p.FreeList[indx]); p.FreeList[indx] = *node; return(node); }
private static void *AllocUnitsRare(CPpmd7 p, uint indx) { uint i; void *retVal; if (p.GlueCount == 0) { GlueFreeBlocks(p); if (p.FreeList[indx].Value != 0) { return(RemoveNode(p, indx)); } } i = indx; do { if (++i == PPMD_NUM_INDEXES) { uint numBytes = U2B(I2U(p, indx)); p.GlueCount--; return(((uint)(p.UnitsStart - p.Text) > numBytes) ? (p.UnitsStart -= numBytes) : null); } }while (p.FreeList[i].Value == 0); retVal = RemoveNode(p, i); SplitBlock(p, retVal, i, indx); return(retVal); }
public static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 p, uint numMasked, uint *escFreq) { CPpmd_See *see; uint nonMasked = p.MinContext->NumStats - numMasked; if (p.MinContext->NumStats != 256) { see = p.See[p.NS2Indx[nonMasked - 1]] + (nonMasked < (uint)SUFFIX(p, p.MinContext)->NumStats - p.MinContext->NumStats ? 1 : 0) + 2 * (p.MinContext->SummFreq < 11 * p.MinContext->NumStats ? 1 : 0) + 4 * (numMasked > nonMasked ? 1 : 0) + p.HiBitsFlag; { uint r = ((uint)see->Summ >> see->Shift); see->Summ = (ushort)(see->Summ - r); *escFreq = r + ((r == 0) ? 1u : 0u); } } else { see = p.DummySee; *escFreq = 1; } return(see); }
public static void Ppmd7_Init(CPpmd7 p, uint maxOrder) { p.MaxOrder = maxOrder; RestartModel(p); p.DummySee->Shift = PPMD_PERIOD_BITS; p.DummySee->Summ = 0; /* unused */ p.DummySee->Count = 64; /* unused */ }
public static void Ppmd7_Construct(CPpmd7 p) { uint i, k, m; p.Base = null; for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) { uint step = (i >= 12 ? 4 : (i >> 2) + 1); do { p.Units2Indx[k++] = (byte)i; } while (--step != 0); p.Indx2Units[i] = (byte)k; } p.NS2BSIndx[0] = (0 << 1); p.NS2BSIndx[1] = (1 << 1); //memset(p.NS2BSIndx + 2, (2 << 1), 9); for (i = 0; i < 9; i++) { p.NS2BSIndx[i + 2] = 2 << 1; } //memset(p.NS2BSIndx + 11, (3 << 1), 256 - 11); for (i = 0; i < 256 - 11; i++) { p.NS2BSIndx[i + 11] = 3 << 1; } for (i = 0; i < 3; i++) { p.NS2Indx[i] = (byte)i; } for (m = i, k = 1; i < 256; i++) { p.NS2Indx[i] = (byte)m; if (--k == 0) { k = (++m) - 2; } } //memset(p.HB2Flag, 0, 0x40); for (i = 0; i < 0x40; i++) { p.HB2Flag[i] = 0; } //memset(p.HB2Flag + 0x40, 8, 0x100 - 0x40); for (i = 0; i < 0x100 - 0x40; i++) { p.HB2Flag[i + 0x40] = 8; } }
private static void RestartModel(CPpmd7 p) { uint i, k, m; //memset(p.FreeList, 0, sizeof(p.FreeList)); for (i = 0; i < p.FreeList.Length; i++) { p.FreeList[i] = default(CPpmd_Void_Ref); } p.Text = p.Base + p.AlignOffset; p.HiUnit = p.Text + p.Size; p.LoUnit = p.UnitsStart = p.HiUnit - p.Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; p.GlueCount = 0; p.OrderFall = p.MaxOrder; p.RunLength = p.InitRL = -(Int32)((p.MaxOrder < 12) ? p.MaxOrder : 12) - 1; p.PrevSuccess = 0; p.MinContext = p.MaxContext = (CPpmd7_Context *)(p.HiUnit -= UNIT_SIZE); /* AllocContext(p); */ p.MinContext->Suffix = default(CPpmd7_Context_Ref); p.MinContext->NumStats = 256; p.MinContext->SummFreq = 256 + 1; p.FoundState = (CPpmd_State *)p.LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ p.LoUnit += U2B(256 / 2); p.MinContext->Stats = REF(p, p.FoundState); for (i = 0; i < 256; i++) { CPpmd_State *s = &p.FoundState[i]; s->Symbol = (byte)i; s->Freq = 1; SetSuccessor(s, default(CPpmd_Void_Ref)); } for (i = 0; i < 128; i++) { for (k = 0; k < 8; k++) { ushort *dest = p.BinSumm[i] + k; ushort val = (ushort)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); for (m = 0; m < 64; m += 8) { dest[m] = val; } } } for (i = 0; i < 25; i++) { for (k = 0; k < 16; k++) { CPpmd_See *s = &p.See[i][k]; s->Summ = (ushort)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); s->Count = 4; } } }
public static void Ppmd7_Update2(CPpmd7 p) { p.MinContext->SummFreq += 4; if ((p.FoundState->Freq += 4) > MAX_FREQ) { Rescale(p); } p.RunLength = p.InitRL; UpdateModel(p); }
private static void SplitBlock(CPpmd7 p, void *ptr, uint oldIndx, uint newIndx) { uint i; uint nu = (uint)I2U(p, oldIndx) - (uint)I2U(p, newIndx); ptr = (byte *)ptr + U2B(I2U(p, newIndx)); if (I2U(p, i = U2I(p, nu)) != nu) { uint k = I2U(p, --i); InsertNode(p, ((byte *)ptr) + U2B(k), nu - k - 1); } InsertNode(p, ptr, i); }
public static void Ppmd7_Update1_0(CPpmd7 p) { var bit = (2 * p.FoundState->Freq > p.MinContext->SummFreq) ? (byte)1 : (byte)0; p.PrevSuccess = bit; p.RunLength += bit; p.MinContext->SummFreq += 4; if ((p.FoundState->Freq += 4) > MAX_FREQ) { Rescale(p); } NextContext(p); }
private static void NextContext(CPpmd7 p) { CPpmd7_Context *c = CTX(p, SUCCESSOR(p.FoundState)); if (p.OrderFall == 0 && (byte *)c > p.Text) { p.MinContext = p.MaxContext = c; } else { UpdateModel(p); } }
public static bool Ppmd7_Alloc(CPpmd7 p, uint size, ISzAlloc alloc) { if (p.Base == null || p.Size != size) { Ppmd7_Free(p, alloc); p.AlignOffset = 4 - (size & 3); if ((p.Base = (byte *)alloc.Alloc(alloc, p.AlignOffset + size + UNIT_SIZE)) == null) { return(false); } p.Size = size; } return(true); }
private static void *AllocUnits(CPpmd7 p, uint indx) { uint numBytes; if (p.FreeList[indx].Value != 0) { return(RemoveNode(p, indx)); } numBytes = U2B(I2U(p, indx)); if (numBytes <= (uint)(p.HiUnit - p.LoUnit)) { void *retVal = p.LoUnit; p.LoUnit += numBytes; return(retVal); } return(AllocUnitsRare(p, indx)); }
public static void Ppmd7_Update1(CPpmd7 p) { CPpmd_State *s = p.FoundState; s->Freq += 4; p.MinContext->SummFreq += 4; if (s[0].Freq > s[-1].Freq) { SwapStates(&s[0], &s[-1]); p.FoundState = --s; if (s->Freq > MAX_FREQ) { Rescale(p); } } NextContext(p); }
private static void *ShrinkUnits(CPpmd7 p, void *oldPtr, uint oldNU, uint newNU) { uint i0 = U2I(p, oldNU); uint i1 = U2I(p, newNU); if (i0 == i1) { return(oldPtr); } if (p.FreeList[i1].Value != 0) { void *ptr = RemoveNode(p, i1); MyMem12Cpy(ptr, oldPtr, newNU); InsertNode(p, oldPtr, i0); return(ptr); } SplitBlock(p, oldPtr, i0, i1); return(oldPtr); }
private static CPpmd_State *STATS(CPpmd7 p, CPpmd7_Context *ctx) => Ppmd7_GetStats(p, ctx);
private static byte I2U(CPpmd7 p, uint indx) => p.Indx2Units[indx];
private static byte U2I(CPpmd7 p, uint nu) => p.Units2Indx[nu - 1];
private static CPpmd_Void_Ref REF(CPpmd7 p, void *ptr) => new CPpmd_Void_Ref((uint)((byte *)ptr - p.Base));
private static void GlueFreeBlocks(CPpmd7 p) { CPpmd7_Node_Ref head = new CPpmd7_Node_Ref(p.AlignOffset + p.Size); CPpmd7_Node_Ref n = head; uint i; p.GlueCount = 255; /* create doubly-linked list of free blocks */ for (i = 0; i < PPMD_NUM_INDEXES; i++) { ushort nu = I2U(p, i); CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p.FreeList[i]; p.FreeList[i] = default(CPpmd_Void_Ref); while (next.Value != 0) { CPpmd7_Node *node = NODE(p, next); node->Next = n; n = NODE(p, n)->Prev = next; next = *(CPpmd7_Node_Ref *)node; node->Stamp = 0; node->NU = (ushort)nu; } } NODE(p, head)->Stamp = 1; NODE(p, head)->Next = n; NODE(p, n)->Prev = head; if (p.LoUnit != p.HiUnit) { ((CPpmd7_Node *)p.LoUnit)->Stamp = 1; } /* Glue free blocks */ while (n != head) { CPpmd7_Node *node = NODE(p, n); uint nu = (uint)node->NU; for (;;) { CPpmd7_Node *node2 = NODE(p, n) + nu; nu += node2->NU; if (node2->Stamp != 0 || nu >= 0x10000) { break; } NODE(p, node2->Prev)->Next = node2->Next; NODE(p, node2->Next)->Prev = node2->Prev; node->NU = (ushort)nu; } n = node->Next; } /* Fill lists of free blocks */ for (n = NODE(p, head)->Next; n != head;) { CPpmd7_Node * node = NODE(p, n); uint nu; CPpmd7_Node_Ref next = node->Next; for (nu = node->NU; nu > 128; nu -= 128, node += 128) { InsertNode(p, node, PPMD_NUM_INDEXES - 1); } if (I2U(p, i = U2I(p, nu)) != nu) { uint k = I2U(p, --i); InsertNode(p, node + k, nu - k - 1); } InsertNode(p, node, i); n = next; } }
private static CPpmd_State_Ref STATS_REF(CPpmd7 p, void *ptr) => REF(p, ptr);
private static void InsertNode(CPpmd7 p, void *node, uint indx) { *((CPpmd_Void_Ref *)node) = p.FreeList[indx]; p.FreeList[indx] = REF(p, node); }
private static CPpmd7_Context *CTX(CPpmd7 p, CPpmd7_Context_Ref r) => Ppmd7_GetContext(p, r);
public static void Ppmd7_Free(CPpmd7 p, ISzAlloc alloc) { alloc.Free(alloc, (IntPtr)p.Base); p.Size = 0; p.Base = null; }
private static CPpmd7_Context *CreateSuccessors(CPpmd7 p, bool skip) { CPpmd_State upState; CPpmd7_Context *c = p.MinContext; CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p.FoundState); CPpmd_State *[] ps = new CPpmd_State *[PPMD7_MAX_ORDER]; uint numPs = 0; if (!skip) { ps[numPs++] = p.FoundState; } while (c->Suffix.Value != 0) { CPpmd_Void_Ref successor; CPpmd_State * s; c = SUFFIX(p, c); if (c->NumStats != 1) { for (s = STATS(p, c); s->Symbol != p.FoundState->Symbol; s++) { ; } } else { s = ONE_STATE(c); } successor = SUCCESSOR(s); if (successor != upBranch) { c = CTX(p, successor); if (numPs == 0) { return(c); } break; } ps[numPs++] = s; } upState.Symbol = *(byte *)Ppmd7_GetPtr(p, upBranch); SetSuccessor(&upState, new CPpmd_Byte_Ref(upBranch.Value + 1)); if (c->NumStats == 1) { upState.Freq = ONE_STATE(c)->Freq; } else { uint cf, s0; CPpmd_State *s; for (s = STATS(p, c); s->Symbol != upState.Symbol; s++) { ; } cf = s->Freq - 1u; s0 = (uint)c->SummFreq - (uint)c->NumStats - cf; upState.Freq = (byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0 ? 1u : 0u) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); } do { /* Create Child */ CPpmd7_Context *c1; /* = AllocContext(p); */ if (p.HiUnit != p.LoUnit) { c1 = (CPpmd7_Context *)(p.HiUnit -= UNIT_SIZE); } else if (p.FreeList[0].Value != 0) { c1 = (CPpmd7_Context *)RemoveNode(p, 0); } else { c1 = (CPpmd7_Context *)AllocUnitsRare(p, 0); if (c1 == null) { return(null); } } c1->NumStats = 1; *ONE_STATE(c1) = upState; c1->Suffix = REF(p, c); SetSuccessor(ps[--numPs], REF(p, c1)); c = c1; }while (numPs != 0); return(c); }
private static CPpmd7_Context *SUFFIX(CPpmd7 p, CPpmd7_Context *ctx) => CTX(p, ctx->Suffix);
private static CPpmd7_Node *NODE(CPpmd7 p, CPpmd7_Node_Ref offs) => (CPpmd7_Node *)(p.Base + offs.Value);
private static void UpdateModel(CPpmd7 p) { CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p.FoundState); CPpmd7_Context *c; uint s0, ns; if (p.FoundState->Freq < MAX_FREQ / 4 && p.MinContext->Suffix.Value != 0) { c = SUFFIX(p, p.MinContext); if (c->NumStats == 1) { CPpmd_State *s = ONE_STATE(c); if (s->Freq < 32) { s->Freq++; } } else { CPpmd_State *s = STATS(p, c); if (s->Symbol != p.FoundState->Symbol) { do { s++; } while (s->Symbol != p.FoundState->Symbol); if (s[0].Freq >= s[-1].Freq) { SwapStates(&s[0], &s[-1]); s--; } } if (s->Freq < MAX_FREQ - 9) { s->Freq += 2; c->SummFreq += 2; } } } if (p.OrderFall == 0) { p.MinContext = p.MaxContext = CreateSuccessors(p, true); if (p.MinContext == null) { RestartModel(p); return; } SetSuccessor(p.FoundState, REF(p, p.MinContext)); return; } *p.Text++ = p.FoundState->Symbol; successor = REF(p, p.Text); if (p.Text >= p.UnitsStart) { RestartModel(p); return; } if (fSuccessor.Value != 0) { if (fSuccessor.Value <= successor.Value) { CPpmd7_Context *cs = CreateSuccessors(p, false); if (cs == null) { RestartModel(p); return; } fSuccessor = REF(p, cs); } if (--p.OrderFall == 0) { successor = fSuccessor; p.Text -= (p.MaxContext != p.MinContext) ? 1 : 0; } } else { SetSuccessor(p.FoundState, successor); fSuccessor = REF(p, p.MinContext); } s0 = p.MinContext->SummFreq - (ns = p.MinContext->NumStats) - (p.FoundState->Freq - 1u); for (c = p.MaxContext; c != p.MinContext; c = SUFFIX(p, c)) { uint ns1; uint cf, sf; if ((ns1 = c->NumStats) != 1) { if ((ns1 & 1) == 0) { /* Expand for one UNIT */ uint oldNU = ns1 >> 1; uint i = U2I(p, oldNU); if (i != U2I(p, oldNU + 1)) { void *ptr = AllocUnits(p, i + 1); void *oldPtr; if (ptr == null) { RestartModel(p); return; } oldPtr = STATS(p, c); MyMem12Cpy(ptr, oldPtr, oldNU); InsertNode(p, oldPtr, i); c->Stats = STATS_REF(p, ptr); } } c->SummFreq = (ushort)(c->SummFreq + (2 * ns1 < ns ? 1u : 0u) + 2 * ((4 * ns1 <= ns ? 1u : 0u) & (c->SummFreq <= 8 * ns1 ? 1u : 0u))); } else { CPpmd_State *s = (CPpmd_State *)AllocUnits(p, 0); if (s == null) { RestartModel(p); return; } *s = *ONE_STATE(c); c->Stats = REF(p, s); if (s->Freq < MAX_FREQ / 4 - 1) { s->Freq <<= 1; } else { s->Freq = MAX_FREQ - 4; } c->SummFreq = (ushort)(s->Freq + p.InitEsc + (ns > 3 ? 1u : 0u)); } cf = 2 * (uint)p.FoundState->Freq * (c->SummFreq + 6u); sf = (uint)s0 + c->SummFreq; if (cf < 6 * sf) { cf = 1 + (cf > sf ? 1u : 0u) + (cf >= 4 * sf ? 1u : 0u); c->SummFreq += 3; } else { cf = 4 + (cf >= 9 * sf ? 1u : 0u) + (cf >= 12 * sf ? 1u : 0u) + (cf >= 15 * sf ? 1u : 0u); c->SummFreq = (ushort)(c->SummFreq + cf); } { CPpmd_State *s = STATS(p, c) + ns1; SetSuccessor(s, successor); s->Symbol = p.FoundState->Symbol; s->Freq = (byte)cf; c->NumStats = (ushort)(ns1 + 1); } } p.MaxContext = p.MinContext = CTX(p, fSuccessor); }
private static void Rescale(CPpmd7 p) { uint i, adder, sumFreq, escFreq; CPpmd_State *stats = STATS(p, p.MinContext); CPpmd_State *s = p.FoundState; { CPpmd_State tmp = *s; for (; s != stats; s--) { s[0] = s[-1]; } *s = tmp; } escFreq = (uint)p.MinContext->SummFreq - s->Freq; s->Freq += 4; adder = (p.OrderFall != 0) ? 1u : 0u; s->Freq = (byte)((s->Freq + adder) >> 1); sumFreq = s->Freq; i = (uint)p.MinContext->NumStats - 1; do { escFreq -= (++s)->Freq; s->Freq = (byte)((s->Freq + adder) >> 1); sumFreq += s->Freq; if (s[0].Freq > s[-1].Freq) { CPpmd_State *s1 = s; CPpmd_State tmp = *s1; do { s1[0] = s1[-1]; }while (--s1 != stats && tmp.Freq > s1[-1].Freq); *s1 = tmp; } }while (--i != 0); if (s->Freq == 0) { uint numStats = p.MinContext->NumStats; uint n0, n1; do { i++; } while ((--s)->Freq == 0); escFreq += i; p.MinContext->NumStats = (ushort)(p.MinContext->NumStats - i); if (p.MinContext->NumStats == 1) { CPpmd_State tmp = *stats; do { tmp.Freq = (byte)(tmp.Freq - (tmp.Freq >> 1)); escFreq >>= 1; }while (escFreq > 1); InsertNode(p, stats, U2I(p, ((numStats + 1) >> 1))); *(p.FoundState = ONE_STATE(p.MinContext)) = tmp; return; } n0 = (numStats + 1) >> 1; n1 = ((uint)p.MinContext->NumStats + 1) >> 1; if (n0 != n1) { p.MinContext->Stats = STATS_REF(p, ShrinkUnits(p, stats, n0, n1)); } } p.MinContext->SummFreq = (ushort)(sumFreq + escFreq - (escFreq >> 1)); p.FoundState = STATS(p, p.MinContext); }