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