xref: /freebsd-src/contrib/libarchive/libarchive/archive_ppmd7.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
16c95142eSMartin Matuska /* Ppmd7.c -- PPMdH codec
26c95142eSMartin Matuska 2010-03-12 : Igor Pavlov : Public domain
36c95142eSMartin Matuska This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
46c95142eSMartin Matuska 
56c95142eSMartin Matuska #include "archive_platform.h"
66c95142eSMartin Matuska 
7c3afd20fSMartin Matuska #include <stdlib.h>
86c95142eSMartin Matuska 
96c95142eSMartin Matuska #include "archive_ppmd7_private.h"
106c95142eSMartin Matuska 
116c95142eSMartin Matuska #ifdef PPMD_32BIT
126c95142eSMartin Matuska   #define Ppmd7_GetPtr(p, ptr) (ptr)
136c95142eSMartin Matuska   #define Ppmd7_GetContext(p, ptr) (ptr)
146c95142eSMartin Matuska   #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
156c95142eSMartin Matuska #else
166c95142eSMartin Matuska   #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
176c95142eSMartin Matuska   #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
186c95142eSMartin Matuska   #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
196c95142eSMartin Matuska #endif
206c95142eSMartin Matuska 
216c95142eSMartin Matuska #define Ppmd7_GetBinSumm(p) \
226c95142eSMartin Matuska     &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
236c95142eSMartin Matuska     p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
246c95142eSMartin Matuska     (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
256c95142eSMartin Matuska     2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
266c95142eSMartin Matuska     ((p->RunLength >> 26) & 0x20)]
276c95142eSMartin Matuska 
286c95142eSMartin Matuska #define kTopValue (1 << 24)
296c95142eSMartin Matuska #define MAX_FREQ 124
306c95142eSMartin Matuska #define UNIT_SIZE 12
316c95142eSMartin Matuska 
326c95142eSMartin Matuska #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
336c95142eSMartin Matuska #define U2I(nu) (p->Units2Indx[(nu) - 1])
346c95142eSMartin Matuska #define I2U(indx) (p->Indx2Units[indx])
356c95142eSMartin Matuska 
366c95142eSMartin Matuska #ifdef PPMD_32BIT
376c95142eSMartin Matuska   #define REF(ptr) (ptr)
386c95142eSMartin Matuska #else
396c95142eSMartin Matuska   #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
406c95142eSMartin Matuska #endif
416c95142eSMartin Matuska 
426c95142eSMartin Matuska #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
436c95142eSMartin Matuska 
446c95142eSMartin Matuska #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
456c95142eSMartin Matuska #define STATS(ctx) Ppmd7_GetStats(p, ctx)
466c95142eSMartin Matuska #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
476c95142eSMartin Matuska #define SUFFIX(ctx) CTX((ctx)->Suffix)
486c95142eSMartin Matuska 
496c95142eSMartin Matuska static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
506c95142eSMartin Matuska static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
516c95142eSMartin Matuska 
526c95142eSMartin Matuska typedef CPpmd7_Context * CTX_PTR;
536c95142eSMartin Matuska 
546c95142eSMartin Matuska struct CPpmd7_Node_;
556c95142eSMartin Matuska 
566c95142eSMartin Matuska typedef
576c95142eSMartin Matuska   #ifdef PPMD_32BIT
586c95142eSMartin Matuska     struct CPpmd7_Node_ *
596c95142eSMartin Matuska   #else
606c95142eSMartin Matuska     UInt32
616c95142eSMartin Matuska   #endif
626c95142eSMartin Matuska   CPpmd7_Node_Ref;
636c95142eSMartin Matuska 
646c95142eSMartin Matuska typedef struct CPpmd7_Node_
656c95142eSMartin Matuska {
666c95142eSMartin Matuska   UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
676c95142eSMartin Matuska   UInt16 NU;
686c95142eSMartin Matuska   CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
696c95142eSMartin Matuska   CPpmd7_Node_Ref Prev;
706c95142eSMartin Matuska } CPpmd7_Node;
716c95142eSMartin Matuska 
726c95142eSMartin Matuska #ifdef PPMD_32BIT
736c95142eSMartin Matuska   #define NODE(ptr) (ptr)
746c95142eSMartin Matuska #else
756c95142eSMartin Matuska   #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
766c95142eSMartin Matuska #endif
776c95142eSMartin Matuska 
786c95142eSMartin Matuska static void Ppmd7_Update1(CPpmd7 *p);
796c95142eSMartin Matuska static void Ppmd7_Update1_0(CPpmd7 *p);
806c95142eSMartin Matuska static void Ppmd7_Update2(CPpmd7 *p);
816c95142eSMartin Matuska static void Ppmd7_UpdateBin(CPpmd7 *p);
826c95142eSMartin Matuska static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked,
836c95142eSMartin Matuska                                     UInt32 *scale);
846c95142eSMartin Matuska 
856c95142eSMartin Matuska /* ----------- Base ----------- */
866c95142eSMartin Matuska 
876c95142eSMartin Matuska static void Ppmd7_Construct(CPpmd7 *p)
886c95142eSMartin Matuska {
896c95142eSMartin Matuska   unsigned i, k, m;
906c95142eSMartin Matuska 
916c95142eSMartin Matuska   p->Base = 0;
926c95142eSMartin Matuska 
936c95142eSMartin Matuska   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
946c95142eSMartin Matuska   {
956c95142eSMartin Matuska     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
966c95142eSMartin Matuska     do { p->Units2Indx[k++] = (Byte)i; } while(--step);
976c95142eSMartin Matuska     p->Indx2Units[i] = (Byte)k;
986c95142eSMartin Matuska   }
996c95142eSMartin Matuska 
1006c95142eSMartin Matuska   p->NS2BSIndx[0] = (0 << 1);
1016c95142eSMartin Matuska   p->NS2BSIndx[1] = (1 << 1);
1026c95142eSMartin Matuska   memset(p->NS2BSIndx + 2, (2 << 1), 9);
1036c95142eSMartin Matuska   memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
1046c95142eSMartin Matuska 
1056c95142eSMartin Matuska   for (i = 0; i < 3; i++)
1066c95142eSMartin Matuska     p->NS2Indx[i] = (Byte)i;
1076c95142eSMartin Matuska   for (m = i, k = 1; i < 256; i++)
1086c95142eSMartin Matuska   {
1096c95142eSMartin Matuska     p->NS2Indx[i] = (Byte)m;
1106c95142eSMartin Matuska     if (--k == 0)
1116c95142eSMartin Matuska       k = (++m) - 2;
1126c95142eSMartin Matuska   }
1136c95142eSMartin Matuska 
1146c95142eSMartin Matuska   memset(p->HB2Flag, 0, 0x40);
1156c95142eSMartin Matuska   memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
1166c95142eSMartin Matuska }
1176c95142eSMartin Matuska 
118a2a3407cSMartin Matuska static void Ppmd7_Free(CPpmd7 *p)
1196c95142eSMartin Matuska {
120a2a3407cSMartin Matuska   free(p->Base);
1216c95142eSMartin Matuska   p->Size = 0;
1226c95142eSMartin Matuska   p->Base = 0;
1236c95142eSMartin Matuska }
1246c95142eSMartin Matuska 
125a2a3407cSMartin Matuska static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
1266c95142eSMartin Matuska {
1276c95142eSMartin Matuska   if (p->Base == 0 || p->Size != size)
1286c95142eSMartin Matuska   {
129f061a221SMartin Matuska     /* RestartModel() below assumes that p->Size >= UNIT_SIZE
130f061a221SMartin Matuska        (see the calculation of m->MinContext). */
131f061a221SMartin Matuska     if (size < UNIT_SIZE) {
132f061a221SMartin Matuska       return False;
133f061a221SMartin Matuska     }
134a2a3407cSMartin Matuska     Ppmd7_Free(p);
1356c95142eSMartin Matuska     p->AlignOffset =
1366c95142eSMartin Matuska       #ifdef PPMD_32BIT
1376c95142eSMartin Matuska         (4 - size) & 3;
1386c95142eSMartin Matuska       #else
1396c95142eSMartin Matuska         4 - (size & 3);
1406c95142eSMartin Matuska       #endif
141*bd66c1b4SMartin Matuska     if ((p->Base = malloc(p->AlignOffset + size
1426c95142eSMartin Matuska         #ifndef PPMD_32BIT
1436c95142eSMartin Matuska         + UNIT_SIZE
1446c95142eSMartin Matuska         #endif
1456c95142eSMartin Matuska         )) == 0)
1466c95142eSMartin Matuska       return False;
1476c95142eSMartin Matuska     p->Size = size;
1486c95142eSMartin Matuska   }
1496c95142eSMartin Matuska   return True;
1506c95142eSMartin Matuska }
1516c95142eSMartin Matuska 
1526c95142eSMartin Matuska static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
1536c95142eSMartin Matuska {
1546c95142eSMartin Matuska   *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
1556c95142eSMartin Matuska   p->FreeList[indx] = REF(node);
1566c95142eSMartin Matuska }
1576c95142eSMartin Matuska 
1586c95142eSMartin Matuska static void *RemoveNode(CPpmd7 *p, unsigned indx)
1596c95142eSMartin Matuska {
1606c95142eSMartin Matuska   CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
1616c95142eSMartin Matuska   p->FreeList[indx] = *node;
1626c95142eSMartin Matuska   return node;
1636c95142eSMartin Matuska }
1646c95142eSMartin Matuska 
1656c95142eSMartin Matuska static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
1666c95142eSMartin Matuska {
1676c95142eSMartin Matuska   unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
1686c95142eSMartin Matuska   ptr = (Byte *)ptr + U2B(I2U(newIndx));
1696c95142eSMartin Matuska   if (I2U(i = U2I(nu)) != nu)
1706c95142eSMartin Matuska   {
1716c95142eSMartin Matuska     unsigned k = I2U(--i);
1726c95142eSMartin Matuska     InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
1736c95142eSMartin Matuska   }
1746c95142eSMartin Matuska   InsertNode(p, ptr, i);
1756c95142eSMartin Matuska }
1766c95142eSMartin Matuska 
1776c95142eSMartin Matuska static void GlueFreeBlocks(CPpmd7 *p)
1786c95142eSMartin Matuska {
1796c95142eSMartin Matuska   #ifdef PPMD_32BIT
1806c95142eSMartin Matuska   CPpmd7_Node headItem;
1816c95142eSMartin Matuska   CPpmd7_Node_Ref head = &headItem;
1826c95142eSMartin Matuska   #else
1836c95142eSMartin Matuska   CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
1846c95142eSMartin Matuska   #endif
1856c95142eSMartin Matuska 
1866c95142eSMartin Matuska   CPpmd7_Node_Ref n = head;
1876c95142eSMartin Matuska   unsigned i;
1886c95142eSMartin Matuska 
1896c95142eSMartin Matuska   p->GlueCount = 255;
1906c95142eSMartin Matuska 
1916c95142eSMartin Matuska   /* create doubly-linked list of free blocks */
1926c95142eSMartin Matuska   for (i = 0; i < PPMD_NUM_INDEXES; i++)
1936c95142eSMartin Matuska   {
1946c95142eSMartin Matuska     UInt16 nu = I2U(i);
1956c95142eSMartin Matuska     CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
1966c95142eSMartin Matuska     p->FreeList[i] = 0;
1976c95142eSMartin Matuska     while (next != 0)
1986c95142eSMartin Matuska     {
1996c95142eSMartin Matuska       CPpmd7_Node *node = NODE(next);
2006c95142eSMartin Matuska       node->Next = n;
2016c95142eSMartin Matuska       n = NODE(n)->Prev = next;
2026c95142eSMartin Matuska       next = *(const CPpmd7_Node_Ref *)node;
2036c95142eSMartin Matuska       node->Stamp = 0;
2046c95142eSMartin Matuska       node->NU = (UInt16)nu;
2056c95142eSMartin Matuska     }
2066c95142eSMartin Matuska   }
2076c95142eSMartin Matuska   NODE(head)->Stamp = 1;
2086c95142eSMartin Matuska   NODE(head)->Next = n;
2096c95142eSMartin Matuska   NODE(n)->Prev = head;
2106c95142eSMartin Matuska   if (p->LoUnit != p->HiUnit)
2116c95142eSMartin Matuska     ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
2126c95142eSMartin Matuska 
2136c95142eSMartin Matuska   /* Glue free blocks */
2146c95142eSMartin Matuska   while (n != head)
2156c95142eSMartin Matuska   {
2166c95142eSMartin Matuska     CPpmd7_Node *node = NODE(n);
2176c95142eSMartin Matuska     UInt32 nu = (UInt32)node->NU;
2186c95142eSMartin Matuska     for (;;)
2196c95142eSMartin Matuska     {
2206c95142eSMartin Matuska       CPpmd7_Node *node2 = NODE(n) + nu;
2216c95142eSMartin Matuska       nu += node2->NU;
2226c95142eSMartin Matuska       if (node2->Stamp != 0 || nu >= 0x10000)
2236c95142eSMartin Matuska         break;
2246c95142eSMartin Matuska       NODE(node2->Prev)->Next = node2->Next;
2256c95142eSMartin Matuska       NODE(node2->Next)->Prev = node2->Prev;
2266c95142eSMartin Matuska       node->NU = (UInt16)nu;
2276c95142eSMartin Matuska     }
2286c95142eSMartin Matuska     n = node->Next;
2296c95142eSMartin Matuska   }
2306c95142eSMartin Matuska 
2316c95142eSMartin Matuska   /* Fill lists of free blocks */
2326c95142eSMartin Matuska   for (n = NODE(head)->Next; n != head;)
2336c95142eSMartin Matuska   {
2346c95142eSMartin Matuska     CPpmd7_Node *node = NODE(n);
2356c95142eSMartin Matuska     unsigned nu;
2366c95142eSMartin Matuska     CPpmd7_Node_Ref next = node->Next;
2376c95142eSMartin Matuska     for (nu = node->NU; nu > 128; nu -= 128, node += 128)
2386c95142eSMartin Matuska       InsertNode(p, node, PPMD_NUM_INDEXES - 1);
2396c95142eSMartin Matuska     if (I2U(i = U2I(nu)) != nu)
2406c95142eSMartin Matuska     {
2416c95142eSMartin Matuska       unsigned k = I2U(--i);
2426c95142eSMartin Matuska       InsertNode(p, node + k, nu - k - 1);
2436c95142eSMartin Matuska     }
2446c95142eSMartin Matuska     InsertNode(p, node, i);
2456c95142eSMartin Matuska     n = next;
2466c95142eSMartin Matuska   }
2476c95142eSMartin Matuska }
2486c95142eSMartin Matuska 
2496c95142eSMartin Matuska static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
2506c95142eSMartin Matuska {
2516c95142eSMartin Matuska   unsigned i;
2526c95142eSMartin Matuska   void *retVal;
2536c95142eSMartin Matuska   if (p->GlueCount == 0)
2546c95142eSMartin Matuska   {
2556c95142eSMartin Matuska     GlueFreeBlocks(p);
2566c95142eSMartin Matuska     if (p->FreeList[indx] != 0)
2576c95142eSMartin Matuska       return RemoveNode(p, indx);
2586c95142eSMartin Matuska   }
2596c95142eSMartin Matuska   i = indx;
2606c95142eSMartin Matuska   do
2616c95142eSMartin Matuska   {
2626c95142eSMartin Matuska     if (++i == PPMD_NUM_INDEXES)
2636c95142eSMartin Matuska     {
2646c95142eSMartin Matuska       UInt32 numBytes = U2B(I2U(indx));
2656c95142eSMartin Matuska       p->GlueCount--;
2666c95142eSMartin Matuska       return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
2676c95142eSMartin Matuska     }
2686c95142eSMartin Matuska   }
2696c95142eSMartin Matuska   while (p->FreeList[i] == 0);
2706c95142eSMartin Matuska   retVal = RemoveNode(p, i);
2716c95142eSMartin Matuska   SplitBlock(p, retVal, i, indx);
2726c95142eSMartin Matuska   return retVal;
2736c95142eSMartin Matuska }
2746c95142eSMartin Matuska 
2756c95142eSMartin Matuska static void *AllocUnits(CPpmd7 *p, unsigned indx)
2766c95142eSMartin Matuska {
2776c95142eSMartin Matuska   UInt32 numBytes;
2786c95142eSMartin Matuska   if (p->FreeList[indx] != 0)
2796c95142eSMartin Matuska     return RemoveNode(p, indx);
2806c95142eSMartin Matuska   numBytes = U2B(I2U(indx));
2816c95142eSMartin Matuska   if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
2826c95142eSMartin Matuska   {
2836c95142eSMartin Matuska     void *retVal = p->LoUnit;
2846c95142eSMartin Matuska     p->LoUnit += numBytes;
2856c95142eSMartin Matuska     return retVal;
2866c95142eSMartin Matuska   }
2876c95142eSMartin Matuska   return AllocUnitsRare(p, indx);
2886c95142eSMartin Matuska }
2896c95142eSMartin Matuska 
2906c95142eSMartin Matuska #define MyMem12Cpy(dest, src, num) \
2916c95142eSMartin Matuska   { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
2926c95142eSMartin Matuska     do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
2936c95142eSMartin Matuska 
2946c95142eSMartin Matuska static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
2956c95142eSMartin Matuska {
2966c95142eSMartin Matuska   unsigned i0 = U2I(oldNU);
2976c95142eSMartin Matuska   unsigned i1 = U2I(newNU);
2986c95142eSMartin Matuska   if (i0 == i1)
2996c95142eSMartin Matuska     return oldPtr;
3006c95142eSMartin Matuska   if (p->FreeList[i1] != 0)
3016c95142eSMartin Matuska   {
3026c95142eSMartin Matuska     void *ptr = RemoveNode(p, i1);
3036c95142eSMartin Matuska     MyMem12Cpy(ptr, oldPtr, newNU);
3046c95142eSMartin Matuska     InsertNode(p, oldPtr, i0);
3056c95142eSMartin Matuska     return ptr;
3066c95142eSMartin Matuska   }
3076c95142eSMartin Matuska   SplitBlock(p, oldPtr, i0, i1);
3086c95142eSMartin Matuska   return oldPtr;
3096c95142eSMartin Matuska }
3106c95142eSMartin Matuska 
3116c95142eSMartin Matuska #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
3126c95142eSMartin Matuska 
3136c95142eSMartin Matuska static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
3146c95142eSMartin Matuska {
3156c95142eSMartin Matuska   (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
3166c95142eSMartin Matuska   (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
3176c95142eSMartin Matuska }
3186c95142eSMartin Matuska 
3196c95142eSMartin Matuska static void RestartModel(CPpmd7 *p)
3206c95142eSMartin Matuska {
3216c95142eSMartin Matuska   unsigned i, k, m;
3226c95142eSMartin Matuska 
3236c95142eSMartin Matuska   memset(p->FreeList, 0, sizeof(p->FreeList));
3246c95142eSMartin Matuska   p->Text = p->Base + p->AlignOffset;
3256c95142eSMartin Matuska   p->HiUnit = p->Text + p->Size;
3266c95142eSMartin Matuska   p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
3276c95142eSMartin Matuska   p->GlueCount = 0;
3286c95142eSMartin Matuska 
3296c95142eSMartin Matuska   p->OrderFall = p->MaxOrder;
3306c95142eSMartin Matuska   p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
3316c95142eSMartin Matuska   p->PrevSuccess = 0;
3326c95142eSMartin Matuska 
3336c95142eSMartin Matuska   p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
3346c95142eSMartin Matuska   p->MinContext->Suffix = 0;
3356c95142eSMartin Matuska   p->MinContext->NumStats = 256;
3366c95142eSMartin Matuska   p->MinContext->SummFreq = 256 + 1;
3376c95142eSMartin Matuska   p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
3386c95142eSMartin Matuska   p->LoUnit += U2B(256 / 2);
3396c95142eSMartin Matuska   p->MinContext->Stats = REF(p->FoundState);
3406c95142eSMartin Matuska   for (i = 0; i < 256; i++)
3416c95142eSMartin Matuska   {
3426c95142eSMartin Matuska     CPpmd_State *s = &p->FoundState[i];
3436c95142eSMartin Matuska     s->Symbol = (Byte)i;
3446c95142eSMartin Matuska     s->Freq = 1;
3456c95142eSMartin Matuska     SetSuccessor(s, 0);
3466c95142eSMartin Matuska   }
3476c95142eSMartin Matuska 
3486c95142eSMartin Matuska   for (i = 0; i < 128; i++)
3496c95142eSMartin Matuska     for (k = 0; k < 8; k++)
3506c95142eSMartin Matuska     {
3516c95142eSMartin Matuska       UInt16 *dest = p->BinSumm[i] + k;
3526c95142eSMartin Matuska       UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
3536c95142eSMartin Matuska       for (m = 0; m < 64; m += 8)
3546c95142eSMartin Matuska         dest[m] = val;
3556c95142eSMartin Matuska     }
3566c95142eSMartin Matuska 
3576c95142eSMartin Matuska   for (i = 0; i < 25; i++)
3586c95142eSMartin Matuska     for (k = 0; k < 16; k++)
3596c95142eSMartin Matuska     {
3606c95142eSMartin Matuska       CPpmd_See *s = &p->See[i][k];
3616c95142eSMartin Matuska       s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
3626c95142eSMartin Matuska       s->Count = 4;
3636c95142eSMartin Matuska     }
3646c95142eSMartin Matuska }
3656c95142eSMartin Matuska 
3666c95142eSMartin Matuska static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
3676c95142eSMartin Matuska {
3686c95142eSMartin Matuska   p->MaxOrder = maxOrder;
3696c95142eSMartin Matuska   RestartModel(p);
3706c95142eSMartin Matuska   p->DummySee.Shift = PPMD_PERIOD_BITS;
3716c95142eSMartin Matuska   p->DummySee.Summ = 0; /* unused */
3726c95142eSMartin Matuska   p->DummySee.Count = 64; /* unused */
3736c95142eSMartin Matuska }
3746c95142eSMartin Matuska 
3756c95142eSMartin Matuska static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
3766c95142eSMartin Matuska {
3776c95142eSMartin Matuska   CPpmd_State upState;
3786c95142eSMartin Matuska   CTX_PTR c = p->MinContext;
3796c95142eSMartin Matuska   CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
3806c95142eSMartin Matuska   CPpmd_State *ps[PPMD7_MAX_ORDER];
3816c95142eSMartin Matuska   unsigned numPs = 0;
3826c95142eSMartin Matuska 
3836c95142eSMartin Matuska   if (!skip)
3846c95142eSMartin Matuska     ps[numPs++] = p->FoundState;
3856c95142eSMartin Matuska 
3866c95142eSMartin Matuska   while (c->Suffix)
3876c95142eSMartin Matuska   {
3886c95142eSMartin Matuska     CPpmd_Void_Ref successor;
3896c95142eSMartin Matuska     CPpmd_State *s;
3906c95142eSMartin Matuska     c = SUFFIX(c);
3916c95142eSMartin Matuska     if (c->NumStats != 1)
3926c95142eSMartin Matuska     {
3936c95142eSMartin Matuska       for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
3946c95142eSMartin Matuska     }
3956c95142eSMartin Matuska     else
3966c95142eSMartin Matuska       s = ONE_STATE(c);
3976c95142eSMartin Matuska     successor = SUCCESSOR(s);
3986c95142eSMartin Matuska     if (successor != upBranch)
3996c95142eSMartin Matuska     {
4006c95142eSMartin Matuska       c = CTX(successor);
4016c95142eSMartin Matuska       if (numPs == 0)
4026c95142eSMartin Matuska         return c;
4036c95142eSMartin Matuska       break;
4046c95142eSMartin Matuska     }
4056c95142eSMartin Matuska     ps[numPs++] = s;
4066c95142eSMartin Matuska   }
4076c95142eSMartin Matuska 
4086c95142eSMartin Matuska   upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
4096c95142eSMartin Matuska   SetSuccessor(&upState, upBranch + 1);
4106c95142eSMartin Matuska 
4116c95142eSMartin Matuska   if (c->NumStats == 1)
4126c95142eSMartin Matuska     upState.Freq = ONE_STATE(c)->Freq;
4136c95142eSMartin Matuska   else
4146c95142eSMartin Matuska   {
4156c95142eSMartin Matuska     UInt32 cf, s0;
4166c95142eSMartin Matuska     CPpmd_State *s;
4176c95142eSMartin Matuska     for (s = STATS(c); s->Symbol != upState.Symbol; s++);
4186c95142eSMartin Matuska     cf = s->Freq - 1;
4196c95142eSMartin Matuska     s0 = c->SummFreq - c->NumStats - cf;
4206c95142eSMartin Matuska     upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
4216c95142eSMartin Matuska   }
4226c95142eSMartin Matuska 
423fd082e96SMartin Matuska   while (numPs != 0)
4246c95142eSMartin Matuska   {
4256c95142eSMartin Matuska     /* Create Child */
4266c95142eSMartin Matuska     CTX_PTR c1; /* = AllocContext(p); */
4276c95142eSMartin Matuska     if (p->HiUnit != p->LoUnit)
4286c95142eSMartin Matuska       c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
4296c95142eSMartin Matuska     else if (p->FreeList[0] != 0)
4306c95142eSMartin Matuska       c1 = (CTX_PTR)RemoveNode(p, 0);
4316c95142eSMartin Matuska     else
4326c95142eSMartin Matuska     {
4336c95142eSMartin Matuska       c1 = (CTX_PTR)AllocUnitsRare(p, 0);
4346c95142eSMartin Matuska       if (!c1)
4356c95142eSMartin Matuska         return NULL;
4366c95142eSMartin Matuska     }
4376c95142eSMartin Matuska     c1->NumStats = 1;
4386c95142eSMartin Matuska     *ONE_STATE(c1) = upState;
4396c95142eSMartin Matuska     c1->Suffix = REF(c);
4406c95142eSMartin Matuska     SetSuccessor(ps[--numPs], REF(c1));
4416c95142eSMartin Matuska     c = c1;
4426c95142eSMartin Matuska   }
4436c95142eSMartin Matuska 
4446c95142eSMartin Matuska   return c;
4456c95142eSMartin Matuska }
4466c95142eSMartin Matuska 
4476c95142eSMartin Matuska static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
4486c95142eSMartin Matuska {
4496c95142eSMartin Matuska   CPpmd_State tmp = *t1;
4506c95142eSMartin Matuska   *t1 = *t2;
4516c95142eSMartin Matuska   *t2 = tmp;
4526c95142eSMartin Matuska }
4536c95142eSMartin Matuska 
4546c95142eSMartin Matuska static void UpdateModel(CPpmd7 *p)
4556c95142eSMartin Matuska {
4566c95142eSMartin Matuska   CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
4576c95142eSMartin Matuska   CTX_PTR c;
4586c95142eSMartin Matuska   unsigned s0, ns;
4596c95142eSMartin Matuska 
4606c95142eSMartin Matuska   if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
4616c95142eSMartin Matuska   {
4626c95142eSMartin Matuska     c = SUFFIX(p->MinContext);
4636c95142eSMartin Matuska 
4646c95142eSMartin Matuska     if (c->NumStats == 1)
4656c95142eSMartin Matuska     {
4666c95142eSMartin Matuska       CPpmd_State *s = ONE_STATE(c);
4676c95142eSMartin Matuska       if (s->Freq < 32)
4686c95142eSMartin Matuska         s->Freq++;
4696c95142eSMartin Matuska     }
4706c95142eSMartin Matuska     else
4716c95142eSMartin Matuska     {
4726c95142eSMartin Matuska       CPpmd_State *s = STATS(c);
4736c95142eSMartin Matuska       if (s->Symbol != p->FoundState->Symbol)
4746c95142eSMartin Matuska       {
4756c95142eSMartin Matuska         do { s++; } while (s->Symbol != p->FoundState->Symbol);
4766c95142eSMartin Matuska         if (s[0].Freq >= s[-1].Freq)
4776c95142eSMartin Matuska         {
4786c95142eSMartin Matuska           SwapStates(&s[0], &s[-1]);
4796c95142eSMartin Matuska           s--;
4806c95142eSMartin Matuska         }
4816c95142eSMartin Matuska       }
4826c95142eSMartin Matuska       if (s->Freq < MAX_FREQ - 9)
4836c95142eSMartin Matuska       {
4846c95142eSMartin Matuska         s->Freq += 2;
4856c95142eSMartin Matuska         c->SummFreq += 2;
4866c95142eSMartin Matuska       }
4876c95142eSMartin Matuska     }
4886c95142eSMartin Matuska   }
4896c95142eSMartin Matuska 
4906c95142eSMartin Matuska   if (p->OrderFall == 0)
4916c95142eSMartin Matuska   {
4926c95142eSMartin Matuska     p->MinContext = p->MaxContext = CreateSuccessors(p, True);
4936c95142eSMartin Matuska     if (p->MinContext == 0)
4946c95142eSMartin Matuska     {
4956c95142eSMartin Matuska       RestartModel(p);
4966c95142eSMartin Matuska       return;
4976c95142eSMartin Matuska     }
4986c95142eSMartin Matuska     SetSuccessor(p->FoundState, REF(p->MinContext));
4996c95142eSMartin Matuska     return;
5006c95142eSMartin Matuska   }
5016c95142eSMartin Matuska 
5026c95142eSMartin Matuska   *p->Text++ = p->FoundState->Symbol;
5036c95142eSMartin Matuska   successor = REF(p->Text);
5046c95142eSMartin Matuska   if (p->Text >= p->UnitsStart)
5056c95142eSMartin Matuska   {
5066c95142eSMartin Matuska     RestartModel(p);
5076c95142eSMartin Matuska     return;
5086c95142eSMartin Matuska   }
5096c95142eSMartin Matuska 
5106c95142eSMartin Matuska   if (fSuccessor)
5116c95142eSMartin Matuska   {
5126c95142eSMartin Matuska     if (fSuccessor <= successor)
5136c95142eSMartin Matuska     {
5146c95142eSMartin Matuska       CTX_PTR cs = CreateSuccessors(p, False);
5156c95142eSMartin Matuska       if (cs == NULL)
5166c95142eSMartin Matuska       {
5176c95142eSMartin Matuska         RestartModel(p);
5186c95142eSMartin Matuska         return;
5196c95142eSMartin Matuska       }
5206c95142eSMartin Matuska       fSuccessor = REF(cs);
5216c95142eSMartin Matuska     }
5226c95142eSMartin Matuska     if (--p->OrderFall == 0)
5236c95142eSMartin Matuska     {
5246c95142eSMartin Matuska       successor = fSuccessor;
5256c95142eSMartin Matuska       p->Text -= (p->MaxContext != p->MinContext);
5266c95142eSMartin Matuska     }
5276c95142eSMartin Matuska   }
5286c95142eSMartin Matuska   else
5296c95142eSMartin Matuska   {
5306c95142eSMartin Matuska     SetSuccessor(p->FoundState, successor);
5316c95142eSMartin Matuska     fSuccessor = REF(p->MinContext);
5326c95142eSMartin Matuska   }
5336c95142eSMartin Matuska 
5346c95142eSMartin Matuska   s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
5356c95142eSMartin Matuska 
5366c95142eSMartin Matuska   for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
5376c95142eSMartin Matuska   {
5386c95142eSMartin Matuska     unsigned ns1;
5396c95142eSMartin Matuska     UInt32 cf, sf;
5406c95142eSMartin Matuska     if ((ns1 = c->NumStats) != 1)
5416c95142eSMartin Matuska     {
5426c95142eSMartin Matuska       if ((ns1 & 1) == 0)
5436c95142eSMartin Matuska       {
5446c95142eSMartin Matuska         /* Expand for one UNIT */
5456c95142eSMartin Matuska         unsigned oldNU = ns1 >> 1;
5466c95142eSMartin Matuska         unsigned i = U2I(oldNU);
5476c95142eSMartin Matuska         if (i != U2I(oldNU + 1))
5486c95142eSMartin Matuska         {
5496c95142eSMartin Matuska           void *ptr = AllocUnits(p, i + 1);
5506c95142eSMartin Matuska           void *oldPtr;
5516c95142eSMartin Matuska           if (!ptr)
5526c95142eSMartin Matuska           {
5536c95142eSMartin Matuska             RestartModel(p);
5546c95142eSMartin Matuska             return;
5556c95142eSMartin Matuska           }
5566c95142eSMartin Matuska           oldPtr = STATS(c);
5576c95142eSMartin Matuska           MyMem12Cpy(ptr, oldPtr, oldNU);
5586c95142eSMartin Matuska           InsertNode(p, oldPtr, i);
5596c95142eSMartin Matuska           c->Stats = STATS_REF(ptr);
5606c95142eSMartin Matuska         }
5616c95142eSMartin Matuska       }
5626c95142eSMartin Matuska       c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
5636c95142eSMartin Matuska     }
5646c95142eSMartin Matuska     else
5656c95142eSMartin Matuska     {
5666c95142eSMartin Matuska       CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
5676c95142eSMartin Matuska       if (!s)
5686c95142eSMartin Matuska       {
5696c95142eSMartin Matuska         RestartModel(p);
5706c95142eSMartin Matuska         return;
5716c95142eSMartin Matuska       }
5726c95142eSMartin Matuska       *s = *ONE_STATE(c);
5736c95142eSMartin Matuska       c->Stats = REF(s);
5746c95142eSMartin Matuska       if (s->Freq < MAX_FREQ / 4 - 1)
5756c95142eSMartin Matuska         s->Freq <<= 1;
5766c95142eSMartin Matuska       else
5776c95142eSMartin Matuska         s->Freq = MAX_FREQ - 4;
5786c95142eSMartin Matuska       c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
5796c95142eSMartin Matuska     }
5806c95142eSMartin Matuska     cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
5816c95142eSMartin Matuska     sf = (UInt32)s0 + c->SummFreq;
5826c95142eSMartin Matuska     if (cf < 6 * sf)
5836c95142eSMartin Matuska     {
5846c95142eSMartin Matuska       cf = 1 + (cf > sf) + (cf >= 4 * sf);
5856c95142eSMartin Matuska       c->SummFreq += 3;
5866c95142eSMartin Matuska     }
5876c95142eSMartin Matuska     else
5886c95142eSMartin Matuska     {
5896c95142eSMartin Matuska       cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
5906c95142eSMartin Matuska       c->SummFreq = (UInt16)(c->SummFreq + cf);
5916c95142eSMartin Matuska     }
5926c95142eSMartin Matuska     {
5936c95142eSMartin Matuska       CPpmd_State *s = STATS(c) + ns1;
5946c95142eSMartin Matuska       SetSuccessor(s, successor);
5956c95142eSMartin Matuska       s->Symbol = p->FoundState->Symbol;
5966c95142eSMartin Matuska       s->Freq = (Byte)cf;
5976c95142eSMartin Matuska       c->NumStats = (UInt16)(ns1 + 1);
5986c95142eSMartin Matuska     }
5996c95142eSMartin Matuska   }
6006c95142eSMartin Matuska   p->MaxContext = p->MinContext = CTX(fSuccessor);
6016c95142eSMartin Matuska }
6026c95142eSMartin Matuska 
6036c95142eSMartin Matuska static void Rescale(CPpmd7 *p)
6046c95142eSMartin Matuska {
6056c95142eSMartin Matuska   unsigned i, adder, sumFreq, escFreq;
6066c95142eSMartin Matuska   CPpmd_State *stats = STATS(p->MinContext);
6076c95142eSMartin Matuska   CPpmd_State *s = p->FoundState;
6086c95142eSMartin Matuska   {
6096c95142eSMartin Matuska     CPpmd_State tmp = *s;
6106c95142eSMartin Matuska     for (; s != stats; s--)
6116c95142eSMartin Matuska       s[0] = s[-1];
6126c95142eSMartin Matuska     *s = tmp;
6136c95142eSMartin Matuska   }
6146c95142eSMartin Matuska   escFreq = p->MinContext->SummFreq - s->Freq;
6156c95142eSMartin Matuska   s->Freq += 4;
6166c95142eSMartin Matuska   adder = (p->OrderFall != 0);
6176c95142eSMartin Matuska   s->Freq = (Byte)((s->Freq + adder) >> 1);
6186c95142eSMartin Matuska   sumFreq = s->Freq;
6196c95142eSMartin Matuska 
6206c95142eSMartin Matuska   i = p->MinContext->NumStats - 1;
6216c95142eSMartin Matuska   do
6226c95142eSMartin Matuska   {
6236c95142eSMartin Matuska     escFreq -= (++s)->Freq;
6246c95142eSMartin Matuska     s->Freq = (Byte)((s->Freq + adder) >> 1);
6256c95142eSMartin Matuska     sumFreq += s->Freq;
6266c95142eSMartin Matuska     if (s[0].Freq > s[-1].Freq)
6276c95142eSMartin Matuska     {
6286c95142eSMartin Matuska       CPpmd_State *s1 = s;
6296c95142eSMartin Matuska       CPpmd_State tmp = *s1;
6306c95142eSMartin Matuska       do
6316c95142eSMartin Matuska         s1[0] = s1[-1];
6326c95142eSMartin Matuska       while (--s1 != stats && tmp.Freq > s1[-1].Freq);
6336c95142eSMartin Matuska       *s1 = tmp;
6346c95142eSMartin Matuska     }
6356c95142eSMartin Matuska   }
6366c95142eSMartin Matuska   while (--i);
6376c95142eSMartin Matuska 
6386c95142eSMartin Matuska   if (s->Freq == 0)
6396c95142eSMartin Matuska   {
6406c95142eSMartin Matuska     unsigned numStats = p->MinContext->NumStats;
6416c95142eSMartin Matuska     unsigned n0, n1;
6426c95142eSMartin Matuska     do { i++; } while ((--s)->Freq == 0);
6436c95142eSMartin Matuska     escFreq += i;
6446c95142eSMartin Matuska     p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
6456c95142eSMartin Matuska     if (p->MinContext->NumStats == 1)
6466c95142eSMartin Matuska     {
6476c95142eSMartin Matuska       CPpmd_State tmp = *stats;
6486c95142eSMartin Matuska       do
6496c95142eSMartin Matuska       {
6506c95142eSMartin Matuska         tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
6516c95142eSMartin Matuska         escFreq >>= 1;
6526c95142eSMartin Matuska       }
6536c95142eSMartin Matuska       while (escFreq > 1);
6546c95142eSMartin Matuska       InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
6556c95142eSMartin Matuska       *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
6566c95142eSMartin Matuska       return;
6576c95142eSMartin Matuska     }
6586c95142eSMartin Matuska     n0 = (numStats + 1) >> 1;
6596c95142eSMartin Matuska     n1 = (p->MinContext->NumStats + 1) >> 1;
6606c95142eSMartin Matuska     if (n0 != n1)
6616c95142eSMartin Matuska       p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
6626c95142eSMartin Matuska   }
6636c95142eSMartin Matuska   p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
6646c95142eSMartin Matuska   p->FoundState = STATS(p->MinContext);
6656c95142eSMartin Matuska }
6666c95142eSMartin Matuska 
6676c95142eSMartin Matuska static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
6686c95142eSMartin Matuska {
6696c95142eSMartin Matuska   CPpmd_See *see;
6706c95142eSMartin Matuska   unsigned nonMasked = p->MinContext->NumStats - numMasked;
6716c95142eSMartin Matuska   if (p->MinContext->NumStats != 256)
6726c95142eSMartin Matuska   {
6736c95142eSMartin Matuska     see = p->See[p->NS2Indx[nonMasked - 1]] +
6746c95142eSMartin Matuska         (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
6756c95142eSMartin Matuska         2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
6766c95142eSMartin Matuska         4 * (numMasked > nonMasked) +
6776c95142eSMartin Matuska         p->HiBitsFlag;
6786c95142eSMartin Matuska     {
6796c95142eSMartin Matuska       unsigned r = (see->Summ >> see->Shift);
6806c95142eSMartin Matuska       see->Summ = (UInt16)(see->Summ - r);
6816c95142eSMartin Matuska       *escFreq = r + (r == 0);
6826c95142eSMartin Matuska     }
6836c95142eSMartin Matuska   }
6846c95142eSMartin Matuska   else
6856c95142eSMartin Matuska   {
6866c95142eSMartin Matuska     see = &p->DummySee;
6876c95142eSMartin Matuska     *escFreq = 1;
6886c95142eSMartin Matuska   }
6896c95142eSMartin Matuska   return see;
6906c95142eSMartin Matuska }
6916c95142eSMartin Matuska 
6926c95142eSMartin Matuska static void NextContext(CPpmd7 *p)
6936c95142eSMartin Matuska {
6946c95142eSMartin Matuska   CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
6956c95142eSMartin Matuska   if (p->OrderFall == 0 && (Byte *)c > p->Text)
6966c95142eSMartin Matuska     p->MinContext = p->MaxContext = c;
6976c95142eSMartin Matuska   else
6986c95142eSMartin Matuska     UpdateModel(p);
6996c95142eSMartin Matuska }
7006c95142eSMartin Matuska 
7016c95142eSMartin Matuska static void Ppmd7_Update1(CPpmd7 *p)
7026c95142eSMartin Matuska {
7036c95142eSMartin Matuska   CPpmd_State *s = p->FoundState;
7046c95142eSMartin Matuska   s->Freq += 4;
7056c95142eSMartin Matuska   p->MinContext->SummFreq += 4;
7066c95142eSMartin Matuska   if (s[0].Freq > s[-1].Freq)
7076c95142eSMartin Matuska   {
7086c95142eSMartin Matuska     SwapStates(&s[0], &s[-1]);
7096c95142eSMartin Matuska     p->FoundState = --s;
7106c95142eSMartin Matuska     if (s->Freq > MAX_FREQ)
7116c95142eSMartin Matuska       Rescale(p);
7126c95142eSMartin Matuska   }
7136c95142eSMartin Matuska   NextContext(p);
7146c95142eSMartin Matuska }
7156c95142eSMartin Matuska 
7166c95142eSMartin Matuska static void Ppmd7_Update1_0(CPpmd7 *p)
7176c95142eSMartin Matuska {
7186c95142eSMartin Matuska   p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
7196c95142eSMartin Matuska   p->RunLength += p->PrevSuccess;
7206c95142eSMartin Matuska   p->MinContext->SummFreq += 4;
7216c95142eSMartin Matuska   if ((p->FoundState->Freq += 4) > MAX_FREQ)
7226c95142eSMartin Matuska     Rescale(p);
7236c95142eSMartin Matuska   NextContext(p);
7246c95142eSMartin Matuska }
7256c95142eSMartin Matuska 
7266c95142eSMartin Matuska static void Ppmd7_UpdateBin(CPpmd7 *p)
7276c95142eSMartin Matuska {
7286c95142eSMartin Matuska   p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
7296c95142eSMartin Matuska   p->PrevSuccess = 1;
7306c95142eSMartin Matuska   p->RunLength++;
7316c95142eSMartin Matuska   NextContext(p);
7326c95142eSMartin Matuska }
7336c95142eSMartin Matuska 
7346c95142eSMartin Matuska static void Ppmd7_Update2(CPpmd7 *p)
7356c95142eSMartin Matuska {
7366c95142eSMartin Matuska   p->MinContext->SummFreq += 4;
7376c95142eSMartin Matuska   if ((p->FoundState->Freq += 4) > MAX_FREQ)
7386c95142eSMartin Matuska     Rescale(p);
7396c95142eSMartin Matuska   p->RunLength = p->InitRL;
7406c95142eSMartin Matuska   UpdateModel(p);
7416c95142eSMartin Matuska }
7426c95142eSMartin Matuska 
7436c95142eSMartin Matuska /* ---------- Decode ---------- */
7446c95142eSMartin Matuska 
7456c95142eSMartin Matuska static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p)
7466c95142eSMartin Matuska {
7476c95142eSMartin Matuska   unsigned i;
7486c95142eSMartin Matuska   p->Low = p->Bottom = 0;
7496c95142eSMartin Matuska   p->Range = 0xFFFFFFFF;
7506c95142eSMartin Matuska   for (i = 0; i < 4; i++)
7516c95142eSMartin Matuska     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
7526c95142eSMartin Matuska   return (p->Code < 0xFFFFFFFF);
7536c95142eSMartin Matuska }
7546c95142eSMartin Matuska 
7556c95142eSMartin Matuska static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
7566c95142eSMartin Matuska {
7576c95142eSMartin Matuska   if (p->Stream->Read((void *)p->Stream) != 0)
7586c95142eSMartin Matuska     return False;
7596c95142eSMartin Matuska   return Ppmd_RangeDec_Init(p);
7606c95142eSMartin Matuska }
7616c95142eSMartin Matuska 
7626c95142eSMartin Matuska static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p)
7636c95142eSMartin Matuska {
7646c95142eSMartin Matuska   if (!Ppmd_RangeDec_Init(p))
7656c95142eSMartin Matuska     return False;
7666c95142eSMartin Matuska   p->Bottom = 0x8000;
7676c95142eSMartin Matuska   return True;
7686c95142eSMartin Matuska }
7696c95142eSMartin Matuska 
7706c95142eSMartin Matuska static UInt32 Range_GetThreshold(void *pp, UInt32 total)
7716c95142eSMartin Matuska {
7726c95142eSMartin Matuska   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
7736c95142eSMartin Matuska   return (p->Code - p->Low) / (p->Range /= total);
7746c95142eSMartin Matuska }
7756c95142eSMartin Matuska 
7766c95142eSMartin Matuska static void Range_Normalize(CPpmd7z_RangeDec *p)
7776c95142eSMartin Matuska {
7786c95142eSMartin Matuska   while (1)
7796c95142eSMartin Matuska   {
7806c95142eSMartin Matuska     if((p->Low ^ (p->Low + p->Range)) >= kTopValue)
7816c95142eSMartin Matuska     {
7826c95142eSMartin Matuska       if(p->Range >= p->Bottom)
7836c95142eSMartin Matuska         break;
7846c95142eSMartin Matuska       else
785fd082e96SMartin Matuska         p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1);
7866c95142eSMartin Matuska     }
7876c95142eSMartin Matuska     p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
7886c95142eSMartin Matuska     p->Range <<= 8;
7896c95142eSMartin Matuska     p->Low <<= 8;
7906c95142eSMartin Matuska   }
7916c95142eSMartin Matuska }
7926c95142eSMartin Matuska 
7936c95142eSMartin Matuska static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size)
7946c95142eSMartin Matuska {
7956c95142eSMartin Matuska   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
7966c95142eSMartin Matuska   p->Code -= start * p->Range;
7976c95142eSMartin Matuska   p->Range *= size;
7986c95142eSMartin Matuska   Range_Normalize(p);
7996c95142eSMartin Matuska }
8006c95142eSMartin Matuska 
8016c95142eSMartin Matuska static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size)
8026c95142eSMartin Matuska {
8036c95142eSMartin Matuska   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
8046c95142eSMartin Matuska   p->Low += start * p->Range;
8056c95142eSMartin Matuska   p->Range *= size;
8066c95142eSMartin Matuska   Range_Normalize(p);
8076c95142eSMartin Matuska }
8086c95142eSMartin Matuska 
8096c95142eSMartin Matuska static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0)
8106c95142eSMartin Matuska {
8116c95142eSMartin Matuska   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
8126c95142eSMartin Matuska   UInt32 newBound = (p->Range >> 14) * size0;
8136c95142eSMartin Matuska   UInt32 symbol;
8146c95142eSMartin Matuska   if (p->Code < newBound)
8156c95142eSMartin Matuska   {
8166c95142eSMartin Matuska     symbol = 0;
8176c95142eSMartin Matuska     p->Range = newBound;
8186c95142eSMartin Matuska   }
8196c95142eSMartin Matuska   else
8206c95142eSMartin Matuska   {
8216c95142eSMartin Matuska     symbol = 1;
8226c95142eSMartin Matuska     p->Code -= newBound;
8236c95142eSMartin Matuska     p->Range -= newBound;
8246c95142eSMartin Matuska   }
8256c95142eSMartin Matuska   Range_Normalize(p);
8266c95142eSMartin Matuska   return symbol;
8276c95142eSMartin Matuska }
8286c95142eSMartin Matuska 
8296c95142eSMartin Matuska static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0)
8306c95142eSMartin Matuska {
8316c95142eSMartin Matuska   CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
8326c95142eSMartin Matuska   UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE);
8336c95142eSMartin Matuska   if(value < size0)
8346c95142eSMartin Matuska   {
8356c95142eSMartin Matuska     bit = 0;
8366c95142eSMartin Matuska     p->p.Decode(p, 0, size0);
8376c95142eSMartin Matuska   }
8386c95142eSMartin Matuska   else
8396c95142eSMartin Matuska   {
8406c95142eSMartin Matuska     bit = 1;
8416c95142eSMartin Matuska     p->p.Decode(p, size0, PPMD_BIN_SCALE - size0);
8426c95142eSMartin Matuska   }
8436c95142eSMartin Matuska   return bit;
8446c95142eSMartin Matuska }
8456c95142eSMartin Matuska 
8466c95142eSMartin Matuska static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
8476c95142eSMartin Matuska {
8486c95142eSMartin Matuska   p->p.GetThreshold = Range_GetThreshold;
8496c95142eSMartin Matuska   p->p.Decode = Range_Decode_7z;
8506c95142eSMartin Matuska   p->p.DecodeBit = Range_DecodeBit_7z;
8516c95142eSMartin Matuska }
8526c95142eSMartin Matuska 
8536c95142eSMartin Matuska static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
8546c95142eSMartin Matuska {
8556c95142eSMartin Matuska   p->p.GetThreshold = Range_GetThreshold;
8566c95142eSMartin Matuska   p->p.Decode = Range_Decode_RAR;
8576c95142eSMartin Matuska   p->p.DecodeBit = Range_DecodeBit_RAR;
8586c95142eSMartin Matuska }
8596c95142eSMartin Matuska 
8606c95142eSMartin Matuska #define MASK(sym) ((signed char *)charMask)[sym]
8616c95142eSMartin Matuska 
8626c95142eSMartin Matuska static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
8636c95142eSMartin Matuska {
8646c95142eSMartin Matuska   size_t charMask[256 / sizeof(size_t)];
8656c95142eSMartin Matuska   if (p->MinContext->NumStats != 1)
8666c95142eSMartin Matuska   {
8676c95142eSMartin Matuska     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
8686c95142eSMartin Matuska     unsigned i;
8696c95142eSMartin Matuska     UInt32 count, hiCnt;
8706c95142eSMartin Matuska     if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
8716c95142eSMartin Matuska     {
8726c95142eSMartin Matuska       Byte symbol;
8736c95142eSMartin Matuska       rc->Decode(rc, 0, s->Freq);
8746c95142eSMartin Matuska       p->FoundState = s;
8756c95142eSMartin Matuska       symbol = s->Symbol;
8766c95142eSMartin Matuska       Ppmd7_Update1_0(p);
8776c95142eSMartin Matuska       return symbol;
8786c95142eSMartin Matuska     }
8796c95142eSMartin Matuska     p->PrevSuccess = 0;
8806c95142eSMartin Matuska     i = p->MinContext->NumStats - 1;
8816c95142eSMartin Matuska     do
8826c95142eSMartin Matuska     {
8836c95142eSMartin Matuska       if ((hiCnt += (++s)->Freq) > count)
8846c95142eSMartin Matuska       {
8856c95142eSMartin Matuska         Byte symbol;
8866c95142eSMartin Matuska         rc->Decode(rc, hiCnt - s->Freq, s->Freq);
8876c95142eSMartin Matuska         p->FoundState = s;
8886c95142eSMartin Matuska         symbol = s->Symbol;
8896c95142eSMartin Matuska         Ppmd7_Update1(p);
8906c95142eSMartin Matuska         return symbol;
8916c95142eSMartin Matuska       }
8926c95142eSMartin Matuska     }
8936c95142eSMartin Matuska     while (--i);
8946c95142eSMartin Matuska     if (count >= p->MinContext->SummFreq)
8956c95142eSMartin Matuska       return -2;
8966c95142eSMartin Matuska     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
8976c95142eSMartin Matuska     rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
8986c95142eSMartin Matuska     PPMD_SetAllBitsIn256Bytes(charMask);
8996c95142eSMartin Matuska     MASK(s->Symbol) = 0;
9006c95142eSMartin Matuska     i = p->MinContext->NumStats - 1;
9016c95142eSMartin Matuska     do { MASK((--s)->Symbol) = 0; } while (--i);
9026c95142eSMartin Matuska   }
9036c95142eSMartin Matuska   else
9046c95142eSMartin Matuska   {
9056c95142eSMartin Matuska     UInt16 *prob = Ppmd7_GetBinSumm(p);
9066c95142eSMartin Matuska     if (rc->DecodeBit(rc, *prob) == 0)
9076c95142eSMartin Matuska     {
9086c95142eSMartin Matuska       Byte symbol;
9096c95142eSMartin Matuska       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
9106c95142eSMartin Matuska       symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
9116c95142eSMartin Matuska       Ppmd7_UpdateBin(p);
9126c95142eSMartin Matuska       return symbol;
9136c95142eSMartin Matuska     }
9146c95142eSMartin Matuska     *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
9156c95142eSMartin Matuska     p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
9166c95142eSMartin Matuska     PPMD_SetAllBitsIn256Bytes(charMask);
9176c95142eSMartin Matuska     MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
9186c95142eSMartin Matuska     p->PrevSuccess = 0;
9196c95142eSMartin Matuska   }
9206c95142eSMartin Matuska   for (;;)
9216c95142eSMartin Matuska   {
9226c95142eSMartin Matuska     CPpmd_State *ps[256], *s;
9236c95142eSMartin Matuska     UInt32 freqSum, count, hiCnt;
9246c95142eSMartin Matuska     CPpmd_See *see;
9256c95142eSMartin Matuska     unsigned i, num, numMasked = p->MinContext->NumStats;
9266c95142eSMartin Matuska     do
9276c95142eSMartin Matuska     {
9286c95142eSMartin Matuska       p->OrderFall++;
9296c95142eSMartin Matuska       if (!p->MinContext->Suffix)
9306c95142eSMartin Matuska         return -1;
9316c95142eSMartin Matuska       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
9326c95142eSMartin Matuska     }
9336c95142eSMartin Matuska     while (p->MinContext->NumStats == numMasked);
9346c95142eSMartin Matuska     hiCnt = 0;
9356c95142eSMartin Matuska     s = Ppmd7_GetStats(p, p->MinContext);
9366c95142eSMartin Matuska     i = 0;
9376c95142eSMartin Matuska     num = p->MinContext->NumStats - numMasked;
9386c95142eSMartin Matuska     do
9396c95142eSMartin Matuska     {
9406c95142eSMartin Matuska       int k = (int)(MASK(s->Symbol));
9416c95142eSMartin Matuska       hiCnt += (s->Freq & k);
9426c95142eSMartin Matuska       ps[i] = s++;
9436c95142eSMartin Matuska       i -= k;
9446c95142eSMartin Matuska     }
9456c95142eSMartin Matuska     while (i != num);
9466c95142eSMartin Matuska 
9476c95142eSMartin Matuska     see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
9486c95142eSMartin Matuska     freqSum += hiCnt;
9496c95142eSMartin Matuska     count = rc->GetThreshold(rc, freqSum);
9506c95142eSMartin Matuska 
9516c95142eSMartin Matuska     if (count < hiCnt)
9526c95142eSMartin Matuska     {
9536c95142eSMartin Matuska       Byte symbol;
9546c95142eSMartin Matuska       CPpmd_State **pps = ps;
9556c95142eSMartin Matuska       for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
9566c95142eSMartin Matuska       s = *pps;
9576c95142eSMartin Matuska       rc->Decode(rc, hiCnt - s->Freq, s->Freq);
9586c95142eSMartin Matuska       Ppmd_See_Update(see);
9596c95142eSMartin Matuska       p->FoundState = s;
9606c95142eSMartin Matuska       symbol = s->Symbol;
9616c95142eSMartin Matuska       Ppmd7_Update2(p);
9626c95142eSMartin Matuska       return symbol;
9636c95142eSMartin Matuska     }
9646c95142eSMartin Matuska     if (count >= freqSum)
9656c95142eSMartin Matuska       return -2;
9666c95142eSMartin Matuska     rc->Decode(rc, hiCnt, freqSum - hiCnt);
9676c95142eSMartin Matuska     see->Summ = (UInt16)(see->Summ + freqSum);
9686c95142eSMartin Matuska     do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
9696c95142eSMartin Matuska   }
9706c95142eSMartin Matuska }
9716c95142eSMartin Matuska 
9726c95142eSMartin Matuska /* ---------- Encode ---------- Ppmd7Enc.c */
9736c95142eSMartin Matuska 
9746c95142eSMartin Matuska #define kTopValue (1 << 24)
9756c95142eSMartin Matuska 
9766c95142eSMartin Matuska static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
9776c95142eSMartin Matuska {
9786c95142eSMartin Matuska   p->Low = 0;
9796c95142eSMartin Matuska   p->Range = 0xFFFFFFFF;
9806c95142eSMartin Matuska   p->Cache = 0;
9816c95142eSMartin Matuska   p->CacheSize = 1;
9826c95142eSMartin Matuska }
9836c95142eSMartin Matuska 
9846c95142eSMartin Matuska static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
9856c95142eSMartin Matuska {
9866c95142eSMartin Matuska   if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
9876c95142eSMartin Matuska   {
9886c95142eSMartin Matuska     Byte temp = p->Cache;
9896c95142eSMartin Matuska     do
9906c95142eSMartin Matuska     {
9916c95142eSMartin Matuska       p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
9926c95142eSMartin Matuska       temp = 0xFF;
9936c95142eSMartin Matuska     }
9946c95142eSMartin Matuska     while(--p->CacheSize != 0);
9956c95142eSMartin Matuska     p->Cache = (Byte)((UInt32)p->Low >> 24);
9966c95142eSMartin Matuska   }
9976c95142eSMartin Matuska   p->CacheSize++;
998acc60b03SMartin Matuska   p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
9996c95142eSMartin Matuska }
10006c95142eSMartin Matuska 
10016c95142eSMartin Matuska static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
10026c95142eSMartin Matuska {
1003f9762417SMartin Matuska   p->Low += (UInt64)start * (UInt64)(p->Range /= total);
10046c95142eSMartin Matuska   p->Range *= size;
10056c95142eSMartin Matuska   while (p->Range < kTopValue)
10066c95142eSMartin Matuska   {
10076c95142eSMartin Matuska     p->Range <<= 8;
10086c95142eSMartin Matuska     RangeEnc_ShiftLow(p);
10096c95142eSMartin Matuska   }
10106c95142eSMartin Matuska }
10116c95142eSMartin Matuska 
10126c95142eSMartin Matuska static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
10136c95142eSMartin Matuska {
10146c95142eSMartin Matuska   p->Range = (p->Range >> 14) * size0;
10156c95142eSMartin Matuska   while (p->Range < kTopValue)
10166c95142eSMartin Matuska   {
10176c95142eSMartin Matuska     p->Range <<= 8;
10186c95142eSMartin Matuska     RangeEnc_ShiftLow(p);
10196c95142eSMartin Matuska   }
10206c95142eSMartin Matuska }
10216c95142eSMartin Matuska 
10226c95142eSMartin Matuska static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
10236c95142eSMartin Matuska {
10246c95142eSMartin Matuska   UInt32 newBound = (p->Range >> 14) * size0;
10256c95142eSMartin Matuska   p->Low += newBound;
10266c95142eSMartin Matuska   p->Range -= newBound;
10276c95142eSMartin Matuska   while (p->Range < kTopValue)
10286c95142eSMartin Matuska   {
10296c95142eSMartin Matuska     p->Range <<= 8;
10306c95142eSMartin Matuska     RangeEnc_ShiftLow(p);
10316c95142eSMartin Matuska   }
10326c95142eSMartin Matuska }
10336c95142eSMartin Matuska 
10346c95142eSMartin Matuska static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
10356c95142eSMartin Matuska {
10366c95142eSMartin Matuska   unsigned i;
10376c95142eSMartin Matuska   for (i = 0; i < 5; i++)
10386c95142eSMartin Matuska     RangeEnc_ShiftLow(p);
10396c95142eSMartin Matuska }
10406c95142eSMartin Matuska 
10416c95142eSMartin Matuska 
10426c95142eSMartin Matuska #define MASK(sym) ((signed char *)charMask)[sym]
10436c95142eSMartin Matuska 
10446c95142eSMartin Matuska static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
10456c95142eSMartin Matuska {
10466c95142eSMartin Matuska   size_t charMask[256 / sizeof(size_t)];
10476c95142eSMartin Matuska   if (p->MinContext->NumStats != 1)
10486c95142eSMartin Matuska   {
10496c95142eSMartin Matuska     CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
10506c95142eSMartin Matuska     UInt32 sum;
10516c95142eSMartin Matuska     unsigned i;
10526c95142eSMartin Matuska     if (s->Symbol == symbol)
10536c95142eSMartin Matuska     {
10546c95142eSMartin Matuska       RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
10556c95142eSMartin Matuska       p->FoundState = s;
10566c95142eSMartin Matuska       Ppmd7_Update1_0(p);
10576c95142eSMartin Matuska       return;
10586c95142eSMartin Matuska     }
10596c95142eSMartin Matuska     p->PrevSuccess = 0;
10606c95142eSMartin Matuska     sum = s->Freq;
10616c95142eSMartin Matuska     i = p->MinContext->NumStats - 1;
10626c95142eSMartin Matuska     do
10636c95142eSMartin Matuska     {
10646c95142eSMartin Matuska       if ((++s)->Symbol == symbol)
10656c95142eSMartin Matuska       {
10666c95142eSMartin Matuska         RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
10676c95142eSMartin Matuska         p->FoundState = s;
10686c95142eSMartin Matuska         Ppmd7_Update1(p);
10696c95142eSMartin Matuska         return;
10706c95142eSMartin Matuska       }
10716c95142eSMartin Matuska       sum += s->Freq;
10726c95142eSMartin Matuska     }
10736c95142eSMartin Matuska     while (--i);
10746c95142eSMartin Matuska 
10756c95142eSMartin Matuska     p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
10766c95142eSMartin Matuska     PPMD_SetAllBitsIn256Bytes(charMask);
10776c95142eSMartin Matuska     MASK(s->Symbol) = 0;
10786c95142eSMartin Matuska     i = p->MinContext->NumStats - 1;
10796c95142eSMartin Matuska     do { MASK((--s)->Symbol) = 0; } while (--i);
10806c95142eSMartin Matuska     RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
10816c95142eSMartin Matuska   }
10826c95142eSMartin Matuska   else
10836c95142eSMartin Matuska   {
10846c95142eSMartin Matuska     UInt16 *prob = Ppmd7_GetBinSumm(p);
10856c95142eSMartin Matuska     CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
10866c95142eSMartin Matuska     if (s->Symbol == symbol)
10876c95142eSMartin Matuska     {
10886c95142eSMartin Matuska       RangeEnc_EncodeBit_0(rc, *prob);
10896c95142eSMartin Matuska       *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
10906c95142eSMartin Matuska       p->FoundState = s;
10916c95142eSMartin Matuska       Ppmd7_UpdateBin(p);
10926c95142eSMartin Matuska       return;
10936c95142eSMartin Matuska     }
10946c95142eSMartin Matuska     else
10956c95142eSMartin Matuska     {
10966c95142eSMartin Matuska       RangeEnc_EncodeBit_1(rc, *prob);
10976c95142eSMartin Matuska       *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
10986c95142eSMartin Matuska       p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
10996c95142eSMartin Matuska       PPMD_SetAllBitsIn256Bytes(charMask);
11006c95142eSMartin Matuska       MASK(s->Symbol) = 0;
11016c95142eSMartin Matuska       p->PrevSuccess = 0;
11026c95142eSMartin Matuska     }
11036c95142eSMartin Matuska   }
11046c95142eSMartin Matuska   for (;;)
11056c95142eSMartin Matuska   {
11066c95142eSMartin Matuska     UInt32 escFreq;
11076c95142eSMartin Matuska     CPpmd_See *see;
11086c95142eSMartin Matuska     CPpmd_State *s;
11096c95142eSMartin Matuska     UInt32 sum;
11106c95142eSMartin Matuska     unsigned i, numMasked = p->MinContext->NumStats;
11116c95142eSMartin Matuska     do
11126c95142eSMartin Matuska     {
11136c95142eSMartin Matuska       p->OrderFall++;
11146c95142eSMartin Matuska       if (!p->MinContext->Suffix)
11156c95142eSMartin Matuska         return; /* EndMarker (symbol = -1) */
11166c95142eSMartin Matuska       p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
11176c95142eSMartin Matuska     }
11186c95142eSMartin Matuska     while (p->MinContext->NumStats == numMasked);
11196c95142eSMartin Matuska 
11206c95142eSMartin Matuska     see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
11216c95142eSMartin Matuska     s = Ppmd7_GetStats(p, p->MinContext);
11226c95142eSMartin Matuska     sum = 0;
11236c95142eSMartin Matuska     i = p->MinContext->NumStats;
11246c95142eSMartin Matuska     do
11256c95142eSMartin Matuska     {
11266c95142eSMartin Matuska       int cur = s->Symbol;
11276c95142eSMartin Matuska       if (cur == symbol)
11286c95142eSMartin Matuska       {
11296c95142eSMartin Matuska         UInt32 low = sum;
11306c95142eSMartin Matuska         CPpmd_State *s1 = s;
11316c95142eSMartin Matuska         do
11326c95142eSMartin Matuska         {
11336c95142eSMartin Matuska           sum += (s->Freq & (int)(MASK(s->Symbol)));
11346c95142eSMartin Matuska           s++;
11356c95142eSMartin Matuska         }
11366c95142eSMartin Matuska         while (--i);
11376c95142eSMartin Matuska         RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
11386c95142eSMartin Matuska         Ppmd_See_Update(see);
11396c95142eSMartin Matuska         p->FoundState = s1;
11406c95142eSMartin Matuska         Ppmd7_Update2(p);
11416c95142eSMartin Matuska         return;
11426c95142eSMartin Matuska       }
11436c95142eSMartin Matuska       sum += (s->Freq & (int)(MASK(cur)));
11446c95142eSMartin Matuska       MASK(cur) = 0;
11456c95142eSMartin Matuska       s++;
11466c95142eSMartin Matuska     }
11476c95142eSMartin Matuska     while (--i);
11486c95142eSMartin Matuska 
11496c95142eSMartin Matuska     RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
11506c95142eSMartin Matuska     see->Summ = (UInt16)(see->Summ + sum + escFreq);
11516c95142eSMartin Matuska   }
11526c95142eSMartin Matuska }
11536c95142eSMartin Matuska 
11546c95142eSMartin Matuska const IPpmd7 __archive_ppmd7_functions =
11556c95142eSMartin Matuska {
11566c95142eSMartin Matuska   &Ppmd7_Construct,
11576c95142eSMartin Matuska   &Ppmd7_Alloc,
11586c95142eSMartin Matuska   &Ppmd7_Free,
11596c95142eSMartin Matuska   &Ppmd7_Init,
11606c95142eSMartin Matuska   &Ppmd7z_RangeDec_CreateVTable,
11616c95142eSMartin Matuska   &PpmdRAR_RangeDec_CreateVTable,
11626c95142eSMartin Matuska   &Ppmd7z_RangeDec_Init,
11636c95142eSMartin Matuska   &PpmdRAR_RangeDec_Init,
11646c95142eSMartin Matuska   &Ppmd7_DecodeSymbol,
11656c95142eSMartin Matuska   &Ppmd7z_RangeEnc_Init,
11666c95142eSMartin Matuska   &Ppmd7z_RangeEnc_FlushData,
11676c95142eSMartin Matuska   &Ppmd7_EncodeSymbol
11686c95142eSMartin Matuska };
1169