xref: /aosp_15_r20/external/lzma/C/Ppmd7.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* Ppmd7.c -- PPMdH codec
2*f6dc9357SAndroid Build Coastguard Worker 2023-09-07 : Igor Pavlov : Public domain
3*f6dc9357SAndroid Build Coastguard Worker This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "Ppmd7.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker /* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */
12*f6dc9357SAndroid Build Coastguard Worker // #define PPMD7_ORDER_0_SUPPPORT
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN(16)
15*f6dc9357SAndroid Build Coastguard Worker static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
16*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN(16)
17*f6dc9357SAndroid Build Coastguard Worker static const UInt16 PPMD7_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #define MAX_FREQ 124
20*f6dc9357SAndroid Build Coastguard Worker #define UNIT_SIZE 12
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
23*f6dc9357SAndroid Build Coastguard Worker #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])
24*f6dc9357SAndroid Build Coastguard Worker #define I2U(indx) ((unsigned)p->Indx2Units[indx])
25*f6dc9357SAndroid Build Coastguard Worker #define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx])
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #define REF(ptr) Ppmd_GetRef(p, ptr)
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
32*f6dc9357SAndroid Build Coastguard Worker #define STATS(ctx) Ppmd7_GetStats(p, ctx)
33*f6dc9357SAndroid Build Coastguard Worker #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
34*f6dc9357SAndroid Build Coastguard Worker #define SUFFIX(ctx) CTX((ctx)->Suffix)
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker typedef CPpmd7_Context * PPMD7_CTX_PTR;
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker struct CPpmd7_Node_;
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker typedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref;
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker typedef struct CPpmd7_Node_
43*f6dc9357SAndroid Build Coastguard Worker {
44*f6dc9357SAndroid Build Coastguard Worker   UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
45*f6dc9357SAndroid Build Coastguard Worker   UInt16 NU;
46*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
47*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Node_Ref Prev;
48*f6dc9357SAndroid Build Coastguard Worker } CPpmd7_Node;
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker #define NODE(r)  Ppmd_GetPtr_Type(p, r, CPpmd7_Node)
51*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Construct(CPpmd7 * p)52*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Construct(CPpmd7 *p)
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker   unsigned i, k, m;
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker   p->Base = NULL;
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
61*f6dc9357SAndroid Build Coastguard Worker     do { p->Units2Indx[k++] = (Byte)i; } while (--step);
62*f6dc9357SAndroid Build Coastguard Worker     p->Indx2Units[i] = (Byte)k;
63*f6dc9357SAndroid Build Coastguard Worker   }
64*f6dc9357SAndroid Build Coastguard Worker 
65*f6dc9357SAndroid Build Coastguard Worker   p->NS2BSIndx[0] = (0 << 1);
66*f6dc9357SAndroid Build Coastguard Worker   p->NS2BSIndx[1] = (1 << 1);
67*f6dc9357SAndroid Build Coastguard Worker   memset(p->NS2BSIndx + 2, (2 << 1), 9);
68*f6dc9357SAndroid Build Coastguard Worker   memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 3; i++)
71*f6dc9357SAndroid Build Coastguard Worker     p->NS2Indx[i] = (Byte)i;
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker   for (m = i, k = 1; i < 256; i++)
74*f6dc9357SAndroid Build Coastguard Worker   {
75*f6dc9357SAndroid Build Coastguard Worker     p->NS2Indx[i] = (Byte)m;
76*f6dc9357SAndroid Build Coastguard Worker     if (--k == 0)
77*f6dc9357SAndroid Build Coastguard Worker       k = (++m) - 2;
78*f6dc9357SAndroid Build Coastguard Worker   }
79*f6dc9357SAndroid Build Coastguard Worker 
80*f6dc9357SAndroid Build Coastguard Worker   memcpy(p->ExpEscape, PPMD7_kExpEscape, 16);
81*f6dc9357SAndroid Build Coastguard Worker }
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Free(CPpmd7 * p,ISzAllocPtr alloc)84*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)
85*f6dc9357SAndroid Build Coastguard Worker {
86*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(alloc, p->Base);
87*f6dc9357SAndroid Build Coastguard Worker   p->Size = 0;
88*f6dc9357SAndroid Build Coastguard Worker   p->Base = NULL;
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker 
91*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Alloc(CPpmd7 * p,UInt32 size,ISzAllocPtr alloc)92*f6dc9357SAndroid Build Coastguard Worker BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
93*f6dc9357SAndroid Build Coastguard Worker {
94*f6dc9357SAndroid Build Coastguard Worker   if (!p->Base || p->Size != size)
95*f6dc9357SAndroid Build Coastguard Worker   {
96*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_Free(p, alloc);
97*f6dc9357SAndroid Build Coastguard Worker     p->AlignOffset = (4 - size) & 3;
98*f6dc9357SAndroid Build Coastguard Worker     if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL)
99*f6dc9357SAndroid Build Coastguard Worker       return False;
100*f6dc9357SAndroid Build Coastguard Worker     p->Size = size;
101*f6dc9357SAndroid Build Coastguard Worker   }
102*f6dc9357SAndroid Build Coastguard Worker   return True;
103*f6dc9357SAndroid Build Coastguard Worker }
104*f6dc9357SAndroid Build Coastguard Worker 
105*f6dc9357SAndroid Build Coastguard Worker 
106*f6dc9357SAndroid Build Coastguard Worker 
107*f6dc9357SAndroid Build Coastguard Worker // ---------- Internal Memory Allocator ----------
108*f6dc9357SAndroid Build Coastguard Worker 
109*f6dc9357SAndroid Build Coastguard Worker /* We can use CPpmd7_Node in list of free units (as in Ppmd8)
110*f6dc9357SAndroid Build Coastguard Worker    But we still need one additional list walk pass in Ppmd7_GlueFreeBlocks().
111*f6dc9357SAndroid Build Coastguard Worker    So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in Ppmd7_InsertNode() / Ppmd7_RemoveNode()
112*f6dc9357SAndroid Build Coastguard Worker */
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker #define EMPTY_NODE 0
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_InsertNode(CPpmd7 * p,void * node,unsigned indx)117*f6dc9357SAndroid Build Coastguard Worker static void Ppmd7_InsertNode(CPpmd7 *p, void *node, unsigned indx)
118*f6dc9357SAndroid Build Coastguard Worker {
119*f6dc9357SAndroid Build Coastguard Worker   *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
120*f6dc9357SAndroid Build Coastguard Worker   // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx];
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker   p->FreeList[indx] = REF(node);
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker }
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_RemoveNode(CPpmd7 * p,unsigned indx)127*f6dc9357SAndroid Build Coastguard Worker static void *Ppmd7_RemoveNode(CPpmd7 *p, unsigned indx)
128*f6dc9357SAndroid Build Coastguard Worker {
129*f6dc9357SAndroid Build Coastguard Worker   CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
130*f6dc9357SAndroid Build Coastguard Worker   p->FreeList[indx] = *node;
131*f6dc9357SAndroid Build Coastguard Worker   // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]);
132*f6dc9357SAndroid Build Coastguard Worker   // p->FreeList[indx] = node->Next;
133*f6dc9357SAndroid Build Coastguard Worker   return node;
134*f6dc9357SAndroid Build Coastguard Worker }
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_SplitBlock(CPpmd7 * p,void * ptr,unsigned oldIndx,unsigned newIndx)137*f6dc9357SAndroid Build Coastguard Worker static void Ppmd7_SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker   unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
140*f6dc9357SAndroid Build Coastguard Worker   ptr = (Byte *)ptr + U2B(I2U(newIndx));
141*f6dc9357SAndroid Build Coastguard Worker   if (I2U(i = U2I(nu)) != nu)
142*f6dc9357SAndroid Build Coastguard Worker   {
143*f6dc9357SAndroid Build Coastguard Worker     unsigned k = I2U(--i);
144*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
145*f6dc9357SAndroid Build Coastguard Worker   }
146*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_InsertNode(p, ptr, i);
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker 
150*f6dc9357SAndroid Build Coastguard Worker /* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker typedef union
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Node     Node;
155*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Node_Ref NextRef;
156*f6dc9357SAndroid Build Coastguard Worker } CPpmd7_Node_Union;
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker /* Original PPmdH (Ppmd7) code uses doubly linked list in Ppmd7_GlueFreeBlocks()
159*f6dc9357SAndroid Build Coastguard Worker    we use single linked list similar to Ppmd8 code */
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_GlueFreeBlocks(CPpmd7 * p)162*f6dc9357SAndroid Build Coastguard Worker static void Ppmd7_GlueFreeBlocks(CPpmd7 *p)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker   /*
165*f6dc9357SAndroid Build Coastguard Worker   we use first UInt16 field of 12-bytes UNITs as record type stamp
166*f6dc9357SAndroid Build Coastguard Worker     CPpmd_State    { Byte Symbol; Byte Freq; : Freq != 0
167*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Context { UInt16 NumStats;        : NumStats != 0
168*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Node    { UInt16 Stamp            : Stamp == 0 for free record
169*f6dc9357SAndroid Build Coastguard Worker                                              : Stamp == 1 for head record and guard
170*f6dc9357SAndroid Build Coastguard Worker     Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record.
171*f6dc9357SAndroid Build Coastguard Worker   */
172*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Node_Ref head, n = 0;
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker   p->GlueCount = 255;
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker 
177*f6dc9357SAndroid Build Coastguard Worker   /* we set guard NODE at LoUnit */
178*f6dc9357SAndroid Build Coastguard Worker   if (p->LoUnit != p->HiUnit)
179*f6dc9357SAndroid Build Coastguard Worker     ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1;
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker   {
182*f6dc9357SAndroid Build Coastguard Worker     /* Create list of free blocks.
183*f6dc9357SAndroid Build Coastguard Worker        We still need one additional list walk pass before Glue. */
184*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
185*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < PPMD_NUM_INDEXES; i++)
186*f6dc9357SAndroid Build Coastguard Worker     {
187*f6dc9357SAndroid Build Coastguard Worker       const UInt16 nu = I2U_UInt16(i);
188*f6dc9357SAndroid Build Coastguard Worker       CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
189*f6dc9357SAndroid Build Coastguard Worker       p->FreeList[i] = 0;
190*f6dc9357SAndroid Build Coastguard Worker       while (next != 0)
191*f6dc9357SAndroid Build Coastguard Worker       {
192*f6dc9357SAndroid Build Coastguard Worker         /* Don't change the order of the following commands: */
193*f6dc9357SAndroid Build Coastguard Worker         CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next);
194*f6dc9357SAndroid Build Coastguard Worker         const CPpmd7_Node_Ref tmp = next;
195*f6dc9357SAndroid Build Coastguard Worker         next = un->NextRef;
196*f6dc9357SAndroid Build Coastguard Worker         un->Node.Stamp = EMPTY_NODE;
197*f6dc9357SAndroid Build Coastguard Worker         un->Node.NU = nu;
198*f6dc9357SAndroid Build Coastguard Worker         un->Node.Next = n;
199*f6dc9357SAndroid Build Coastguard Worker         n = tmp;
200*f6dc9357SAndroid Build Coastguard Worker       }
201*f6dc9357SAndroid Build Coastguard Worker     }
202*f6dc9357SAndroid Build Coastguard Worker   }
203*f6dc9357SAndroid Build Coastguard Worker 
204*f6dc9357SAndroid Build Coastguard Worker   head = n;
205*f6dc9357SAndroid Build Coastguard Worker   /* Glue and Fill must walk the list in same direction */
206*f6dc9357SAndroid Build Coastguard Worker   {
207*f6dc9357SAndroid Build Coastguard Worker     /* Glue free blocks */
208*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Node_Ref *prev = &head;
209*f6dc9357SAndroid Build Coastguard Worker     while (n)
210*f6dc9357SAndroid Build Coastguard Worker     {
211*f6dc9357SAndroid Build Coastguard Worker       CPpmd7_Node *node = NODE(n);
212*f6dc9357SAndroid Build Coastguard Worker       UInt32 nu = node->NU;
213*f6dc9357SAndroid Build Coastguard Worker       n = node->Next;
214*f6dc9357SAndroid Build Coastguard Worker       if (nu == 0)
215*f6dc9357SAndroid Build Coastguard Worker       {
216*f6dc9357SAndroid Build Coastguard Worker         *prev = n;
217*f6dc9357SAndroid Build Coastguard Worker         continue;
218*f6dc9357SAndroid Build Coastguard Worker       }
219*f6dc9357SAndroid Build Coastguard Worker       prev = &node->Next;
220*f6dc9357SAndroid Build Coastguard Worker       for (;;)
221*f6dc9357SAndroid Build Coastguard Worker       {
222*f6dc9357SAndroid Build Coastguard Worker         CPpmd7_Node *node2 = node + nu;
223*f6dc9357SAndroid Build Coastguard Worker         nu += node2->NU;
224*f6dc9357SAndroid Build Coastguard Worker         if (node2->Stamp != EMPTY_NODE || nu >= 0x10000)
225*f6dc9357SAndroid Build Coastguard Worker           break;
226*f6dc9357SAndroid Build Coastguard Worker         node->NU = (UInt16)nu;
227*f6dc9357SAndroid Build Coastguard Worker         node2->NU = 0;
228*f6dc9357SAndroid Build Coastguard Worker       }
229*f6dc9357SAndroid Build Coastguard Worker     }
230*f6dc9357SAndroid Build Coastguard Worker   }
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker   /* Fill lists of free blocks */
233*f6dc9357SAndroid Build Coastguard Worker   for (n = head; n != 0;)
234*f6dc9357SAndroid Build Coastguard Worker   {
235*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Node *node = NODE(n);
236*f6dc9357SAndroid Build Coastguard Worker     UInt32 nu = node->NU;
237*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
238*f6dc9357SAndroid Build Coastguard Worker     n = node->Next;
239*f6dc9357SAndroid Build Coastguard Worker     if (nu == 0)
240*f6dc9357SAndroid Build Coastguard Worker       continue;
241*f6dc9357SAndroid Build Coastguard Worker     for (; nu > 128; nu -= 128, node += 128)
242*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_InsertNode(p, node, PPMD_NUM_INDEXES - 1);
243*f6dc9357SAndroid Build Coastguard Worker     if (I2U(i = U2I(nu)) != nu)
244*f6dc9357SAndroid Build Coastguard Worker     {
245*f6dc9357SAndroid Build Coastguard Worker       unsigned k = I2U(--i);
246*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_InsertNode(p, node + k, (unsigned)nu - k - 1);
247*f6dc9357SAndroid Build Coastguard Worker     }
248*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_InsertNode(p, node, i);
249*f6dc9357SAndroid Build Coastguard Worker   }
250*f6dc9357SAndroid Build Coastguard Worker }
251*f6dc9357SAndroid Build Coastguard Worker 
252*f6dc9357SAndroid Build Coastguard Worker 
253*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Ppmd7_AllocUnitsRare(CPpmd7 * p,unsigned indx)254*f6dc9357SAndroid Build Coastguard Worker static void *Ppmd7_AllocUnitsRare(CPpmd7 *p, unsigned indx)
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker   if (p->GlueCount == 0)
259*f6dc9357SAndroid Build Coastguard Worker   {
260*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_GlueFreeBlocks(p);
261*f6dc9357SAndroid Build Coastguard Worker     if (p->FreeList[indx] != 0)
262*f6dc9357SAndroid Build Coastguard Worker       return Ppmd7_RemoveNode(p, indx);
263*f6dc9357SAndroid Build Coastguard Worker   }
264*f6dc9357SAndroid Build Coastguard Worker 
265*f6dc9357SAndroid Build Coastguard Worker   i = indx;
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker   do
268*f6dc9357SAndroid Build Coastguard Worker   {
269*f6dc9357SAndroid Build Coastguard Worker     if (++i == PPMD_NUM_INDEXES)
270*f6dc9357SAndroid Build Coastguard Worker     {
271*f6dc9357SAndroid Build Coastguard Worker       UInt32 numBytes = U2B(I2U(indx));
272*f6dc9357SAndroid Build Coastguard Worker       Byte *us = p->UnitsStart;
273*f6dc9357SAndroid Build Coastguard Worker       p->GlueCount--;
274*f6dc9357SAndroid Build Coastguard Worker       return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL;
275*f6dc9357SAndroid Build Coastguard Worker     }
276*f6dc9357SAndroid Build Coastguard Worker   }
277*f6dc9357SAndroid Build Coastguard Worker   while (p->FreeList[i] == 0);
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker   {
280*f6dc9357SAndroid Build Coastguard Worker     void *block = Ppmd7_RemoveNode(p, i);
281*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_SplitBlock(p, block, i, indx);
282*f6dc9357SAndroid Build Coastguard Worker     return block;
283*f6dc9357SAndroid Build Coastguard Worker   }
284*f6dc9357SAndroid Build Coastguard Worker }
285*f6dc9357SAndroid Build Coastguard Worker 
286*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_AllocUnits(CPpmd7 * p,unsigned indx)287*f6dc9357SAndroid Build Coastguard Worker static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx)
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker   if (p->FreeList[indx] != 0)
290*f6dc9357SAndroid Build Coastguard Worker     return Ppmd7_RemoveNode(p, indx);
291*f6dc9357SAndroid Build Coastguard Worker   {
292*f6dc9357SAndroid Build Coastguard Worker     UInt32 numBytes = U2B(I2U(indx));
293*f6dc9357SAndroid Build Coastguard Worker     Byte *lo = p->LoUnit;
294*f6dc9357SAndroid Build Coastguard Worker     if ((UInt32)(p->HiUnit - lo) >= numBytes)
295*f6dc9357SAndroid Build Coastguard Worker     {
296*f6dc9357SAndroid Build Coastguard Worker       p->LoUnit = lo + numBytes;
297*f6dc9357SAndroid Build Coastguard Worker       return lo;
298*f6dc9357SAndroid Build Coastguard Worker     }
299*f6dc9357SAndroid Build Coastguard Worker   }
300*f6dc9357SAndroid Build Coastguard Worker   return Ppmd7_AllocUnitsRare(p, indx);
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker 
303*f6dc9357SAndroid Build Coastguard Worker 
304*f6dc9357SAndroid Build Coastguard Worker #define MEM_12_CPY(dest, src, num) \
305*f6dc9357SAndroid Build Coastguard Worker   { UInt32 *d = (UInt32 *)(dest); \
306*f6dc9357SAndroid Build Coastguard Worker     const UInt32 *z = (const UInt32 *)(src); \
307*f6dc9357SAndroid Build Coastguard Worker     unsigned n = (num); \
308*f6dc9357SAndroid Build Coastguard Worker     do { \
309*f6dc9357SAndroid Build Coastguard Worker       d[0] = z[0]; \
310*f6dc9357SAndroid Build Coastguard Worker       d[1] = z[1]; \
311*f6dc9357SAndroid Build Coastguard Worker       d[2] = z[2]; \
312*f6dc9357SAndroid Build Coastguard Worker       z += 3; \
313*f6dc9357SAndroid Build Coastguard Worker       d += 3; \
314*f6dc9357SAndroid Build Coastguard Worker     } while (--n); \
315*f6dc9357SAndroid Build Coastguard Worker   }
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker 
318*f6dc9357SAndroid Build Coastguard Worker /*
319*f6dc9357SAndroid Build Coastguard Worker static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
320*f6dc9357SAndroid Build Coastguard Worker {
321*f6dc9357SAndroid Build Coastguard Worker   unsigned i0 = U2I(oldNU);
322*f6dc9357SAndroid Build Coastguard Worker   unsigned i1 = U2I(newNU);
323*f6dc9357SAndroid Build Coastguard Worker   if (i0 == i1)
324*f6dc9357SAndroid Build Coastguard Worker     return oldPtr;
325*f6dc9357SAndroid Build Coastguard Worker   if (p->FreeList[i1] != 0)
326*f6dc9357SAndroid Build Coastguard Worker   {
327*f6dc9357SAndroid Build Coastguard Worker     void *ptr = Ppmd7_RemoveNode(p, i1);
328*f6dc9357SAndroid Build Coastguard Worker     MEM_12_CPY(ptr, oldPtr, newNU)
329*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_InsertNode(p, oldPtr, i0);
330*f6dc9357SAndroid Build Coastguard Worker     return ptr;
331*f6dc9357SAndroid Build Coastguard Worker   }
332*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_SplitBlock(p, oldPtr, i0, i1);
333*f6dc9357SAndroid Build Coastguard Worker   return oldPtr;
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker */
336*f6dc9357SAndroid Build Coastguard Worker 
337*f6dc9357SAndroid Build Coastguard Worker 
338*f6dc9357SAndroid Build Coastguard Worker #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
SetSuccessor(CPpmd_State * p,CPpmd_Void_Ref v)339*f6dc9357SAndroid Build Coastguard Worker static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
340*f6dc9357SAndroid Build Coastguard Worker {
341*f6dc9357SAndroid Build Coastguard Worker   Ppmd_SET_SUCCESSOR(p, v)
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker 
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker 
346*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
347*f6dc9357SAndroid Build Coastguard Worker static
Ppmd7_RestartModel(CPpmd7 * p)348*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_RestartModel(CPpmd7 *p)
349*f6dc9357SAndroid Build Coastguard Worker {
350*f6dc9357SAndroid Build Coastguard Worker   unsigned i, k;
351*f6dc9357SAndroid Build Coastguard Worker 
352*f6dc9357SAndroid Build Coastguard Worker   memset(p->FreeList, 0, sizeof(p->FreeList));
353*f6dc9357SAndroid Build Coastguard Worker 
354*f6dc9357SAndroid Build Coastguard Worker   p->Text = p->Base + p->AlignOffset;
355*f6dc9357SAndroid Build Coastguard Worker   p->HiUnit = p->Text + p->Size;
356*f6dc9357SAndroid Build Coastguard Worker   p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
357*f6dc9357SAndroid Build Coastguard Worker   p->GlueCount = 0;
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker   p->OrderFall = p->MaxOrder;
360*f6dc9357SAndroid Build Coastguard Worker   p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
361*f6dc9357SAndroid Build Coastguard Worker   p->PrevSuccess = 0;
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker   {
364*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Context *mc = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
365*f6dc9357SAndroid Build Coastguard Worker     CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd7_AllocUnits(p, PPMD_NUM_INDEXES - 1); */
366*f6dc9357SAndroid Build Coastguard Worker 
367*f6dc9357SAndroid Build Coastguard Worker     p->LoUnit += U2B(256 / 2);
368*f6dc9357SAndroid Build Coastguard Worker     p->MaxContext = p->MinContext = mc;
369*f6dc9357SAndroid Build Coastguard Worker     p->FoundState = s;
370*f6dc9357SAndroid Build Coastguard Worker 
371*f6dc9357SAndroid Build Coastguard Worker     mc->NumStats = 256;
372*f6dc9357SAndroid Build Coastguard Worker     mc->Union2.SummFreq = 256 + 1;
373*f6dc9357SAndroid Build Coastguard Worker     mc->Union4.Stats = REF(s);
374*f6dc9357SAndroid Build Coastguard Worker     mc->Suffix = 0;
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 256; i++, s++)
377*f6dc9357SAndroid Build Coastguard Worker     {
378*f6dc9357SAndroid Build Coastguard Worker       s->Symbol = (Byte)i;
379*f6dc9357SAndroid Build Coastguard Worker       s->Freq = 1;
380*f6dc9357SAndroid Build Coastguard Worker       SetSuccessor(s, 0);
381*f6dc9357SAndroid Build Coastguard Worker     }
382*f6dc9357SAndroid Build Coastguard Worker 
383*f6dc9357SAndroid Build Coastguard Worker     #ifdef PPMD7_ORDER_0_SUPPPORT
384*f6dc9357SAndroid Build Coastguard Worker     if (p->MaxOrder == 0)
385*f6dc9357SAndroid Build Coastguard Worker     {
386*f6dc9357SAndroid Build Coastguard Worker       CPpmd_Void_Ref r = REF(mc);
387*f6dc9357SAndroid Build Coastguard Worker       s = p->FoundState;
388*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < 256; i++, s++)
389*f6dc9357SAndroid Build Coastguard Worker         SetSuccessor(s, r);
390*f6dc9357SAndroid Build Coastguard Worker       return;
391*f6dc9357SAndroid Build Coastguard Worker     }
392*f6dc9357SAndroid Build Coastguard Worker     #endif
393*f6dc9357SAndroid Build Coastguard Worker   }
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 128; i++)
396*f6dc9357SAndroid Build Coastguard Worker 
397*f6dc9357SAndroid Build Coastguard Worker 
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker     for (k = 0; k < 8; k++)
400*f6dc9357SAndroid Build Coastguard Worker     {
401*f6dc9357SAndroid Build Coastguard Worker       unsigned m;
402*f6dc9357SAndroid Build Coastguard Worker       UInt16 *dest = p->BinSumm[i] + k;
403*f6dc9357SAndroid Build Coastguard Worker       const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD7_kInitBinEsc[k] / (i + 2));
404*f6dc9357SAndroid Build Coastguard Worker       for (m = 0; m < 64; m += 8)
405*f6dc9357SAndroid Build Coastguard Worker         dest[m] = val;
406*f6dc9357SAndroid Build Coastguard Worker     }
407*f6dc9357SAndroid Build Coastguard Worker 
408*f6dc9357SAndroid Build Coastguard Worker 
409*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 25; i++)
410*f6dc9357SAndroid Build Coastguard Worker   {
411*f6dc9357SAndroid Build Coastguard Worker 
412*f6dc9357SAndroid Build Coastguard Worker     CPpmd_See *s = p->See[i];
413*f6dc9357SAndroid Build Coastguard Worker 
414*f6dc9357SAndroid Build Coastguard Worker 
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker     unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4));
417*f6dc9357SAndroid Build Coastguard Worker     for (k = 0; k < 16; k++, s++)
418*f6dc9357SAndroid Build Coastguard Worker     {
419*f6dc9357SAndroid Build Coastguard Worker       s->Summ = (UInt16)summ;
420*f6dc9357SAndroid Build Coastguard Worker       s->Shift = (PPMD_PERIOD_BITS - 4);
421*f6dc9357SAndroid Build Coastguard Worker       s->Count = 4;
422*f6dc9357SAndroid Build Coastguard Worker     }
423*f6dc9357SAndroid Build Coastguard Worker   }
424*f6dc9357SAndroid Build Coastguard Worker 
425*f6dc9357SAndroid Build Coastguard Worker   p->DummySee.Summ = 0; /* unused */
426*f6dc9357SAndroid Build Coastguard Worker   p->DummySee.Shift = PPMD_PERIOD_BITS;
427*f6dc9357SAndroid Build Coastguard Worker   p->DummySee.Count = 64; /* unused */
428*f6dc9357SAndroid Build Coastguard Worker }
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Init(CPpmd7 * p,unsigned maxOrder)431*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker   p->MaxOrder = maxOrder;
434*f6dc9357SAndroid Build Coastguard Worker 
435*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_RestartModel(p);
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker 
438*f6dc9357SAndroid Build Coastguard Worker 
439*f6dc9357SAndroid Build Coastguard Worker 
440*f6dc9357SAndroid Build Coastguard Worker /*
441*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_CreateSuccessors()
442*f6dc9357SAndroid Build Coastguard Worker   It's called when (FoundState->Successor) is RAW-Successor,
443*f6dc9357SAndroid Build Coastguard Worker   that is the link to position in Raw text.
444*f6dc9357SAndroid Build Coastguard Worker   So we create Context records and write the links to
445*f6dc9357SAndroid Build Coastguard Worker   FoundState->Successor and to identical RAW-Successors in suffix
446*f6dc9357SAndroid Build Coastguard Worker   contexts of MinContex.
447*f6dc9357SAndroid Build Coastguard Worker 
448*f6dc9357SAndroid Build Coastguard Worker   The function returns:
449*f6dc9357SAndroid Build Coastguard Worker   if (OrderFall == 0) then MinContext is already at MAX order,
450*f6dc9357SAndroid Build Coastguard Worker     { return pointer to new or existing context of same MAX order }
451*f6dc9357SAndroid Build Coastguard Worker   else
452*f6dc9357SAndroid Build Coastguard Worker     { return pointer to new real context that will be (Order+1) in comparison with MinContext
453*f6dc9357SAndroid Build Coastguard Worker 
454*f6dc9357SAndroid Build Coastguard Worker   also it can return pointer to real context of same order,
455*f6dc9357SAndroid Build Coastguard Worker */
456*f6dc9357SAndroid Build Coastguard Worker 
457*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Ppmd7_CreateSuccessors(CPpmd7 * p)458*f6dc9357SAndroid Build Coastguard Worker static PPMD7_CTX_PTR Ppmd7_CreateSuccessors(CPpmd7 *p)
459*f6dc9357SAndroid Build Coastguard Worker {
460*f6dc9357SAndroid Build Coastguard Worker   PPMD7_CTX_PTR c = p->MinContext;
461*f6dc9357SAndroid Build Coastguard Worker   CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
462*f6dc9357SAndroid Build Coastguard Worker   Byte newSym, newFreq;
463*f6dc9357SAndroid Build Coastguard Worker   unsigned numPs = 0;
464*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *ps[PPMD7_MAX_ORDER];
465*f6dc9357SAndroid Build Coastguard Worker 
466*f6dc9357SAndroid Build Coastguard Worker   if (p->OrderFall != 0)
467*f6dc9357SAndroid Build Coastguard Worker     ps[numPs++] = p->FoundState;
468*f6dc9357SAndroid Build Coastguard Worker 
469*f6dc9357SAndroid Build Coastguard Worker   while (c->Suffix)
470*f6dc9357SAndroid Build Coastguard Worker   {
471*f6dc9357SAndroid Build Coastguard Worker     CPpmd_Void_Ref successor;
472*f6dc9357SAndroid Build Coastguard Worker     CPpmd_State *s;
473*f6dc9357SAndroid Build Coastguard Worker     c = SUFFIX(c);
474*f6dc9357SAndroid Build Coastguard Worker 
475*f6dc9357SAndroid Build Coastguard Worker 
476*f6dc9357SAndroid Build Coastguard Worker     if (c->NumStats != 1)
477*f6dc9357SAndroid Build Coastguard Worker     {
478*f6dc9357SAndroid Build Coastguard Worker       Byte sym = p->FoundState->Symbol;
479*f6dc9357SAndroid Build Coastguard Worker       for (s = STATS(c); s->Symbol != sym; s++);
480*f6dc9357SAndroid Build Coastguard Worker 
481*f6dc9357SAndroid Build Coastguard Worker     }
482*f6dc9357SAndroid Build Coastguard Worker     else
483*f6dc9357SAndroid Build Coastguard Worker     {
484*f6dc9357SAndroid Build Coastguard Worker       s = ONE_STATE(c);
485*f6dc9357SAndroid Build Coastguard Worker 
486*f6dc9357SAndroid Build Coastguard Worker     }
487*f6dc9357SAndroid Build Coastguard Worker     successor = SUCCESSOR(s);
488*f6dc9357SAndroid Build Coastguard Worker     if (successor != upBranch)
489*f6dc9357SAndroid Build Coastguard Worker     {
490*f6dc9357SAndroid Build Coastguard Worker       // (c) is real record Context here,
491*f6dc9357SAndroid Build Coastguard Worker       c = CTX(successor);
492*f6dc9357SAndroid Build Coastguard Worker       if (numPs == 0)
493*f6dc9357SAndroid Build Coastguard Worker       {
494*f6dc9357SAndroid Build Coastguard Worker         // (c) is real record MAX Order Context here,
495*f6dc9357SAndroid Build Coastguard Worker         // So we don't need to create any new contexts.
496*f6dc9357SAndroid Build Coastguard Worker         return c;
497*f6dc9357SAndroid Build Coastguard Worker       }
498*f6dc9357SAndroid Build Coastguard Worker       break;
499*f6dc9357SAndroid Build Coastguard Worker     }
500*f6dc9357SAndroid Build Coastguard Worker     ps[numPs++] = s;
501*f6dc9357SAndroid Build Coastguard Worker   }
502*f6dc9357SAndroid Build Coastguard Worker 
503*f6dc9357SAndroid Build Coastguard Worker   // All created contexts will have single-symbol with new RAW-Successor
504*f6dc9357SAndroid Build Coastguard Worker   // All new RAW-Successors will point to next position in RAW text
505*f6dc9357SAndroid Build Coastguard Worker   // after FoundState->Successor
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker   newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
508*f6dc9357SAndroid Build Coastguard Worker   upBranch++;
509*f6dc9357SAndroid Build Coastguard Worker 
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker   if (c->NumStats == 1)
512*f6dc9357SAndroid Build Coastguard Worker     newFreq = ONE_STATE(c)->Freq;
513*f6dc9357SAndroid Build Coastguard Worker   else
514*f6dc9357SAndroid Build Coastguard Worker   {
515*f6dc9357SAndroid Build Coastguard Worker     UInt32 cf, s0;
516*f6dc9357SAndroid Build Coastguard Worker     CPpmd_State *s;
517*f6dc9357SAndroid Build Coastguard Worker     for (s = STATS(c); s->Symbol != newSym; s++);
518*f6dc9357SAndroid Build Coastguard Worker     cf = (UInt32)s->Freq - 1;
519*f6dc9357SAndroid Build Coastguard Worker     s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf;
520*f6dc9357SAndroid Build Coastguard Worker     /*
521*f6dc9357SAndroid Build Coastguard Worker       cf - is frequency of symbol that will be Successor in new context records.
522*f6dc9357SAndroid Build Coastguard Worker       s0 - is commulative frequency sum of another symbols from parent context.
523*f6dc9357SAndroid Build Coastguard Worker       max(newFreq)= (s->Freq + 1), when (s0 == 1)
524*f6dc9357SAndroid Build Coastguard Worker       we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[]
525*f6dc9357SAndroid Build Coastguard Worker       so (s->Freq < 128) - is requirement for multi-symbol contexts
526*f6dc9357SAndroid Build Coastguard Worker     */
527*f6dc9357SAndroid Build Coastguard Worker     newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1));
528*f6dc9357SAndroid Build Coastguard Worker   }
529*f6dc9357SAndroid Build Coastguard Worker 
530*f6dc9357SAndroid Build Coastguard Worker   // Create new single-symbol contexts from low order to high order in loop
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker   do
533*f6dc9357SAndroid Build Coastguard Worker   {
534*f6dc9357SAndroid Build Coastguard Worker     PPMD7_CTX_PTR c1;
535*f6dc9357SAndroid Build Coastguard Worker     /* = AllocContext(p); */
536*f6dc9357SAndroid Build Coastguard Worker     if (p->HiUnit != p->LoUnit)
537*f6dc9357SAndroid Build Coastguard Worker       c1 = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE);
538*f6dc9357SAndroid Build Coastguard Worker     else if (p->FreeList[0] != 0)
539*f6dc9357SAndroid Build Coastguard Worker       c1 = (PPMD7_CTX_PTR)Ppmd7_RemoveNode(p, 0);
540*f6dc9357SAndroid Build Coastguard Worker     else
541*f6dc9357SAndroid Build Coastguard Worker     {
542*f6dc9357SAndroid Build Coastguard Worker       c1 = (PPMD7_CTX_PTR)Ppmd7_AllocUnitsRare(p, 0);
543*f6dc9357SAndroid Build Coastguard Worker       if (!c1)
544*f6dc9357SAndroid Build Coastguard Worker         return NULL;
545*f6dc9357SAndroid Build Coastguard Worker     }
546*f6dc9357SAndroid Build Coastguard Worker 
547*f6dc9357SAndroid Build Coastguard Worker     c1->NumStats = 1;
548*f6dc9357SAndroid Build Coastguard Worker     ONE_STATE(c1)->Symbol = newSym;
549*f6dc9357SAndroid Build Coastguard Worker     ONE_STATE(c1)->Freq = newFreq;
550*f6dc9357SAndroid Build Coastguard Worker     SetSuccessor(ONE_STATE(c1), upBranch);
551*f6dc9357SAndroid Build Coastguard Worker     c1->Suffix = REF(c);
552*f6dc9357SAndroid Build Coastguard Worker     SetSuccessor(ps[--numPs], REF(c1));
553*f6dc9357SAndroid Build Coastguard Worker     c = c1;
554*f6dc9357SAndroid Build Coastguard Worker   }
555*f6dc9357SAndroid Build Coastguard Worker   while (numPs != 0);
556*f6dc9357SAndroid Build Coastguard Worker 
557*f6dc9357SAndroid Build Coastguard Worker   return c;
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker 
560*f6dc9357SAndroid Build Coastguard Worker 
561*f6dc9357SAndroid Build Coastguard Worker 
562*f6dc9357SAndroid Build Coastguard Worker #define SWAP_STATES(s) \
563*f6dc9357SAndroid Build Coastguard Worker   { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; }
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker 
566*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_UpdateModel(CPpmd7 *p);
567*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Ppmd7_UpdateModel(CPpmd7 * p)568*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_UpdateModel(CPpmd7 *p)
569*f6dc9357SAndroid Build Coastguard Worker {
570*f6dc9357SAndroid Build Coastguard Worker   CPpmd_Void_Ref maxSuccessor, minSuccessor;
571*f6dc9357SAndroid Build Coastguard Worker   PPMD7_CTX_PTR c, mc;
572*f6dc9357SAndroid Build Coastguard Worker   unsigned s0, ns;
573*f6dc9357SAndroid Build Coastguard Worker 
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker 
576*f6dc9357SAndroid Build Coastguard Worker   if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
577*f6dc9357SAndroid Build Coastguard Worker   {
578*f6dc9357SAndroid Build Coastguard Worker     /* Update Freqs in Suffix Context */
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker     c = SUFFIX(p->MinContext);
581*f6dc9357SAndroid Build Coastguard Worker 
582*f6dc9357SAndroid Build Coastguard Worker     if (c->NumStats == 1)
583*f6dc9357SAndroid Build Coastguard Worker     {
584*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State *s = ONE_STATE(c);
585*f6dc9357SAndroid Build Coastguard Worker       if (s->Freq < 32)
586*f6dc9357SAndroid Build Coastguard Worker         s->Freq++;
587*f6dc9357SAndroid Build Coastguard Worker     }
588*f6dc9357SAndroid Build Coastguard Worker     else
589*f6dc9357SAndroid Build Coastguard Worker     {
590*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State *s = STATS(c);
591*f6dc9357SAndroid Build Coastguard Worker       Byte sym = p->FoundState->Symbol;
592*f6dc9357SAndroid Build Coastguard Worker 
593*f6dc9357SAndroid Build Coastguard Worker       if (s->Symbol != sym)
594*f6dc9357SAndroid Build Coastguard Worker       {
595*f6dc9357SAndroid Build Coastguard Worker         do
596*f6dc9357SAndroid Build Coastguard Worker         {
597*f6dc9357SAndroid Build Coastguard Worker           // s++; if (s->Symbol == sym) break;
598*f6dc9357SAndroid Build Coastguard Worker           s++;
599*f6dc9357SAndroid Build Coastguard Worker         }
600*f6dc9357SAndroid Build Coastguard Worker         while (s->Symbol != sym);
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker         if (s[0].Freq >= s[-1].Freq)
603*f6dc9357SAndroid Build Coastguard Worker         {
604*f6dc9357SAndroid Build Coastguard Worker           SWAP_STATES(s)
605*f6dc9357SAndroid Build Coastguard Worker           s--;
606*f6dc9357SAndroid Build Coastguard Worker         }
607*f6dc9357SAndroid Build Coastguard Worker       }
608*f6dc9357SAndroid Build Coastguard Worker 
609*f6dc9357SAndroid Build Coastguard Worker       if (s->Freq < MAX_FREQ - 9)
610*f6dc9357SAndroid Build Coastguard Worker       {
611*f6dc9357SAndroid Build Coastguard Worker         s->Freq = (Byte)(s->Freq + 2);
612*f6dc9357SAndroid Build Coastguard Worker         c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);
613*f6dc9357SAndroid Build Coastguard Worker       }
614*f6dc9357SAndroid Build Coastguard Worker     }
615*f6dc9357SAndroid Build Coastguard Worker   }
616*f6dc9357SAndroid Build Coastguard Worker 
617*f6dc9357SAndroid Build Coastguard Worker 
618*f6dc9357SAndroid Build Coastguard Worker   if (p->OrderFall == 0)
619*f6dc9357SAndroid Build Coastguard Worker   {
620*f6dc9357SAndroid Build Coastguard Worker     /* MAX ORDER context */
621*f6dc9357SAndroid Build Coastguard Worker     /* (FoundState->Successor) is RAW-Successor. */
622*f6dc9357SAndroid Build Coastguard Worker     p->MaxContext = p->MinContext = Ppmd7_CreateSuccessors(p);
623*f6dc9357SAndroid Build Coastguard Worker     if (!p->MinContext)
624*f6dc9357SAndroid Build Coastguard Worker     {
625*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_RestartModel(p);
626*f6dc9357SAndroid Build Coastguard Worker       return;
627*f6dc9357SAndroid Build Coastguard Worker     }
628*f6dc9357SAndroid Build Coastguard Worker     SetSuccessor(p->FoundState, REF(p->MinContext));
629*f6dc9357SAndroid Build Coastguard Worker     return;
630*f6dc9357SAndroid Build Coastguard Worker   }
631*f6dc9357SAndroid Build Coastguard Worker 
632*f6dc9357SAndroid Build Coastguard Worker 
633*f6dc9357SAndroid Build Coastguard Worker   /* NON-MAX ORDER context */
634*f6dc9357SAndroid Build Coastguard Worker 
635*f6dc9357SAndroid Build Coastguard Worker   {
636*f6dc9357SAndroid Build Coastguard Worker     Byte *text = p->Text;
637*f6dc9357SAndroid Build Coastguard Worker     *text++ = p->FoundState->Symbol;
638*f6dc9357SAndroid Build Coastguard Worker     p->Text = text;
639*f6dc9357SAndroid Build Coastguard Worker     if (text >= p->UnitsStart)
640*f6dc9357SAndroid Build Coastguard Worker     {
641*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_RestartModel(p);
642*f6dc9357SAndroid Build Coastguard Worker       return;
643*f6dc9357SAndroid Build Coastguard Worker     }
644*f6dc9357SAndroid Build Coastguard Worker     maxSuccessor = REF(text);
645*f6dc9357SAndroid Build Coastguard Worker   }
646*f6dc9357SAndroid Build Coastguard Worker 
647*f6dc9357SAndroid Build Coastguard Worker   minSuccessor = SUCCESSOR(p->FoundState);
648*f6dc9357SAndroid Build Coastguard Worker 
649*f6dc9357SAndroid Build Coastguard Worker   if (minSuccessor)
650*f6dc9357SAndroid Build Coastguard Worker   {
651*f6dc9357SAndroid Build Coastguard Worker     // there is Successor for FoundState in MinContext.
652*f6dc9357SAndroid Build Coastguard Worker     // So the next context will be one order higher than MinContext.
653*f6dc9357SAndroid Build Coastguard Worker 
654*f6dc9357SAndroid Build Coastguard Worker     if (minSuccessor <= maxSuccessor)
655*f6dc9357SAndroid Build Coastguard Worker     {
656*f6dc9357SAndroid Build Coastguard Worker       // minSuccessor is RAW-Successor. So we will create real contexts records:
657*f6dc9357SAndroid Build Coastguard Worker       PPMD7_CTX_PTR cs = Ppmd7_CreateSuccessors(p);
658*f6dc9357SAndroid Build Coastguard Worker       if (!cs)
659*f6dc9357SAndroid Build Coastguard Worker       {
660*f6dc9357SAndroid Build Coastguard Worker         Ppmd7_RestartModel(p);
661*f6dc9357SAndroid Build Coastguard Worker         return;
662*f6dc9357SAndroid Build Coastguard Worker       }
663*f6dc9357SAndroid Build Coastguard Worker       minSuccessor = REF(cs);
664*f6dc9357SAndroid Build Coastguard Worker     }
665*f6dc9357SAndroid Build Coastguard Worker 
666*f6dc9357SAndroid Build Coastguard Worker     // minSuccessor now is real Context pointer that points to existing (Order+1) context
667*f6dc9357SAndroid Build Coastguard Worker 
668*f6dc9357SAndroid Build Coastguard Worker     if (--p->OrderFall == 0)
669*f6dc9357SAndroid Build Coastguard Worker     {
670*f6dc9357SAndroid Build Coastguard Worker       /*
671*f6dc9357SAndroid Build Coastguard Worker       if we move to MaxOrder context, then minSuccessor will be common Succesor for both:
672*f6dc9357SAndroid Build Coastguard Worker         MinContext that is (MaxOrder - 1)
673*f6dc9357SAndroid Build Coastguard Worker         MaxContext that is (MaxOrder)
674*f6dc9357SAndroid Build Coastguard Worker       so we don't need new RAW-Successor, and we can use real minSuccessor
675*f6dc9357SAndroid Build Coastguard Worker       as succssors for both MinContext and MaxContext.
676*f6dc9357SAndroid Build Coastguard Worker       */
677*f6dc9357SAndroid Build Coastguard Worker       maxSuccessor = minSuccessor;
678*f6dc9357SAndroid Build Coastguard Worker 
679*f6dc9357SAndroid Build Coastguard Worker       /*
680*f6dc9357SAndroid Build Coastguard Worker       if (MaxContext != MinContext)
681*f6dc9357SAndroid Build Coastguard Worker       {
682*f6dc9357SAndroid Build Coastguard Worker         there was order fall from MaxOrder and we don't need current symbol
683*f6dc9357SAndroid Build Coastguard Worker         to transfer some RAW-Succesors to real contexts.
684*f6dc9357SAndroid Build Coastguard Worker         So we roll back pointer in raw data for one position.
685*f6dc9357SAndroid Build Coastguard Worker       }
686*f6dc9357SAndroid Build Coastguard Worker       */
687*f6dc9357SAndroid Build Coastguard Worker       p->Text -= (p->MaxContext != p->MinContext);
688*f6dc9357SAndroid Build Coastguard Worker     }
689*f6dc9357SAndroid Build Coastguard Worker   }
690*f6dc9357SAndroid Build Coastguard Worker   else
691*f6dc9357SAndroid Build Coastguard Worker   {
692*f6dc9357SAndroid Build Coastguard Worker     /*
693*f6dc9357SAndroid Build Coastguard Worker     FoundState has NULL-Successor here.
694*f6dc9357SAndroid Build Coastguard Worker     And only root 0-order context can contain NULL-Successors.
695*f6dc9357SAndroid Build Coastguard Worker     We change Successor in FoundState to RAW-Successor,
696*f6dc9357SAndroid Build Coastguard Worker     And next context will be same 0-order root Context.
697*f6dc9357SAndroid Build Coastguard Worker     */
698*f6dc9357SAndroid Build Coastguard Worker     SetSuccessor(p->FoundState, maxSuccessor);
699*f6dc9357SAndroid Build Coastguard Worker     minSuccessor = REF(p->MinContext);
700*f6dc9357SAndroid Build Coastguard Worker   }
701*f6dc9357SAndroid Build Coastguard Worker 
702*f6dc9357SAndroid Build Coastguard Worker   mc = p->MinContext;
703*f6dc9357SAndroid Build Coastguard Worker   c = p->MaxContext;
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker   p->MaxContext = p->MinContext = CTX(minSuccessor);
706*f6dc9357SAndroid Build Coastguard Worker 
707*f6dc9357SAndroid Build Coastguard Worker   if (c == mc)
708*f6dc9357SAndroid Build Coastguard Worker     return;
709*f6dc9357SAndroid Build Coastguard Worker 
710*f6dc9357SAndroid Build Coastguard Worker   // s0 : is pure Escape Freq
711*f6dc9357SAndroid Build Coastguard Worker   s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1);
712*f6dc9357SAndroid Build Coastguard Worker 
713*f6dc9357SAndroid Build Coastguard Worker   do
714*f6dc9357SAndroid Build Coastguard Worker   {
715*f6dc9357SAndroid Build Coastguard Worker     unsigned ns1;
716*f6dc9357SAndroid Build Coastguard Worker     UInt32 sum;
717*f6dc9357SAndroid Build Coastguard Worker 
718*f6dc9357SAndroid Build Coastguard Worker     if ((ns1 = c->NumStats) != 1)
719*f6dc9357SAndroid Build Coastguard Worker     {
720*f6dc9357SAndroid Build Coastguard Worker       if ((ns1 & 1) == 0)
721*f6dc9357SAndroid Build Coastguard Worker       {
722*f6dc9357SAndroid Build Coastguard Worker         /* Expand for one UNIT */
723*f6dc9357SAndroid Build Coastguard Worker         const unsigned oldNU = ns1 >> 1;
724*f6dc9357SAndroid Build Coastguard Worker         const unsigned i = U2I(oldNU);
725*f6dc9357SAndroid Build Coastguard Worker         if (i != U2I((size_t)oldNU + 1))
726*f6dc9357SAndroid Build Coastguard Worker         {
727*f6dc9357SAndroid Build Coastguard Worker           void *ptr = Ppmd7_AllocUnits(p, i + 1);
728*f6dc9357SAndroid Build Coastguard Worker           void *oldPtr;
729*f6dc9357SAndroid Build Coastguard Worker           if (!ptr)
730*f6dc9357SAndroid Build Coastguard Worker           {
731*f6dc9357SAndroid Build Coastguard Worker             Ppmd7_RestartModel(p);
732*f6dc9357SAndroid Build Coastguard Worker             return;
733*f6dc9357SAndroid Build Coastguard Worker           }
734*f6dc9357SAndroid Build Coastguard Worker           oldPtr = STATS(c);
735*f6dc9357SAndroid Build Coastguard Worker           MEM_12_CPY(ptr, oldPtr, oldNU)
736*f6dc9357SAndroid Build Coastguard Worker           Ppmd7_InsertNode(p, oldPtr, i);
737*f6dc9357SAndroid Build Coastguard Worker           c->Union4.Stats = STATS_REF(ptr);
738*f6dc9357SAndroid Build Coastguard Worker         }
739*f6dc9357SAndroid Build Coastguard Worker       }
740*f6dc9357SAndroid Build Coastguard Worker       sum = c->Union2.SummFreq;
741*f6dc9357SAndroid Build Coastguard Worker       /* max increase of Escape_Freq is 3 here.
742*f6dc9357SAndroid Build Coastguard Worker          total increase of Union2.SummFreq for all symbols is less than 256 here */
743*f6dc9357SAndroid Build Coastguard Worker       sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)));
744*f6dc9357SAndroid Build Coastguard Worker       /* original PPMdH uses 16-bit variable for (sum) here.
745*f6dc9357SAndroid Build Coastguard Worker          But (sum < 0x9000). So we don't truncate (sum) to 16-bit */
746*f6dc9357SAndroid Build Coastguard Worker       // sum = (UInt16)sum;
747*f6dc9357SAndroid Build Coastguard Worker     }
748*f6dc9357SAndroid Build Coastguard Worker     else
749*f6dc9357SAndroid Build Coastguard Worker     {
750*f6dc9357SAndroid Build Coastguard Worker       // instead of One-symbol context we create 2-symbol context
751*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State *s = (CPpmd_State*)Ppmd7_AllocUnits(p, 0);
752*f6dc9357SAndroid Build Coastguard Worker       if (!s)
753*f6dc9357SAndroid Build Coastguard Worker       {
754*f6dc9357SAndroid Build Coastguard Worker         Ppmd7_RestartModel(p);
755*f6dc9357SAndroid Build Coastguard Worker         return;
756*f6dc9357SAndroid Build Coastguard Worker       }
757*f6dc9357SAndroid Build Coastguard Worker       {
758*f6dc9357SAndroid Build Coastguard Worker         unsigned freq = c->Union2.State2.Freq;
759*f6dc9357SAndroid Build Coastguard Worker         // s = *ONE_STATE(c);
760*f6dc9357SAndroid Build Coastguard Worker         s->Symbol = c->Union2.State2.Symbol;
761*f6dc9357SAndroid Build Coastguard Worker         s->Successor_0 = c->Union4.State4.Successor_0;
762*f6dc9357SAndroid Build Coastguard Worker         s->Successor_1 = c->Union4.State4.Successor_1;
763*f6dc9357SAndroid Build Coastguard Worker         // SetSuccessor(s, c->Union4.Stats);  // call it only for debug purposes to check the order of
764*f6dc9357SAndroid Build Coastguard Worker                                               // (Successor_0 and Successor_1) in LE/BE.
765*f6dc9357SAndroid Build Coastguard Worker         c->Union4.Stats = REF(s);
766*f6dc9357SAndroid Build Coastguard Worker         if (freq < MAX_FREQ / 4 - 1)
767*f6dc9357SAndroid Build Coastguard Worker           freq <<= 1;
768*f6dc9357SAndroid Build Coastguard Worker         else
769*f6dc9357SAndroid Build Coastguard Worker           freq = MAX_FREQ - 4;
770*f6dc9357SAndroid Build Coastguard Worker         // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context
771*f6dc9357SAndroid Build Coastguard Worker         s->Freq = (Byte)freq;
772*f6dc9357SAndroid Build Coastguard Worker         // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here
773*f6dc9357SAndroid Build Coastguard Worker         sum = (UInt32)(freq + p->InitEsc + (ns > 3));
774*f6dc9357SAndroid Build Coastguard Worker       }
775*f6dc9357SAndroid Build Coastguard Worker     }
776*f6dc9357SAndroid Build Coastguard Worker 
777*f6dc9357SAndroid Build Coastguard Worker     {
778*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State *s = STATS(c) + ns1;
779*f6dc9357SAndroid Build Coastguard Worker       UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq;
780*f6dc9357SAndroid Build Coastguard Worker       UInt32 sf = (UInt32)s0 + sum;
781*f6dc9357SAndroid Build Coastguard Worker       s->Symbol = p->FoundState->Symbol;
782*f6dc9357SAndroid Build Coastguard Worker       c->NumStats = (UInt16)(ns1 + 1);
783*f6dc9357SAndroid Build Coastguard Worker       SetSuccessor(s, maxSuccessor);
784*f6dc9357SAndroid Build Coastguard Worker 
785*f6dc9357SAndroid Build Coastguard Worker       if (cf < 6 * sf)
786*f6dc9357SAndroid Build Coastguard Worker       {
787*f6dc9357SAndroid Build Coastguard Worker         cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf);
788*f6dc9357SAndroid Build Coastguard Worker         sum += 3;
789*f6dc9357SAndroid Build Coastguard Worker         /* It can add (0, 1, 2) to Escape_Freq */
790*f6dc9357SAndroid Build Coastguard Worker       }
791*f6dc9357SAndroid Build Coastguard Worker       else
792*f6dc9357SAndroid Build Coastguard Worker       {
793*f6dc9357SAndroid Build Coastguard Worker         cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
794*f6dc9357SAndroid Build Coastguard Worker         sum += cf;
795*f6dc9357SAndroid Build Coastguard Worker       }
796*f6dc9357SAndroid Build Coastguard Worker 
797*f6dc9357SAndroid Build Coastguard Worker       c->Union2.SummFreq = (UInt16)sum;
798*f6dc9357SAndroid Build Coastguard Worker       s->Freq = (Byte)cf;
799*f6dc9357SAndroid Build Coastguard Worker     }
800*f6dc9357SAndroid Build Coastguard Worker     c = SUFFIX(c);
801*f6dc9357SAndroid Build Coastguard Worker   }
802*f6dc9357SAndroid Build Coastguard Worker   while (c != mc);
803*f6dc9357SAndroid Build Coastguard Worker }
804*f6dc9357SAndroid Build Coastguard Worker 
805*f6dc9357SAndroid Build Coastguard Worker 
806*f6dc9357SAndroid Build Coastguard Worker 
807*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Ppmd7_Rescale(CPpmd7 * p)808*f6dc9357SAndroid Build Coastguard Worker static void Ppmd7_Rescale(CPpmd7 *p)
809*f6dc9357SAndroid Build Coastguard Worker {
810*f6dc9357SAndroid Build Coastguard Worker   unsigned i, adder, sumFreq, escFreq;
811*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *stats = STATS(p->MinContext);
812*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *s = p->FoundState;
813*f6dc9357SAndroid Build Coastguard Worker 
814*f6dc9357SAndroid Build Coastguard Worker   /* Sort the list by Freq */
815*f6dc9357SAndroid Build Coastguard Worker   if (s != stats)
816*f6dc9357SAndroid Build Coastguard Worker   {
817*f6dc9357SAndroid Build Coastguard Worker     CPpmd_State tmp = *s;
818*f6dc9357SAndroid Build Coastguard Worker     do
819*f6dc9357SAndroid Build Coastguard Worker       s[0] = s[-1];
820*f6dc9357SAndroid Build Coastguard Worker     while (--s != stats);
821*f6dc9357SAndroid Build Coastguard Worker     *s = tmp;
822*f6dc9357SAndroid Build Coastguard Worker   }
823*f6dc9357SAndroid Build Coastguard Worker 
824*f6dc9357SAndroid Build Coastguard Worker   sumFreq = s->Freq;
825*f6dc9357SAndroid Build Coastguard Worker   escFreq = p->MinContext->Union2.SummFreq - sumFreq;
826*f6dc9357SAndroid Build Coastguard Worker 
827*f6dc9357SAndroid Build Coastguard Worker   /*
828*f6dc9357SAndroid Build Coastguard Worker   if (p->OrderFall == 0), adder = 0 : it's     allowed to remove symbol from     MAX Order context
829*f6dc9357SAndroid Build Coastguard Worker   if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context
830*f6dc9357SAndroid Build Coastguard Worker   */
831*f6dc9357SAndroid Build Coastguard Worker 
832*f6dc9357SAndroid Build Coastguard Worker   adder = (p->OrderFall != 0);
833*f6dc9357SAndroid Build Coastguard Worker 
834*f6dc9357SAndroid Build Coastguard Worker   #ifdef PPMD7_ORDER_0_SUPPPORT
835*f6dc9357SAndroid Build Coastguard Worker   adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context
836*f6dc9357SAndroid Build Coastguard Worker   #endif
837*f6dc9357SAndroid Build Coastguard Worker 
838*f6dc9357SAndroid Build Coastguard Worker   sumFreq = (sumFreq + 4 + adder) >> 1;
839*f6dc9357SAndroid Build Coastguard Worker   i = (unsigned)p->MinContext->NumStats - 1;
840*f6dc9357SAndroid Build Coastguard Worker   s->Freq = (Byte)sumFreq;
841*f6dc9357SAndroid Build Coastguard Worker 
842*f6dc9357SAndroid Build Coastguard Worker   do
843*f6dc9357SAndroid Build Coastguard Worker   {
844*f6dc9357SAndroid Build Coastguard Worker     unsigned freq = (++s)->Freq;
845*f6dc9357SAndroid Build Coastguard Worker     escFreq -= freq;
846*f6dc9357SAndroid Build Coastguard Worker     freq = (freq + adder) >> 1;
847*f6dc9357SAndroid Build Coastguard Worker     sumFreq += freq;
848*f6dc9357SAndroid Build Coastguard Worker     s->Freq = (Byte)freq;
849*f6dc9357SAndroid Build Coastguard Worker     if (freq > s[-1].Freq)
850*f6dc9357SAndroid Build Coastguard Worker     {
851*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State tmp = *s;
852*f6dc9357SAndroid Build Coastguard Worker       CPpmd_State *s1 = s;
853*f6dc9357SAndroid Build Coastguard Worker       do
854*f6dc9357SAndroid Build Coastguard Worker       {
855*f6dc9357SAndroid Build Coastguard Worker         s1[0] = s1[-1];
856*f6dc9357SAndroid Build Coastguard Worker       }
857*f6dc9357SAndroid Build Coastguard Worker       while (--s1 != stats && freq > s1[-1].Freq);
858*f6dc9357SAndroid Build Coastguard Worker       *s1 = tmp;
859*f6dc9357SAndroid Build Coastguard Worker     }
860*f6dc9357SAndroid Build Coastguard Worker   }
861*f6dc9357SAndroid Build Coastguard Worker   while (--i);
862*f6dc9357SAndroid Build Coastguard Worker 
863*f6dc9357SAndroid Build Coastguard Worker   if (s->Freq == 0)
864*f6dc9357SAndroid Build Coastguard Worker   {
865*f6dc9357SAndroid Build Coastguard Worker     /* Remove all items with Freq == 0 */
866*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Context *mc;
867*f6dc9357SAndroid Build Coastguard Worker     unsigned numStats, numStatsNew, n0, n1;
868*f6dc9357SAndroid Build Coastguard Worker 
869*f6dc9357SAndroid Build Coastguard Worker     i = 0; do { i++; } while ((--s)->Freq == 0);
870*f6dc9357SAndroid Build Coastguard Worker 
871*f6dc9357SAndroid Build Coastguard Worker     /* We increase (escFreq) for the number of removed symbols.
872*f6dc9357SAndroid Build Coastguard Worker        So we will have (0.5) increase for Escape_Freq in avarage per
873*f6dc9357SAndroid Build Coastguard Worker        removed symbol after Escape_Freq halving */
874*f6dc9357SAndroid Build Coastguard Worker     escFreq += i;
875*f6dc9357SAndroid Build Coastguard Worker     mc = p->MinContext;
876*f6dc9357SAndroid Build Coastguard Worker     numStats = mc->NumStats;
877*f6dc9357SAndroid Build Coastguard Worker     numStatsNew = numStats - i;
878*f6dc9357SAndroid Build Coastguard Worker     mc->NumStats = (UInt16)(numStatsNew);
879*f6dc9357SAndroid Build Coastguard Worker     n0 = (numStats + 1) >> 1;
880*f6dc9357SAndroid Build Coastguard Worker 
881*f6dc9357SAndroid Build Coastguard Worker     if (numStatsNew == 1)
882*f6dc9357SAndroid Build Coastguard Worker     {
883*f6dc9357SAndroid Build Coastguard Worker       /* Create Single-Symbol context */
884*f6dc9357SAndroid Build Coastguard Worker       unsigned freq = stats->Freq;
885*f6dc9357SAndroid Build Coastguard Worker 
886*f6dc9357SAndroid Build Coastguard Worker       do
887*f6dc9357SAndroid Build Coastguard Worker       {
888*f6dc9357SAndroid Build Coastguard Worker         escFreq >>= 1;
889*f6dc9357SAndroid Build Coastguard Worker         freq = (freq + 1) >> 1;
890*f6dc9357SAndroid Build Coastguard Worker       }
891*f6dc9357SAndroid Build Coastguard Worker       while (escFreq > 1);
892*f6dc9357SAndroid Build Coastguard Worker 
893*f6dc9357SAndroid Build Coastguard Worker       s = ONE_STATE(mc);
894*f6dc9357SAndroid Build Coastguard Worker       *s = *stats;
895*f6dc9357SAndroid Build Coastguard Worker       s->Freq = (Byte)freq; // (freq <= 260 / 4)
896*f6dc9357SAndroid Build Coastguard Worker       p->FoundState = s;
897*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_InsertNode(p, stats, U2I(n0));
898*f6dc9357SAndroid Build Coastguard Worker       return;
899*f6dc9357SAndroid Build Coastguard Worker     }
900*f6dc9357SAndroid Build Coastguard Worker 
901*f6dc9357SAndroid Build Coastguard Worker     n1 = (numStatsNew + 1) >> 1;
902*f6dc9357SAndroid Build Coastguard Worker     if (n0 != n1)
903*f6dc9357SAndroid Build Coastguard Worker     {
904*f6dc9357SAndroid Build Coastguard Worker       // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
905*f6dc9357SAndroid Build Coastguard Worker       unsigned i0 = U2I(n0);
906*f6dc9357SAndroid Build Coastguard Worker       unsigned i1 = U2I(n1);
907*f6dc9357SAndroid Build Coastguard Worker       if (i0 != i1)
908*f6dc9357SAndroid Build Coastguard Worker       {
909*f6dc9357SAndroid Build Coastguard Worker         if (p->FreeList[i1] != 0)
910*f6dc9357SAndroid Build Coastguard Worker         {
911*f6dc9357SAndroid Build Coastguard Worker           void *ptr = Ppmd7_RemoveNode(p, i1);
912*f6dc9357SAndroid Build Coastguard Worker           p->MinContext->Union4.Stats = STATS_REF(ptr);
913*f6dc9357SAndroid Build Coastguard Worker           MEM_12_CPY(ptr, (const void *)stats, n1)
914*f6dc9357SAndroid Build Coastguard Worker           Ppmd7_InsertNode(p, stats, i0);
915*f6dc9357SAndroid Build Coastguard Worker         }
916*f6dc9357SAndroid Build Coastguard Worker         else
917*f6dc9357SAndroid Build Coastguard Worker           Ppmd7_SplitBlock(p, stats, i0, i1);
918*f6dc9357SAndroid Build Coastguard Worker       }
919*f6dc9357SAndroid Build Coastguard Worker     }
920*f6dc9357SAndroid Build Coastguard Worker   }
921*f6dc9357SAndroid Build Coastguard Worker   {
922*f6dc9357SAndroid Build Coastguard Worker     CPpmd7_Context *mc = p->MinContext;
923*f6dc9357SAndroid Build Coastguard Worker     mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
924*f6dc9357SAndroid Build Coastguard Worker     // Escape_Freq halving here
925*f6dc9357SAndroid Build Coastguard Worker     p->FoundState = STATS(mc);
926*f6dc9357SAndroid Build Coastguard Worker   }
927*f6dc9357SAndroid Build Coastguard Worker }
928*f6dc9357SAndroid Build Coastguard Worker 
929*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_MakeEscFreq(CPpmd7 * p,unsigned numMasked,UInt32 * escFreq)930*f6dc9357SAndroid Build Coastguard Worker CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
931*f6dc9357SAndroid Build Coastguard Worker {
932*f6dc9357SAndroid Build Coastguard Worker   CPpmd_See *see;
933*f6dc9357SAndroid Build Coastguard Worker   const CPpmd7_Context *mc = p->MinContext;
934*f6dc9357SAndroid Build Coastguard Worker   unsigned numStats = mc->NumStats;
935*f6dc9357SAndroid Build Coastguard Worker   if (numStats != 256)
936*f6dc9357SAndroid Build Coastguard Worker   {
937*f6dc9357SAndroid Build Coastguard Worker     unsigned nonMasked = numStats - numMasked;
938*f6dc9357SAndroid Build Coastguard Worker     see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]]
939*f6dc9357SAndroid Build Coastguard Worker         + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats)
940*f6dc9357SAndroid Build Coastguard Worker         + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats)
941*f6dc9357SAndroid Build Coastguard Worker         + 4 * (unsigned)(numMasked > nonMasked) +
942*f6dc9357SAndroid Build Coastguard Worker         p->HiBitsFlag;
943*f6dc9357SAndroid Build Coastguard Worker     {
944*f6dc9357SAndroid Build Coastguard Worker       // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
945*f6dc9357SAndroid Build Coastguard Worker       const unsigned summ = (UInt16)see->Summ; // & 0xFFFF
946*f6dc9357SAndroid Build Coastguard Worker       const unsigned r = (summ >> see->Shift);
947*f6dc9357SAndroid Build Coastguard Worker       see->Summ = (UInt16)(summ - r);
948*f6dc9357SAndroid Build Coastguard Worker       *escFreq = (UInt32)(r + (r == 0));
949*f6dc9357SAndroid Build Coastguard Worker     }
950*f6dc9357SAndroid Build Coastguard Worker   }
951*f6dc9357SAndroid Build Coastguard Worker   else
952*f6dc9357SAndroid Build Coastguard Worker   {
953*f6dc9357SAndroid Build Coastguard Worker     see = &p->DummySee;
954*f6dc9357SAndroid Build Coastguard Worker     *escFreq = 1;
955*f6dc9357SAndroid Build Coastguard Worker   }
956*f6dc9357SAndroid Build Coastguard Worker   return see;
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_NextContext(CPpmd7 * p)960*f6dc9357SAndroid Build Coastguard Worker static void Ppmd7_NextContext(CPpmd7 *p)
961*f6dc9357SAndroid Build Coastguard Worker {
962*f6dc9357SAndroid Build Coastguard Worker   PPMD7_CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
963*f6dc9357SAndroid Build Coastguard Worker   if (p->OrderFall == 0 && (const Byte *)c > p->Text)
964*f6dc9357SAndroid Build Coastguard Worker     p->MaxContext = p->MinContext = c;
965*f6dc9357SAndroid Build Coastguard Worker   else
966*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_UpdateModel(p);
967*f6dc9357SAndroid Build Coastguard Worker }
968*f6dc9357SAndroid Build Coastguard Worker 
969*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Update1(CPpmd7 * p)970*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Update1(CPpmd7 *p)
971*f6dc9357SAndroid Build Coastguard Worker {
972*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *s = p->FoundState;
973*f6dc9357SAndroid Build Coastguard Worker   unsigned freq = s->Freq;
974*f6dc9357SAndroid Build Coastguard Worker   freq += 4;
975*f6dc9357SAndroid Build Coastguard Worker   p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);
976*f6dc9357SAndroid Build Coastguard Worker   s->Freq = (Byte)freq;
977*f6dc9357SAndroid Build Coastguard Worker   if (freq > s[-1].Freq)
978*f6dc9357SAndroid Build Coastguard Worker   {
979*f6dc9357SAndroid Build Coastguard Worker     SWAP_STATES(s)
980*f6dc9357SAndroid Build Coastguard Worker     p->FoundState = --s;
981*f6dc9357SAndroid Build Coastguard Worker     if (freq > MAX_FREQ)
982*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_Rescale(p);
983*f6dc9357SAndroid Build Coastguard Worker   }
984*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_NextContext(p);
985*f6dc9357SAndroid Build Coastguard Worker }
986*f6dc9357SAndroid Build Coastguard Worker 
987*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Update1_0(CPpmd7 * p)988*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Update1_0(CPpmd7 *p)
989*f6dc9357SAndroid Build Coastguard Worker {
990*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *s = p->FoundState;
991*f6dc9357SAndroid Build Coastguard Worker   CPpmd7_Context *mc = p->MinContext;
992*f6dc9357SAndroid Build Coastguard Worker   unsigned freq = s->Freq;
993*f6dc9357SAndroid Build Coastguard Worker   const unsigned summFreq = mc->Union2.SummFreq;
994*f6dc9357SAndroid Build Coastguard Worker   p->PrevSuccess = (2 * freq > summFreq);
995*f6dc9357SAndroid Build Coastguard Worker   p->RunLength += (Int32)p->PrevSuccess;
996*f6dc9357SAndroid Build Coastguard Worker   mc->Union2.SummFreq = (UInt16)(summFreq + 4);
997*f6dc9357SAndroid Build Coastguard Worker   freq += 4;
998*f6dc9357SAndroid Build Coastguard Worker   s->Freq = (Byte)freq;
999*f6dc9357SAndroid Build Coastguard Worker   if (freq > MAX_FREQ)
1000*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_Rescale(p);
1001*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_NextContext(p);
1002*f6dc9357SAndroid Build Coastguard Worker }
1003*f6dc9357SAndroid Build Coastguard Worker 
1004*f6dc9357SAndroid Build Coastguard Worker 
1005*f6dc9357SAndroid Build Coastguard Worker /*
1006*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_UpdateBin(CPpmd7 *p)
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker   unsigned freq = p->FoundState->Freq;
1009*f6dc9357SAndroid Build Coastguard Worker   p->FoundState->Freq = (Byte)(freq + (freq < 128));
1010*f6dc9357SAndroid Build Coastguard Worker   p->PrevSuccess = 1;
1011*f6dc9357SAndroid Build Coastguard Worker   p->RunLength++;
1012*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_NextContext(p);
1013*f6dc9357SAndroid Build Coastguard Worker }
1014*f6dc9357SAndroid Build Coastguard Worker */
1015*f6dc9357SAndroid Build Coastguard Worker 
Ppmd7_Update2(CPpmd7 * p)1016*f6dc9357SAndroid Build Coastguard Worker void Ppmd7_Update2(CPpmd7 *p)
1017*f6dc9357SAndroid Build Coastguard Worker {
1018*f6dc9357SAndroid Build Coastguard Worker   CPpmd_State *s = p->FoundState;
1019*f6dc9357SAndroid Build Coastguard Worker   unsigned freq = s->Freq;
1020*f6dc9357SAndroid Build Coastguard Worker   freq += 4;
1021*f6dc9357SAndroid Build Coastguard Worker   p->RunLength = p->InitRL;
1022*f6dc9357SAndroid Build Coastguard Worker   p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);
1023*f6dc9357SAndroid Build Coastguard Worker   s->Freq = (Byte)freq;
1024*f6dc9357SAndroid Build Coastguard Worker   if (freq > MAX_FREQ)
1025*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_Rescale(p);
1026*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_UpdateModel(p);
1027*f6dc9357SAndroid Build Coastguard Worker }
1028*f6dc9357SAndroid Build Coastguard Worker 
1029*f6dc9357SAndroid Build Coastguard Worker 
1030*f6dc9357SAndroid Build Coastguard Worker 
1031*f6dc9357SAndroid Build Coastguard Worker /*
1032*f6dc9357SAndroid Build Coastguard Worker PPMd Memory Map:
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker   [ 0 ]           contains subset of original raw text, that is required to create context
1035*f6dc9357SAndroid Build Coastguard Worker                   records, Some symbols are not written, when max order context was reached
1036*f6dc9357SAndroid Build Coastguard Worker   [ Text ]        free area
1037*f6dc9357SAndroid Build Coastguard Worker   [ UnitsStart ]  CPpmd_State vectors and CPpmd7_Context records
1038*f6dc9357SAndroid Build Coastguard Worker   [ LoUnit ]      free  area for CPpmd_State and CPpmd7_Context items
1039*f6dc9357SAndroid Build Coastguard Worker [ HiUnit ]      CPpmd7_Context records
1040*f6dc9357SAndroid Build Coastguard Worker   [ Size ]        end of array
1041*f6dc9357SAndroid Build Coastguard Worker }
1042*f6dc9357SAndroid Build Coastguard Worker 
1043*f6dc9357SAndroid Build Coastguard Worker These addresses don't cross at any time.
1044*f6dc9357SAndroid Build Coastguard Worker And the following condtions is true for addresses:
1045*f6dc9357SAndroid Build Coastguard Worker   (0  <= Text < UnitsStart <= LoUnit <= HiUnit <= Size)
1046*f6dc9357SAndroid Build Coastguard Worker 
1047*f6dc9357SAndroid Build Coastguard Worker Raw text is BYTE--aligned.
1048*f6dc9357SAndroid Build Coastguard Worker the data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs.
1049*f6dc9357SAndroid Build Coastguard Worker 
1050*f6dc9357SAndroid Build Coastguard Worker Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record.
1051*f6dc9357SAndroid Build Coastguard Worker The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors.
1052*f6dc9357SAndroid Build Coastguard Worker The code doesn't free UNITs allocated for CPpmd7_Context records.
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker The code calls Ppmd7_RestartModel(), when there is no free memory for allocation.
1055*f6dc9357SAndroid Build Coastguard Worker And Ppmd7_RestartModel() changes the state to orignal start state, with full free block.
1056*f6dc9357SAndroid Build Coastguard Worker 
1057*f6dc9357SAndroid Build Coastguard Worker 
1058*f6dc9357SAndroid Build Coastguard Worker The code allocates UNITs with the following order:
1059*f6dc9357SAndroid Build Coastguard Worker 
1060*f6dc9357SAndroid Build Coastguard Worker Allocation of 1 UNIT for Context record
1061*f6dc9357SAndroid Build Coastguard Worker   - from free space (HiUnit) down to (LoUnit)
1062*f6dc9357SAndroid Build Coastguard Worker   - from FreeList[0]
1063*f6dc9357SAndroid Build Coastguard Worker   - Ppmd7_AllocUnitsRare()
1064*f6dc9357SAndroid Build Coastguard Worker 
1065*f6dc9357SAndroid Build Coastguard Worker Ppmd7_AllocUnits() for CPpmd_State vectors:
1066*f6dc9357SAndroid Build Coastguard Worker   - from FreeList[i]
1067*f6dc9357SAndroid Build Coastguard Worker   - from free space (LoUnit) up to (HiUnit)
1068*f6dc9357SAndroid Build Coastguard Worker   - Ppmd7_AllocUnitsRare()
1069*f6dc9357SAndroid Build Coastguard Worker 
1070*f6dc9357SAndroid Build Coastguard Worker Ppmd7_AllocUnitsRare()
1071*f6dc9357SAndroid Build Coastguard Worker   - if (GlueCount == 0)
1072*f6dc9357SAndroid Build Coastguard Worker        {  Glue lists, GlueCount = 255, allocate from FreeList[i]] }
1073*f6dc9357SAndroid Build Coastguard Worker   - loop for all higher sized FreeList[...] lists
1074*f6dc9357SAndroid Build Coastguard Worker   - from (UnitsStart - Text), GlueCount--
1075*f6dc9357SAndroid Build Coastguard Worker   - ERROR
1076*f6dc9357SAndroid Build Coastguard Worker 
1077*f6dc9357SAndroid Build Coastguard Worker 
1078*f6dc9357SAndroid Build Coastguard Worker Each Record with Context contains the CPpmd_State vector, where each
1079*f6dc9357SAndroid Build Coastguard Worker CPpmd_State contains the link to Successor.
1080*f6dc9357SAndroid Build Coastguard Worker There are 3 types of Successor:
1081*f6dc9357SAndroid Build Coastguard Worker   1) NULL-Successor   - NULL pointer. NULL-Successor links can be stored
1082*f6dc9357SAndroid Build Coastguard Worker                         only in 0-order Root Context Record.
1083*f6dc9357SAndroid Build Coastguard Worker                         We use 0 value as NULL-Successor
1084*f6dc9357SAndroid Build Coastguard Worker   2) RAW-Successor    - the link to position in raw text,
1085*f6dc9357SAndroid Build Coastguard Worker                         that "RAW-Successor" is being created after first
1086*f6dc9357SAndroid Build Coastguard Worker                         occurrence of new symbol for some existing context record.
1087*f6dc9357SAndroid Build Coastguard Worker                         (RAW-Successor > 0).
1088*f6dc9357SAndroid Build Coastguard Worker   3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1),
1089*f6dc9357SAndroid Build Coastguard Worker                         that record is being created when we go via RAW-Successor again.
1090*f6dc9357SAndroid Build Coastguard Worker 
1091*f6dc9357SAndroid Build Coastguard Worker For any successors at any time: the following condtions are true for Successor links:
1092*f6dc9357SAndroid Build Coastguard Worker (NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor)
1093*f6dc9357SAndroid Build Coastguard Worker 
1094*f6dc9357SAndroid Build Coastguard Worker 
1095*f6dc9357SAndroid Build Coastguard Worker ---------- Symbol Frequency, SummFreq and Range in Range_Coder ----------
1096*f6dc9357SAndroid Build Coastguard Worker 
1097*f6dc9357SAndroid Build Coastguard Worker CPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq
1098*f6dc9357SAndroid Build Coastguard Worker 
1099*f6dc9357SAndroid Build Coastguard Worker The PPMd code tries to fulfill the condition:
1100*f6dc9357SAndroid Build Coastguard Worker   (SummFreq <= (256 * 128 = RC::kBot))
1101*f6dc9357SAndroid Build Coastguard Worker 
1102*f6dc9357SAndroid Build Coastguard Worker We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124)
1103*f6dc9357SAndroid Build Coastguard Worker So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol.
1104*f6dc9357SAndroid Build Coastguard Worker If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7.
1105*f6dc9357SAndroid Build Coastguard Worker SummFreq and Escape_Freq can be changed in Ppmd7_Rescale() and *Update*() functions.
1106*f6dc9357SAndroid Build Coastguard Worker Ppmd7_Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Ppmd7_Rescale() for
1107*f6dc9357SAndroid Build Coastguard Worker max-order context.
1108*f6dc9357SAndroid Build Coastguard Worker 
1109*f6dc9357SAndroid Build Coastguard Worker When the PPMd code still break (Total <= RC::Range) condition in range coder,
1110*f6dc9357SAndroid Build Coastguard Worker we have two ways to resolve that problem:
1111*f6dc9357SAndroid Build Coastguard Worker   1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases.
1112*f6dc9357SAndroid Build Coastguard Worker   2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value.
1113*f6dc9357SAndroid Build Coastguard Worker */
1114*f6dc9357SAndroid Build Coastguard Worker 
1115*f6dc9357SAndroid Build Coastguard Worker #undef MAX_FREQ
1116*f6dc9357SAndroid Build Coastguard Worker #undef UNIT_SIZE
1117*f6dc9357SAndroid Build Coastguard Worker #undef U2B
1118*f6dc9357SAndroid Build Coastguard Worker #undef U2I
1119*f6dc9357SAndroid Build Coastguard Worker #undef I2U
1120*f6dc9357SAndroid Build Coastguard Worker #undef I2U_UInt16
1121*f6dc9357SAndroid Build Coastguard Worker #undef REF
1122*f6dc9357SAndroid Build Coastguard Worker #undef STATS_REF
1123*f6dc9357SAndroid Build Coastguard Worker #undef CTX
1124*f6dc9357SAndroid Build Coastguard Worker #undef STATS
1125*f6dc9357SAndroid Build Coastguard Worker #undef ONE_STATE
1126*f6dc9357SAndroid Build Coastguard Worker #undef SUFFIX
1127*f6dc9357SAndroid Build Coastguard Worker #undef NODE
1128*f6dc9357SAndroid Build Coastguard Worker #undef EMPTY_NODE
1129*f6dc9357SAndroid Build Coastguard Worker #undef MEM_12_CPY
1130*f6dc9357SAndroid Build Coastguard Worker #undef SUCCESSOR
1131*f6dc9357SAndroid Build Coastguard Worker #undef SWAP_STATES
1132