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