xref: /aosp_15_r20/external/lzma/C/Ppmd8Enc.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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