/src/minizip-ng/third_party/ppmd/C/Ppmd8Enc.c
Line | Count | Source |
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 | 577M | #define kTop ((UInt32)1 << 24) |
12 | 400M | #define kBot ((UInt32)1 << 15) |
13 | | |
14 | 88.4M | #define WRITE_BYTE(p) IByteOut_Write(p->Stream.Out, (Byte)(p->Low >> 24)) |
15 | | |
16 | | void Ppmd8_Flush_RangeEnc(CPpmd8 *p) |
17 | 1.70k | { |
18 | 1.70k | unsigned i; |
19 | 8.51k | for (i = 0; i < 4; i++, p->Low <<= 8 ) |
20 | 6.81k | WRITE_BYTE(p); |
21 | 1.70k | } |
22 | | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | | #define RC_NORM(p) \ |
29 | 288M | while ((p->Low ^ (p->Low + p->Range)) < kTop \ |
30 | 288M | || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) \ |
31 | 200M | { 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 | 182M | #define RC_NORM_REMOTE(p) RC_NORM(p) |
48 | | |
49 | | // #define RC_PRE(total) p->Range /= total; |
50 | | // #define RC_PRE(total) |
51 | | |
52 | 604M | #define R p |
53 | | |
54 | | |
55 | | |
56 | | |
57 | | Z7_FORCE_INLINE |
58 | | // Z7_NO_INLINE |
59 | | static void Ppmd8_RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total) |
60 | 161M | { |
61 | 161M | R->Low += start * (R->Range /= total); |
62 | 161M | R->Range *= size; |
63 | 161M | RC_NORM_LOCAL(R) |
64 | 161M | } |
65 | | |
66 | | |
67 | | |
68 | | |
69 | | |
70 | | |
71 | | |
72 | | |
73 | | |
74 | | |
75 | 161M | #define RC_Encode(start, size, total) Ppmd8_RangeEnc_Encode(p, start, size, total); |
76 | 96.2M | #define RC_EncodeFinal(start, size, total) RC_Encode(start, size, total) RC_NORM_REMOTE(p) |
77 | | |
78 | 17.3M | #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 | 19.9G | #define MASK(sym) ((Byte *)charMask)[sym] |
86 | | |
87 | | // Z7_FORCE_INLINE |
88 | | // static |
89 | | void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol) |
90 | 113M | { |
91 | 113M | size_t charMask[256 / sizeof(size_t)]; |
92 | | |
93 | 113M | if (p->MinContext->NumStats != 0) |
94 | 74.7M | { |
95 | 74.7M | CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext); |
96 | 74.7M | UInt32 sum; |
97 | 74.7M | unsigned i; |
98 | 74.7M | UInt32 summFreq = p->MinContext->Union2.SummFreq; |
99 | | |
100 | 74.7M | PPMD8_CORRECT_SUM_RANGE(p, summFreq) |
101 | | |
102 | | // RC_PRE(summFreq); |
103 | | |
104 | 74.7M | if (s->Symbol == symbol) |
105 | 6.08M | { |
106 | | |
107 | 6.08M | RC_EncodeFinal(0, s->Freq, summFreq) |
108 | 6.08M | p->FoundState = s; |
109 | 6.08M | Ppmd8_Update1_0(p); |
110 | 6.08M | return; |
111 | 6.08M | } |
112 | 68.6M | p->PrevSuccess = 0; |
113 | 68.6M | sum = s->Freq; |
114 | 68.6M | i = p->MinContext->NumStats; |
115 | 68.6M | do |
116 | 2.68G | { |
117 | 2.68G | if ((++s)->Symbol == symbol) |
118 | 20.1M | { |
119 | | |
120 | 20.1M | RC_EncodeFinal(sum, s->Freq, summFreq) |
121 | 20.1M | p->FoundState = s; |
122 | 20.1M | Ppmd8_Update1(p); |
123 | 20.1M | return; |
124 | 20.1M | } |
125 | 2.66G | sum += s->Freq; |
126 | 2.66G | } |
127 | 2.66G | while (--i); |
128 | | |
129 | | |
130 | 48.4M | RC_Encode(sum, summFreq - sum, summFreq) |
131 | | |
132 | | |
133 | 48.4M | PPMD_SetAllBitsIn256Bytes(charMask) |
134 | | // MASK(s->Symbol) = 0; |
135 | | // i = p->MinContext->NumStats; |
136 | | // do { MASK((--s)->Symbol) = 0; } while (--i); |
137 | 48.4M | { |
138 | 48.4M | CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext); |
139 | 48.4M | MASK(s->Symbol) = 0; |
140 | 48.4M | do |
141 | 938M | { |
142 | 938M | const unsigned sym0 = s2[0].Symbol; |
143 | 938M | const unsigned sym1 = s2[1].Symbol; |
144 | 938M | s2 += 2; |
145 | 938M | MASK(sym0) = 0; |
146 | 938M | MASK(sym1) = 0; |
147 | 938M | } |
148 | 938M | while (s2 < s); |
149 | 48.4M | } |
150 | 48.4M | } |
151 | 38.9M | else |
152 | 38.9M | { |
153 | 38.9M | UInt16 *prob = Ppmd8_GetBinSumm(p); |
154 | 38.9M | CPpmd_State *s = Ppmd8Context_OneState(p->MinContext); |
155 | 38.9M | UInt32 pr = *prob; |
156 | 38.9M | const UInt32 bound = (R->Range >> 14) * pr; |
157 | 38.9M | pr = PPMD_UPDATE_PROB_1(pr); |
158 | 38.9M | if (s->Symbol == symbol) |
159 | 17.3M | { |
160 | 17.3M | *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); |
161 | | // RangeEnc_EncodeBit_0(p, bound); |
162 | 17.3M | R->Range = bound; |
163 | 17.3M | RC_NORM(R) |
164 | | |
165 | | // p->FoundState = s; |
166 | | // Ppmd8_UpdateBin(p); |
167 | 17.3M | { |
168 | 17.3M | const unsigned freq = s->Freq; |
169 | 17.3M | CPpmd8_Context *c = CTX(SUCCESSOR(s)); |
170 | 17.3M | p->FoundState = s; |
171 | 17.3M | p->PrevSuccess = 1; |
172 | 17.3M | p->RunLength++; |
173 | 17.3M | s->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196) |
174 | | // NextContext(p); |
175 | 17.3M | if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart) |
176 | 8.25M | p->MaxContext = p->MinContext = c; |
177 | 9.13M | else |
178 | 9.13M | Ppmd8_UpdateModel(p); |
179 | 17.3M | } |
180 | 17.3M | return; |
181 | 17.3M | } |
182 | | |
183 | 21.5M | *prob = (UInt16)pr; |
184 | 21.5M | p->InitEsc = p->ExpEscape[pr >> 10]; |
185 | | // RangeEnc_EncodeBit_1(p, bound); |
186 | 21.5M | R->Low += bound; |
187 | 21.5M | R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - bound; |
188 | 21.5M | RC_NORM_LOCAL(R) |
189 | | |
190 | 21.5M | PPMD_SetAllBitsIn256Bytes(charMask) |
191 | 21.5M | MASK(s->Symbol) = 0; |
192 | 21.5M | p->PrevSuccess = 0; |
193 | 21.5M | } |
194 | | |
195 | 70.0M | for (;;) |
196 | 86.4M | { |
197 | 86.4M | CPpmd_See *see; |
198 | 86.4M | CPpmd_State *s; |
199 | 86.4M | UInt32 sum, escFreq; |
200 | 86.4M | CPpmd8_Context *mc; |
201 | 86.4M | unsigned i, numMasked; |
202 | | |
203 | 86.4M | RC_NORM_REMOTE(p) |
204 | | |
205 | 86.4M | mc = p->MinContext; |
206 | 86.4M | numMasked = mc->NumStats; |
207 | | |
208 | 86.4M | do |
209 | 88.3M | { |
210 | 88.3M | p->OrderFall++; |
211 | 88.3M | if (!mc->Suffix) |
212 | 1.70k | return; /* EndMarker (symbol = -1) */ |
213 | 88.3M | mc = Ppmd8_GetContext(p, mc->Suffix); |
214 | | |
215 | 88.3M | } |
216 | 88.3M | while (mc->NumStats == numMasked); |
217 | | |
218 | 86.4M | p->MinContext = mc; |
219 | | |
220 | 86.4M | 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 | 86.4M | s = Ppmd8_GetStats(p, p->MinContext); |
246 | 86.4M | sum = 0; |
247 | 86.4M | i = (unsigned)p->MinContext->NumStats + 1; |
248 | | |
249 | 86.4M | do |
250 | 8.90G | { |
251 | 8.90G | const unsigned cur = s->Symbol; |
252 | 8.90G | if ((int)cur == symbol) |
253 | 70.0M | { |
254 | 70.0M | const UInt32 low = sum; |
255 | 70.0M | const UInt32 freq = s->Freq; |
256 | 70.0M | unsigned num2; |
257 | | |
258 | 70.0M | Ppmd_See_UPDATE(see) |
259 | 70.0M | p->FoundState = s; |
260 | 70.0M | sum += escFreq; |
261 | | |
262 | 70.0M | num2 = i / 2; |
263 | 70.0M | i &= 1; |
264 | 70.0M | sum += freq & (0 - (UInt32)i); |
265 | 70.0M | if (num2 != 0) |
266 | 69.4M | { |
267 | 69.4M | s += i; |
268 | 69.4M | do |
269 | 3.77G | { |
270 | 3.77G | const unsigned sym0 = s[0].Symbol; |
271 | 3.77G | const unsigned sym1 = s[1].Symbol; |
272 | 3.77G | s += 2; |
273 | 3.77G | sum += (s[-2].Freq & (unsigned)(MASK(sym0))); |
274 | 3.77G | sum += (s[-1].Freq & (unsigned)(MASK(sym1))); |
275 | 3.77G | } |
276 | 3.77G | while (--num2); |
277 | 69.4M | } |
278 | | |
279 | 70.0M | PPMD8_CORRECT_SUM_RANGE(p, sum) |
280 | | |
281 | 70.0M | RC_EncodeFinal(low, freq, sum) |
282 | 70.0M | Ppmd8_Update2(p); |
283 | 70.0M | return; |
284 | 70.0M | } |
285 | 8.83G | sum += (s->Freq & (unsigned)(MASK(cur))); |
286 | 8.83G | s++; |
287 | 8.83G | } |
288 | 8.83G | while (--i); |
289 | | |
290 | 16.3M | { |
291 | 16.3M | UInt32 total = sum + escFreq; |
292 | 16.3M | see->Summ = (UInt16)(see->Summ + total); |
293 | 16.3M | PPMD8_CORRECT_SUM_RANGE(p, total) |
294 | | |
295 | 16.3M | RC_Encode(sum, total - sum, total) |
296 | 16.3M | } |
297 | | |
298 | 16.3M | { |
299 | 16.3M | const CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext); |
300 | 16.3M | s--; |
301 | 16.3M | MASK(s->Symbol) = 0; |
302 | 16.3M | do |
303 | 807M | { |
304 | 807M | const unsigned sym0 = s2[0].Symbol; |
305 | 807M | const unsigned sym1 = s2[1].Symbol; |
306 | 807M | s2 += 2; |
307 | 807M | MASK(sym0) = 0; |
308 | 807M | MASK(sym1) = 0; |
309 | 807M | } |
310 | 807M | while (s2 < s); |
311 | 16.3M | } |
312 | 16.3M | } |
313 | 70.0M | } |
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 |