]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_ppmd7.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / archive_ppmd7.c
1 /* Ppmd7.c -- PPMdH codec
2 2010-03-12 : Igor Pavlov : Public domain
3 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4
5 #include "archive_platform.h"
6
7 #include <stdlib.h>
8
9 #include "archive_ppmd7_private.h"
10
11 #ifdef PPMD_32BIT
12   #define Ppmd7_GetPtr(p, ptr) (ptr)
13   #define Ppmd7_GetContext(p, ptr) (ptr)
14   #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
15 #else
16   #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
17   #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
18   #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
19 #endif
20
21 #define Ppmd7_GetBinSumm(p) \
22     &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
23     p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
24     (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
25     2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
26     ((p->RunLength >> 26) & 0x20)]
27
28 #define kTopValue (1 << 24)
29 #define MAX_FREQ 124
30 #define UNIT_SIZE 12
31
32 #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
33 #define U2I(nu) (p->Units2Indx[(nu) - 1])
34 #define I2U(indx) (p->Indx2Units[indx])
35
36 #ifdef PPMD_32BIT
37   #define REF(ptr) (ptr)
38 #else
39   #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
40 #endif
41
42 #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
43
44 #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
45 #define STATS(ctx) Ppmd7_GetStats(p, ctx)
46 #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
47 #define SUFFIX(ctx) CTX((ctx)->Suffix)
48
49 static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
50 static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
51
52 typedef CPpmd7_Context * CTX_PTR;
53
54 struct CPpmd7_Node_;
55
56 typedef
57   #ifdef PPMD_32BIT
58     struct CPpmd7_Node_ *
59   #else
60     UInt32
61   #endif
62   CPpmd7_Node_Ref;
63
64 typedef struct CPpmd7_Node_
65 {
66   UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
67   UInt16 NU;
68   CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
69   CPpmd7_Node_Ref Prev;
70 } CPpmd7_Node;
71
72 #ifdef PPMD_32BIT
73   #define NODE(ptr) (ptr)
74 #else
75   #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
76 #endif
77
78 static void Ppmd7_Update1(CPpmd7 *p);
79 static void Ppmd7_Update1_0(CPpmd7 *p);
80 static void Ppmd7_Update2(CPpmd7 *p);
81 static void Ppmd7_UpdateBin(CPpmd7 *p);
82 static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked,
83                                     UInt32 *scale);
84
85 /* ----------- Base ----------- */
86
87 static void Ppmd7_Construct(CPpmd7 *p)
88 {
89   unsigned i, k, m;
90
91   p->Base = 0;
92
93   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
94   {
95     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
96     do { p->Units2Indx[k++] = (Byte)i; } while(--step);
97     p->Indx2Units[i] = (Byte)k;
98   }
99
100   p->NS2BSIndx[0] = (0 << 1);
101   p->NS2BSIndx[1] = (1 << 1);
102   memset(p->NS2BSIndx + 2, (2 << 1), 9);
103   memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
104
105   for (i = 0; i < 3; i++)
106     p->NS2Indx[i] = (Byte)i;
107   for (m = i, k = 1; i < 256; i++)
108   {
109     p->NS2Indx[i] = (Byte)m;
110     if (--k == 0)
111       k = (++m) - 2;
112   }
113
114   memset(p->HB2Flag, 0, 0x40);
115   memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
116 }
117
118 static void Ppmd7_Free(CPpmd7 *p)
119 {
120   free(p->Base);
121   p->Size = 0;
122   p->Base = 0;
123 }
124
125 static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
126 {
127   if (p->Base == 0 || p->Size != size)
128   {
129     /* RestartModel() below assumes that p->Size >= UNIT_SIZE
130        (see the calculation of m->MinContext). */
131     if (size < UNIT_SIZE) {
132       return False;
133     }
134     Ppmd7_Free(p);
135     p->AlignOffset =
136       #ifdef PPMD_32BIT
137         (4 - size) & 3;
138       #else
139         4 - (size & 3);
140       #endif
141     if ((p->Base = (Byte *)malloc(p->AlignOffset + size
142         #ifndef PPMD_32BIT
143         + UNIT_SIZE
144         #endif
145         )) == 0)
146       return False;
147     p->Size = size;
148   }
149   return True;
150 }
151
152 static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
153 {
154   *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
155   p->FreeList[indx] = REF(node);
156 }
157
158 static void *RemoveNode(CPpmd7 *p, unsigned indx)
159 {
160   CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
161   p->FreeList[indx] = *node;
162   return node;
163 }
164
165 static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
166 {
167   unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
168   ptr = (Byte *)ptr + U2B(I2U(newIndx));
169   if (I2U(i = U2I(nu)) != nu)
170   {
171     unsigned k = I2U(--i);
172     InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
173   }
174   InsertNode(p, ptr, i);
175 }
176
177 static void GlueFreeBlocks(CPpmd7 *p)
178 {
179   #ifdef PPMD_32BIT
180   CPpmd7_Node headItem;
181   CPpmd7_Node_Ref head = &headItem;
182   #else
183   CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
184   #endif
185   
186   CPpmd7_Node_Ref n = head;
187   unsigned i;
188
189   p->GlueCount = 255;
190
191   /* create doubly-linked list of free blocks */
192   for (i = 0; i < PPMD_NUM_INDEXES; i++)
193   {
194     UInt16 nu = I2U(i);
195     CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
196     p->FreeList[i] = 0;
197     while (next != 0)
198     {
199       CPpmd7_Node *node = NODE(next);
200       node->Next = n;
201       n = NODE(n)->Prev = next;
202       next = *(const CPpmd7_Node_Ref *)node;
203       node->Stamp = 0;
204       node->NU = (UInt16)nu;
205     }
206   }
207   NODE(head)->Stamp = 1;
208   NODE(head)->Next = n;
209   NODE(n)->Prev = head;
210   if (p->LoUnit != p->HiUnit)
211     ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
212   
213   /* Glue free blocks */
214   while (n != head)
215   {
216     CPpmd7_Node *node = NODE(n);
217     UInt32 nu = (UInt32)node->NU;
218     for (;;)
219     {
220       CPpmd7_Node *node2 = NODE(n) + nu;
221       nu += node2->NU;
222       if (node2->Stamp != 0 || nu >= 0x10000)
223         break;
224       NODE(node2->Prev)->Next = node2->Next;
225       NODE(node2->Next)->Prev = node2->Prev;
226       node->NU = (UInt16)nu;
227     }
228     n = node->Next;
229   }
230   
231   /* Fill lists of free blocks */
232   for (n = NODE(head)->Next; n != head;)
233   {
234     CPpmd7_Node *node = NODE(n);
235     unsigned nu;
236     CPpmd7_Node_Ref next = node->Next;
237     for (nu = node->NU; nu > 128; nu -= 128, node += 128)
238       InsertNode(p, node, PPMD_NUM_INDEXES - 1);
239     if (I2U(i = U2I(nu)) != nu)
240     {
241       unsigned k = I2U(--i);
242       InsertNode(p, node + k, nu - k - 1);
243     }
244     InsertNode(p, node, i);
245     n = next;
246   }
247 }
248
249 static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
250 {
251   unsigned i;
252   void *retVal;
253   if (p->GlueCount == 0)
254   {
255     GlueFreeBlocks(p);
256     if (p->FreeList[indx] != 0)
257       return RemoveNode(p, indx);
258   }
259   i = indx;
260   do
261   {
262     if (++i == PPMD_NUM_INDEXES)
263     {
264       UInt32 numBytes = U2B(I2U(indx));
265       p->GlueCount--;
266       return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
267     }
268   }
269   while (p->FreeList[i] == 0);
270   retVal = RemoveNode(p, i);
271   SplitBlock(p, retVal, i, indx);
272   return retVal;
273 }
274
275 static void *AllocUnits(CPpmd7 *p, unsigned indx)
276 {
277   UInt32 numBytes;
278   if (p->FreeList[indx] != 0)
279     return RemoveNode(p, indx);
280   numBytes = U2B(I2U(indx));
281   if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
282   {
283     void *retVal = p->LoUnit;
284     p->LoUnit += numBytes;
285     return retVal;
286   }
287   return AllocUnitsRare(p, indx);
288 }
289
290 #define MyMem12Cpy(dest, src, num) \
291   { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
292     do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
293
294 static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
295 {
296   unsigned i0 = U2I(oldNU);
297   unsigned i1 = U2I(newNU);
298   if (i0 == i1)
299     return oldPtr;
300   if (p->FreeList[i1] != 0)
301   {
302     void *ptr = RemoveNode(p, i1);
303     MyMem12Cpy(ptr, oldPtr, newNU);
304     InsertNode(p, oldPtr, i0);
305     return ptr;
306   }
307   SplitBlock(p, oldPtr, i0, i1);
308   return oldPtr;
309 }
310
311 #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
312
313 static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
314 {
315   (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
316   (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
317 }
318
319 static void RestartModel(CPpmd7 *p)
320 {
321   unsigned i, k, m;
322
323   memset(p->FreeList, 0, sizeof(p->FreeList));
324   p->Text = p->Base + p->AlignOffset;
325   p->HiUnit = p->Text + p->Size;
326   p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
327   p->GlueCount = 0;
328
329   p->OrderFall = p->MaxOrder;
330   p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
331   p->PrevSuccess = 0;
332
333   p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
334   p->MinContext->Suffix = 0;
335   p->MinContext->NumStats = 256;
336   p->MinContext->SummFreq = 256 + 1;
337   p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
338   p->LoUnit += U2B(256 / 2);
339   p->MinContext->Stats = REF(p->FoundState);
340   for (i = 0; i < 256; i++)
341   {
342     CPpmd_State *s = &p->FoundState[i];
343     s->Symbol = (Byte)i;
344     s->Freq = 1;
345     SetSuccessor(s, 0);
346   }
347
348   for (i = 0; i < 128; i++)
349     for (k = 0; k < 8; k++)
350     {
351       UInt16 *dest = p->BinSumm[i] + k;
352       UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
353       for (m = 0; m < 64; m += 8)
354         dest[m] = val;
355     }
356   
357   for (i = 0; i < 25; i++)
358     for (k = 0; k < 16; k++)
359     {
360       CPpmd_See *s = &p->See[i][k];
361       s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
362       s->Count = 4;
363     }
364 }
365
366 static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
367 {
368   p->MaxOrder = maxOrder;
369   RestartModel(p);
370   p->DummySee.Shift = PPMD_PERIOD_BITS;
371   p->DummySee.Summ = 0; /* unused */
372   p->DummySee.Count = 64; /* unused */
373 }
374
375 static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
376 {
377   CPpmd_State upState;
378   CTX_PTR c = p->MinContext;
379   CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
380   CPpmd_State *ps[PPMD7_MAX_ORDER];
381   unsigned numPs = 0;
382   
383   if (!skip)
384     ps[numPs++] = p->FoundState;
385   
386   while (c->Suffix)
387   {
388     CPpmd_Void_Ref successor;
389     CPpmd_State *s;
390     c = SUFFIX(c);
391     if (c->NumStats != 1)
392     {
393       for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
394     }
395     else
396       s = ONE_STATE(c);
397     successor = SUCCESSOR(s);
398     if (successor != upBranch)
399     {
400       c = CTX(successor);
401       if (numPs == 0)
402         return c;
403       break;
404     }
405     ps[numPs++] = s;
406   }
407   
408   upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
409   SetSuccessor(&upState, upBranch + 1);
410   
411   if (c->NumStats == 1)
412     upState.Freq = ONE_STATE(c)->Freq;
413   else
414   {
415     UInt32 cf, s0;
416     CPpmd_State *s;
417     for (s = STATS(c); s->Symbol != upState.Symbol; s++);
418     cf = s->Freq - 1;
419     s0 = c->SummFreq - c->NumStats - cf;
420     upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
421   }
422
423   while (numPs != 0)
424   {
425     /* Create Child */
426     CTX_PTR c1; /* = AllocContext(p); */
427     if (p->HiUnit != p->LoUnit)
428       c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
429     else if (p->FreeList[0] != 0)
430       c1 = (CTX_PTR)RemoveNode(p, 0);
431     else
432     {
433       c1 = (CTX_PTR)AllocUnitsRare(p, 0);
434       if (!c1)
435         return NULL;
436     }
437     c1->NumStats = 1;
438     *ONE_STATE(c1) = upState;
439     c1->Suffix = REF(c);
440     SetSuccessor(ps[--numPs], REF(c1));
441     c = c1;
442   }
443   
444   return c;
445 }
446
447 static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
448 {
449   CPpmd_State tmp = *t1;
450   *t1 = *t2;
451   *t2 = tmp;
452 }
453
454 static void UpdateModel(CPpmd7 *p)
455 {
456   CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
457   CTX_PTR c;
458   unsigned s0, ns;
459   
460   if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
461   {
462     c = SUFFIX(p->MinContext);
463     
464     if (c->NumStats == 1)
465     {
466       CPpmd_State *s = ONE_STATE(c);
467       if (s->Freq < 32)
468         s->Freq++;
469     }
470     else
471     {
472       CPpmd_State *s = STATS(c);
473       if (s->Symbol != p->FoundState->Symbol)
474       {
475         do { s++; } while (s->Symbol != p->FoundState->Symbol);
476         if (s[0].Freq >= s[-1].Freq)
477         {
478           SwapStates(&s[0], &s[-1]);
479           s--;
480         }
481       }
482       if (s->Freq < MAX_FREQ - 9)
483       {
484         s->Freq += 2;
485         c->SummFreq += 2;
486       }
487     }
488   }
489
490   if (p->OrderFall == 0)
491   {
492     p->MinContext = p->MaxContext = CreateSuccessors(p, True);
493     if (p->MinContext == 0)
494     {
495       RestartModel(p);
496       return;
497     }
498     SetSuccessor(p->FoundState, REF(p->MinContext));
499     return;
500   }
501   
502   *p->Text++ = p->FoundState->Symbol;
503   successor = REF(p->Text);
504   if (p->Text >= p->UnitsStart)
505   {
506     RestartModel(p);
507     return;
508   }
509   
510   if (fSuccessor)
511   {
512     if (fSuccessor <= successor)
513     {
514       CTX_PTR cs = CreateSuccessors(p, False);
515       if (cs == NULL)
516       {
517         RestartModel(p);
518         return;
519       }
520       fSuccessor = REF(cs);
521     }
522     if (--p->OrderFall == 0)
523     {
524       successor = fSuccessor;
525       p->Text -= (p->MaxContext != p->MinContext);
526     }
527   }
528   else
529   {
530     SetSuccessor(p->FoundState, successor);
531     fSuccessor = REF(p->MinContext);
532   }
533   
534   s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
535   
536   for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
537   {
538     unsigned ns1;
539     UInt32 cf, sf;
540     if ((ns1 = c->NumStats) != 1)
541     {
542       if ((ns1 & 1) == 0)
543       {
544         /* Expand for one UNIT */
545         unsigned oldNU = ns1 >> 1;
546         unsigned i = U2I(oldNU);
547         if (i != U2I(oldNU + 1))
548         {
549           void *ptr = AllocUnits(p, i + 1);
550           void *oldPtr;
551           if (!ptr)
552           {
553             RestartModel(p);
554             return;
555           }
556           oldPtr = STATS(c);
557           MyMem12Cpy(ptr, oldPtr, oldNU);
558           InsertNode(p, oldPtr, i);
559           c->Stats = STATS_REF(ptr);
560         }
561       }
562       c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
563     }
564     else
565     {
566       CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
567       if (!s)
568       {
569         RestartModel(p);
570         return;
571       }
572       *s = *ONE_STATE(c);
573       c->Stats = REF(s);
574       if (s->Freq < MAX_FREQ / 4 - 1)
575         s->Freq <<= 1;
576       else
577         s->Freq = MAX_FREQ - 4;
578       c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
579     }
580     cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
581     sf = (UInt32)s0 + c->SummFreq;
582     if (cf < 6 * sf)
583     {
584       cf = 1 + (cf > sf) + (cf >= 4 * sf);
585       c->SummFreq += 3;
586     }
587     else
588     {
589       cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
590       c->SummFreq = (UInt16)(c->SummFreq + cf);
591     }
592     {
593       CPpmd_State *s = STATS(c) + ns1;
594       SetSuccessor(s, successor);
595       s->Symbol = p->FoundState->Symbol;
596       s->Freq = (Byte)cf;
597       c->NumStats = (UInt16)(ns1 + 1);
598     }
599   }
600   p->MaxContext = p->MinContext = CTX(fSuccessor);
601 }
602   
603 static void Rescale(CPpmd7 *p)
604 {
605   unsigned i, adder, sumFreq, escFreq;
606   CPpmd_State *stats = STATS(p->MinContext);
607   CPpmd_State *s = p->FoundState;
608   {
609     CPpmd_State tmp = *s;
610     for (; s != stats; s--)
611       s[0] = s[-1];
612     *s = tmp;
613   }
614   escFreq = p->MinContext->SummFreq - s->Freq;
615   s->Freq += 4;
616   adder = (p->OrderFall != 0);
617   s->Freq = (Byte)((s->Freq + adder) >> 1);
618   sumFreq = s->Freq;
619   
620   i = p->MinContext->NumStats - 1;
621   do
622   {
623     escFreq -= (++s)->Freq;
624     s->Freq = (Byte)((s->Freq + adder) >> 1);
625     sumFreq += s->Freq;
626     if (s[0].Freq > s[-1].Freq)
627     {
628       CPpmd_State *s1 = s;
629       CPpmd_State tmp = *s1;
630       do
631         s1[0] = s1[-1];
632       while (--s1 != stats && tmp.Freq > s1[-1].Freq);
633       *s1 = tmp;
634     }
635   }
636   while (--i);
637   
638   if (s->Freq == 0)
639   {
640     unsigned numStats = p->MinContext->NumStats;
641     unsigned n0, n1;
642     do { i++; } while ((--s)->Freq == 0);
643     escFreq += i;
644     p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
645     if (p->MinContext->NumStats == 1)
646     {
647       CPpmd_State tmp = *stats;
648       do
649       {
650         tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
651         escFreq >>= 1;
652       }
653       while (escFreq > 1);
654       InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
655       *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
656       return;
657     }
658     n0 = (numStats + 1) >> 1;
659     n1 = (p->MinContext->NumStats + 1) >> 1;
660     if (n0 != n1)
661       p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
662   }
663   p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
664   p->FoundState = STATS(p->MinContext);
665 }
666
667 static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
668 {
669   CPpmd_See *see;
670   unsigned nonMasked = p->MinContext->NumStats - numMasked;
671   if (p->MinContext->NumStats != 256)
672   {
673     see = p->See[p->NS2Indx[nonMasked - 1]] +
674         (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
675         2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
676         4 * (numMasked > nonMasked) +
677         p->HiBitsFlag;
678     {
679       unsigned r = (see->Summ >> see->Shift);
680       see->Summ = (UInt16)(see->Summ - r);
681       *escFreq = r + (r == 0);
682     }
683   }
684   else
685   {
686     see = &p->DummySee;
687     *escFreq = 1;
688   }
689   return see;
690 }
691
692 static void NextContext(CPpmd7 *p)
693 {
694   CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
695   if (p->OrderFall == 0 && (Byte *)c > p->Text)
696     p->MinContext = p->MaxContext = c;
697   else
698     UpdateModel(p);
699 }
700
701 static void Ppmd7_Update1(CPpmd7 *p)
702 {
703   CPpmd_State *s = p->FoundState;
704   s->Freq += 4;
705   p->MinContext->SummFreq += 4;
706   if (s[0].Freq > s[-1].Freq)
707   {
708     SwapStates(&s[0], &s[-1]);
709     p->FoundState = --s;
710     if (s->Freq > MAX_FREQ)
711       Rescale(p);
712   }
713   NextContext(p);
714 }
715
716 static void Ppmd7_Update1_0(CPpmd7 *p)
717 {
718   p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
719   p->RunLength += p->PrevSuccess;
720   p->MinContext->SummFreq += 4;
721   if ((p->FoundState->Freq += 4) > MAX_FREQ)
722     Rescale(p);
723   NextContext(p);
724 }
725
726 static void Ppmd7_UpdateBin(CPpmd7 *p)
727 {
728   p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
729   p->PrevSuccess = 1;
730   p->RunLength++;
731   NextContext(p);
732 }
733
734 static void Ppmd7_Update2(CPpmd7 *p)
735 {
736   p->MinContext->SummFreq += 4;
737   if ((p->FoundState->Freq += 4) > MAX_FREQ)
738     Rescale(p);
739   p->RunLength = p->InitRL;
740   UpdateModel(p);
741 }
742
743 /* ---------- Decode ---------- */
744
745 static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p)
746 {
747   unsigned i;
748   p->Low = p->Bottom = 0;
749   p->Range = 0xFFFFFFFF;
750   for (i = 0; i < 4; i++)
751     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
752   return (p->Code < 0xFFFFFFFF);
753 }
754
755 static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
756 {
757   if (p->Stream->Read((void *)p->Stream) != 0)
758     return False;
759   return Ppmd_RangeDec_Init(p);
760 }
761
762 static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p)
763 {
764   if (!Ppmd_RangeDec_Init(p))
765     return False;
766   p->Bottom = 0x8000;
767   return True;
768 }
769
770 static UInt32 Range_GetThreshold(void *pp, UInt32 total)
771 {
772   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
773   return (p->Code - p->Low) / (p->Range /= total);
774 }
775
776 static void Range_Normalize(CPpmd7z_RangeDec *p)
777 {
778   while (1)
779   {
780     if((p->Low ^ (p->Low + p->Range)) >= kTopValue)
781     {
782       if(p->Range >= p->Bottom)
783         break;
784       else
785         p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1);
786     }
787     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
788     p->Range <<= 8;
789     p->Low <<= 8;
790   }
791 }
792
793 static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size)
794 {
795   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
796   p->Code -= start * p->Range;
797   p->Range *= size;
798   Range_Normalize(p);
799 }
800
801 static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size)
802 {
803   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
804   p->Low += start * p->Range;
805   p->Range *= size;
806   Range_Normalize(p);
807 }
808
809 static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0)
810 {
811   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
812   UInt32 newBound = (p->Range >> 14) * size0;
813   UInt32 symbol;
814   if (p->Code < newBound)
815   {
816     symbol = 0;
817     p->Range = newBound;
818   }
819   else
820   {
821     symbol = 1;
822     p->Code -= newBound;
823     p->Range -= newBound;
824   }
825   Range_Normalize(p);
826   return symbol;
827 }
828
829 static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0)
830 {
831   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
832   UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE);
833   if(value < size0)
834   {
835     bit = 0;
836     p->p.Decode(p, 0, size0);
837   }
838   else
839   {
840     bit = 1;
841     p->p.Decode(p, size0, PPMD_BIN_SCALE - size0);
842   }
843   return bit;
844 }
845
846 static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
847 {
848   p->p.GetThreshold = Range_GetThreshold;
849   p->p.Decode = Range_Decode_7z;
850   p->p.DecodeBit = Range_DecodeBit_7z;
851 }
852
853 static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
854 {
855   p->p.GetThreshold = Range_GetThreshold;
856   p->p.Decode = Range_Decode_RAR;
857   p->p.DecodeBit = Range_DecodeBit_RAR;
858 }
859
860 #define MASK(sym) ((signed char *)charMask)[sym]
861
862 static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
863 {
864   size_t charMask[256 / sizeof(size_t)];
865   if (p->MinContext->NumStats != 1)
866   {
867     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
868     unsigned i;
869     UInt32 count, hiCnt;
870     if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
871     {
872       Byte symbol;
873       rc->Decode(rc, 0, s->Freq);
874       p->FoundState = s;
875       symbol = s->Symbol;
876       Ppmd7_Update1_0(p);
877       return symbol;
878     }
879     p->PrevSuccess = 0;
880     i = p->MinContext->NumStats - 1;
881     do
882     {
883       if ((hiCnt += (++s)->Freq) > count)
884       {
885         Byte symbol;
886         rc->Decode(rc, hiCnt - s->Freq, s->Freq);
887         p->FoundState = s;
888         symbol = s->Symbol;
889         Ppmd7_Update1(p);
890         return symbol;
891       }
892     }
893     while (--i);
894     if (count >= p->MinContext->SummFreq)
895       return -2;
896     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
897     rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
898     PPMD_SetAllBitsIn256Bytes(charMask);
899     MASK(s->Symbol) = 0;
900     i = p->MinContext->NumStats - 1;
901     do { MASK((--s)->Symbol) = 0; } while (--i);
902   }
903   else
904   {
905     UInt16 *prob = Ppmd7_GetBinSumm(p);
906     if (rc->DecodeBit(rc, *prob) == 0)
907     {
908       Byte symbol;
909       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
910       symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
911       Ppmd7_UpdateBin(p);
912       return symbol;
913     }
914     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
915     p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
916     PPMD_SetAllBitsIn256Bytes(charMask);
917     MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
918     p->PrevSuccess = 0;
919   }
920   for (;;)
921   {
922     CPpmd_State *ps[256], *s;
923     UInt32 freqSum, count, hiCnt;
924     CPpmd_See *see;
925     unsigned i, num, numMasked = p->MinContext->NumStats;
926     do
927     {
928       p->OrderFall++;
929       if (!p->MinContext->Suffix)
930         return -1;
931       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
932     }
933     while (p->MinContext->NumStats == numMasked);
934     hiCnt = 0;
935     s = Ppmd7_GetStats(p, p->MinContext);
936     i = 0;
937     num = p->MinContext->NumStats - numMasked;
938     do
939     {
940       int k = (int)(MASK(s->Symbol));
941       hiCnt += (s->Freq & k);
942       ps[i] = s++;
943       i -= k;
944     }
945     while (i != num);
946
947     see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
948     freqSum += hiCnt;
949     count = rc->GetThreshold(rc, freqSum);
950
951     if (count < hiCnt)
952     {
953       Byte symbol;
954       CPpmd_State **pps = ps;
955       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
956       s = *pps;
957       rc->Decode(rc, hiCnt - s->Freq, s->Freq);
958       Ppmd_See_Update(see);
959       p->FoundState = s;
960       symbol = s->Symbol;
961       Ppmd7_Update2(p);
962       return symbol;
963     }
964     if (count >= freqSum)
965       return -2;
966     rc->Decode(rc, hiCnt, freqSum - hiCnt);
967     see->Summ = (UInt16)(see->Summ + freqSum);
968     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
969   }
970 }
971
972 /* ---------- Encode ---------- Ppmd7Enc.c */
973
974 #define kTopValue (1 << 24)
975
976 static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
977 {
978   p->Low = 0;
979   p->Range = 0xFFFFFFFF;
980   p->Cache = 0;
981   p->CacheSize = 1;
982 }
983
984 static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
985 {
986   if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
987   {
988     Byte temp = p->Cache;
989     do
990     {
991       p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
992       temp = 0xFF;
993     }
994     while(--p->CacheSize != 0);
995     p->Cache = (Byte)((UInt32)p->Low >> 24);
996   }
997   p->CacheSize++;
998   p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
999 }
1000
1001 static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
1002 {
1003   p->Low += (UInt64)start * (UInt64)(p->Range /= total);
1004   p->Range *= size;
1005   while (p->Range < kTopValue)
1006   {
1007     p->Range <<= 8;
1008     RangeEnc_ShiftLow(p);
1009   }
1010 }
1011
1012 static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
1013 {
1014   p->Range = (p->Range >> 14) * size0;
1015   while (p->Range < kTopValue)
1016   {
1017     p->Range <<= 8;
1018     RangeEnc_ShiftLow(p);
1019   }
1020 }
1021
1022 static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
1023 {
1024   UInt32 newBound = (p->Range >> 14) * size0;
1025   p->Low += newBound;
1026   p->Range -= newBound;
1027   while (p->Range < kTopValue)
1028   {
1029     p->Range <<= 8;
1030     RangeEnc_ShiftLow(p);
1031   }
1032 }
1033
1034 static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
1035 {
1036   unsigned i;
1037   for (i = 0; i < 5; i++)
1038     RangeEnc_ShiftLow(p);
1039 }
1040
1041
1042 #define MASK(sym) ((signed char *)charMask)[sym]
1043
1044 static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
1045 {
1046   size_t charMask[256 / sizeof(size_t)];
1047   if (p->MinContext->NumStats != 1)
1048   {
1049     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
1050     UInt32 sum;
1051     unsigned i;
1052     if (s->Symbol == symbol)
1053     {
1054       RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
1055       p->FoundState = s;
1056       Ppmd7_Update1_0(p);
1057       return;
1058     }
1059     p->PrevSuccess = 0;
1060     sum = s->Freq;
1061     i = p->MinContext->NumStats - 1;
1062     do
1063     {
1064       if ((++s)->Symbol == symbol)
1065       {
1066         RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
1067         p->FoundState = s;
1068         Ppmd7_Update1(p);
1069         return;
1070       }
1071       sum += s->Freq;
1072     }
1073     while (--i);
1074     
1075     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
1076     PPMD_SetAllBitsIn256Bytes(charMask);
1077     MASK(s->Symbol) = 0;
1078     i = p->MinContext->NumStats - 1;
1079     do { MASK((--s)->Symbol) = 0; } while (--i);
1080     RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
1081   }
1082   else
1083   {
1084     UInt16 *prob = Ppmd7_GetBinSumm(p);
1085     CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
1086     if (s->Symbol == symbol)
1087     {
1088       RangeEnc_EncodeBit_0(rc, *prob);
1089       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
1090       p->FoundState = s;
1091       Ppmd7_UpdateBin(p);
1092       return;
1093     }
1094     else
1095     {
1096       RangeEnc_EncodeBit_1(rc, *prob);
1097       *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
1098       p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
1099       PPMD_SetAllBitsIn256Bytes(charMask);
1100       MASK(s->Symbol) = 0;
1101       p->PrevSuccess = 0;
1102     }
1103   }
1104   for (;;)
1105   {
1106     UInt32 escFreq;
1107     CPpmd_See *see;
1108     CPpmd_State *s;
1109     UInt32 sum;
1110     unsigned i, numMasked = p->MinContext->NumStats;
1111     do
1112     {
1113       p->OrderFall++;
1114       if (!p->MinContext->Suffix)
1115         return; /* EndMarker (symbol = -1) */
1116       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
1117     }
1118     while (p->MinContext->NumStats == numMasked);
1119     
1120     see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
1121     s = Ppmd7_GetStats(p, p->MinContext);
1122     sum = 0;
1123     i = p->MinContext->NumStats;
1124     do
1125     {
1126       int cur = s->Symbol;
1127       if (cur == symbol)
1128       {
1129         UInt32 low = sum;
1130         CPpmd_State *s1 = s;
1131         do
1132         {
1133           sum += (s->Freq & (int)(MASK(s->Symbol)));
1134           s++;
1135         }
1136         while (--i);
1137         RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
1138         Ppmd_See_Update(see);
1139         p->FoundState = s1;
1140         Ppmd7_Update2(p);
1141         return;
1142       }
1143       sum += (s->Freq & (int)(MASK(cur)));
1144       MASK(cur) = 0;
1145       s++;
1146     }
1147     while (--i);
1148     
1149     RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
1150     see->Summ = (UInt16)(see->Summ + sum + escFreq);
1151   }
1152 }
1153
1154 const IPpmd7 __archive_ppmd7_functions =
1155 {
1156   &Ppmd7_Construct,
1157   &Ppmd7_Alloc,
1158   &Ppmd7_Free,
1159   &Ppmd7_Init,
1160   &Ppmd7z_RangeDec_CreateVTable,
1161   &PpmdRAR_RangeDec_CreateVTable,
1162   &Ppmd7z_RangeDec_Init,
1163   &PpmdRAR_RangeDec_Init,
1164   &Ppmd7_DecodeSymbol,
1165   &Ppmd7z_RangeEnc_Init,
1166   &Ppmd7z_RangeEnc_FlushData,
1167   &Ppmd7_EncodeSymbol
1168 };