/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder 2023-04-02 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ #include "Precomp.h" #include "Ppmd7.h" #define kTop ((UInt32)1 << 24) #define kBot ((UInt32)1 << 15) #define READ_BYTE(p) IByteIn_Read((p)->Stream) BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p) { unsigned i; p->Code = 0; p->Range = 0xFFFFFFFF; p->Low = 0; for (i = 0; i < 4; i++) p->Code = (p->Code << 8) | READ_BYTE(p); return (p->Code < 0xFFFFFFFF); } #define RC_NORM(p) \ while ((p->Low ^ (p->Low + p->Range)) < kTop \ || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) { \ p->Code = (p->Code << 8) | READ_BYTE(p); \ p->Range <<= 8; p->Low <<= 8; } // we must use only one type of Normalization from two: LOCAL or REMOTE #define RC_NORM_LOCAL(p) // RC_NORM(p) #define RC_NORM_REMOTE(p) RC_NORM(p) #define R (&p->rc.dec) Z7_FORCE_INLINE // Z7_NO_INLINE static void Ppmd7a_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size) { start *= R->Range; R->Low += start; R->Code -= start; R->Range *= size; RC_NORM_LOCAL(R) } #define RC_Decode(start, size) Ppmd7a_RD_Decode(p, start, size); #define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) #define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) typedef CPpmd7_Context * CTX_PTR; #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) void Ppmd7_UpdateModel(CPpmd7 *p); #define MASK(sym) ((unsigned char *)charMask)[sym] int Ppmd7a_DecodeSymbol(CPpmd7 *p) { size_t charMask[256 / sizeof(size_t)]; if (p->MinContext->NumStats != 1) { CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); unsigned i; UInt32 count, hiCnt; const UInt32 summFreq = p->MinContext->Union2.SummFreq; if (summFreq > R->Range) return PPMD7_SYM_ERROR; count = RC_GetThreshold(summFreq); hiCnt = count; if ((Int32)(count -= s->Freq) < 0) { Byte sym; RC_DecodeFinal(0, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1_0(p); return sym; } p->PrevSuccess = 0; i = (unsigned)p->MinContext->NumStats - 1; do { if ((Int32)(count -= (++s)->Freq) < 0) { Byte sym; RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) p->FoundState = s; sym = s->Symbol; Ppmd7_Update1(p); return sym; } } while (--i); if (hiCnt >= summFreq) return PPMD7_SYM_ERROR; hiCnt -= count; RC_Decode(hiCnt, summFreq - hiCnt) p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); PPMD_SetAllBitsIn256Bytes(charMask) // i = p->MinContext->NumStats - 1; // do { MASK((--s)->Symbol) = 0; } while (--i); { CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); MASK(s->Symbol) = 0; do { unsigned sym0 = s2[0].Symbol; unsigned sym1 = s2[1].Symbol; s2 += 2; MASK(sym0) = 0; MASK(sym1) = 0; } while (s2 < s); } } else { CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); UInt16 *prob = Ppmd7_GetBinSumm(p); UInt32 pr = *prob; UInt32 size0 = (R->Range >> 14) * pr; pr = PPMD_UPDATE_PROB_1(pr); if (R->Code < size0) { Byte sym; *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); // RangeDec_DecodeBit0(size0); R->Range = size0; RC_NORM(R) // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; // Ppmd7_UpdateBin(p); { unsigned freq = s->Freq; CTX_PTR c = CTX(SUCCESSOR(s)); sym = s->Symbol; p->FoundState = s; p->PrevSuccess = 1; p->RunLength++; s->Freq = (Byte)(freq + (freq < 128)); // NextContext(p); if (p->OrderFall == 0 && (const Byte *)c > p->Text) p->MaxContext = p->MinContext = c; else Ppmd7_UpdateModel(p); } return sym; } *prob = (UInt16)pr; p->InitEsc = p->ExpEscape[pr >> 10]; // RangeDec_DecodeBit1(size0); R->Low += size0; R->Code -= size0; R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - size0; RC_NORM_LOCAL(R) PPMD_SetAllBitsIn256Bytes(charMask) MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; p->PrevSuccess = 0; } for (;;) { CPpmd_State *s, *s2; UInt32 freqSum, count, hiCnt; CPpmd_See *see; CPpmd7_Context *mc; unsigned numMasked; RC_NORM_REMOTE(R) mc = p->MinContext; numMasked = mc->NumStats; do { p->OrderFall++; if (!mc->Suffix) return PPMD7_SYM_END; mc = Ppmd7_GetContext(p, mc->Suffix); } while (mc->NumStats == numMasked); s = Ppmd7_GetStats(p, mc); { unsigned num = mc->NumStats; unsigned num2 = num / 2; num &= 1; hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); s += num; p->MinContext = mc; do { unsigned sym0 = s[0].Symbol; unsigned sym1 = s[1].Symbol; s += 2; hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); } while (--num2); } see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); freqSum += hiCnt; if (freqSum > R->Range) return PPMD7_SYM_ERROR; count = RC_GetThreshold(freqSum); if (count < hiCnt) { Byte sym; s = Ppmd7_GetStats(p, p->MinContext); hiCnt = count; // count -= s->Freq & (unsigned)(MASK(s->Symbol)); // if ((Int32)count >= 0) { for (;;) { count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; } } s--; RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq) // new (see->Summ) value can overflow over 16-bits in some rare cases Ppmd_See_UPDATE(see) p->FoundState = s; sym = s->Symbol; Ppmd7_Update2(p); return sym; } if (count >= freqSum) return PPMD7_SYM_ERROR; RC_Decode(hiCnt, freqSum - hiCnt) // We increase (see->Summ) for sum of Freqs of all non_Masked symbols. // new (see->Summ) value can overflow over 16-bits in some rare cases see->Summ = (UInt16)(see->Summ + freqSum); s = Ppmd7_GetStats(p, p->MinContext); s2 = s + p->MinContext->NumStats; do { MASK(s->Symbol) = 0; s++; } while (s != s2); } } #undef kTop #undef kBot #undef READ_BYTE #undef RC_NORM_BASE #undef RC_NORM_1 #undef RC_NORM #undef RC_NORM_LOCAL #undef RC_NORM_REMOTE #undef R #undef RC_Decode #undef RC_DecodeFinal #undef RC_GetThreshold #undef CTX #undef SUCCESSOR #undef MASK