1 /* Ppmd8Enc.c -- PPMdI Encoder
\r
2 2010-04-16 : Igor Pavlov : Public domain
\r
3 This code is based on:
\r
4 PPMd var.I (2002): Dmitry Shkarin : Public domain
\r
5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
\r
9 #define kTop (1 << 24)
\r
10 #define kBot (1 << 15)
\r
12 void Ppmd8_RangeEnc_FlushData(CPpmd8 *p)
\r
15 for (i = 0; i < 4; i++, p->Low <<= 8 )
\r
16 p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));
\r
19 static void RangeEnc_Normalize(CPpmd8 *p)
\r
21 while ((p->Low ^ (p->Low + p->Range)) < kTop ||
\r
22 (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
\r
24 p->Stream.Out->Write(p->Stream.Out, (Byte)(p->Low >> 24));
\r
30 static void RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)
\r
32 p->Low += start * (p->Range /= total);
\r
34 RangeEnc_Normalize(p);
\r
37 static void RangeEnc_EncodeBit_0(CPpmd8 *p, UInt32 size0)
\r
41 RangeEnc_Normalize(p);
\r
44 static void RangeEnc_EncodeBit_1(CPpmd8 *p, UInt32 size0)
\r
46 p->Low += size0 * (p->Range >>= 14);
\r
47 p->Range *= ((1 << 14) - size0);
\r
48 RangeEnc_Normalize(p);
\r
52 #define MASK(sym) ((signed char *)charMask)[sym]
\r
54 void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
\r
56 size_t charMask[256 / sizeof(size_t)];
\r
57 if (p->MinContext->NumStats != 0)
\r
59 CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
\r
62 if (s->Symbol == symbol)
\r
64 RangeEnc_Encode(p, 0, s->Freq, p->MinContext->SummFreq);
\r
71 i = p->MinContext->NumStats;
\r
74 if ((++s)->Symbol == symbol)
\r
76 RangeEnc_Encode(p, sum, s->Freq, p->MinContext->SummFreq);
\r
85 PPMD_SetAllBitsIn256Bytes(charMask);
\r
86 MASK(s->Symbol) = 0;
\r
87 i = p->MinContext->NumStats;
\r
88 do { MASK((--s)->Symbol) = 0; } while (--i);
\r
89 RangeEnc_Encode(p, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
\r
93 UInt16 *prob = Ppmd8_GetBinSumm(p);
\r
94 CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);
\r
95 if (s->Symbol == symbol)
\r
97 RangeEnc_EncodeBit_0(p, *prob);
\r
98 *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
\r
100 Ppmd8_UpdateBin(p);
\r
105 RangeEnc_EncodeBit_1(p, *prob);
\r
106 *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
\r
107 p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
\r
108 PPMD_SetAllBitsIn256Bytes(charMask);
\r
109 MASK(s->Symbol) = 0;
\r
110 p->PrevSuccess = 0;
\r
119 unsigned i, numMasked = p->MinContext->NumStats;
\r
123 if (!p->MinContext->Suffix)
\r
124 return; /* EndMarker (symbol = -1) */
\r
125 p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
\r
127 while (p->MinContext->NumStats == numMasked);
\r
129 see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);
\r
130 s = Ppmd8_GetStats(p, p->MinContext);
\r
132 i = p->MinContext->NumStats + 1;
\r
135 int cur = s->Symbol;
\r
139 CPpmd_State *s1 = s;
\r
142 sum += (s->Freq & (int)(MASK(s->Symbol)));
\r
146 RangeEnc_Encode(p, low, s1->Freq, sum + escFreq);
\r
147 Ppmd_See_Update(see);
\r
148 p->FoundState = s1;
\r
152 sum += (s->Freq & (int)(MASK(cur)));
\r
158 RangeEnc_Encode(p, sum, escFreq, sum + escFreq);
\r
159 see->Summ = (UInt16)(see->Summ + sum + escFreq);
\r