1 /* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder
2 2023-09-07 : Igor Pavlov : Public domain
3 This code is based on:
4 PPMd var.I (2002): Dmitry Shkarin : Public domain
5 Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6
7 #include "Precomp.h"
8
9 #include "Ppmd8.h"
10
11 #define kTop ((UInt32)1 << 24)
12 #define kBot ((UInt32)1 << 15)
13
14 #define WRITE_BYTE(p) IByteOut_Write(p->Stream.Out, (Byte)(p->Low >> 24))
15
Ppmd8_Flush_RangeEnc(CPpmd8 * p)16 void Ppmd8_Flush_RangeEnc(CPpmd8 *p)
17 {
18 unsigned i;
19 for (i = 0; i < 4; i++, p->Low <<= 8 )
20 WRITE_BYTE(p);
21 }
22
23
24
25
26
27
28 #define RC_NORM(p) \
29 while ((p->Low ^ (p->Low + p->Range)) < kTop \
30 || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) \
31 { WRITE_BYTE(p); p->Range <<= 8; p->Low <<= 8; }
32
33
34
35
36
37
38
39
40
41
42
43
44
45 // we must use only one type of Normalization from two: LOCAL or REMOTE
46 #define RC_NORM_LOCAL(p) // RC_NORM(p)
47 #define RC_NORM_REMOTE(p) RC_NORM(p)
48
49 // #define RC_PRE(total) p->Range /= total;
50 // #define RC_PRE(total)
51
52 #define R p
53
54
55
56
57 Z7_FORCE_INLINE
58 // Z7_NO_INLINE
Ppmd8_RangeEnc_Encode(CPpmd8 * p,UInt32 start,UInt32 size,UInt32 total)59 static void Ppmd8_RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)
60 {
61 R->Low += start * (R->Range /= total);
62 R->Range *= size;
63 RC_NORM_LOCAL(R)
64 }
65
66
67
68
69
70
71
72
73
74
75 #define RC_Encode(start, size, total) Ppmd8_RangeEnc_Encode(p, start, size, total);
76 #define RC_EncodeFinal(start, size, total) RC_Encode(start, size, total) RC_NORM_REMOTE(p)
77
78 #define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))
79
80 // typedef CPpmd8_Context * CTX_PTR;
81 #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
82
83 void Ppmd8_UpdateModel(CPpmd8 *p);
84
85 #define MASK(sym) ((Byte *)charMask)[sym]
86
87 // Z7_FORCE_INLINE
88 // static
Ppmd8_EncodeSymbol(CPpmd8 * p,int symbol)89 void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
90 {
91 size_t charMask[256 / sizeof(size_t)];
92
93 if (p->MinContext->NumStats != 0)
94 {
95 CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
96 UInt32 sum;
97 unsigned i;
98 UInt32 summFreq = p->MinContext->Union2.SummFreq;
99
100 PPMD8_CORRECT_SUM_RANGE(p, summFreq)
101
102 // RC_PRE(summFreq);
103
104 if (s->Symbol == symbol)
105 {
106
107 RC_EncodeFinal(0, s->Freq, summFreq)
108 p->FoundState = s;
109 Ppmd8_Update1_0(p);
110 return;
111 }
112 p->PrevSuccess = 0;
113 sum = s->Freq;
114 i = p->MinContext->NumStats;
115 do
116 {
117 if ((++s)->Symbol == symbol)
118 {
119
120 RC_EncodeFinal(sum, s->Freq, summFreq)
121 p->FoundState = s;
122 Ppmd8_Update1(p);
123 return;
124 }
125 sum += s->Freq;
126 }
127 while (--i);
128
129
130 RC_Encode(sum, summFreq - sum, summFreq)
131
132
133 PPMD_SetAllBitsIn256Bytes(charMask)
134 // MASK(s->Symbol) = 0;
135 // i = p->MinContext->NumStats;
136 // do { MASK((--s)->Symbol) = 0; } while (--i);
137 {
138 CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);
139 MASK(s->Symbol) = 0;
140 do
141 {
142 const unsigned sym0 = s2[0].Symbol;
143 const unsigned sym1 = s2[1].Symbol;
144 s2 += 2;
145 MASK(sym0) = 0;
146 MASK(sym1) = 0;
147 }
148 while (s2 < s);
149 }
150 }
151 else
152 {
153 UInt16 *prob = Ppmd8_GetBinSumm(p);
154 CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);
155 UInt32 pr = *prob;
156 const UInt32 bound = (R->Range >> 14) * pr;
157 pr = PPMD_UPDATE_PROB_1(pr);
158 if (s->Symbol == symbol)
159 {
160 *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
161 // RangeEnc_EncodeBit_0(p, bound);
162 R->Range = bound;
163 RC_NORM(R)
164
165 // p->FoundState = s;
166 // Ppmd8_UpdateBin(p);
167 {
168 const unsigned freq = s->Freq;
169 CPpmd8_Context *c = CTX(SUCCESSOR(s));
170 p->FoundState = s;
171 p->PrevSuccess = 1;
172 p->RunLength++;
173 s->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196)
174 // NextContext(p);
175 if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)
176 p->MaxContext = p->MinContext = c;
177 else
178 Ppmd8_UpdateModel(p);
179 }
180 return;
181 }
182
183 *prob = (UInt16)pr;
184 p->InitEsc = p->ExpEscape[pr >> 10];
185 // RangeEnc_EncodeBit_1(p, bound);
186 R->Low += bound;
187 R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - bound;
188 RC_NORM_LOCAL(R)
189
190 PPMD_SetAllBitsIn256Bytes(charMask)
191 MASK(s->Symbol) = 0;
192 p->PrevSuccess = 0;
193 }
194
195 for (;;)
196 {
197 CPpmd_See *see;
198 CPpmd_State *s;
199 UInt32 sum, escFreq;
200 CPpmd8_Context *mc;
201 unsigned i, numMasked;
202
203 RC_NORM_REMOTE(p)
204
205 mc = p->MinContext;
206 numMasked = mc->NumStats;
207
208 do
209 {
210 p->OrderFall++;
211 if (!mc->Suffix)
212 return; /* EndMarker (symbol = -1) */
213 mc = Ppmd8_GetContext(p, mc->Suffix);
214
215 }
216 while (mc->NumStats == numMasked);
217
218 p->MinContext = mc;
219
220 see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 s = Ppmd8_GetStats(p, p->MinContext);
246 sum = 0;
247 i = (unsigned)p->MinContext->NumStats + 1;
248
249 do
250 {
251 const unsigned cur = s->Symbol;
252 if ((int)cur == symbol)
253 {
254 const UInt32 low = sum;
255 const UInt32 freq = s->Freq;
256 unsigned num2;
257
258 Ppmd_See_UPDATE(see)
259 p->FoundState = s;
260 sum += escFreq;
261
262 num2 = i / 2;
263 i &= 1;
264 sum += freq & (0 - (UInt32)i);
265 if (num2 != 0)
266 {
267 s += i;
268 do
269 {
270 const unsigned sym0 = s[0].Symbol;
271 const unsigned sym1 = s[1].Symbol;
272 s += 2;
273 sum += (s[-2].Freq & (unsigned)(MASK(sym0)));
274 sum += (s[-1].Freq & (unsigned)(MASK(sym1)));
275 }
276 while (--num2);
277 }
278
279 PPMD8_CORRECT_SUM_RANGE(p, sum)
280
281 RC_EncodeFinal(low, freq, sum)
282 Ppmd8_Update2(p);
283 return;
284 }
285 sum += (s->Freq & (unsigned)(MASK(cur)));
286 s++;
287 }
288 while (--i);
289
290 {
291 UInt32 total = sum + escFreq;
292 see->Summ = (UInt16)(see->Summ + total);
293 PPMD8_CORRECT_SUM_RANGE(p, total)
294
295 RC_Encode(sum, total - sum, total)
296 }
297
298 {
299 const CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);
300 s--;
301 MASK(s->Symbol) = 0;
302 do
303 {
304 const unsigned sym0 = s2[0].Symbol;
305 const unsigned sym1 = s2[1].Symbol;
306 s2 += 2;
307 MASK(sym0) = 0;
308 MASK(sym1) = 0;
309 }
310 while (s2 < s);
311 }
312 }
313 }
314
315
316
317
318
319
320
321
322
323 #undef kTop
324 #undef kBot
325 #undef WRITE_BYTE
326 #undef RC_NORM_BASE
327 #undef RC_NORM_1
328 #undef RC_NORM
329 #undef RC_NORM_LOCAL
330 #undef RC_NORM_REMOTE
331 #undef R
332 #undef RC_Encode
333 #undef RC_EncodeFinal
334
335 #undef CTX
336 #undef SUCCESSOR
337 #undef MASK
338