Home | History | Annotate | Download | only in 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 <memory.h>
      6 
      7 #include "Ppmd7.h"
      8 
      9 const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
     10 static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
     11 
     12 #define MAX_FREQ 124
     13 #define UNIT_SIZE 12
     14 
     15 #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
     16 #define U2I(nu) (p->Units2Indx[(nu) - 1])
     17 #define I2U(indx) (p->Indx2Units[indx])
     18 
     19 #ifdef PPMD_32BIT
     20   #define REF(ptr) (ptr)
     21 #else
     22   #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
     23 #endif
     24 
     25 #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
     26 
     27 #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
     28 #define STATS(ctx) Ppmd7_GetStats(p, ctx)
     29 #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
     30 #define SUFFIX(ctx) CTX((ctx)->Suffix)
     31 
     32 typedef CPpmd7_Context * CTX_PTR;
     33 
     34 struct CPpmd7_Node_;
     35 
     36 typedef
     37   #ifdef PPMD_32BIT
     38     struct CPpmd7_Node_ *
     39   #else
     40     UInt32
     41   #endif
     42   CPpmd7_Node_Ref;
     43 
     44 typedef struct CPpmd7_Node_
     45 {
     46   UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
     47   UInt16 NU;
     48   CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
     49   CPpmd7_Node_Ref Prev;
     50 } CPpmd7_Node;
     51 
     52 #ifdef PPMD_32BIT
     53   #define NODE(ptr) (ptr)
     54 #else
     55   #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
     56 #endif
     57 
     58 void Ppmd7_Construct(CPpmd7 *p)
     59 {
     60   unsigned i, k, m;
     61 
     62   p->Base = 0;
     63 
     64   for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
     65   {
     66     unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
     67     do { p->Units2Indx[k++] = (Byte)i; } while(--step);
     68     p->Indx2Units[i] = (Byte)k;
     69   }
     70 
     71   p->NS2BSIndx[0] = (0 << 1);
     72   p->NS2BSIndx[1] = (1 << 1);
     73   memset(p->NS2BSIndx + 2, (2 << 1), 9);
     74   memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
     75 
     76   for (i = 0; i < 3; i++)
     77     p->NS2Indx[i] = (Byte)i;
     78   for (m = i, k = 1; i < 256; i++)
     79   {
     80     p->NS2Indx[i] = (Byte)m;
     81     if (--k == 0)
     82       k = (++m) - 2;
     83   }
     84 
     85   memset(p->HB2Flag, 0, 0x40);
     86   memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
     87 }
     88 
     89 void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
     90 {
     91   alloc->Free(alloc, p->Base);
     92   p->Size = 0;
     93   p->Base = 0;
     94 }
     95 
     96 Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
     97 {
     98   if (p->Base == 0 || p->Size != size)
     99   {
    100     Ppmd7_Free(p, alloc);
    101     p->AlignOffset =
    102       #ifdef PPMD_32BIT
    103         (4 - size) & 3;
    104       #else
    105         4 - (size & 3);
    106       #endif
    107     if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
    108         #ifndef PPMD_32BIT
    109         + UNIT_SIZE
    110         #endif
    111         )) == 0)
    112       return False;
    113     p->Size = size;
    114   }
    115   return True;
    116 }
    117 
    118 static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
    119 {
    120   *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
    121   p->FreeList[indx] = REF(node);
    122 }
    123 
    124 static void *RemoveNode(CPpmd7 *p, unsigned indx)
    125 {
    126   CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
    127   p->FreeList[indx] = *node;
    128   return node;
    129 }
    130 
    131 static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
    132 {
    133   unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
    134   ptr = (Byte *)ptr + U2B(I2U(newIndx));
    135   if (I2U(i = U2I(nu)) != nu)
    136   {
    137     unsigned k = I2U(--i);
    138     InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
    139   }
    140   InsertNode(p, ptr, i);
    141 }
    142 
    143 static void GlueFreeBlocks(CPpmd7 *p)
    144 {
    145   #ifdef PPMD_32BIT
    146   CPpmd7_Node headItem;
    147   CPpmd7_Node_Ref head = &headItem;
    148   #else
    149   CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
    150   #endif
    151 
    152   CPpmd7_Node_Ref n = head;
    153   unsigned i;
    154 
    155   p->GlueCount = 255;
    156 
    157   /* create doubly-linked list of free blocks */
    158   for (i = 0; i < PPMD_NUM_INDEXES; i++)
    159   {
    160     UInt16 nu = I2U(i);
    161     CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
    162     p->FreeList[i] = 0;
    163     while (next != 0)
    164     {
    165       CPpmd7_Node *node = NODE(next);
    166       node->Next = n;
    167       n = NODE(n)->Prev = next;
    168       next = *(const CPpmd7_Node_Ref *)node;
    169       node->Stamp = 0;
    170       node->NU = (UInt16)nu;
    171     }
    172   }
    173   NODE(head)->Stamp = 1;
    174   NODE(head)->Next = n;
    175   NODE(n)->Prev = head;
    176   if (p->LoUnit != p->HiUnit)
    177     ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
    178 
    179   /* Glue free blocks */
    180   while (n != head)
    181   {
    182     CPpmd7_Node *node = NODE(n);
    183     UInt32 nu = (UInt32)node->NU;
    184     for (;;)
    185     {
    186       CPpmd7_Node *node2 = NODE(n) + nu;
    187       nu += node2->NU;
    188       if (node2->Stamp != 0 || nu >= 0x10000)
    189         break;
    190       NODE(node2->Prev)->Next = node2->Next;
    191       NODE(node2->Next)->Prev = node2->Prev;
    192       node->NU = (UInt16)nu;
    193     }
    194     n = node->Next;
    195   }
    196 
    197   /* Fill lists of free blocks */
    198   for (n = NODE(head)->Next; n != head;)
    199   {
    200     CPpmd7_Node *node = NODE(n);
    201     unsigned nu;
    202     CPpmd7_Node_Ref next = node->Next;
    203     for (nu = node->NU; nu > 128; nu -= 128, node += 128)
    204       InsertNode(p, node, PPMD_NUM_INDEXES - 1);
    205     if (I2U(i = U2I(nu)) != nu)
    206     {
    207       unsigned k = I2U(--i);
    208       InsertNode(p, node + k, nu - k - 1);
    209     }
    210     InsertNode(p, node, i);
    211     n = next;
    212   }
    213 }
    214 
    215 static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
    216 {
    217   unsigned i;
    218   void *retVal;
    219   if (p->GlueCount == 0)
    220   {
    221     GlueFreeBlocks(p);
    222     if (p->FreeList[indx] != 0)
    223       return RemoveNode(p, indx);
    224   }
    225   i = indx;
    226   do
    227   {
    228     if (++i == PPMD_NUM_INDEXES)
    229     {
    230       UInt32 numBytes = U2B(I2U(indx));
    231       p->GlueCount--;
    232       return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
    233     }
    234   }
    235   while (p->FreeList[i] == 0);
    236   retVal = RemoveNode(p, i);
    237   SplitBlock(p, retVal, i, indx);
    238   return retVal;
    239 }
    240 
    241 static void *AllocUnits(CPpmd7 *p, unsigned indx)
    242 {
    243   UInt32 numBytes;
    244   if (p->FreeList[indx] != 0)
    245     return RemoveNode(p, indx);
    246   numBytes = U2B(I2U(indx));
    247   if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
    248   {
    249     void *retVal = p->LoUnit;
    250     p->LoUnit += numBytes;
    251     return retVal;
    252   }
    253   return AllocUnitsRare(p, indx);
    254 }
    255 
    256 #define MyMem12Cpy(dest, src, num) \
    257   { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
    258     do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
    259 
    260 static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
    261 {
    262   unsigned i0 = U2I(oldNU);
    263   unsigned i1 = U2I(newNU);
    264   if (i0 == i1)
    265     return oldPtr;
    266   if (p->FreeList[i1] != 0)
    267   {
    268     void *ptr = RemoveNode(p, i1);
    269     MyMem12Cpy(ptr, oldPtr, newNU);
    270     InsertNode(p, oldPtr, i0);
    271     return ptr;
    272   }
    273   SplitBlock(p, oldPtr, i0, i1);
    274   return oldPtr;
    275 }
    276 
    277 #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
    278 
    279 static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
    280 {
    281   (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
    282   (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
    283 }
    284 
    285 static void RestartModel(CPpmd7 *p)
    286 {
    287   unsigned i, k, m;
    288 
    289   memset(p->FreeList, 0, sizeof(p->FreeList));
    290   p->Text = p->Base + p->AlignOffset;
    291   p->HiUnit = p->Text + p->Size;
    292   p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
    293   p->GlueCount = 0;
    294 
    295   p->OrderFall = p->MaxOrder;
    296   p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
    297   p->PrevSuccess = 0;
    298 
    299   p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
    300   p->MinContext->Suffix = 0;
    301   p->MinContext->NumStats = 256;
    302   p->MinContext->SummFreq = 256 + 1;
    303   p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
    304   p->LoUnit += U2B(256 / 2);
    305   p->MinContext->Stats = REF(p->FoundState);
    306   for (i = 0; i < 256; i++)
    307   {
    308     CPpmd_State *s = &p->FoundState[i];
    309     s->Symbol = (Byte)i;
    310     s->Freq = 1;
    311     SetSuccessor(s, 0);
    312   }
    313 
    314   for (i = 0; i < 128; i++)
    315     for (k = 0; k < 8; k++)
    316     {
    317       UInt16 *dest = p->BinSumm[i] + k;
    318       UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
    319       for (m = 0; m < 64; m += 8)
    320         dest[m] = val;
    321     }
    322 
    323   for (i = 0; i < 25; i++)
    324     for (k = 0; k < 16; k++)
    325     {
    326       CPpmd_See *s = &p->See[i][k];
    327       s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
    328       s->Count = 4;
    329     }
    330 }
    331 
    332 void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
    333 {
    334   p->MaxOrder = maxOrder;
    335   RestartModel(p);
    336   p->DummySee.Shift = PPMD_PERIOD_BITS;
    337   p->DummySee.Summ = 0; /* unused */
    338   p->DummySee.Count = 64; /* unused */
    339 }
    340 
    341 static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
    342 {
    343   CPpmd_State upState;
    344   CTX_PTR c = p->MinContext;
    345   CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
    346   CPpmd_State *ps[PPMD7_MAX_ORDER];
    347   unsigned numPs = 0;
    348 
    349   if (!skip)
    350     ps[numPs++] = p->FoundState;
    351 
    352   while (c->Suffix)
    353   {
    354     CPpmd_Void_Ref successor;
    355     CPpmd_State *s;
    356     c = SUFFIX(c);
    357     if (c->NumStats != 1)
    358     {
    359       for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
    360     }
    361     else
    362       s = ONE_STATE(c);
    363     successor = SUCCESSOR(s);
    364     if (successor != upBranch)
    365     {
    366       c = CTX(successor);
    367       if (numPs == 0)
    368         return c;
    369       break;
    370     }
    371     ps[numPs++] = s;
    372   }
    373 
    374   upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
    375   SetSuccessor(&upState, upBranch + 1);
    376 
    377   if (c->NumStats == 1)
    378     upState.Freq = ONE_STATE(c)->Freq;
    379   else
    380   {
    381     UInt32 cf, s0;
    382     CPpmd_State *s;
    383     for (s = STATS(c); s->Symbol != upState.Symbol; s++);
    384     cf = s->Freq - 1;
    385     s0 = c->SummFreq - c->NumStats - cf;
    386     upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
    387   }
    388 
    389   do
    390   {
    391     /* Create Child */
    392     CTX_PTR c1; /* = AllocContext(p); */
    393     if (p->HiUnit != p->LoUnit)
    394       c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
    395     else if (p->FreeList[0] != 0)
    396       c1 = (CTX_PTR)RemoveNode(p, 0);
    397     else
    398     {
    399       c1 = (CTX_PTR)AllocUnitsRare(p, 0);
    400       if (!c1)
    401         return NULL;
    402     }
    403     c1->NumStats = 1;
    404     *ONE_STATE(c1) = upState;
    405     c1->Suffix = REF(c);
    406     SetSuccessor(ps[--numPs], REF(c1));
    407     c = c1;
    408   }
    409   while (numPs != 0);
    410 
    411   return c;
    412 }
    413 
    414 static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
    415 {
    416   CPpmd_State tmp = *t1;
    417   *t1 = *t2;
    418   *t2 = tmp;
    419 }
    420 
    421 static void UpdateModel(CPpmd7 *p)
    422 {
    423   CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
    424   CTX_PTR c;
    425   unsigned s0, ns;
    426 
    427   if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
    428   {
    429     c = SUFFIX(p->MinContext);
    430 
    431     if (c->NumStats == 1)
    432     {
    433       CPpmd_State *s = ONE_STATE(c);
    434       if (s->Freq < 32)
    435         s->Freq++;
    436     }
    437     else
    438     {
    439       CPpmd_State *s = STATS(c);
    440       if (s->Symbol != p->FoundState->Symbol)
    441       {
    442         do { s++; } while (s->Symbol != p->FoundState->Symbol);
    443         if (s[0].Freq >= s[-1].Freq)
    444         {
    445           SwapStates(&s[0], &s[-1]);
    446           s--;
    447         }
    448       }
    449       if (s->Freq < MAX_FREQ - 9)
    450       {
    451         s->Freq += 2;
    452         c->SummFreq += 2;
    453       }
    454     }
    455   }
    456 
    457   if (p->OrderFall == 0)
    458   {
    459     p->MinContext = p->MaxContext = CreateSuccessors(p, True);
    460     if (p->MinContext == 0)
    461     {
    462       RestartModel(p);
    463       return;
    464     }
    465     SetSuccessor(p->FoundState, REF(p->MinContext));
    466     return;
    467   }
    468 
    469   *p->Text++ = p->FoundState->Symbol;
    470   successor = REF(p->Text);
    471   if (p->Text >= p->UnitsStart)
    472   {
    473     RestartModel(p);
    474     return;
    475   }
    476 
    477   if (fSuccessor)
    478   {
    479     if (fSuccessor <= successor)
    480     {
    481       CTX_PTR cs = CreateSuccessors(p, False);
    482       if (cs == NULL)
    483       {
    484         RestartModel(p);
    485         return;
    486       }
    487       fSuccessor = REF(cs);
    488     }
    489     if (--p->OrderFall == 0)
    490     {
    491       successor = fSuccessor;
    492       p->Text -= (p->MaxContext != p->MinContext);
    493     }
    494   }
    495   else
    496   {
    497     SetSuccessor(p->FoundState, successor);
    498     fSuccessor = REF(p->MinContext);
    499   }
    500 
    501   s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
    502 
    503   for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
    504   {
    505     unsigned ns1;
    506     UInt32 cf, sf;
    507     if ((ns1 = c->NumStats) != 1)
    508     {
    509       if ((ns1 & 1) == 0)
    510       {
    511         /* Expand for one UNIT */
    512         unsigned oldNU = ns1 >> 1;
    513         unsigned i = U2I(oldNU);
    514         if (i != U2I(oldNU + 1))
    515         {
    516           void *ptr = AllocUnits(p, i + 1);
    517           void *oldPtr;
    518           if (!ptr)
    519           {
    520             RestartModel(p);
    521             return;
    522           }
    523           oldPtr = STATS(c);
    524           MyMem12Cpy(ptr, oldPtr, oldNU);
    525           InsertNode(p, oldPtr, i);
    526           c->Stats = STATS_REF(ptr);
    527         }
    528       }
    529       c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
    530     }
    531     else
    532     {
    533       CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
    534       if (!s)
    535       {
    536         RestartModel(p);
    537         return;
    538       }
    539       *s = *ONE_STATE(c);
    540       c->Stats = REF(s);
    541       if (s->Freq < MAX_FREQ / 4 - 1)
    542         s->Freq <<= 1;
    543       else
    544         s->Freq = MAX_FREQ - 4;
    545       c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
    546     }
    547     cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
    548     sf = (UInt32)s0 + c->SummFreq;
    549     if (cf < 6 * sf)
    550     {
    551       cf = 1 + (cf > sf) + (cf >= 4 * sf);
    552       c->SummFreq += 3;
    553     }
    554     else
    555     {
    556       cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
    557       c->SummFreq = (UInt16)(c->SummFreq + cf);
    558     }
    559     {
    560       CPpmd_State *s = STATS(c) + ns1;
    561       SetSuccessor(s, successor);
    562       s->Symbol = p->FoundState->Symbol;
    563       s->Freq = (Byte)cf;
    564       c->NumStats = (UInt16)(ns1 + 1);
    565     }
    566   }
    567   p->MaxContext = p->MinContext = CTX(fSuccessor);
    568 }
    569 
    570 static void Rescale(CPpmd7 *p)
    571 {
    572   unsigned i, adder, sumFreq, escFreq;
    573   CPpmd_State *stats = STATS(p->MinContext);
    574   CPpmd_State *s = p->FoundState;
    575   {
    576     CPpmd_State tmp = *s;
    577     for (; s != stats; s--)
    578       s[0] = s[-1];
    579     *s = tmp;
    580   }
    581   escFreq = p->MinContext->SummFreq - s->Freq;
    582   s->Freq += 4;
    583   adder = (p->OrderFall != 0);
    584   s->Freq = (Byte)((s->Freq + adder) >> 1);
    585   sumFreq = s->Freq;
    586 
    587   i = p->MinContext->NumStats - 1;
    588   do
    589   {
    590     escFreq -= (++s)->Freq;
    591     s->Freq = (Byte)((s->Freq + adder) >> 1);
    592     sumFreq += s->Freq;
    593     if (s[0].Freq > s[-1].Freq)
    594     {
    595       CPpmd_State *s1 = s;
    596       CPpmd_State tmp = *s1;
    597       do
    598         s1[0] = s1[-1];
    599       while (--s1 != stats && tmp.Freq > s1[-1].Freq);
    600       *s1 = tmp;
    601     }
    602   }
    603   while (--i);
    604 
    605   if (s->Freq == 0)
    606   {
    607     unsigned numStats = p->MinContext->NumStats;
    608     unsigned n0, n1;
    609     do { i++; } while ((--s)->Freq == 0);
    610     escFreq += i;
    611     p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
    612     if (p->MinContext->NumStats == 1)
    613     {
    614       CPpmd_State tmp = *stats;
    615       do
    616       {
    617         tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
    618         escFreq >>= 1;
    619       }
    620       while (escFreq > 1);
    621       InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
    622       *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
    623       return;
    624     }
    625     n0 = (numStats + 1) >> 1;
    626     n1 = (p->MinContext->NumStats + 1) >> 1;
    627     if (n0 != n1)
    628       p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
    629   }
    630   p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
    631   p->FoundState = STATS(p->MinContext);
    632 }
    633 
    634 CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
    635 {
    636   CPpmd_See *see;
    637   unsigned nonMasked = p->MinContext->NumStats - numMasked;
    638   if (p->MinContext->NumStats != 256)
    639   {
    640     see = p->See[p->NS2Indx[nonMasked - 1]] +
    641         (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
    642         2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
    643         4 * (numMasked > nonMasked) +
    644         p->HiBitsFlag;
    645     {
    646       unsigned r = (see->Summ >> see->Shift);
    647       see->Summ = (UInt16)(see->Summ - r);
    648       *escFreq = r + (r == 0);
    649     }
    650   }
    651   else
    652   {
    653     see = &p->DummySee;
    654     *escFreq = 1;
    655   }
    656   return see;
    657 }
    658 
    659 static void NextContext(CPpmd7 *p)
    660 {
    661   CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
    662   if (p->OrderFall == 0 && (Byte *)c > p->Text)
    663     p->MinContext = p->MaxContext = c;
    664   else
    665     UpdateModel(p);
    666 }
    667 
    668 void Ppmd7_Update1(CPpmd7 *p)
    669 {
    670   CPpmd_State *s = p->FoundState;
    671   s->Freq += 4;
    672   p->MinContext->SummFreq += 4;
    673   if (s[0].Freq > s[-1].Freq)
    674   {
    675     SwapStates(&s[0], &s[-1]);
    676     p->FoundState = --s;
    677     if (s->Freq > MAX_FREQ)
    678       Rescale(p);
    679   }
    680   NextContext(p);
    681 }
    682 
    683 void Ppmd7_Update1_0(CPpmd7 *p)
    684 {
    685   p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
    686   p->RunLength += p->PrevSuccess;
    687   p->MinContext->SummFreq += 4;
    688   if ((p->FoundState->Freq += 4) > MAX_FREQ)
    689     Rescale(p);
    690   NextContext(p);
    691 }
    692 
    693 void Ppmd7_UpdateBin(CPpmd7 *p)
    694 {
    695   p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
    696   p->PrevSuccess = 1;
    697   p->RunLength++;
    698   NextContext(p);
    699 }
    700 
    701 void Ppmd7_Update2(CPpmd7 *p)
    702 {
    703   p->MinContext->SummFreq += 4;
    704   if ((p->FoundState->Freq += 4) > MAX_FREQ)
    705     Rescale(p);
    706   p->RunLength = p->InitRL;
    707   UpdateModel(p);
    708 }
    709