1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* Ppmd7Enc.c -- PPMdH Encoder 2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync2010-03-12 : Igor Pavlov : Public domain 3baa3858d3f5d128a5c8466b700098109edcad5f2repo syncThis code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 5cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "Precomp.h" 6cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Ppmd7.h" 8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kTopValue (1 << 24) 10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 11baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) 12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Low = 0; 14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range = 0xFFFFFFFF; 15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Cache = 0; 16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->CacheSize = 1; 17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 19baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) 20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) 22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Byte temp = p->Cache; 24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do 25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); 27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync temp = 0xFF; 28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while(--p->CacheSize != 0); 30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Cache = (Byte)((UInt32)p->Low >> 24); 31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->CacheSize++; 33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Low = (UInt32)p->Low << 8; 34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 36baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) 37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Low += start * (p->Range /= total); 39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range *= size; 40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (p->Range < kTopValue) 41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range <<= 8; 43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_ShiftLow(p); 44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 47baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) 48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range = (p->Range >> 14) * size0; 50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (p->Range < kTopValue) 51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range <<= 8; 53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_ShiftLow(p); 54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 57baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) 58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 newBound = (p->Range >> 14) * size0; 60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Low += newBound; 61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range -= newBound; 62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (p->Range < kTopValue) 63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->Range <<= 8; 65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_ShiftLow(p); 66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 69baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) 70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync unsigned i; 72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (i = 0; i < 5; i++) 73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_ShiftLow(p); 74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define MASK(sym) ((signed char *)charMask)[sym] 78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 79baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) 80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync size_t charMask[256 / sizeof(size_t)]; 82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (p->MinContext->NumStats != 1) 83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 sum; 86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync unsigned i; 87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (s->Symbol == symbol) 88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); 90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->FoundState = s; 91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Ppmd7_Update1_0(p); 92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return; 93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->PrevSuccess = 0; 95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sum = s->Freq; 96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync i = p->MinContext->NumStats - 1; 97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do 98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if ((++s)->Symbol == symbol) 100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); 102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->FoundState = s; 103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Ppmd7_Update1(p); 104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return; 105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sum += s->Freq; 107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (--i); 109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync PPMD_SetAllBitsIn256Bytes(charMask); 112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync MASK(s->Symbol) = 0; 113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync i = p->MinContext->NumStats - 1; 114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do { MASK((--s)->Symbol) = 0; } while (--i); 115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); 116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt16 *prob = Ppmd7_GetBinSumm(p); 120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); 121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (s->Symbol == symbol) 122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_EncodeBit_0(rc, *prob); 124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->FoundState = s; 126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Ppmd7_UpdateBin(p); 127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return; 128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_EncodeBit_1(rc, *prob); 132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync PPMD_SetAllBitsIn256Bytes(charMask); 135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync MASK(s->Symbol) = 0; 136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->PrevSuccess = 0; 137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (;;) 140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 escFreq; 142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CPpmd_See *see; 143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CPpmd_State *s; 144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 sum; 145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync unsigned i, numMasked = p->MinContext->NumStats; 146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do 147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->OrderFall++; 149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (!p->MinContext->Suffix) 150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return; /* EndMarker (symbol = -1) */ 151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (p->MinContext->NumStats == numMasked); 154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); 156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync s = Ppmd7_GetStats(p, p->MinContext); 157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sum = 0; 158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync i = p->MinContext->NumStats; 159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do 160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int cur = s->Symbol; 162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (cur == symbol) 163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 low = sum; 165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CPpmd_State *s1 = s; 166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync do 167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sum += (s->Freq & (int)(MASK(s->Symbol))); 169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync s++; 170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (--i); 172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); 173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Ppmd_See_Update(see); 174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p->FoundState = s1; 175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Ppmd7_Update2(p); 176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return; 177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sum += (s->Freq & (int)(MASK(cur))); 179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync MASK(cur) = 0; 180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync s++; 181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (--i); 183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); 185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync see->Summ = (UInt16)(see->Summ + sum + escFreq); 186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 188