1370b324cSopenharmony_ci/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder 2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain 3370b324cSopenharmony_ciThis code is based on: 4370b324cSopenharmony_ci PPMd var.H (2001): Dmitry Shkarin : Public domain */ 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "Precomp.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_ci#include "Ppmd7.h" 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci#define kTopValue ((UInt32)1 << 24) 12370b324cSopenharmony_ci 13370b324cSopenharmony_ci#define R (&p->rc.enc) 14370b324cSopenharmony_ci 15370b324cSopenharmony_civoid Ppmd7z_Init_RangeEnc(CPpmd7 *p) 16370b324cSopenharmony_ci{ 17370b324cSopenharmony_ci R->Low = 0; 18370b324cSopenharmony_ci R->Range = 0xFFFFFFFF; 19370b324cSopenharmony_ci R->Cache = 0; 20370b324cSopenharmony_ci R->CacheSize = 1; 21370b324cSopenharmony_ci} 22370b324cSopenharmony_ci 23370b324cSopenharmony_ciZ7_NO_INLINE 24370b324cSopenharmony_cistatic void Ppmd7z_RangeEnc_ShiftLow(CPpmd7 *p) 25370b324cSopenharmony_ci{ 26370b324cSopenharmony_ci if ((UInt32)R->Low < (UInt32)0xFF000000 || (unsigned)(R->Low >> 32) != 0) 27370b324cSopenharmony_ci { 28370b324cSopenharmony_ci Byte temp = R->Cache; 29370b324cSopenharmony_ci do 30370b324cSopenharmony_ci { 31370b324cSopenharmony_ci IByteOut_Write(R->Stream, (Byte)(temp + (Byte)(R->Low >> 32))); 32370b324cSopenharmony_ci temp = 0xFF; 33370b324cSopenharmony_ci } 34370b324cSopenharmony_ci while (--R->CacheSize != 0); 35370b324cSopenharmony_ci R->Cache = (Byte)((UInt32)R->Low >> 24); 36370b324cSopenharmony_ci } 37370b324cSopenharmony_ci R->CacheSize++; 38370b324cSopenharmony_ci R->Low = (UInt32)((UInt32)R->Low << 8); 39370b324cSopenharmony_ci} 40370b324cSopenharmony_ci 41370b324cSopenharmony_ci#define RC_NORM_BASE(p) if (R->Range < kTopValue) { R->Range <<= 8; Ppmd7z_RangeEnc_ShiftLow(p); 42370b324cSopenharmony_ci#define RC_NORM_1(p) RC_NORM_BASE(p) } 43370b324cSopenharmony_ci#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} 44370b324cSopenharmony_ci 45370b324cSopenharmony_ci// we must use only one type of Normalization from two: LOCAL or REMOTE 46370b324cSopenharmony_ci#define RC_NORM_LOCAL(p) // RC_NORM(p) 47370b324cSopenharmony_ci#define RC_NORM_REMOTE(p) RC_NORM(p) 48370b324cSopenharmony_ci 49370b324cSopenharmony_ci/* 50370b324cSopenharmony_ci#define Ppmd7z_RangeEnc_Encode(p, start, _size_) \ 51370b324cSopenharmony_ci { UInt32 size = _size_; \ 52370b324cSopenharmony_ci R->Low += start * R->Range; \ 53370b324cSopenharmony_ci R->Range *= size; \ 54370b324cSopenharmony_ci RC_NORM_LOCAL(p); } 55370b324cSopenharmony_ci*/ 56370b324cSopenharmony_ci 57370b324cSopenharmony_ciZ7_FORCE_INLINE 58370b324cSopenharmony_ci// Z7_NO_INLINE 59370b324cSopenharmony_cistatic void Ppmd7z_RangeEnc_Encode(CPpmd7 *p, UInt32 start, UInt32 size) 60370b324cSopenharmony_ci{ 61370b324cSopenharmony_ci R->Low += start * R->Range; 62370b324cSopenharmony_ci R->Range *= size; 63370b324cSopenharmony_ci RC_NORM_LOCAL(p) 64370b324cSopenharmony_ci} 65370b324cSopenharmony_ci 66370b324cSopenharmony_civoid Ppmd7z_Flush_RangeEnc(CPpmd7 *p) 67370b324cSopenharmony_ci{ 68370b324cSopenharmony_ci unsigned i; 69370b324cSopenharmony_ci for (i = 0; i < 5; i++) 70370b324cSopenharmony_ci Ppmd7z_RangeEnc_ShiftLow(p); 71370b324cSopenharmony_ci} 72370b324cSopenharmony_ci 73370b324cSopenharmony_ci 74370b324cSopenharmony_ci 75370b324cSopenharmony_ci#define RC_Encode(start, size) Ppmd7z_RangeEnc_Encode(p, start, size); 76370b324cSopenharmony_ci#define RC_EncodeFinal(start, size) RC_Encode(start, size) RC_NORM_REMOTE(p) 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) 79370b324cSopenharmony_ci#define SUFFIX(ctx) CTX((ctx)->Suffix) 80370b324cSopenharmony_ci// typedef CPpmd7_Context * CTX_PTR; 81370b324cSopenharmony_ci#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) 82370b324cSopenharmony_ci 83370b324cSopenharmony_civoid Ppmd7_UpdateModel(CPpmd7 *p); 84370b324cSopenharmony_ci 85370b324cSopenharmony_ci#define MASK(sym) ((unsigned char *)charMask)[sym] 86370b324cSopenharmony_ci 87370b324cSopenharmony_ciZ7_FORCE_INLINE 88370b324cSopenharmony_cistatic 89370b324cSopenharmony_civoid Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol) 90370b324cSopenharmony_ci{ 91370b324cSopenharmony_ci size_t charMask[256 / sizeof(size_t)]; 92370b324cSopenharmony_ci 93370b324cSopenharmony_ci if (p->MinContext->NumStats != 1) 94370b324cSopenharmony_ci { 95370b324cSopenharmony_ci CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 96370b324cSopenharmony_ci UInt32 sum; 97370b324cSopenharmony_ci unsigned i; 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci 100370b324cSopenharmony_ci 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci R->Range /= p->MinContext->Union2.SummFreq; 103370b324cSopenharmony_ci 104370b324cSopenharmony_ci if (s->Symbol == symbol) 105370b324cSopenharmony_ci { 106370b324cSopenharmony_ci // R->Range /= p->MinContext->Union2.SummFreq; 107370b324cSopenharmony_ci RC_EncodeFinal(0, s->Freq) 108370b324cSopenharmony_ci p->FoundState = s; 109370b324cSopenharmony_ci Ppmd7_Update1_0(p); 110370b324cSopenharmony_ci return; 111370b324cSopenharmony_ci } 112370b324cSopenharmony_ci p->PrevSuccess = 0; 113370b324cSopenharmony_ci sum = s->Freq; 114370b324cSopenharmony_ci i = (unsigned)p->MinContext->NumStats - 1; 115370b324cSopenharmony_ci do 116370b324cSopenharmony_ci { 117370b324cSopenharmony_ci if ((++s)->Symbol == symbol) 118370b324cSopenharmony_ci { 119370b324cSopenharmony_ci // R->Range /= p->MinContext->Union2.SummFreq; 120370b324cSopenharmony_ci RC_EncodeFinal(sum, s->Freq) 121370b324cSopenharmony_ci p->FoundState = s; 122370b324cSopenharmony_ci Ppmd7_Update1(p); 123370b324cSopenharmony_ci return; 124370b324cSopenharmony_ci } 125370b324cSopenharmony_ci sum += s->Freq; 126370b324cSopenharmony_ci } 127370b324cSopenharmony_ci while (--i); 128370b324cSopenharmony_ci 129370b324cSopenharmony_ci // R->Range /= p->MinContext->Union2.SummFreq; 130370b324cSopenharmony_ci RC_Encode(sum, p->MinContext->Union2.SummFreq - sum) 131370b324cSopenharmony_ci 132370b324cSopenharmony_ci p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); 133370b324cSopenharmony_ci PPMD_SetAllBitsIn256Bytes(charMask) 134370b324cSopenharmony_ci // MASK(s->Symbol) = 0; 135370b324cSopenharmony_ci // i = p->MinContext->NumStats - 1; 136370b324cSopenharmony_ci // do { MASK((--s)->Symbol) = 0; } while (--i); 137370b324cSopenharmony_ci { 138370b324cSopenharmony_ci CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); 139370b324cSopenharmony_ci MASK(s->Symbol) = 0; 140370b324cSopenharmony_ci do 141370b324cSopenharmony_ci { 142370b324cSopenharmony_ci unsigned sym0 = s2[0].Symbol; 143370b324cSopenharmony_ci unsigned sym1 = s2[1].Symbol; 144370b324cSopenharmony_ci s2 += 2; 145370b324cSopenharmony_ci MASK(sym0) = 0; 146370b324cSopenharmony_ci MASK(sym1) = 0; 147370b324cSopenharmony_ci } 148370b324cSopenharmony_ci while (s2 < s); 149370b324cSopenharmony_ci } 150370b324cSopenharmony_ci } 151370b324cSopenharmony_ci else 152370b324cSopenharmony_ci { 153370b324cSopenharmony_ci UInt16 *prob = Ppmd7_GetBinSumm(p); 154370b324cSopenharmony_ci CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); 155370b324cSopenharmony_ci UInt32 pr = *prob; 156370b324cSopenharmony_ci const UInt32 bound = (R->Range >> 14) * pr; 157370b324cSopenharmony_ci pr = PPMD_UPDATE_PROB_1(pr); 158370b324cSopenharmony_ci if (s->Symbol == symbol) 159370b324cSopenharmony_ci { 160370b324cSopenharmony_ci *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); 161370b324cSopenharmony_ci // RangeEnc_EncodeBit_0(p, bound); 162370b324cSopenharmony_ci R->Range = bound; 163370b324cSopenharmony_ci RC_NORM_1(p) 164370b324cSopenharmony_ci 165370b324cSopenharmony_ci // p->FoundState = s; 166370b324cSopenharmony_ci // Ppmd7_UpdateBin(p); 167370b324cSopenharmony_ci { 168370b324cSopenharmony_ci const unsigned freq = s->Freq; 169370b324cSopenharmony_ci CPpmd7_Context *c = CTX(SUCCESSOR(s)); 170370b324cSopenharmony_ci p->FoundState = s; 171370b324cSopenharmony_ci p->PrevSuccess = 1; 172370b324cSopenharmony_ci p->RunLength++; 173370b324cSopenharmony_ci s->Freq = (Byte)(freq + (freq < 128)); 174370b324cSopenharmony_ci // NextContext(p); 175370b324cSopenharmony_ci if (p->OrderFall == 0 && (const Byte *)c > p->Text) 176370b324cSopenharmony_ci p->MaxContext = p->MinContext = c; 177370b324cSopenharmony_ci else 178370b324cSopenharmony_ci Ppmd7_UpdateModel(p); 179370b324cSopenharmony_ci } 180370b324cSopenharmony_ci return; 181370b324cSopenharmony_ci } 182370b324cSopenharmony_ci 183370b324cSopenharmony_ci *prob = (UInt16)pr; 184370b324cSopenharmony_ci p->InitEsc = p->ExpEscape[pr >> 10]; 185370b324cSopenharmony_ci // RangeEnc_EncodeBit_1(p, bound); 186370b324cSopenharmony_ci R->Low += bound; 187370b324cSopenharmony_ci R->Range -= bound; 188370b324cSopenharmony_ci RC_NORM_LOCAL(p) 189370b324cSopenharmony_ci 190370b324cSopenharmony_ci PPMD_SetAllBitsIn256Bytes(charMask) 191370b324cSopenharmony_ci MASK(s->Symbol) = 0; 192370b324cSopenharmony_ci p->PrevSuccess = 0; 193370b324cSopenharmony_ci } 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci for (;;) 196370b324cSopenharmony_ci { 197370b324cSopenharmony_ci CPpmd_See *see; 198370b324cSopenharmony_ci CPpmd_State *s; 199370b324cSopenharmony_ci UInt32 sum, escFreq; 200370b324cSopenharmony_ci CPpmd7_Context *mc; 201370b324cSopenharmony_ci unsigned i, numMasked; 202370b324cSopenharmony_ci 203370b324cSopenharmony_ci RC_NORM_REMOTE(p) 204370b324cSopenharmony_ci 205370b324cSopenharmony_ci mc = p->MinContext; 206370b324cSopenharmony_ci numMasked = mc->NumStats; 207370b324cSopenharmony_ci 208370b324cSopenharmony_ci do 209370b324cSopenharmony_ci { 210370b324cSopenharmony_ci p->OrderFall++; 211370b324cSopenharmony_ci if (!mc->Suffix) 212370b324cSopenharmony_ci return; /* EndMarker (symbol = -1) */ 213370b324cSopenharmony_ci mc = Ppmd7_GetContext(p, mc->Suffix); 214370b324cSopenharmony_ci i = mc->NumStats; 215370b324cSopenharmony_ci } 216370b324cSopenharmony_ci while (i == numMasked); 217370b324cSopenharmony_ci 218370b324cSopenharmony_ci p->MinContext = mc; 219370b324cSopenharmony_ci 220370b324cSopenharmony_ci // see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); 221370b324cSopenharmony_ci { 222370b324cSopenharmony_ci if (i != 256) 223370b324cSopenharmony_ci { 224370b324cSopenharmony_ci unsigned nonMasked = i - numMasked; 225370b324cSopenharmony_ci see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] 226370b324cSopenharmony_ci + p->HiBitsFlag 227370b324cSopenharmony_ci + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - i) 228370b324cSopenharmony_ci + 2 * (unsigned)(mc->Union2.SummFreq < 11 * i) 229370b324cSopenharmony_ci + 4 * (unsigned)(numMasked > nonMasked); 230370b324cSopenharmony_ci { 231370b324cSopenharmony_ci // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ 232370b324cSopenharmony_ci unsigned summ = (UInt16)see->Summ; // & 0xFFFF 233370b324cSopenharmony_ci unsigned r = (summ >> see->Shift); 234370b324cSopenharmony_ci see->Summ = (UInt16)(summ - r); 235370b324cSopenharmony_ci escFreq = r + (r == 0); 236370b324cSopenharmony_ci } 237370b324cSopenharmony_ci } 238370b324cSopenharmony_ci else 239370b324cSopenharmony_ci { 240370b324cSopenharmony_ci see = &p->DummySee; 241370b324cSopenharmony_ci escFreq = 1; 242370b324cSopenharmony_ci } 243370b324cSopenharmony_ci } 244370b324cSopenharmony_ci 245370b324cSopenharmony_ci s = Ppmd7_GetStats(p, mc); 246370b324cSopenharmony_ci sum = 0; 247370b324cSopenharmony_ci // i = mc->NumStats; 248370b324cSopenharmony_ci 249370b324cSopenharmony_ci do 250370b324cSopenharmony_ci { 251370b324cSopenharmony_ci const unsigned cur = s->Symbol; 252370b324cSopenharmony_ci if ((int)cur == symbol) 253370b324cSopenharmony_ci { 254370b324cSopenharmony_ci const UInt32 low = sum; 255370b324cSopenharmony_ci const UInt32 freq = s->Freq; 256370b324cSopenharmony_ci unsigned num2; 257370b324cSopenharmony_ci 258370b324cSopenharmony_ci Ppmd_See_UPDATE(see) 259370b324cSopenharmony_ci p->FoundState = s; 260370b324cSopenharmony_ci sum += escFreq; 261370b324cSopenharmony_ci 262370b324cSopenharmony_ci num2 = i / 2; 263370b324cSopenharmony_ci i &= 1; 264370b324cSopenharmony_ci sum += freq & (0 - (UInt32)i); 265370b324cSopenharmony_ci if (num2 != 0) 266370b324cSopenharmony_ci { 267370b324cSopenharmony_ci s += i; 268370b324cSopenharmony_ci for (;;) 269370b324cSopenharmony_ci { 270370b324cSopenharmony_ci unsigned sym0 = s[0].Symbol; 271370b324cSopenharmony_ci unsigned sym1 = s[1].Symbol; 272370b324cSopenharmony_ci s += 2; 273370b324cSopenharmony_ci sum += (s[-2].Freq & (unsigned)(MASK(sym0))); 274370b324cSopenharmony_ci sum += (s[-1].Freq & (unsigned)(MASK(sym1))); 275370b324cSopenharmony_ci if (--num2 == 0) 276370b324cSopenharmony_ci break; 277370b324cSopenharmony_ci } 278370b324cSopenharmony_ci } 279370b324cSopenharmony_ci 280370b324cSopenharmony_ci 281370b324cSopenharmony_ci R->Range /= sum; 282370b324cSopenharmony_ci RC_EncodeFinal(low, freq) 283370b324cSopenharmony_ci Ppmd7_Update2(p); 284370b324cSopenharmony_ci return; 285370b324cSopenharmony_ci } 286370b324cSopenharmony_ci sum += (s->Freq & (unsigned)(MASK(cur))); 287370b324cSopenharmony_ci s++; 288370b324cSopenharmony_ci } 289370b324cSopenharmony_ci while (--i); 290370b324cSopenharmony_ci 291370b324cSopenharmony_ci { 292370b324cSopenharmony_ci const UInt32 total = sum + escFreq; 293370b324cSopenharmony_ci see->Summ = (UInt16)(see->Summ + total); 294370b324cSopenharmony_ci 295370b324cSopenharmony_ci R->Range /= total; 296370b324cSopenharmony_ci RC_Encode(sum, escFreq) 297370b324cSopenharmony_ci } 298370b324cSopenharmony_ci 299370b324cSopenharmony_ci { 300370b324cSopenharmony_ci const CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); 301370b324cSopenharmony_ci s--; 302370b324cSopenharmony_ci MASK(s->Symbol) = 0; 303370b324cSopenharmony_ci do 304370b324cSopenharmony_ci { 305370b324cSopenharmony_ci const unsigned sym0 = s2[0].Symbol; 306370b324cSopenharmony_ci const unsigned sym1 = s2[1].Symbol; 307370b324cSopenharmony_ci s2 += 2; 308370b324cSopenharmony_ci MASK(sym0) = 0; 309370b324cSopenharmony_ci MASK(sym1) = 0; 310370b324cSopenharmony_ci } 311370b324cSopenharmony_ci while (s2 < s); 312370b324cSopenharmony_ci } 313370b324cSopenharmony_ci } 314370b324cSopenharmony_ci} 315370b324cSopenharmony_ci 316370b324cSopenharmony_ci 317370b324cSopenharmony_civoid Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim) 318370b324cSopenharmony_ci{ 319370b324cSopenharmony_ci for (; buf < lim; buf++) 320370b324cSopenharmony_ci { 321370b324cSopenharmony_ci Ppmd7z_EncodeSymbol(p, *buf); 322370b324cSopenharmony_ci } 323370b324cSopenharmony_ci} 324370b324cSopenharmony_ci 325370b324cSopenharmony_ci#undef kTopValue 326370b324cSopenharmony_ci#undef WRITE_BYTE 327370b324cSopenharmony_ci#undef RC_NORM_BASE 328370b324cSopenharmony_ci#undef RC_NORM_1 329370b324cSopenharmony_ci#undef RC_NORM 330370b324cSopenharmony_ci#undef RC_NORM_LOCAL 331370b324cSopenharmony_ci#undef RC_NORM_REMOTE 332370b324cSopenharmony_ci#undef R 333370b324cSopenharmony_ci#undef RC_Encode 334370b324cSopenharmony_ci#undef RC_EncodeFinal 335370b324cSopenharmony_ci#undef SUFFIX 336370b324cSopenharmony_ci#undef CTX 337370b324cSopenharmony_ci#undef SUCCESSOR 338370b324cSopenharmony_ci#undef MASK 339