]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_ppmd8.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / archive_ppmd8.c
1 /* Ppmd8.c -- PPMdI codec
2 2016-05-21 : Igor Pavlov : Public domain
3 This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
4
5 #include "archive_platform.h"
6
7 #include <string.h>
8
9 #include "archive_ppmd8_private.h"
10
11 const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
12 static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
13
14 #define MAX_FREQ 124
15 #define UNIT_SIZE 12
16
17 #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
18 #define U2I(nu) (p->Units2Indx[(nu) - 1])
19 #define I2U(indx) (p->Indx2Units[indx])
20
21 #ifdef PPMD_32BIT
22   #define REF(ptr) (ptr)
23 #else
24   #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
25 #endif
26
27 #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
28
29 #define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))
30 #define STATS(ctx) Ppmd8_GetStats(p, ctx)
31 #define ONE_STATE(ctx) Ppmd8Context_OneState(ctx)
32 #define SUFFIX(ctx) CTX((ctx)->Suffix)
33
34 #define kTop (1 << 24)
35 #define kBot (1 << 15)
36
37 typedef CPpmd8_Context * CTX_PTR;
38
39 struct CPpmd8_Node_;
40
41 typedef
42   #ifdef PPMD_32BIT
43     struct CPpmd8_Node_ *
44   #else
45     UInt32
46   #endif
47   CPpmd8_Node_Ref;
48
49 typedef struct CPpmd8_Node_
50 {
51   UInt32 Stamp;
52   CPpmd8_Node_Ref Next;
53   UInt32 NU;
54 } CPpmd8_Node;
55
56 #ifdef PPMD_32BIT
57   #define NODE(ptr) (ptr)
58 #else
59   #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs)))
60 #endif
61
62 #define EMPTY_NODE 0xFFFFFFFF
63
64 void Ppmd8_Construct(CPpmd8 *p)
65 {
66   unsigned i, k, m;
67
68   p->Base = 0;
69
70   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
71   {
72     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
73     do { p->Units2Indx[k++] = (Byte)i; } while (--step);
74     p->Indx2Units[i] = (Byte)k;
75   }
76
77   p->NS2BSIndx[0] = (0 << 1);
78   p->NS2BSIndx[1] = (1 << 1);
79   memset(p->NS2BSIndx + 2, (2 << 1), 9);
80   memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
81
82   for (i = 0; i < 5; i++)
83     p->NS2Indx[i] = (Byte)i;
84   for (m = i, k = 1; i < 260; i++)
85   {
86     p->NS2Indx[i] = (Byte)m;
87     if (--k == 0)
88       k = (++m) - 4;
89   }
90 }
91
92 void Ppmd8_Free(CPpmd8 *p)
93 {
94   free(p->Base);
95   p->Size = 0;
96   p->Base = 0;
97 }
98
99 Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size)
100 {
101   if (p->Base == 0 || p->Size != size)
102   {
103     Ppmd8_Free(p);
104     p->AlignOffset =
105       #ifdef PPMD_32BIT
106         (4 - size) & 3;
107       #else
108         4 - (size & 3);
109       #endif
110     if ((p->Base = (Byte *)malloc(p->AlignOffset + size)) == 0)
111       return False;
112     p->Size = size;
113   }
114   return True;
115 }
116
117 static void InsertNode(CPpmd8 *p, void *node, unsigned indx)
118 {
119   ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;
120   ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx];
121   ((CPpmd8_Node *)node)->NU = I2U(indx);
122   p->FreeList[indx] = REF(node);
123   p->Stamps[indx]++;
124 }
125
126 static void *RemoveNode(CPpmd8 *p, unsigned indx)
127 {
128   CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);
129   p->FreeList[indx] = node->Next;
130   p->Stamps[indx]--;
131   return node;
132 }
133
134 static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
135 {
136   unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
137   ptr = (Byte *)ptr + U2B(I2U(newIndx));
138   if (I2U(i = U2I(nu)) != nu)
139   {
140     unsigned k = I2U(--i);
141     InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
142   }
143   InsertNode(p, ptr, i);
144 }
145
146 static void GlueFreeBlocks(CPpmd8 *p)
147 {
148   CPpmd8_Node_Ref head = 0;
149   CPpmd8_Node_Ref *prev = &head;
150   unsigned i;
151
152   p->GlueCount = 1 << 13;
153   memset(p->Stamps, 0, sizeof(p->Stamps));
154   
155   /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end.
156      All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */
157   if (p->LoUnit != p->HiUnit)
158     ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
159
160   /* Glue free blocks */
161   for (i = 0; i < PPMD_NUM_INDEXES; i++)
162   {
163     CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];
164     p->FreeList[i] = 0;
165     while (next != 0)
166     {
167       CPpmd8_Node *node = NODE(next);
168       if (node->NU != 0)
169       {
170         CPpmd8_Node *node2;
171         *prev = next;
172         prev = &(node->Next);
173         while ((node2 = node + node->NU)->Stamp == EMPTY_NODE)
174         {
175           node->NU += node2->NU;
176           node2->NU = 0;
177         }
178       }
179       next = node->Next;
180     }
181   }
182   *prev = 0;
183   
184   /* Fill lists of free blocks */
185   while (head != 0)
186   {
187     CPpmd8_Node *node = NODE(head);
188     unsigned nu;
189     head = node->Next;
190     nu = node->NU;
191     if (nu == 0)
192       continue;
193     for (; nu > 128; nu -= 128, node += 128)
194       InsertNode(p, node, PPMD_NUM_INDEXES - 1);
195     if (I2U(i = U2I(nu)) != nu)
196     {
197       unsigned k = I2U(--i);
198       InsertNode(p, node + k, nu - k - 1);
199     }
200     InsertNode(p, node, i);
201   }
202 }
203
204 static void *AllocUnitsRare(CPpmd8 *p, unsigned indx)
205 {
206   unsigned i;
207   void *retVal;
208   if (p->GlueCount == 0)
209   {
210     GlueFreeBlocks(p);
211     if (p->FreeList[indx] != 0)
212       return RemoveNode(p, indx);
213   }
214   i = indx;
215   do
216   {
217     if (++i == PPMD_NUM_INDEXES)
218     {
219       UInt32 numBytes = U2B(I2U(indx));
220       p->GlueCount--;
221       return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
222     }
223   }
224   while (p->FreeList[i] == 0);
225   retVal = RemoveNode(p, i);
226   SplitBlock(p, retVal, i, indx);
227   return retVal;
228 }
229
230 static void *AllocUnits(CPpmd8 *p, unsigned indx)
231 {
232   UInt32 numBytes;
233   if (p->FreeList[indx] != 0)
234     return RemoveNode(p, indx);
235   numBytes = U2B(I2U(indx));
236   if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
237   {
238     void *retVal = p->LoUnit;
239     p->LoUnit += numBytes;
240     return retVal;
241   }
242   return AllocUnitsRare(p, indx);
243 }
244
245 #define MyMem12Cpy(dest, src, num) \
246   { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
247     do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
248
249 static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
250 {
251   unsigned i0 = U2I(oldNU);
252   unsigned i1 = U2I(newNU);
253   if (i0 == i1)
254     return oldPtr;
255   if (p->FreeList[i1] != 0)
256   {
257     void *ptr = RemoveNode(p, i1);
258     MyMem12Cpy(ptr, oldPtr, newNU);
259     InsertNode(p, oldPtr, i0);
260     return ptr;
261   }
262   SplitBlock(p, oldPtr, i0, i1);
263   return oldPtr;
264 }
265
266 static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)
267 {
268   InsertNode(p, ptr, U2I(nu));
269 }
270
271 static void SpecialFreeUnit(CPpmd8 *p, void *ptr)
272 {
273   if ((Byte *)ptr != p->UnitsStart)
274     InsertNode(p, ptr, 0);
275   else
276   {
277     #ifdef PPMD8_FREEZE_SUPPORT
278     *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */
279     #endif
280     p->UnitsStart += UNIT_SIZE;
281   }
282 }
283
284 static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)
285 {
286   unsigned indx = U2I(nu);
287   void *ptr;
288   if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx])
289     return oldPtr;
290   ptr = RemoveNode(p, indx);
291   MyMem12Cpy(ptr, oldPtr, nu);
292   if ((Byte*)oldPtr != p->UnitsStart)
293     InsertNode(p, oldPtr, indx);
294   else
295     p->UnitsStart += U2B(I2U(indx));
296   return ptr;
297 }
298
299 static void ExpandTextArea(CPpmd8 *p)
300 {
301   UInt32 count[PPMD_NUM_INDEXES];
302   unsigned i;
303   memset(count, 0, sizeof(count));
304   if (p->LoUnit != p->HiUnit)
305     ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
306   
307   {
308     CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart;
309     for (; node->Stamp == EMPTY_NODE; node += node->NU)
310     {
311       node->Stamp = 0;
312       count[U2I(node->NU)]++;
313     }
314     p->UnitsStart = (Byte *)node;
315   }
316   
317   for (i = 0; i < PPMD_NUM_INDEXES; i++)
318   {
319     CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i];
320     while (count[i] != 0)
321     {
322       CPpmd8_Node *node = NODE(*next);
323       while (node->Stamp == 0)
324       {
325         *next = node->Next;
326         node = NODE(*next);
327         p->Stamps[i]--;
328         if (--count[i] == 0)
329           break;
330       }
331       next = &node->Next;
332     }
333   }
334 }
335
336 #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
337
338 static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
339 {
340   (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
341   (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
342 }
343
344 #define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
345
346 static void RestartModel(CPpmd8 *p)
347 {
348   unsigned i, k, m, r;
349
350   memset(p->FreeList, 0, sizeof(p->FreeList));
351   memset(p->Stamps, 0, sizeof(p->Stamps));
352   RESET_TEXT(0);
353   p->HiUnit = p->Text + p->Size;
354   p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
355   p->GlueCount = 0;
356
357   p->OrderFall = p->MaxOrder;
358   p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
359   p->PrevSuccess = 0;
360
361   p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
362   p->MinContext->Suffix = 0;
363   p->MinContext->NumStats = 255;
364   p->MinContext->Flags = 0;
365   p->MinContext->SummFreq = 256 + 1;
366   p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
367   p->LoUnit += U2B(256 / 2);
368   p->MinContext->Stats = REF(p->FoundState);
369   for (i = 0; i < 256; i++)
370   {
371     CPpmd_State *s = &p->FoundState[i];
372     s->Symbol = (Byte)i;
373     s->Freq = 1;
374     SetSuccessor(s, 0);
375   }
376
377   for (i = m = 0; m < 25; m++)
378   {
379     while (p->NS2Indx[i] == m)
380       i++;
381     for (k = 0; k < 8; k++)
382     {
383       UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));
384       UInt16 *dest = p->BinSumm[m] + k;
385       for (r = 0; r < 64; r += 8)
386         dest[r] = val;
387     }
388   }
389
390   for (i = m = 0; m < 24; m++)
391   {
392     while (p->NS2Indx[i + 3] == m + 3)
393       i++;
394     for (k = 0; k < 32; k++)
395     {
396       CPpmd_See *s = &p->See[m][k];
397       s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4));
398       s->Count = 7;
399     }
400   }
401 }
402
403 void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)
404 {
405   p->MaxOrder = maxOrder;
406   p->RestoreMethod = restoreMethod;
407   RestartModel(p);
408   p->DummySee.Shift = PPMD_PERIOD_BITS;
409   p->DummySee.Summ = 0; /* unused */
410   p->DummySee.Count = 64; /* unused */
411 }
412
413 static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)
414 {
415   unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
416   CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
417   ctx->Stats = REF(s);
418   #ifdef PPMD8_FREEZE_SUPPORT
419   /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */
420   scale |= (ctx->SummFreq >= ((UInt32)1 << 15));
421   #endif
422   flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
423   escFreq = ctx->SummFreq - s->Freq;
424   sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));
425   do
426   {
427     escFreq -= (++s)->Freq;
428     sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale));
429     flags |= 0x08 * (s->Symbol >= 0x40);
430   }
431   while (--i);
432   ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));
433   ctx->Flags = (Byte)flags;
434 }
435
436 static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
437 {
438   CPpmd_State tmp = *t1;
439   *t1 = *t2;
440   *t2 = tmp;
441 }
442
443 static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order)
444 {
445   int i;
446   unsigned tmp;
447   CPpmd_State *s;
448   
449   if (!ctx->NumStats)
450   {
451     s = ONE_STATE(ctx);
452     if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart)
453     {
454       if (order < p->MaxOrder)
455         SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
456       else
457         SetSuccessor(s, 0);
458       if (SUCCESSOR(s) || order <= 9) /* O_BOUND */
459         return REF(ctx);
460     }
461     SpecialFreeUnit(p, ctx);
462     return 0;
463   }
464
465   ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1));
466
467   for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--)
468     if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart)
469     {
470       CPpmd_State *s2 = STATS(ctx) + (i--);
471       SetSuccessor(s, 0);
472       SwapStates(s, s2);
473     }
474     else if (order < p->MaxOrder)
475       SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
476     else
477       SetSuccessor(s, 0);
478     
479   if (i != ctx->NumStats && order)
480   {
481     ctx->NumStats = (Byte)i;
482     s = STATS(ctx);
483     if (i < 0)
484     {
485       FreeUnits(p, s, tmp);
486       SpecialFreeUnit(p, ctx);
487       return 0;
488     }
489     if (i == 0)
490     {
491       ctx->Flags = (Byte)((ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
492       *ONE_STATE(ctx) = *s;
493       FreeUnits(p, s, tmp);
494       /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */
495       ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3);
496     }
497     else
498       Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i);
499   }
500   return REF(ctx);
501 }
502
503 #ifdef PPMD8_FREEZE_SUPPORT
504 static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order)
505 {
506   CPpmd_State *s;
507   if (!ctx->NumStats)
508   {
509     s = ONE_STATE(ctx);
510     if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
511       SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
512     else
513       SetSuccessor(s, 0);
514     /* Suffix context can be removed already, since different (high-order)
515        Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */
516     if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))
517     {
518       FreeUnits(p, ctx, 1);
519       return 0;
520     }
521     else
522       return REF(ctx);
523   }
524
525   for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--)
526     if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
527       SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
528     else
529       SetSuccessor(s, 0);
530   
531   return REF(ctx);
532 }
533 #endif
534
535 static UInt32 GetUsedMemory(const CPpmd8 *p)
536 {
537   UInt32 v = 0;
538   unsigned i;
539   for (i = 0; i < PPMD_NUM_INDEXES; i++)
540     v += p->Stamps[i] * I2U(i);
541   return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v);
542 }
543
544 #ifdef PPMD8_FREEZE_SUPPORT
545   #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor)
546 #else
547   #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)
548 #endif
549
550 static void RestoreModel(CPpmd8 *p, CTX_PTR c1
551     #ifdef PPMD8_FREEZE_SUPPORT
552     , CTX_PTR fSuccessor
553     #endif
554     )
555 {
556   CTX_PTR c;
557   CPpmd_State *s;
558   RESET_TEXT(0);
559   for (c = p->MaxContext; c != c1; c = SUFFIX(c))
560     if (--(c->NumStats) == 0)
561     {
562       s = STATS(c);
563       c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
564       *ONE_STATE(c) = *s;
565       SpecialFreeUnit(p, s);
566       ONE_STATE(c)->Freq = (Byte)(((unsigned)ONE_STATE(c)->Freq + 11) >> 3);
567     }
568     else
569       Refresh(p, c, (c->NumStats+3) >> 1, 0);
570  
571   for (; c != p->MinContext; c = SUFFIX(c))
572     if (!c->NumStats)
573       ONE_STATE(c)->Freq = (Byte)(ONE_STATE(c)->Freq - (ONE_STATE(c)->Freq >> 1));
574     else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats)
575       Refresh(p, c, (c->NumStats + 2) >> 1, 1);
576
577   #ifdef PPMD8_FREEZE_SUPPORT
578   if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
579   {
580     p->MaxContext = fSuccessor;
581     p->GlueCount += !(p->Stamps[1] & 1);
582   }
583   else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)
584   {
585     while (p->MaxContext->Suffix)
586       p->MaxContext = SUFFIX(p->MaxContext);
587     RemoveBinContexts(p, p->MaxContext, 0);
588     p->RestoreMethod++;
589     p->GlueCount = 0;
590     p->OrderFall = p->MaxOrder;
591   }
592   else
593   #endif
594   if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1))
595     RestartModel(p);
596   else
597   {
598     while (p->MaxContext->Suffix)
599       p->MaxContext = SUFFIX(p->MaxContext);
600     do
601     {
602       CutOff(p, p->MaxContext, 0);
603       ExpandTextArea(p);
604     }
605     while (GetUsedMemory(p) > 3 * (p->Size >> 2));
606     p->GlueCount = 0;
607     p->OrderFall = p->MaxOrder;
608   }
609 }
610
611 static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c)
612 {
613   CPpmd_State upState;
614   Byte flags;
615   CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
616   /* fixed over Shkarin's code. Maybe it could work without + 1 too. */
617   CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
618   unsigned numPs = 0;
619   
620   if (!skip)
621     ps[numPs++] = p->FoundState;
622   
623   while (c->Suffix)
624   {
625     CPpmd_Void_Ref successor;
626     CPpmd_State *s;
627     c = SUFFIX(c);
628     if (s1)
629     {
630       s = s1;
631       s1 = NULL;
632     }
633     else if (c->NumStats != 0)
634     {
635       for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
636       if (s->Freq < MAX_FREQ - 9)
637       {
638         s->Freq++;
639         c->SummFreq++;
640       }
641     }
642     else
643     {
644       s = ONE_STATE(c);
645       s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24)));
646     }
647     successor = SUCCESSOR(s);
648     if (successor != upBranch)
649     {
650       c = CTX(successor);
651       if (numPs == 0)
652         return c;
653       break;
654     }
655     ps[numPs++] = s;
656   }
657   
658   upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch);
659   SetSuccessor(&upState, upBranch + 1);
660   flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40));
661
662   if (c->NumStats == 0)
663     upState.Freq = ONE_STATE(c)->Freq;
664   else
665   {
666     UInt32 cf, s0;
667     CPpmd_State *s;
668     for (s = STATS(c); s->Symbol != upState.Symbol; s++);
669     cf = s->Freq - 1;
670     s0 = c->SummFreq - c->NumStats - cf;
671     upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
672   }
673
674   do
675   {
676     /* Create Child */
677     CTX_PTR c1; /* = AllocContext(p); */
678     if (p->HiUnit != p->LoUnit)
679       c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
680     else if (p->FreeList[0] != 0)
681       c1 = (CTX_PTR)RemoveNode(p, 0);
682     else
683     {
684       c1 = (CTX_PTR)AllocUnitsRare(p, 0);
685       if (!c1)
686         return NULL;
687     }
688     c1->NumStats = 0;
689     c1->Flags = flags;
690     *ONE_STATE(c1) = upState;
691     c1->Suffix = REF(c);
692     SetSuccessor(ps[--numPs], REF(c1));
693     c = c1;
694   }
695   while (numPs != 0);
696   
697   return c;
698 }
699
700 static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
701 {
702   CPpmd_State *s = NULL;
703   CTX_PTR c1 = c;
704   CPpmd_Void_Ref upBranch = REF(p->Text);
705   
706   #ifdef PPMD8_FREEZE_SUPPORT
707   /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */
708   CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
709   unsigned numPs = 0;
710   ps[numPs++] = p->FoundState;
711   #endif
712
713   SetSuccessor(p->FoundState, upBranch);
714   p->OrderFall++;
715
716   for (;;)
717   {
718     if (s1)
719     {
720       c = SUFFIX(c);
721       s = s1;
722       s1 = NULL;
723     }
724     else
725     {
726       if (!c->Suffix)
727       {
728         #ifdef PPMD8_FREEZE_SUPPORT
729         if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
730         {
731           do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
732           RESET_TEXT(1);
733           p->OrderFall = 1;
734         }
735         #endif
736         return c;
737       }
738       c = SUFFIX(c);
739       if (c->NumStats)
740       {
741         if ((s = STATS(c))->Symbol != p->FoundState->Symbol)
742           do { s++; } while (s->Symbol != p->FoundState->Symbol);
743         if (s->Freq < MAX_FREQ - 9)
744         {
745           s->Freq += 2;
746           c->SummFreq += 2;
747         }
748       }
749       else
750       {
751         s = ONE_STATE(c);
752         s->Freq = (Byte)(s->Freq + (s->Freq < 32));
753       }
754     }
755     if (SUCCESSOR(s))
756       break;
757     #ifdef PPMD8_FREEZE_SUPPORT
758     ps[numPs++] = s;
759     #endif
760     SetSuccessor(s, upBranch);
761     p->OrderFall++;
762   }
763   
764   #ifdef PPMD8_FREEZE_SUPPORT
765   if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
766   {
767     c = CTX(SUCCESSOR(s));
768     do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
769     RESET_TEXT(1);
770     p->OrderFall = 1;
771     return c;
772   }
773   else
774   #endif
775   if (SUCCESSOR(s) <= upBranch)
776   {
777     CTX_PTR successor;
778     CPpmd_State *s2 = p->FoundState;
779     p->FoundState = s;
780
781     successor = CreateSuccessors(p, False, NULL, c);
782     if (successor == NULL)
783       SetSuccessor(s, 0);
784     else
785       SetSuccessor(s, REF(successor));
786     p->FoundState = s2;
787   }
788   
789   if (p->OrderFall == 1 && c1 == p->MaxContext)
790   {
791     SetSuccessor(p->FoundState, SUCCESSOR(s));
792     p->Text--;
793   }
794   if (SUCCESSOR(s) == 0)
795     return NULL;
796   return CTX(SUCCESSOR(s));
797 }
798
799 static void UpdateModel(CPpmd8 *p)
800 {
801   CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
802   CTX_PTR c;
803   unsigned s0, ns, fFreq = p->FoundState->Freq;
804   Byte flag, fSymbol = p->FoundState->Symbol;
805   CPpmd_State *s = NULL;
806   
807   if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
808   {
809     c = SUFFIX(p->MinContext);
810     
811     if (c->NumStats == 0)
812     {
813       s = ONE_STATE(c);
814       if (s->Freq < 32)
815         s->Freq++;
816     }
817     else
818     {
819       s = STATS(c);
820       if (s->Symbol != p->FoundState->Symbol)
821       {
822         do { s++; } while (s->Symbol != p->FoundState->Symbol);
823         if (s[0].Freq >= s[-1].Freq)
824         {
825           SwapStates(&s[0], &s[-1]);
826           s--;
827         }
828       }
829       if (s->Freq < MAX_FREQ - 9)
830       {
831         s->Freq += 2;
832         c->SummFreq += 2;
833       }
834     }
835   }
836   
837   c = p->MaxContext;
838   if (p->OrderFall == 0 && fSuccessor)
839   {
840     CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext);
841     if (cs == 0)
842     {
843       SetSuccessor(p->FoundState, 0);
844       RESTORE_MODEL(c, CTX(fSuccessor));
845     }
846     else
847     {
848       SetSuccessor(p->FoundState, REF(cs));
849       p->MaxContext = cs;
850     }
851     return;
852   }
853   
854   *p->Text++ = p->FoundState->Symbol;
855   successor = REF(p->Text);
856   if (p->Text >= p->UnitsStart)
857   {
858     RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */
859     return;
860   }
861   
862   if (!fSuccessor)
863   {
864     CTX_PTR cs = ReduceOrder(p, s, p->MinContext);
865     if (cs == NULL)
866     {
867       RESTORE_MODEL(c, 0);
868       return;
869     }
870     fSuccessor = REF(cs);
871   }
872   else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart)
873   {
874     CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext);
875     if (cs == NULL)
876     {
877       RESTORE_MODEL(c, 0);
878       return;
879     }
880     fSuccessor = REF(cs);
881   }
882   
883   if (--p->OrderFall == 0)
884   {
885     successor = fSuccessor;
886     p->Text -= (p->MaxContext != p->MinContext);
887   }
888   #ifdef PPMD8_FREEZE_SUPPORT
889   else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
890   {
891     successor = fSuccessor;
892     RESET_TEXT(0);
893     p->OrderFall = 0;
894   }
895   #endif
896   
897   s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq;
898   flag = (Byte)(0x08 * (fSymbol >= 0x40));
899   
900   for (; c != p->MinContext; c = SUFFIX(c))
901   {
902     unsigned ns1;
903     UInt32 cf, sf;
904     if ((ns1 = c->NumStats) != 0)
905     {
906       if ((ns1 & 1) != 0)
907       {
908         /* Expand for one UNIT */
909         unsigned oldNU = (ns1 + 1) >> 1;
910         unsigned i = U2I(oldNU);
911         if (i != U2I(oldNU + 1))
912         {
913           void *ptr = AllocUnits(p, i + 1);
914           void *oldPtr;
915           if (!ptr)
916           {
917             RESTORE_MODEL(c, CTX(fSuccessor));
918             return;
919           }
920           oldPtr = STATS(c);
921           MyMem12Cpy(ptr, oldPtr, oldNU);
922           InsertNode(p, oldPtr, i);
923           c->Stats = STATS_REF(ptr);
924         }
925       }
926       c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns));
927     }
928     else
929     {
930       CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0);
931       if (!s2)
932       {
933         RESTORE_MODEL(c, CTX(fSuccessor));
934         return;
935       }
936       *s2 = *ONE_STATE(c);
937       c->Stats = REF(s2);
938       if (s2->Freq < MAX_FREQ / 4 - 1)
939         s2->Freq <<= 1;
940       else
941         s2->Freq = MAX_FREQ - 4;
942       c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2));
943     }
944     cf = 2 * fFreq * (c->SummFreq + 6);
945     sf = (UInt32)s0 + c->SummFreq;
946     if (cf < 6 * sf)
947     {
948       cf = 1 + (cf > sf) + (cf >= 4 * sf);
949       c->SummFreq += 4;
950     }
951     else
952     {
953       cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);
954       c->SummFreq = (UInt16)(c->SummFreq + cf);
955     }
956     {
957       CPpmd_State *s2 = STATS(c) + ns1 + 1;
958       SetSuccessor(s2, successor);
959       s2->Symbol = fSymbol;
960       s2->Freq = (Byte)cf;
961       c->Flags |= flag;
962       c->NumStats = (Byte)(ns1 + 1);
963     }
964   }
965   p->MaxContext = p->MinContext = CTX(fSuccessor);
966 }
967   
968 static void Rescale(CPpmd8 *p)
969 {
970   unsigned i, adder, sumFreq, escFreq;
971   CPpmd_State *stats = STATS(p->MinContext);
972   CPpmd_State *s = p->FoundState;
973   {
974     CPpmd_State tmp = *s;
975     for (; s != stats; s--)
976       s[0] = s[-1];
977     *s = tmp;
978   }
979   escFreq = p->MinContext->SummFreq - s->Freq;
980   s->Freq += 4;
981   adder = (p->OrderFall != 0
982       #ifdef PPMD8_FREEZE_SUPPORT
983       || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE
984       #endif
985       );
986   s->Freq = (Byte)((s->Freq + adder) >> 1);
987   sumFreq = s->Freq;
988   
989   i = p->MinContext->NumStats;
990   do
991   {
992     escFreq -= (++s)->Freq;
993     s->Freq = (Byte)((s->Freq + adder) >> 1);
994     sumFreq += s->Freq;
995     if (s[0].Freq > s[-1].Freq)
996     {
997       CPpmd_State *s1 = s;
998       CPpmd_State tmp = *s1;
999       do
1000         s1[0] = s1[-1];
1001       while (--s1 != stats && tmp.Freq > s1[-1].Freq);
1002       *s1 = tmp;
1003     }
1004   }
1005   while (--i);
1006   
1007   if (s->Freq == 0)
1008   {
1009     unsigned numStats = p->MinContext->NumStats;
1010     unsigned n0, n1;
1011     do { i++; } while ((--s)->Freq == 0);
1012     escFreq += i;
1013     p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i);
1014     if (p->MinContext->NumStats == 0)
1015     {
1016       CPpmd_State tmp = *stats;
1017       tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq);
1018       if (tmp.Freq > MAX_FREQ / 3)
1019         tmp.Freq = MAX_FREQ / 3;
1020       InsertNode(p, stats, U2I((numStats + 2) >> 1));
1021       p->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40));
1022       *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
1023       return;
1024     }
1025     n0 = (numStats + 2) >> 1;
1026     n1 = (p->MinContext->NumStats + 2) >> 1;
1027     if (n0 != n1)
1028       p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
1029     p->MinContext->Flags &= ~0x08;
1030     p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40);
1031     i = p->MinContext->NumStats;
1032     do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i);
1033   }
1034   p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
1035   p->MinContext->Flags |= 0x4;
1036   p->FoundState = STATS(p->MinContext);
1037 }
1038
1039 CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
1040 {
1041   CPpmd_See *see;
1042   if (p->MinContext->NumStats != 0xFF)
1043   {
1044     see = p->See[(unsigned)p->NS2Indx[(unsigned)p->MinContext->NumStats + 2] - 3] +
1045         (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +
1046         2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats <
1047         ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +
1048         p->MinContext->Flags;
1049     {
1050       unsigned r = (see->Summ >> see->Shift);
1051       see->Summ = (UInt16)(see->Summ - r);
1052       *escFreq = r + (r == 0);
1053     }
1054   }
1055   else
1056   {
1057     see = &p->DummySee;
1058     *escFreq = 1;
1059   }
1060   return see;
1061 }
1062
1063 static void NextContext(CPpmd8 *p)
1064 {
1065   CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
1066   if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart)
1067     p->MinContext = p->MaxContext = c;
1068   else
1069   {
1070     UpdateModel(p);
1071     p->MinContext = p->MaxContext;
1072   }
1073 }
1074
1075 void Ppmd8_Update1(CPpmd8 *p)
1076 {
1077   CPpmd_State *s = p->FoundState;
1078   s->Freq += 4;
1079   p->MinContext->SummFreq += 4;
1080   if (s[0].Freq > s[-1].Freq)
1081   {
1082     SwapStates(&s[0], &s[-1]);
1083     p->FoundState = --s;
1084     if (s->Freq > MAX_FREQ)
1085       Rescale(p);
1086   }
1087   NextContext(p);
1088 }
1089
1090 void Ppmd8_Update1_0(CPpmd8 *p)
1091 {
1092   p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);
1093   p->RunLength += p->PrevSuccess;
1094   p->MinContext->SummFreq += 4;
1095   if ((p->FoundState->Freq += 4) > MAX_FREQ)
1096     Rescale(p);
1097   NextContext(p);
1098 }
1099
1100 void Ppmd8_UpdateBin(CPpmd8 *p)
1101 {
1102   p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));
1103   p->PrevSuccess = 1;
1104   p->RunLength++;
1105   NextContext(p);
1106 }
1107
1108 void Ppmd8_Update2(CPpmd8 *p)
1109 {
1110   p->MinContext->SummFreq += 4;
1111   if ((p->FoundState->Freq += 4) > MAX_FREQ)
1112     Rescale(p);
1113   p->RunLength = p->InitRL;
1114   UpdateModel(p);
1115   p->MinContext = p->MaxContext;
1116 }
1117
1118 /* Ppmd8Dec.c -- PPMdI Decoder
1119 2010-04-16 : Igor Pavlov : Public domain
1120 This code is based on:
1121   PPMd var.I (2002): Dmitry Shkarin : Public domain
1122   Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
1123
1124 Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
1125 {
1126   unsigned i;
1127   p->Low = 0;
1128   p->Range = 0xFFFFFFFF;
1129   p->Code = 0;
1130   for (i = 0; i < 4; i++)
1131     p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
1132   return (p->Code < 0xFFFFFFFF);
1133 }
1134
1135 static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
1136 {
1137   return p->Code / (p->Range /= total);
1138 }
1139
1140 static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
1141 {
1142   start *= p->Range;
1143   p->Low += start;
1144   p->Code -= start;
1145   p->Range *= size;
1146
1147   while ((p->Low ^ (p->Low + p->Range)) < kTop ||
1148       (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
1149   {
1150     p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
1151     p->Range <<= 8;
1152     p->Low <<= 8;
1153   }
1154 }
1155
1156 #define MASK(sym) ((signed char *)charMask)[sym]
1157
1158 int Ppmd8_DecodeSymbol(CPpmd8 *p)
1159 {
1160   size_t charMask[256 / sizeof(size_t)];
1161   if (p->MinContext->NumStats != 0)
1162   {
1163     CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
1164     unsigned i;
1165     UInt32 count, hiCnt;
1166     if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
1167     {
1168       Byte symbol;
1169       RangeDec_Decode(p, 0, s->Freq);
1170       p->FoundState = s;
1171       symbol = s->Symbol;
1172       Ppmd8_Update1_0(p);
1173       return symbol;
1174     }
1175     p->PrevSuccess = 0;
1176     i = p->MinContext->NumStats;
1177     do
1178     {
1179       if ((hiCnt += (++s)->Freq) > count)
1180       {
1181         Byte symbol;
1182         RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
1183         p->FoundState = s;
1184         symbol = s->Symbol;
1185         Ppmd8_Update1(p);
1186         return symbol;
1187       }
1188     }
1189     while (--i);
1190     if (count >= p->MinContext->SummFreq)
1191       return -2;
1192     RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
1193     PPMD_SetAllBitsIn256Bytes(charMask);
1194     MASK(s->Symbol) = 0;
1195     i = p->MinContext->NumStats;
1196     do { MASK((--s)->Symbol) = 0; } while (--i);
1197   }
1198   else
1199   {
1200     UInt16 *prob = Ppmd8_GetBinSumm(p);
1201     if (((p->Code / (p->Range >>= 14)) < *prob))
1202     {
1203       Byte symbol;
1204       RangeDec_Decode(p, 0, *prob);
1205       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
1206       symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
1207       Ppmd8_UpdateBin(p);
1208       return symbol;
1209     }
1210     RangeDec_Decode(p, *prob, (1 << 14) - *prob);
1211     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
1212     p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
1213     PPMD_SetAllBitsIn256Bytes(charMask);
1214     MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
1215     p->PrevSuccess = 0;
1216   }
1217   for (;;)
1218   {
1219     CPpmd_State *ps[256], *s;
1220     UInt32 freqSum, count, hiCnt;
1221     CPpmd_See *see;
1222     unsigned i, num, numMasked = p->MinContext->NumStats;
1223     do
1224     {
1225       p->OrderFall++;
1226       if (!p->MinContext->Suffix)
1227         return -1;
1228       p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
1229     }
1230     while (p->MinContext->NumStats == numMasked);
1231     hiCnt = 0;
1232     s = Ppmd8_GetStats(p, p->MinContext);
1233     i = 0;
1234     num = p->MinContext->NumStats - numMasked;
1235     do
1236     {
1237       int k = (int)(MASK(s->Symbol));
1238       hiCnt += (s->Freq & k);
1239       ps[i] = s++;
1240       i -= k;
1241     }
1242     while (i != num);
1243     
1244     see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
1245     freqSum += hiCnt;
1246     count = RangeDec_GetThreshold(p, freqSum);
1247     
1248     if (count < hiCnt)
1249     {
1250       Byte symbol;
1251       CPpmd_State **pps = ps;
1252       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
1253       s = *pps;
1254       RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
1255       Ppmd_See_Update(see);
1256       p->FoundState = s;
1257       symbol = s->Symbol;
1258       Ppmd8_Update2(p);
1259       return symbol;
1260     }
1261     if (count >= freqSum)
1262       return -2;
1263     RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
1264     see->Summ = (UInt16)(see->Summ + freqSum);
1265     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
1266   }
1267 }
1268
1269 /* H->I changes:
1270   NS2Indx
1271   GlewCount, and Glue method
1272   BinSum
1273   See / EscFreq
1274   CreateSuccessors updates more suffix contexts
1275   UpdateModel consts.
1276   PrevSuccess Update
1277 */
1278
1279 const IPpmd8 __archive_ppmd8_functions =
1280 {
1281   &Ppmd8_Construct,
1282   &Ppmd8_Alloc,
1283   &Ppmd8_Free,
1284   &Ppmd8_Init,
1285   &Ppmd8_RangeDec_Init,
1286   &Ppmd8_DecodeSymbol,
1287 };