1/* Ppmd7.c -- PPMdH codec 22010-03-12 : Igor Pavlov : Public domain 3This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 4 5#include <memory.h> 6 7#include "Ppmd7.h" 8 9const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 10static 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 32typedef CPpmd7_Context * CTX_PTR; 33 34struct CPpmd7_Node_; 35 36typedef 37 #ifdef PPMD_32BIT 38 struct CPpmd7_Node_ * 39 #else 40 UInt32 41 #endif 42 CPpmd7_Node_Ref; 43 44typedef 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 58void 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 89void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc) 90{ 91 alloc->Free(alloc, p->Base); 92 p->Size = 0; 93 p->Base = 0; 94} 95 96Bool 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 118static 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 124static 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 131static 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 143static 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 215static 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 241static 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 260static 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 279static 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 285static 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 332void 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 341static 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 414static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) 415{ 416 CPpmd_State tmp = *t1; 417 *t1 = *t2; 418 *t2 = tmp; 419} 420 421static 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 570static 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 634CPpmd_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 659static 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 668void 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 683void 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 693void 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 701void 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