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); } }
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 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 CPpmd_State *ONE_STATE(CPpmd7_Context *ctx) => Ppmd7Context_OneState(ctx);
private static CPpmd_State *STATS(CPpmd7 p, CPpmd7_Context *ctx) => Ppmd7_GetStats(p, ctx);