/src/minizip-ng/third_party/ppmd/C/Ppmd8.c
Line | Count | Source |
1 | | /* Ppmd8.c -- PPMdI codec |
2 | | 2023-09-07 : Igor Pavlov : Public domain |
3 | | This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ |
4 | | |
5 | | #include "Precomp.h" |
6 | | |
7 | | #include <string.h> |
8 | | |
9 | | #include "Ppmd8.h" |
10 | | |
11 | | |
12 | | |
13 | | |
14 | | MY_ALIGN(16) |
15 | | static const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; |
16 | | MY_ALIGN(16) |
17 | | static const UInt16 PPMD8_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; |
18 | | |
19 | 272M | #define MAX_FREQ 124 |
20 | 69.3M | #define UNIT_SIZE 12 |
21 | | |
22 | 35.6M | #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) |
23 | 72.8M | #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) |
24 | 58.0M | #define I2U(indx) ((unsigned)p->Indx2Units[indx]) |
25 | | |
26 | | |
27 | 279M | #define REF(ptr) Ppmd_GetRef(p, ptr) |
28 | | |
29 | 22.2M | #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) |
30 | | |
31 | 390M | #define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref)) |
32 | 199M | #define STATS(ctx) Ppmd8_GetStats(p, ctx) |
33 | 54.0M | #define ONE_STATE(ctx) Ppmd8Context_OneState(ctx) |
34 | 245M | #define SUFFIX(ctx) CTX((ctx)->Suffix) |
35 | | |
36 | | typedef CPpmd8_Context * PPMD8_CTX_PTR; |
37 | | |
38 | | struct CPpmd8_Node_; |
39 | | |
40 | | typedef Ppmd_Ref_Type(struct CPpmd8_Node_) CPpmd8_Node_Ref; |
41 | | |
42 | | typedef struct CPpmd8_Node_ |
43 | | { |
44 | | UInt32 Stamp; |
45 | | |
46 | | CPpmd8_Node_Ref Next; |
47 | | UInt32 NU; |
48 | | } CPpmd8_Node; |
49 | | |
50 | 32.8M | #define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd8_Node) |
51 | | |
52 | | void Ppmd8_Construct(CPpmd8 *p) |
53 | 1.74k | { |
54 | 1.74k | unsigned i, k, m; |
55 | | |
56 | 1.74k | p->Base = NULL; |
57 | | |
58 | 68.1k | for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) |
59 | 66.3k | { |
60 | 66.3k | unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); |
61 | 223k | do { p->Units2Indx[k++] = (Byte)i; } while (--step); |
62 | 66.3k | p->Indx2Units[i] = (Byte)k; |
63 | 66.3k | } |
64 | | |
65 | 1.74k | p->NS2BSIndx[0] = (0 << 1); |
66 | 1.74k | p->NS2BSIndx[1] = (1 << 1); |
67 | 1.74k | memset(p->NS2BSIndx + 2, (2 << 1), 9); |
68 | 1.74k | memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); |
69 | | |
70 | 10.4k | for (i = 0; i < 5; i++) |
71 | 8.73k | p->NS2Indx[i] = (Byte)i; |
72 | | |
73 | 447k | for (m = i, k = 1; i < 260; i++) |
74 | 445k | { |
75 | 445k | p->NS2Indx[i] = (Byte)m; |
76 | 445k | if (--k == 0) |
77 | 38.4k | k = (++m) - 4; |
78 | 445k | } |
79 | | |
80 | 1.74k | memcpy(p->ExpEscape, PPMD8_kExpEscape, 16); |
81 | 1.74k | } |
82 | | |
83 | | |
84 | | void Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc) |
85 | 3.40k | { |
86 | 3.40k | ISzAlloc_Free(alloc, p->Base); |
87 | 3.40k | p->Size = 0; |
88 | 3.40k | p->Base = NULL; |
89 | 3.40k | } |
90 | | |
91 | | |
92 | | BoolInt Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc) |
93 | 1.70k | { |
94 | 1.70k | if (!p->Base || p->Size != size) |
95 | 1.70k | { |
96 | 1.70k | Ppmd8_Free(p, alloc); |
97 | 1.70k | p->AlignOffset = (4 - size) & 3; |
98 | 1.70k | if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL) |
99 | 0 | return False; |
100 | 1.70k | p->Size = size; |
101 | 1.70k | } |
102 | 1.70k | return True; |
103 | 1.70k | } |
104 | | |
105 | | |
106 | | |
107 | | // ---------- Internal Memory Allocator ---------- |
108 | | |
109 | | |
110 | | |
111 | | |
112 | | |
113 | | |
114 | 35.0M | #define EMPTY_NODE 0xFFFFFFFF |
115 | | |
116 | | |
117 | | static void Ppmd8_InsertNode(CPpmd8 *p, void *node, unsigned indx) |
118 | 33.2M | { |
119 | 33.2M | ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE; |
120 | 33.2M | ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx]; |
121 | 33.2M | ((CPpmd8_Node *)node)->NU = I2U(indx); |
122 | 33.2M | p->FreeList[indx] = REF(node); |
123 | 33.2M | p->Stamps[indx]++; |
124 | 33.2M | } |
125 | | |
126 | | |
127 | | static void *Ppmd8_RemoveNode(CPpmd8 *p, unsigned indx) |
128 | 29.9M | { |
129 | 29.9M | CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]); |
130 | 29.9M | p->FreeList[indx] = node->Next; |
131 | 29.9M | p->Stamps[indx]--; |
132 | | |
133 | 29.9M | return node; |
134 | 29.9M | } |
135 | | |
136 | | |
137 | | static void Ppmd8_SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx) |
138 | 6.94M | { |
139 | 6.94M | unsigned i, nu = I2U(oldIndx) - I2U(newIndx); |
140 | 6.94M | ptr = (Byte *)ptr + U2B(I2U(newIndx)); |
141 | 6.94M | if (I2U(i = U2I(nu)) != nu) |
142 | 2.83M | { |
143 | 2.83M | unsigned k = I2U(--i); |
144 | 2.83M | Ppmd8_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); |
145 | 2.83M | } |
146 | 6.94M | Ppmd8_InsertNode(p, ptr, i); |
147 | 6.94M | } |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
155 | | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | static void Ppmd8_GlueFreeBlocks(CPpmd8 *p) |
163 | 736 | { |
164 | | /* |
165 | | we use first UInt32 field of 12-bytes UNITs as record type stamp |
166 | | CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0xFF |
167 | | CPpmd8_Context { Byte NumStats; Byte Flags; UInt16 SummFreq; : Flags != 0xFF ??? |
168 | | CPpmd8_Node { UInt32 Stamp : Stamp == 0xFFFFFFFF for free record |
169 | | : Stamp == 0 for guard |
170 | | Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd8_Context record |
171 | | */ |
172 | 736 | CPpmd8_Node_Ref n; |
173 | | |
174 | 736 | p->GlueCount = 1 << 13; |
175 | 736 | memset(p->Stamps, 0, sizeof(p->Stamps)); |
176 | | |
177 | | /* we set guard NODE at LoUnit */ |
178 | 736 | if (p->LoUnit != p->HiUnit) |
179 | 449 | ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0; |
180 | | |
181 | 736 | { |
182 | | /* Glue free blocks */ |
183 | 736 | CPpmd8_Node_Ref *prev = &n; |
184 | 736 | unsigned i; |
185 | 28.7k | for (i = 0; i < PPMD_NUM_INDEXES; i++) |
186 | 27.9k | { |
187 | | |
188 | 27.9k | CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i]; |
189 | 27.9k | p->FreeList[i] = 0; |
190 | 1.69M | while (next != 0) |
191 | 1.67M | { |
192 | 1.67M | CPpmd8_Node *node = NODE(next); |
193 | 1.67M | UInt32 nu = node->NU; |
194 | 1.67M | *prev = next; |
195 | 1.67M | next = node->Next; |
196 | 1.67M | if (nu != 0) |
197 | 1.27M | { |
198 | 1.27M | CPpmd8_Node *node2; |
199 | 1.27M | prev = &(node->Next); |
200 | 1.84M | while ((node2 = node + nu)->Stamp == EMPTY_NODE) |
201 | 569k | { |
202 | 569k | nu += node2->NU; |
203 | 569k | node2->NU = 0; |
204 | 569k | node->NU = nu; |
205 | 569k | } |
206 | 1.27M | } |
207 | 1.67M | } |
208 | 27.9k | } |
209 | | |
210 | 736 | *prev = 0; |
211 | 736 | } |
212 | | |
213 | | |
214 | | |
215 | | |
216 | | |
217 | | |
218 | | |
219 | | |
220 | | |
221 | | |
222 | | |
223 | | |
224 | | |
225 | | |
226 | | |
227 | | |
228 | | |
229 | | |
230 | | |
231 | | |
232 | | /* Fill lists of free blocks */ |
233 | 1.27M | while (n != 0) |
234 | 1.27M | { |
235 | 1.27M | CPpmd8_Node *node = NODE(n); |
236 | 1.27M | UInt32 nu = node->NU; |
237 | 1.27M | unsigned i; |
238 | 1.27M | n = node->Next; |
239 | 1.27M | if (nu == 0) |
240 | 177k | continue; |
241 | 1.13M | for (; nu > 128; nu -= 128, node += 128) |
242 | 34.1k | Ppmd8_InsertNode(p, node, PPMD_NUM_INDEXES - 1); |
243 | 1.10M | if (I2U(i = U2I(nu)) != nu) |
244 | 74.7k | { |
245 | 74.7k | unsigned k = I2U(--i); |
246 | 74.7k | Ppmd8_InsertNode(p, node + k, (unsigned)nu - k - 1); |
247 | 74.7k | } |
248 | 1.10M | Ppmd8_InsertNode(p, node, i); |
249 | 1.10M | } |
250 | 736 | } |
251 | | |
252 | | |
253 | | Z7_NO_INLINE |
254 | | static void *Ppmd8_AllocUnitsRare(CPpmd8 *p, unsigned indx) |
255 | 7.84M | { |
256 | 7.84M | unsigned i; |
257 | | |
258 | 7.84M | if (p->GlueCount == 0) |
259 | 736 | { |
260 | 736 | Ppmd8_GlueFreeBlocks(p); |
261 | 736 | if (p->FreeList[indx] != 0) |
262 | 630 | return Ppmd8_RemoveNode(p, indx); |
263 | 736 | } |
264 | | |
265 | 7.84M | i = indx; |
266 | | |
267 | 7.84M | do |
268 | 69.8M | { |
269 | 69.8M | if (++i == PPMD_NUM_INDEXES) |
270 | 910k | { |
271 | 910k | UInt32 numBytes = U2B(I2U(indx)); |
272 | 910k | Byte *us = p->UnitsStart; |
273 | 910k | p->GlueCount--; |
274 | 910k | return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : (NULL); |
275 | 910k | } |
276 | 69.8M | } |
277 | 68.8M | while (p->FreeList[i] == 0); |
278 | | |
279 | 6.93M | { |
280 | 6.93M | void *block = Ppmd8_RemoveNode(p, i); |
281 | 6.93M | Ppmd8_SplitBlock(p, block, i, indx); |
282 | 6.93M | return block; |
283 | 7.84M | } |
284 | 7.84M | } |
285 | | |
286 | | |
287 | | static void *Ppmd8_AllocUnits(CPpmd8 *p, unsigned indx) |
288 | 44.5M | { |
289 | 44.5M | if (p->FreeList[indx] != 0) |
290 | 19.5M | return Ppmd8_RemoveNode(p, indx); |
291 | 24.9M | { |
292 | 24.9M | UInt32 numBytes = U2B(I2U(indx)); |
293 | 24.9M | Byte *lo = p->LoUnit; |
294 | 24.9M | if ((UInt32)(p->HiUnit - lo) >= numBytes) |
295 | 21.2M | { |
296 | 21.2M | p->LoUnit = lo + numBytes; |
297 | 21.2M | return lo; |
298 | 21.2M | } |
299 | 24.9M | } |
300 | 3.72M | return Ppmd8_AllocUnitsRare(p, indx); |
301 | 24.9M | } |
302 | | |
303 | | |
304 | | #define MEM_12_CPY(dest, src, num) \ |
305 | 22.2M | { UInt32 *d = (UInt32 *)(dest); \ |
306 | 22.2M | const UInt32 *z = (const UInt32 *)(src); \ |
307 | 22.2M | unsigned n = (num); \ |
308 | 251M | do { \ |
309 | 251M | d[0] = z[0]; \ |
310 | 251M | d[1] = z[1]; \ |
311 | 251M | d[2] = z[2]; \ |
312 | 251M | z += 3; \ |
313 | 251M | d += 3; \ |
314 | 251M | } while (--n); \ |
315 | 22.2M | } |
316 | | |
317 | | |
318 | | |
319 | | static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU) |
320 | 54.6k | { |
321 | 54.6k | unsigned i0 = U2I(oldNU); |
322 | 54.6k | unsigned i1 = U2I(newNU); |
323 | 54.6k | if (i0 == i1) |
324 | 2.93k | return oldPtr; |
325 | 51.7k | if (p->FreeList[i1] != 0) |
326 | 40.7k | { |
327 | 40.7k | void *ptr = Ppmd8_RemoveNode(p, i1); |
328 | 40.7k | MEM_12_CPY(ptr, oldPtr, newNU) |
329 | 40.7k | Ppmd8_InsertNode(p, oldPtr, i0); |
330 | 40.7k | return ptr; |
331 | 40.7k | } |
332 | 10.9k | Ppmd8_SplitBlock(p, oldPtr, i0, i1); |
333 | 10.9k | return oldPtr; |
334 | 51.7k | } |
335 | | |
336 | | |
337 | | static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu) |
338 | 0 | { |
339 | 0 | Ppmd8_InsertNode(p, ptr, U2I(nu)); |
340 | 0 | } |
341 | | |
342 | | |
343 | | static void SpecialFreeUnit(CPpmd8 *p, void *ptr) |
344 | 139 | { |
345 | 139 | if ((Byte *)ptr != p->UnitsStart) |
346 | 137 | Ppmd8_InsertNode(p, ptr, 0); |
347 | 2 | else |
348 | 2 | { |
349 | | #ifdef PPMD8_FREEZE_SUPPORT |
350 | | *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts() */ |
351 | | #endif |
352 | 2 | p->UnitsStart += UNIT_SIZE; |
353 | 2 | } |
354 | 139 | } |
355 | | |
356 | | |
357 | | /* |
358 | | static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu) |
359 | | { |
360 | | unsigned indx = U2I(nu); |
361 | | void *ptr; |
362 | | if ((Byte *)oldPtr > p->UnitsStart + (1 << 14) || REF(oldPtr) > p->FreeList[indx]) |
363 | | return oldPtr; |
364 | | ptr = Ppmd8_RemoveNode(p, indx); |
365 | | MEM_12_CPY(ptr, oldPtr, nu) |
366 | | if ((Byte *)oldPtr != p->UnitsStart) |
367 | | Ppmd8_InsertNode(p, oldPtr, indx); |
368 | | else |
369 | | p->UnitsStart += U2B(I2U(indx)); |
370 | | return ptr; |
371 | | } |
372 | | */ |
373 | | |
374 | | static void ExpandTextArea(CPpmd8 *p) |
375 | 0 | { |
376 | 0 | UInt32 count[PPMD_NUM_INDEXES]; |
377 | 0 | unsigned i; |
378 | | |
379 | 0 | memset(count, 0, sizeof(count)); |
380 | 0 | if (p->LoUnit != p->HiUnit) |
381 | 0 | ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0; |
382 | | |
383 | 0 | { |
384 | 0 | CPpmd8_Node *node = (CPpmd8_Node *)(void *)p->UnitsStart; |
385 | 0 | while (node->Stamp == EMPTY_NODE) |
386 | 0 | { |
387 | 0 | UInt32 nu = node->NU; |
388 | 0 | node->Stamp = 0; |
389 | 0 | count[U2I(nu)]++; |
390 | 0 | node += nu; |
391 | 0 | } |
392 | 0 | p->UnitsStart = (Byte *)node; |
393 | 0 | } |
394 | | |
395 | 0 | for (i = 0; i < PPMD_NUM_INDEXES; i++) |
396 | 0 | { |
397 | 0 | UInt32 cnt = count[i]; |
398 | 0 | if (cnt == 0) |
399 | 0 | continue; |
400 | 0 | { |
401 | 0 | CPpmd8_Node_Ref *prev = (CPpmd8_Node_Ref *)&p->FreeList[i]; |
402 | 0 | CPpmd8_Node_Ref n = *prev; |
403 | 0 | p->Stamps[i] -= cnt; |
404 | 0 | for (;;) |
405 | 0 | { |
406 | 0 | CPpmd8_Node *node = NODE(n); |
407 | 0 | n = node->Next; |
408 | 0 | if (node->Stamp != 0) |
409 | 0 | { |
410 | 0 | prev = &node->Next; |
411 | 0 | continue; |
412 | 0 | } |
413 | 0 | *prev = n; |
414 | 0 | if (--cnt == 0) |
415 | 0 | break; |
416 | 0 | } |
417 | 0 | } |
418 | 0 | } |
419 | 0 | } |
420 | | |
421 | | |
422 | 178M | #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) |
423 | | static void Ppmd8State_SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) |
424 | 180M | { |
425 | 180M | Ppmd_SET_SUCCESSOR(p, v) |
426 | 180M | } |
427 | | |
428 | 2.66k | #define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); } |
429 | | |
430 | | Z7_NO_INLINE |
431 | | static |
432 | | void Ppmd8_RestartModel(CPpmd8 *p) |
433 | 2.18k | { |
434 | 2.18k | unsigned i, k, m; |
435 | | |
436 | 2.18k | memset(p->FreeList, 0, sizeof(p->FreeList)); |
437 | 2.18k | memset(p->Stamps, 0, sizeof(p->Stamps)); |
438 | 2.18k | RESET_TEXT(0) |
439 | 2.18k | p->HiUnit = p->Text + p->Size; |
440 | 2.18k | p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; |
441 | 2.18k | p->GlueCount = 0; |
442 | | |
443 | 2.18k | p->OrderFall = p->MaxOrder; |
444 | 2.18k | p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; |
445 | 2.18k | p->PrevSuccess = 0; |
446 | | |
447 | 2.18k | { |
448 | 2.18k | CPpmd8_Context *mc = (PPMD8_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ |
449 | 2.18k | CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd8_AllocUnits(p, PPMD_NUM_INDEXES - 1); */ |
450 | | |
451 | 2.18k | p->LoUnit += U2B(256 / 2); |
452 | 2.18k | p->MaxContext = p->MinContext = mc; |
453 | 2.18k | p->FoundState = s; |
454 | 2.18k | mc->Flags = 0; |
455 | 2.18k | mc->NumStats = 256 - 1; |
456 | 2.18k | mc->Union2.SummFreq = 256 + 1; |
457 | 2.18k | mc->Union4.Stats = REF(s); |
458 | 2.18k | mc->Suffix = 0; |
459 | | |
460 | 561k | for (i = 0; i < 256; i++, s++) |
461 | 559k | { |
462 | 559k | s->Symbol = (Byte)i; |
463 | 559k | s->Freq = 1; |
464 | 559k | Ppmd8State_SetSuccessor(s, 0); |
465 | 559k | } |
466 | 2.18k | } |
467 | | |
468 | | |
469 | | |
470 | | |
471 | | |
472 | | |
473 | | |
474 | | |
475 | | |
476 | | |
477 | | |
478 | | |
479 | 56.8k | for (i = m = 0; m < 25; m++) |
480 | 54.6k | { |
481 | 524k | while (p->NS2Indx[i] == m) |
482 | 469k | i++; |
483 | 491k | for (k = 0; k < 8; k++) |
484 | 437k | { |
485 | 437k | unsigned r; |
486 | 437k | UInt16 *dest = p->BinSumm[m] + k; |
487 | 437k | const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD8_kInitBinEsc[k] / (i + 1)); |
488 | 3.93M | for (r = 0; r < 64; r += 8) |
489 | 3.49M | dest[r] = val; |
490 | 437k | } |
491 | 54.6k | } |
492 | | |
493 | 54.6k | for (i = m = 0; m < 24; m++) |
494 | 52.4k | { |
495 | 52.4k | unsigned summ; |
496 | 52.4k | CPpmd_See *s; |
497 | 609k | while (p->NS2Indx[(size_t)i + 3] == m + 3) |
498 | 557k | i++; |
499 | 52.4k | s = p->See[m]; |
500 | 52.4k | summ = ((2 * i + 5) << (PPMD_PERIOD_BITS - 4)); |
501 | 1.73M | for (k = 0; k < 32; k++, s++) |
502 | 1.67M | { |
503 | 1.67M | s->Summ = (UInt16)summ; |
504 | 1.67M | s->Shift = (PPMD_PERIOD_BITS - 4); |
505 | 1.67M | s->Count = 7; |
506 | 1.67M | } |
507 | 52.4k | } |
508 | | |
509 | 2.18k | p->DummySee.Summ = 0; /* unused */ |
510 | 2.18k | p->DummySee.Shift = PPMD_PERIOD_BITS; |
511 | 2.18k | p->DummySee.Count = 64; /* unused */ |
512 | 2.18k | } |
513 | | |
514 | | |
515 | | void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod) |
516 | 1.70k | { |
517 | 1.70k | p->MaxOrder = maxOrder; |
518 | 1.70k | p->RestoreMethod = restoreMethod; |
519 | 1.70k | Ppmd8_RestartModel(p); |
520 | 1.70k | } |
521 | | |
522 | | |
523 | 294k | #define FLAG_RESCALED (1 << 2) |
524 | | // #define FLAG_SYM_HIGH (1 << 3) |
525 | 16.3k | #define FLAG_PREV_HIGH (1 << 4) |
526 | | |
527 | 82.3k | #define HiBits_Prepare(sym) ((unsigned)(sym) + 0xC0) |
528 | | |
529 | 117M | #define HiBits_Convert_3(flags) (((flags) >> (8 - 3)) & (1 << 3)) |
530 | 28.5M | #define HiBits_Convert_4(flags) (((flags) >> (8 - 4)) & (1 << 4)) |
531 | | |
532 | 117M | #define PPMD8_HiBitsFlag_3(sym) HiBits_Convert_3(HiBits_Prepare(sym)) |
533 | 28.5M | #define PPMD8_HiBitsFlag_4(sym) HiBits_Convert_4(HiBits_Prepare(sym)) |
534 | | |
535 | | // #define PPMD8_HiBitsFlag_3(sym) (0x08 * ((sym) >= 0x40)) |
536 | | // #define PPMD8_HiBitsFlag_4(sym) (0x10 * ((sym) >= 0x40)) |
537 | | |
538 | | /* |
539 | | Refresh() is called when we remove some symbols (successors) in context. |
540 | | It increases Escape_Freq for sum of all removed symbols. |
541 | | */ |
542 | | |
543 | | static void Refresh(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned oldNU, unsigned scale) |
544 | 602 | { |
545 | 602 | unsigned i = ctx->NumStats, escFreq, sumFreq, flags; |
546 | 602 | CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1); |
547 | 602 | ctx->Union4.Stats = REF(s); |
548 | | |
549 | | // #ifdef PPMD8_FREEZE_SUPPORT |
550 | | /* |
551 | | (ctx->Union2.SummFreq >= ((UInt32)1 << 15)) can be in FREEZE mode for some files. |
552 | | It's not good for range coder. So new versions of support fix: |
553 | | - original PPMdI code rev.1 |
554 | | + original PPMdI code rev.2 |
555 | | - 7-Zip default ((PPMD8_FREEZE_SUPPORT is not defined) |
556 | | + 7-Zip (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE) |
557 | | if we use that fixed line, we can lose compatibility with some files created before fix |
558 | | if we don't use that fixed line, the program can work incorrectly in FREEZE mode in rare case. |
559 | | */ |
560 | | // if (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE) |
561 | 602 | { |
562 | 602 | scale |= (ctx->Union2.SummFreq >= ((UInt32)1 << 15)); |
563 | 602 | } |
564 | | // #endif |
565 | | |
566 | | |
567 | | |
568 | 602 | flags = HiBits_Prepare(s->Symbol); |
569 | 602 | { |
570 | 602 | unsigned freq = s->Freq; |
571 | 602 | escFreq = ctx->Union2.SummFreq - freq; |
572 | 602 | freq = (freq + scale) >> scale; |
573 | 602 | sumFreq = freq; |
574 | 602 | s->Freq = (Byte)freq; |
575 | 602 | } |
576 | | |
577 | 602 | do |
578 | 81.7k | { |
579 | 81.7k | unsigned freq = (++s)->Freq; |
580 | 81.7k | escFreq -= freq; |
581 | 81.7k | freq = (freq + scale) >> scale; |
582 | 81.7k | sumFreq += freq; |
583 | 81.7k | s->Freq = (Byte)freq; |
584 | 81.7k | flags |= HiBits_Prepare(s->Symbol); |
585 | 81.7k | } |
586 | 81.7k | while (--i); |
587 | | |
588 | 602 | ctx->Union2.SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale)); |
589 | 602 | ctx->Flags = (Byte)((ctx->Flags & (FLAG_PREV_HIGH + FLAG_RESCALED * scale)) + HiBits_Convert_3(flags)); |
590 | 602 | } |
591 | | |
592 | | |
593 | | static void SWAP_STATES(CPpmd_State *t1, CPpmd_State *t2) |
594 | 39.0M | { |
595 | 39.0M | CPpmd_State tmp = *t1; |
596 | 39.0M | *t1 = *t2; |
597 | 39.0M | *t2 = tmp; |
598 | 39.0M | } |
599 | | |
600 | | |
601 | | /* |
602 | | CutOff() reduces contexts: |
603 | | It conversts Successors at MaxOrder to another Contexts to NULL-Successors |
604 | | It removes RAW-Successors and NULL-Successors that are not Order-0 |
605 | | and it removes contexts when it has no Successors. |
606 | | if the (Union4.Stats) is close to (UnitsStart), it moves it up. |
607 | | */ |
608 | | |
609 | | static CPpmd_Void_Ref CutOff(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned order) |
610 | 0 | { |
611 | 0 | int ns = ctx->NumStats; |
612 | 0 | unsigned nu; |
613 | 0 | CPpmd_State *stats; |
614 | | |
615 | 0 | if (ns == 0) |
616 | 0 | { |
617 | 0 | CPpmd_State *s = ONE_STATE(ctx); |
618 | 0 | CPpmd_Void_Ref successor = SUCCESSOR(s); |
619 | 0 | if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart) |
620 | 0 | { |
621 | 0 | if (order < p->MaxOrder) |
622 | 0 | successor = CutOff(p, CTX(successor), order + 1); |
623 | 0 | else |
624 | 0 | successor = 0; |
625 | 0 | Ppmd8State_SetSuccessor(s, successor); |
626 | 0 | if (successor || order <= 9) /* O_BOUND */ |
627 | 0 | return REF(ctx); |
628 | 0 | } |
629 | 0 | SpecialFreeUnit(p, ctx); |
630 | 0 | return 0; |
631 | 0 | } |
632 | | |
633 | 0 | nu = ((unsigned)ns + 2) >> 1; |
634 | | // ctx->Union4.Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), nu)); |
635 | 0 | { |
636 | 0 | unsigned indx = U2I(nu); |
637 | 0 | stats = STATS(ctx); |
638 | |
|
639 | 0 | if ((UInt32)((Byte *)stats - p->UnitsStart) <= (1 << 14) |
640 | 0 | && (CPpmd_Void_Ref)ctx->Union4.Stats <= p->FreeList[indx]) |
641 | 0 | { |
642 | 0 | void *ptr = Ppmd8_RemoveNode(p, indx); |
643 | 0 | ctx->Union4.Stats = STATS_REF(ptr); |
644 | 0 | MEM_12_CPY(ptr, (const void *)stats, nu) |
645 | 0 | if ((Byte *)stats != p->UnitsStart) |
646 | 0 | Ppmd8_InsertNode(p, stats, indx); |
647 | 0 | else |
648 | 0 | p->UnitsStart += U2B(I2U(indx)); |
649 | 0 | stats = ptr; |
650 | 0 | } |
651 | 0 | } |
652 | |
|
653 | 0 | { |
654 | 0 | CPpmd_State *s = stats + (unsigned)ns; |
655 | 0 | do |
656 | 0 | { |
657 | 0 | CPpmd_Void_Ref successor = SUCCESSOR(s); |
658 | 0 | if ((Byte *)Ppmd8_GetPtr(p, successor) < p->UnitsStart) |
659 | 0 | { |
660 | 0 | CPpmd_State *s2 = stats + (unsigned)(ns--); |
661 | 0 | if (order) |
662 | 0 | { |
663 | 0 | if (s != s2) |
664 | 0 | *s = *s2; |
665 | 0 | } |
666 | 0 | else |
667 | 0 | { |
668 | 0 | SWAP_STATES(s, s2); |
669 | 0 | Ppmd8State_SetSuccessor(s2, 0); |
670 | 0 | } |
671 | 0 | } |
672 | 0 | else |
673 | 0 | { |
674 | 0 | if (order < p->MaxOrder) |
675 | 0 | Ppmd8State_SetSuccessor(s, CutOff(p, CTX(successor), order + 1)); |
676 | 0 | else |
677 | 0 | Ppmd8State_SetSuccessor(s, 0); |
678 | 0 | } |
679 | 0 | } |
680 | 0 | while (--s >= stats); |
681 | 0 | } |
682 | | |
683 | 0 | if (ns != ctx->NumStats && order) |
684 | 0 | { |
685 | 0 | if (ns < 0) |
686 | 0 | { |
687 | 0 | FreeUnits(p, stats, nu); |
688 | 0 | SpecialFreeUnit(p, ctx); |
689 | 0 | return 0; |
690 | 0 | } |
691 | 0 | ctx->NumStats = (Byte)ns; |
692 | 0 | if (ns == 0) |
693 | 0 | { |
694 | 0 | const Byte sym = stats->Symbol; |
695 | 0 | ctx->Flags = (Byte)((ctx->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(sym)); |
696 | | // *ONE_STATE(ctx) = *stats; |
697 | 0 | ctx->Union2.State2.Symbol = sym; |
698 | 0 | ctx->Union2.State2.Freq = (Byte)(((unsigned)stats->Freq + 11) >> 3); |
699 | 0 | ctx->Union4.State4.Successor_0 = stats->Successor_0; |
700 | 0 | ctx->Union4.State4.Successor_1 = stats->Successor_1; |
701 | 0 | FreeUnits(p, stats, nu); |
702 | 0 | } |
703 | 0 | else |
704 | 0 | { |
705 | 0 | Refresh(p, ctx, nu, ctx->Union2.SummFreq > 16 * (unsigned)ns); |
706 | 0 | } |
707 | 0 | } |
708 | | |
709 | 0 | return REF(ctx); |
710 | 0 | } |
711 | | |
712 | | |
713 | | |
714 | | #ifdef PPMD8_FREEZE_SUPPORT |
715 | | |
716 | | /* |
717 | | RemoveBinContexts() |
718 | | It conversts Successors at MaxOrder to another Contexts to NULL-Successors |
719 | | It changes RAW-Successors to NULL-Successors |
720 | | removes Bin Context without Successor, if suffix of that context is also binary. |
721 | | */ |
722 | | |
723 | | static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned order) |
724 | | { |
725 | | if (!ctx->NumStats) |
726 | | { |
727 | | CPpmd_State *s = ONE_STATE(ctx); |
728 | | CPpmd_Void_Ref successor = SUCCESSOR(s); |
729 | | if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder) |
730 | | successor = RemoveBinContexts(p, CTX(successor), order + 1); |
731 | | else |
732 | | successor = 0; |
733 | | Ppmd8State_SetSuccessor(s, successor); |
734 | | /* Suffix context can be removed already, since different (high-order) |
735 | | Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */ |
736 | | if (!successor && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF)) |
737 | | { |
738 | | FreeUnits(p, ctx, 1); |
739 | | return 0; |
740 | | } |
741 | | } |
742 | | else |
743 | | { |
744 | | CPpmd_State *s = STATS(ctx) + ctx->NumStats; |
745 | | do |
746 | | { |
747 | | CPpmd_Void_Ref successor = SUCCESSOR(s); |
748 | | if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder) |
749 | | Ppmd8State_SetSuccessor(s, RemoveBinContexts(p, CTX(successor), order + 1)); |
750 | | else |
751 | | Ppmd8State_SetSuccessor(s, 0); |
752 | | } |
753 | | while (--s >= STATS(ctx)); |
754 | | } |
755 | | |
756 | | return REF(ctx); |
757 | | } |
758 | | |
759 | | #endif |
760 | | |
761 | | |
762 | | |
763 | | static UInt32 GetUsedMemory(const CPpmd8 *p) |
764 | 0 | { |
765 | 0 | UInt32 v = 0; |
766 | 0 | unsigned i; |
767 | 0 | for (i = 0; i < PPMD_NUM_INDEXES; i++) |
768 | 0 | v += p->Stamps[i] * I2U(i); |
769 | 0 | return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v); |
770 | 0 | } |
771 | | |
772 | | #ifdef PPMD8_FREEZE_SUPPORT |
773 | | #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor) |
774 | | #else |
775 | 483 | #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1) |
776 | | #endif |
777 | | |
778 | | |
779 | | static void RestoreModel(CPpmd8 *p, PPMD8_CTX_PTR ctxError |
780 | | #ifdef PPMD8_FREEZE_SUPPORT |
781 | | , PPMD8_CTX_PTR fSuccessor |
782 | | #endif |
783 | | ) |
784 | 483 | { |
785 | 483 | PPMD8_CTX_PTR c; |
786 | 483 | CPpmd_State *s; |
787 | 483 | RESET_TEXT(0) |
788 | | |
789 | | // we go here in cases of error of allocation for context (c1) |
790 | | // Order(MinContext) < Order(ctxError) <= Order(MaxContext) |
791 | | |
792 | | // We remove last symbol from each of contexts [p->MaxContext ... ctxError) contexts |
793 | | // So we rollback all created (symbols) before error. |
794 | 797 | for (c = p->MaxContext; c != ctxError; c = SUFFIX(c)) |
795 | 314 | if (--(c->NumStats) == 0) |
796 | 139 | { |
797 | 139 | s = STATS(c); |
798 | 139 | c->Flags = (Byte)((c->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(s->Symbol)); |
799 | | // *ONE_STATE(c) = *s; |
800 | 139 | c->Union2.State2.Symbol = s->Symbol; |
801 | 139 | c->Union2.State2.Freq = (Byte)(((unsigned)s->Freq + 11) >> 3); |
802 | 139 | c->Union4.State4.Successor_0 = s->Successor_0; |
803 | 139 | c->Union4.State4.Successor_1 = s->Successor_1; |
804 | | |
805 | 139 | SpecialFreeUnit(p, s); |
806 | 139 | } |
807 | 175 | else |
808 | 175 | { |
809 | | /* Refresh() can increase Escape_Freq on value of Freq of last symbol, that was added before error. |
810 | | so the largest possible increase for Escape_Freq is (8) from value before ModelUpoadet() */ |
811 | 175 | Refresh(p, c, ((unsigned)c->NumStats + 3) >> 1, 0); |
812 | 175 | } |
813 | | |
814 | | // increase Escape Freq for context [ctxError ... p->MinContext) |
815 | 960 | for (; c != p->MinContext; c = SUFFIX(c)) |
816 | 477 | if (c->NumStats == 0) |
817 | 13 | { |
818 | | // ONE_STATE(c) |
819 | 13 | c->Union2.State2.Freq = (Byte)(((unsigned)c->Union2.State2.Freq + 1) >> 1); |
820 | 13 | } |
821 | 464 | else if ((c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 4)) > 128 + 4 * c->NumStats) |
822 | 427 | Refresh(p, c, ((unsigned)c->NumStats + 2) >> 1, 1); |
823 | | |
824 | | #ifdef PPMD8_FREEZE_SUPPORT |
825 | | if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) |
826 | | { |
827 | | p->MaxContext = fSuccessor; |
828 | | p->GlueCount += !(p->Stamps[1] & 1); // why? |
829 | | } |
830 | | else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE) |
831 | | { |
832 | | while (p->MaxContext->Suffix) |
833 | | p->MaxContext = SUFFIX(p->MaxContext); |
834 | | RemoveBinContexts(p, p->MaxContext, 0); |
835 | | // we change the current mode to (PPMD8_RESTORE_METHOD_FREEZE + 1) |
836 | | p->RestoreMethod = PPMD8_RESTORE_METHOD_FREEZE + 1; |
837 | | p->GlueCount = 0; |
838 | | p->OrderFall = p->MaxOrder; |
839 | | } |
840 | | else |
841 | | #endif |
842 | 483 | if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1)) |
843 | 483 | Ppmd8_RestartModel(p); |
844 | 0 | else |
845 | 0 | { |
846 | 0 | while (p->MaxContext->Suffix) |
847 | 0 | p->MaxContext = SUFFIX(p->MaxContext); |
848 | 0 | do |
849 | 0 | { |
850 | 0 | CutOff(p, p->MaxContext, 0); |
851 | 0 | ExpandTextArea(p); |
852 | 0 | } |
853 | 0 | while (GetUsedMemory(p) > 3 * (p->Size >> 2)); |
854 | 0 | p->GlueCount = 0; |
855 | 0 | p->OrderFall = p->MaxOrder; |
856 | 0 | } |
857 | 483 | p->MinContext = p->MaxContext; |
858 | 483 | } |
859 | | |
860 | | |
861 | | |
862 | | Z7_NO_INLINE |
863 | | static PPMD8_CTX_PTR Ppmd8_CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, PPMD8_CTX_PTR c) |
864 | 30.4M | { |
865 | | |
866 | 30.4M | CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); |
867 | 30.4M | Byte newSym, newFreq, flags; |
868 | 30.4M | unsigned numPs = 0; |
869 | 30.4M | CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; /* fixed over Shkarin's code. Maybe it could work without + 1 too. */ |
870 | | |
871 | 30.4M | if (!skip) |
872 | 21.2M | ps[numPs++] = p->FoundState; |
873 | | |
874 | 50.2M | while (c->Suffix) |
875 | 50.0M | { |
876 | 50.0M | CPpmd_Void_Ref successor; |
877 | 50.0M | CPpmd_State *s; |
878 | 50.0M | c = SUFFIX(c); |
879 | | |
880 | 50.0M | if (s1) { s = s1; s1 = NULL; } |
881 | 19.9M | else if (c->NumStats != 0) |
882 | 12.5M | { |
883 | 12.5M | Byte sym = p->FoundState->Symbol; |
884 | 759M | for (s = STATS(c); s->Symbol != sym; s++); |
885 | 12.5M | if (s->Freq < MAX_FREQ - 9) { s->Freq++; c->Union2.SummFreq++; } |
886 | 12.5M | } |
887 | 7.38M | else |
888 | 7.38M | { |
889 | 7.38M | s = ONE_STATE(c); |
890 | 7.38M | s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24))); |
891 | 7.38M | } |
892 | 50.0M | successor = SUCCESSOR(s); |
893 | 50.0M | if (successor != upBranch) |
894 | 30.1M | { |
895 | | |
896 | 30.1M | c = CTX(successor); |
897 | 30.1M | if (numPs == 0) |
898 | 1.82M | { |
899 | | |
900 | | |
901 | 1.82M | return c; |
902 | 1.82M | } |
903 | 28.3M | break; |
904 | 30.1M | } |
905 | 19.8M | ps[numPs++] = s; |
906 | 19.8M | } |
907 | | |
908 | | |
909 | | |
910 | | |
911 | | |
912 | 28.5M | newSym = *(const Byte *)Ppmd8_GetPtr(p, upBranch); |
913 | 28.5M | upBranch++; |
914 | 28.5M | flags = (Byte)(PPMD8_HiBitsFlag_4(p->FoundState->Symbol) + PPMD8_HiBitsFlag_3(newSym)); |
915 | | |
916 | 28.5M | if (c->NumStats == 0) |
917 | 654k | newFreq = c->Union2.State2.Freq; |
918 | 27.9M | else |
919 | 27.9M | { |
920 | 27.9M | UInt32 cf, s0; |
921 | 27.9M | CPpmd_State *s; |
922 | 1.29G | for (s = STATS(c); s->Symbol != newSym; s++); |
923 | 27.9M | cf = (UInt32)s->Freq - 1; |
924 | 27.9M | s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf; |
925 | | /* |
926 | | |
927 | | |
928 | | max(newFreq)= (s->Freq - 1), when (s0 == 1) |
929 | | |
930 | | |
931 | | */ |
932 | 27.9M | newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0))); |
933 | 27.9M | } |
934 | | |
935 | | |
936 | | |
937 | 28.5M | do |
938 | 41.1M | { |
939 | 41.1M | PPMD8_CTX_PTR c1; |
940 | | /* = AllocContext(p); */ |
941 | 41.1M | if (p->HiUnit != p->LoUnit) |
942 | 33.6M | c1 = (PPMD8_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); |
943 | 7.52M | else if (p->FreeList[0] != 0) |
944 | 3.39M | c1 = (PPMD8_CTX_PTR)Ppmd8_RemoveNode(p, 0); |
945 | 4.12M | else |
946 | 4.12M | { |
947 | 4.12M | c1 = (PPMD8_CTX_PTR)Ppmd8_AllocUnitsRare(p, 0); |
948 | 4.12M | if (!c1) |
949 | 10 | return NULL; |
950 | 4.12M | } |
951 | 41.1M | c1->Flags = flags; |
952 | 41.1M | c1->NumStats = 0; |
953 | 41.1M | c1->Union2.State2.Symbol = newSym; |
954 | 41.1M | c1->Union2.State2.Freq = newFreq; |
955 | 41.1M | Ppmd8State_SetSuccessor(ONE_STATE(c1), upBranch); |
956 | 41.1M | c1->Suffix = REF(c); |
957 | 41.1M | Ppmd8State_SetSuccessor(ps[--numPs], REF(c1)); |
958 | 41.1M | c = c1; |
959 | 41.1M | } |
960 | 41.1M | while (numPs != 0); |
961 | | |
962 | 28.5M | return c; |
963 | 28.5M | } |
964 | | |
965 | | |
966 | | static PPMD8_CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, PPMD8_CTX_PTR c) |
967 | 301k | { |
968 | 301k | CPpmd_State *s = NULL; |
969 | 301k | PPMD8_CTX_PTR c1 = c; |
970 | 301k | CPpmd_Void_Ref upBranch = REF(p->Text); |
971 | | |
972 | | #ifdef PPMD8_FREEZE_SUPPORT |
973 | | /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */ |
974 | | CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; |
975 | | unsigned numPs = 0; |
976 | | ps[numPs++] = p->FoundState; |
977 | | #endif |
978 | | |
979 | 301k | Ppmd8State_SetSuccessor(p->FoundState, upBranch); |
980 | 301k | p->OrderFall++; |
981 | | |
982 | 301k | for (;;) |
983 | 301k | { |
984 | 301k | if (s1) |
985 | 0 | { |
986 | 0 | c = SUFFIX(c); |
987 | 0 | s = s1; |
988 | 0 | s1 = NULL; |
989 | 0 | } |
990 | 301k | else |
991 | 301k | { |
992 | 301k | if (!c->Suffix) |
993 | 301k | { |
994 | | #ifdef PPMD8_FREEZE_SUPPORT |
995 | | if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) |
996 | | { |
997 | | do { Ppmd8State_SetSuccessor(ps[--numPs], REF(c)); } while (numPs); |
998 | | RESET_TEXT(1) |
999 | | p->OrderFall = 1; |
1000 | | } |
1001 | | #endif |
1002 | 301k | return c; |
1003 | 301k | } |
1004 | 0 | c = SUFFIX(c); |
1005 | 0 | if (c->NumStats) |
1006 | 0 | { |
1007 | 0 | if ((s = STATS(c))->Symbol != p->FoundState->Symbol) |
1008 | 0 | do { s++; } while (s->Symbol != p->FoundState->Symbol); |
1009 | 0 | if (s->Freq < MAX_FREQ - 9) |
1010 | 0 | { |
1011 | 0 | s->Freq = (Byte)(s->Freq + 2); |
1012 | 0 | c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); |
1013 | 0 | } |
1014 | 0 | } |
1015 | 0 | else |
1016 | 0 | { |
1017 | 0 | s = ONE_STATE(c); |
1018 | 0 | s->Freq = (Byte)(s->Freq + (s->Freq < 32)); |
1019 | 0 | } |
1020 | 0 | } |
1021 | 0 | if (SUCCESSOR(s)) |
1022 | 0 | break; |
1023 | | #ifdef PPMD8_FREEZE_SUPPORT |
1024 | | ps[numPs++] = s; |
1025 | | #endif |
1026 | 0 | Ppmd8State_SetSuccessor(s, upBranch); |
1027 | 0 | p->OrderFall++; |
1028 | 0 | } |
1029 | | |
1030 | | #ifdef PPMD8_FREEZE_SUPPORT |
1031 | | if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) |
1032 | | { |
1033 | | c = CTX(SUCCESSOR(s)); |
1034 | | do { Ppmd8State_SetSuccessor(ps[--numPs], REF(c)); } while (numPs); |
1035 | | RESET_TEXT(1) |
1036 | | p->OrderFall = 1; |
1037 | | return c; |
1038 | | } |
1039 | | else |
1040 | | #endif |
1041 | 0 | if (SUCCESSOR(s) <= upBranch) |
1042 | 0 | { |
1043 | 0 | PPMD8_CTX_PTR successor; |
1044 | 0 | CPpmd_State *s2 = p->FoundState; |
1045 | 0 | p->FoundState = s; |
1046 | |
|
1047 | 0 | successor = Ppmd8_CreateSuccessors(p, False, NULL, c); |
1048 | 0 | if (!successor) |
1049 | 0 | Ppmd8State_SetSuccessor(s, 0); |
1050 | 0 | else |
1051 | 0 | Ppmd8State_SetSuccessor(s, REF(successor)); |
1052 | 0 | p->FoundState = s2; |
1053 | 0 | } |
1054 | | |
1055 | 0 | { |
1056 | 0 | CPpmd_Void_Ref successor = SUCCESSOR(s); |
1057 | 0 | if (p->OrderFall == 1 && c1 == p->MaxContext) |
1058 | 0 | { |
1059 | 0 | Ppmd8State_SetSuccessor(p->FoundState, successor); |
1060 | 0 | p->Text--; |
1061 | 0 | } |
1062 | 0 | if (successor == 0) |
1063 | 0 | return NULL; |
1064 | 0 | return CTX(successor); |
1065 | 0 | } |
1066 | 0 | } |
1067 | | |
1068 | | |
1069 | | |
1070 | | void Ppmd8_UpdateModel(CPpmd8 *p); |
1071 | | Z7_NO_INLINE |
1072 | | void Ppmd8_UpdateModel(CPpmd8 *p) |
1073 | 97.7M | { |
1074 | 97.7M | CPpmd_Void_Ref maxSuccessor, minSuccessor = SUCCESSOR(p->FoundState); |
1075 | 97.7M | PPMD8_CTX_PTR c; |
1076 | 97.7M | unsigned s0, ns, fFreq = p->FoundState->Freq; |
1077 | 97.7M | Byte flag, fSymbol = p->FoundState->Symbol; |
1078 | 97.7M | { |
1079 | 97.7M | CPpmd_State *s = NULL; |
1080 | 97.7M | if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) |
1081 | 53.6M | { |
1082 | | /* Update Freqs in Suffix Context */ |
1083 | | |
1084 | 53.6M | c = SUFFIX(p->MinContext); |
1085 | | |
1086 | 53.6M | if (c->NumStats == 0) |
1087 | 5.48M | { |
1088 | 5.48M | s = ONE_STATE(c); |
1089 | 5.48M | if (s->Freq < 32) |
1090 | 5.47M | s->Freq++; |
1091 | 5.48M | } |
1092 | 48.1M | else |
1093 | 48.1M | { |
1094 | 48.1M | Byte sym = p->FoundState->Symbol; |
1095 | 48.1M | s = STATS(c); |
1096 | | |
1097 | 48.1M | if (s->Symbol != sym) |
1098 | 45.1M | { |
1099 | 45.1M | do |
1100 | 4.76G | { |
1101 | | |
1102 | 4.76G | s++; |
1103 | 4.76G | } |
1104 | 4.76G | while (s->Symbol != sym); |
1105 | | |
1106 | 45.1M | if (s[0].Freq >= s[-1].Freq) |
1107 | 23.5M | { |
1108 | 23.5M | SWAP_STATES(&s[0], &s[-1]); |
1109 | 23.5M | s--; |
1110 | 23.5M | } |
1111 | 45.1M | } |
1112 | | |
1113 | 48.1M | if (s->Freq < MAX_FREQ - 9) |
1114 | 44.6M | { |
1115 | 44.6M | s->Freq = (Byte)(s->Freq + 2); |
1116 | 44.6M | c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); |
1117 | 44.6M | } |
1118 | 48.1M | } |
1119 | 53.6M | } |
1120 | | |
1121 | 97.7M | c = p->MaxContext; |
1122 | 97.7M | if (p->OrderFall == 0 && minSuccessor) |
1123 | 9.11M | { |
1124 | 9.11M | PPMD8_CTX_PTR cs = Ppmd8_CreateSuccessors(p, True, s, p->MinContext); |
1125 | 9.11M | if (!cs) |
1126 | 8 | { |
1127 | 8 | Ppmd8State_SetSuccessor(p->FoundState, 0); |
1128 | 8 | RESTORE_MODEL(c, CTX(minSuccessor)); |
1129 | 8 | return; |
1130 | 8 | } |
1131 | 9.11M | Ppmd8State_SetSuccessor(p->FoundState, REF(cs)); |
1132 | 9.11M | p->MinContext = p->MaxContext = cs; |
1133 | 9.11M | return; |
1134 | 9.11M | } |
1135 | | |
1136 | | |
1137 | | |
1138 | | |
1139 | 88.6M | { |
1140 | 88.6M | Byte *text = p->Text; |
1141 | 88.6M | *text++ = p->FoundState->Symbol; |
1142 | 88.6M | p->Text = text; |
1143 | 88.6M | if (text >= p->UnitsStart) |
1144 | 47 | { |
1145 | 47 | RESTORE_MODEL(c, CTX(minSuccessor)); /* check it */ |
1146 | 47 | return; |
1147 | 47 | } |
1148 | 88.6M | maxSuccessor = REF(text); |
1149 | 88.6M | } |
1150 | | |
1151 | 88.6M | if (!minSuccessor) |
1152 | 301k | { |
1153 | 301k | PPMD8_CTX_PTR cs = ReduceOrder(p, s, p->MinContext); |
1154 | 301k | if (!cs) |
1155 | 0 | { |
1156 | 0 | RESTORE_MODEL(c, NULL); |
1157 | 0 | return; |
1158 | 0 | } |
1159 | 301k | minSuccessor = REF(cs); |
1160 | 301k | } |
1161 | 88.3M | else if ((Byte *)Ppmd8_GetPtr(p, minSuccessor) < p->UnitsStart) |
1162 | 21.2M | { |
1163 | 21.2M | PPMD8_CTX_PTR cs = Ppmd8_CreateSuccessors(p, False, s, p->MinContext); |
1164 | 21.2M | if (!cs) |
1165 | 2 | { |
1166 | 2 | RESTORE_MODEL(c, NULL); |
1167 | 2 | return; |
1168 | 2 | } |
1169 | 21.2M | minSuccessor = REF(cs); |
1170 | 21.2M | } |
1171 | | |
1172 | 88.6M | if (--p->OrderFall == 0) |
1173 | 27.8M | { |
1174 | 27.8M | maxSuccessor = minSuccessor; |
1175 | 27.8M | p->Text -= (p->MaxContext != p->MinContext); |
1176 | 27.8M | } |
1177 | | #ifdef PPMD8_FREEZE_SUPPORT |
1178 | | else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE) |
1179 | | { |
1180 | | maxSuccessor = minSuccessor; |
1181 | | RESET_TEXT(0) |
1182 | | p->OrderFall = 0; |
1183 | | } |
1184 | | #endif |
1185 | 88.6M | } |
1186 | | |
1187 | | |
1188 | | |
1189 | | |
1190 | | |
1191 | | |
1192 | | |
1193 | | |
1194 | | |
1195 | | |
1196 | | |
1197 | | |
1198 | | |
1199 | | |
1200 | | |
1201 | | |
1202 | | |
1203 | | |
1204 | | |
1205 | | |
1206 | | |
1207 | | |
1208 | | |
1209 | | |
1210 | | |
1211 | | |
1212 | | |
1213 | | |
1214 | 88.6M | flag = (Byte)(PPMD8_HiBitsFlag_3(fSymbol)); |
1215 | 88.6M | s0 = p->MinContext->Union2.SummFreq - (ns = p->MinContext->NumStats) - fFreq; |
1216 | | |
1217 | 177M | for (; c != p->MinContext; c = SUFFIX(c)) |
1218 | 88.3M | { |
1219 | 88.3M | unsigned ns1; |
1220 | 88.3M | UInt32 sum; |
1221 | | |
1222 | 88.3M | if ((ns1 = c->NumStats) != 0) |
1223 | 65.9M | { |
1224 | 65.9M | if ((ns1 & 1) != 0) |
1225 | 36.3M | { |
1226 | | /* Expand for one UNIT */ |
1227 | 36.3M | const unsigned oldNU = (ns1 + 1) >> 1; |
1228 | 36.3M | const unsigned i = U2I(oldNU); |
1229 | 36.3M | if (i != U2I((size_t)oldNU + 1)) |
1230 | 22.1M | { |
1231 | 22.1M | void *ptr = Ppmd8_AllocUnits(p, i + 1); |
1232 | 22.1M | void *oldPtr; |
1233 | 22.1M | if (!ptr) |
1234 | 424 | { |
1235 | 424 | RESTORE_MODEL(c, CTX(minSuccessor)); |
1236 | 424 | return; |
1237 | 424 | } |
1238 | 22.1M | oldPtr = STATS(c); |
1239 | 22.1M | MEM_12_CPY(ptr, oldPtr, oldNU) |
1240 | 22.1M | Ppmd8_InsertNode(p, oldPtr, i); |
1241 | 22.1M | c->Union4.Stats = STATS_REF(ptr); |
1242 | 22.1M | } |
1243 | 36.3M | } |
1244 | 65.9M | sum = c->Union2.SummFreq; |
1245 | | /* max increase of Escape_Freq is 1 here. |
1246 | | an average increase is 1/3 per symbol */ |
1247 | 65.9M | sum += (UInt32)(unsigned)(3 * ns1 + 1 < ns); |
1248 | | /* original PPMdH uses 16-bit variable for (sum) here. |
1249 | | But (sum < ???). Do we need to truncate (sum) to 16-bit */ |
1250 | | // sum = (UInt16)sum; |
1251 | 65.9M | } |
1252 | 22.3M | else |
1253 | 22.3M | { |
1254 | | |
1255 | 22.3M | CPpmd_State *s = (CPpmd_State*)Ppmd8_AllocUnits(p, 0); |
1256 | 22.3M | if (!s) |
1257 | 2 | { |
1258 | 2 | RESTORE_MODEL(c, CTX(minSuccessor)); |
1259 | 2 | return; |
1260 | 2 | } |
1261 | 22.3M | { |
1262 | 22.3M | unsigned freq = c->Union2.State2.Freq; |
1263 | | // s = *ONE_STATE(c); |
1264 | 22.3M | s->Symbol = c->Union2.State2.Symbol; |
1265 | 22.3M | s->Successor_0 = c->Union4.State4.Successor_0; |
1266 | 22.3M | s->Successor_1 = c->Union4.State4.Successor_1; |
1267 | | // Ppmd8State_SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of |
1268 | | // (Successor_0 and Successor_1) in LE/BE. |
1269 | 22.3M | c->Union4.Stats = REF(s); |
1270 | 22.3M | if (freq < MAX_FREQ / 4 - 1) |
1271 | 22.3M | freq <<= 1; |
1272 | 16.8k | else |
1273 | 16.8k | freq = MAX_FREQ - 4; |
1274 | | |
1275 | 22.3M | s->Freq = (Byte)freq; |
1276 | | |
1277 | 22.3M | sum = (UInt32)(freq + p->InitEsc + (ns > 2)); // Ppmd8 (> 2) |
1278 | 22.3M | } |
1279 | 22.3M | } |
1280 | | |
1281 | 88.3M | { |
1282 | 88.3M | CPpmd_State *s = STATS(c) + ns1 + 1; |
1283 | 88.3M | UInt32 cf = 2 * (sum + 6) * (UInt32)fFreq; |
1284 | 88.3M | UInt32 sf = (UInt32)s0 + sum; |
1285 | 88.3M | s->Symbol = fSymbol; |
1286 | 88.3M | c->NumStats = (Byte)(ns1 + 1); |
1287 | 88.3M | Ppmd8State_SetSuccessor(s, maxSuccessor); |
1288 | 88.3M | c->Flags |= flag; |
1289 | 88.3M | if (cf < 6 * sf) |
1290 | 70.8M | { |
1291 | 70.8M | cf = (unsigned)1 + (cf > sf) + (cf >= 4 * sf); |
1292 | 70.8M | sum += 4; |
1293 | | /* It can add (1, 2, 3) to Escape_Freq */ |
1294 | 70.8M | } |
1295 | 17.5M | else |
1296 | 17.5M | { |
1297 | 17.5M | cf = (unsigned)4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf); |
1298 | 17.5M | sum += cf; |
1299 | 17.5M | } |
1300 | | |
1301 | 88.3M | c->Union2.SummFreq = (UInt16)sum; |
1302 | 88.3M | s->Freq = (Byte)cf; |
1303 | 88.3M | } |
1304 | | |
1305 | 88.3M | } |
1306 | 88.6M | p->MaxContext = p->MinContext = CTX(minSuccessor); |
1307 | 88.6M | } |
1308 | | |
1309 | | |
1310 | | |
1311 | | Z7_NO_INLINE |
1312 | | static void Ppmd8_Rescale(CPpmd8 *p) |
1313 | 309k | { |
1314 | 309k | unsigned i, adder, sumFreq, escFreq; |
1315 | 309k | CPpmd_State *stats = STATS(p->MinContext); |
1316 | 309k | CPpmd_State *s = p->FoundState; |
1317 | | |
1318 | | /* Sort the list by Freq */ |
1319 | 309k | if (s != stats) |
1320 | 27.5k | { |
1321 | 27.5k | CPpmd_State tmp = *s; |
1322 | 27.5k | do |
1323 | 1.72M | s[0] = s[-1]; |
1324 | 1.72M | while (--s != stats); |
1325 | 27.5k | *s = tmp; |
1326 | 27.5k | } |
1327 | | |
1328 | 309k | sumFreq = s->Freq; |
1329 | 309k | escFreq = p->MinContext->Union2.SummFreq - sumFreq; |
1330 | | |
1331 | | |
1332 | | |
1333 | | |
1334 | | |
1335 | | |
1336 | 309k | adder = (p->OrderFall != 0); |
1337 | | |
1338 | | #ifdef PPMD8_FREEZE_SUPPORT |
1339 | | adder |= (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE); |
1340 | | #endif |
1341 | | |
1342 | 309k | sumFreq = (sumFreq + 4 + adder) >> 1; |
1343 | 309k | i = p->MinContext->NumStats; |
1344 | 309k | s->Freq = (Byte)sumFreq; |
1345 | | |
1346 | 309k | do |
1347 | 38.5M | { |
1348 | 38.5M | unsigned freq = (++s)->Freq; |
1349 | 38.5M | escFreq -= freq; |
1350 | 38.5M | freq = (freq + adder) >> 1; |
1351 | 38.5M | sumFreq += freq; |
1352 | 38.5M | s->Freq = (Byte)freq; |
1353 | 38.5M | if (freq > s[-1].Freq) |
1354 | 12.6M | { |
1355 | 12.6M | CPpmd_State tmp = *s; |
1356 | 12.6M | CPpmd_State *s1 = s; |
1357 | 12.6M | do |
1358 | 802M | { |
1359 | 802M | s1[0] = s1[-1]; |
1360 | 802M | } |
1361 | 802M | while (--s1 != stats && freq > s1[-1].Freq); |
1362 | 12.6M | *s1 = tmp; |
1363 | 12.6M | } |
1364 | 38.5M | } |
1365 | 38.5M | while (--i); |
1366 | | |
1367 | 309k | if (s->Freq == 0) |
1368 | 74.8k | { |
1369 | | /* Remove all items with Freq == 0 */ |
1370 | 74.8k | CPpmd8_Context *mc; |
1371 | 74.8k | unsigned numStats, numStatsNew, n0, n1; |
1372 | | |
1373 | 616k | i = 0; do { i++; } while ((--s)->Freq == 0); |
1374 | | |
1375 | | |
1376 | | |
1377 | | |
1378 | 74.8k | escFreq += i; |
1379 | 74.8k | mc = p->MinContext; |
1380 | 74.8k | numStats = mc->NumStats; |
1381 | 74.8k | numStatsNew = numStats - i; |
1382 | 74.8k | mc->NumStats = (Byte)(numStatsNew); |
1383 | 74.8k | n0 = (numStats + 2) >> 1; |
1384 | | |
1385 | 74.8k | if (numStatsNew == 0) |
1386 | 15.5k | { |
1387 | | |
1388 | 15.5k | unsigned freq = (2 * (unsigned)stats->Freq + escFreq - 1) / escFreq; |
1389 | 15.5k | if (freq > MAX_FREQ / 3) |
1390 | 3.74k | freq = MAX_FREQ / 3; |
1391 | 15.5k | mc->Flags = (Byte)((mc->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(stats->Symbol)); |
1392 | | |
1393 | | |
1394 | | |
1395 | | |
1396 | | |
1397 | 15.5k | s = ONE_STATE(mc); |
1398 | 15.5k | *s = *stats; |
1399 | 15.5k | s->Freq = (Byte)freq; |
1400 | 15.5k | p->FoundState = s; |
1401 | 15.5k | Ppmd8_InsertNode(p, stats, U2I(n0)); |
1402 | 15.5k | return; |
1403 | 15.5k | } |
1404 | | |
1405 | 59.2k | n1 = (numStatsNew + 2) >> 1; |
1406 | 59.2k | if (n0 != n1) |
1407 | 54.0k | mc->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); |
1408 | 59.2k | { |
1409 | | // here we are for max order only. So Ppmd8_MakeEscFreq() doesn't use mc->Flags |
1410 | | // but we still need current (Flags & FLAG_PREV_HIGH), if we will convert context to 1-symbol context later. |
1411 | | /* |
1412 | | unsigned flags = HiBits_Prepare((s = STATS(mc))->Symbol); |
1413 | | i = mc->NumStats; |
1414 | | do { flags |= HiBits_Prepare((++s)->Symbol); } while (--i); |
1415 | | mc->Flags = (Byte)((mc->Flags & ~FLAG_SYM_HIGH) + HiBits_Convert_3(flags)); |
1416 | | */ |
1417 | 59.2k | } |
1418 | 59.2k | } |
1419 | | |
1420 | | |
1421 | | |
1422 | | |
1423 | | |
1424 | | |
1425 | 293k | { |
1426 | 293k | CPpmd8_Context *mc = p->MinContext; |
1427 | 293k | mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); |
1428 | 293k | mc->Flags |= FLAG_RESCALED; |
1429 | 293k | p->FoundState = STATS(mc); |
1430 | 293k | } |
1431 | 293k | } |
1432 | | |
1433 | | |
1434 | | CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq) |
1435 | 86.4M | { |
1436 | 86.4M | CPpmd_See *see; |
1437 | 86.4M | const CPpmd8_Context *mc = p->MinContext; |
1438 | 86.4M | unsigned numStats = mc->NumStats; |
1439 | 86.4M | if (numStats != 0xFF) |
1440 | 45.6M | { |
1441 | | // (3 <= numStats + 2 <= 256) (3 <= NS2Indx[3] and NS2Indx[256] === 26) |
1442 | 45.6M | see = p->See[(size_t)(unsigned)p->NS2Indx[(size_t)numStats + 2] - 3] |
1443 | 45.6M | + (mc->Union2.SummFreq > 11 * (numStats + 1)) |
1444 | 45.6M | + 2 * (unsigned)(2 * numStats < ((unsigned)SUFFIX(mc)->NumStats + numMasked1)) |
1445 | 45.6M | + mc->Flags; |
1446 | | |
1447 | 45.6M | { |
1448 | | // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ |
1449 | 45.6M | const unsigned summ = (UInt16)see->Summ; // & 0xFFFF |
1450 | 45.6M | const unsigned r = (summ >> see->Shift); |
1451 | 45.6M | see->Summ = (UInt16)(summ - r); |
1452 | 45.6M | *escFreq = (UInt32)(r + (r == 0)); |
1453 | 45.6M | } |
1454 | 45.6M | } |
1455 | 40.8M | else |
1456 | 40.8M | { |
1457 | 40.8M | see = &p->DummySee; |
1458 | 40.8M | *escFreq = 1; |
1459 | 40.8M | } |
1460 | 86.4M | return see; |
1461 | 86.4M | } |
1462 | | |
1463 | | |
1464 | | static void Ppmd8_NextContext(CPpmd8 *p) |
1465 | 26.2M | { |
1466 | 26.2M | PPMD8_CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); |
1467 | 26.2M | if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart) |
1468 | 7.63M | p->MaxContext = p->MinContext = c; |
1469 | 18.5M | else |
1470 | 18.5M | Ppmd8_UpdateModel(p); |
1471 | 26.2M | } |
1472 | | |
1473 | | |
1474 | | void Ppmd8_Update1(CPpmd8 *p) |
1475 | 20.1M | { |
1476 | 20.1M | CPpmd_State *s = p->FoundState; |
1477 | 20.1M | unsigned freq = s->Freq; |
1478 | 20.1M | freq += 4; |
1479 | 20.1M | p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); |
1480 | 20.1M | s->Freq = (Byte)freq; |
1481 | 20.1M | if (freq > s[-1].Freq) |
1482 | 15.4M | { |
1483 | 15.4M | SWAP_STATES(s, &s[-1]); |
1484 | 15.4M | p->FoundState = --s; |
1485 | 15.4M | if (freq > MAX_FREQ) |
1486 | 2.11k | Ppmd8_Rescale(p); |
1487 | 15.4M | } |
1488 | 20.1M | Ppmd8_NextContext(p); |
1489 | 20.1M | } |
1490 | | |
1491 | | |
1492 | | void Ppmd8_Update1_0(CPpmd8 *p) |
1493 | 6.08M | { |
1494 | 6.08M | CPpmd_State *s = p->FoundState; |
1495 | 6.08M | CPpmd8_Context *mc = p->MinContext; |
1496 | 6.08M | unsigned freq = s->Freq; |
1497 | 6.08M | const unsigned summFreq = mc->Union2.SummFreq; |
1498 | 6.08M | p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=) |
1499 | 6.08M | p->RunLength += (Int32)p->PrevSuccess; |
1500 | 6.08M | mc->Union2.SummFreq = (UInt16)(summFreq + 4); |
1501 | 6.08M | freq += 4; |
1502 | 6.08M | s->Freq = (Byte)freq; |
1503 | 6.08M | if (freq > MAX_FREQ) |
1504 | 164k | Ppmd8_Rescale(p); |
1505 | 6.08M | Ppmd8_NextContext(p); |
1506 | 6.08M | } |
1507 | | |
1508 | | |
1509 | | /* |
1510 | | void Ppmd8_UpdateBin(CPpmd8 *p) |
1511 | | { |
1512 | | unsigned freq = p->FoundState->Freq; |
1513 | | p->FoundState->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196) |
1514 | | p->PrevSuccess = 1; |
1515 | | p->RunLength++; |
1516 | | Ppmd8_NextContext(p); |
1517 | | } |
1518 | | */ |
1519 | | |
1520 | | void Ppmd8_Update2(CPpmd8 *p) |
1521 | 70.0M | { |
1522 | 70.0M | CPpmd_State *s = p->FoundState; |
1523 | 70.0M | unsigned freq = s->Freq; |
1524 | 70.0M | freq += 4; |
1525 | 70.0M | p->RunLength = p->InitRL; |
1526 | 70.0M | p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); |
1527 | 70.0M | s->Freq = (Byte)freq; |
1528 | 70.0M | if (freq > MAX_FREQ) |
1529 | 142k | Ppmd8_Rescale(p); |
1530 | 70.0M | Ppmd8_UpdateModel(p); |
1531 | 70.0M | } |
1532 | | |
1533 | | /* H->I changes: |
1534 | | NS2Indx |
1535 | | GlueCount, and Glue method |
1536 | | BinSum |
1537 | | See / EscFreq |
1538 | | Ppmd8_CreateSuccessors updates more suffix contexts |
1539 | | Ppmd8_UpdateModel consts. |
1540 | | PrevSuccess Update |
1541 | | |
1542 | | Flags: |
1543 | | (1 << 2) - the Context was Rescaled |
1544 | | (1 << 3) - there is symbol in Stats with (sym >= 0x40) in |
1545 | | (1 << 4) - main symbol of context is (sym >= 0x40) |
1546 | | */ |
1547 | | |
1548 | | #undef RESET_TEXT |
1549 | | #undef FLAG_RESCALED |
1550 | | #undef FLAG_PREV_HIGH |
1551 | | #undef HiBits_Prepare |
1552 | | #undef HiBits_Convert_3 |
1553 | | #undef HiBits_Convert_4 |
1554 | | #undef PPMD8_HiBitsFlag_3 |
1555 | | #undef PPMD8_HiBitsFlag_4 |
1556 | | #undef RESTORE_MODEL |
1557 | | |
1558 | | #undef MAX_FREQ |
1559 | | #undef UNIT_SIZE |
1560 | | #undef U2B |
1561 | | #undef U2I |
1562 | | #undef I2U |
1563 | | |
1564 | | #undef REF |
1565 | | #undef STATS_REF |
1566 | | #undef CTX |
1567 | | #undef STATS |
1568 | | #undef ONE_STATE |
1569 | | #undef SUFFIX |
1570 | | #undef NODE |
1571 | | #undef EMPTY_NODE |
1572 | | #undef MEM_12_CPY |
1573 | | #undef SUCCESSOR |
1574 | | #undef SWAP_STATES |