1 /* Ppmd7.c -- PPMdH codec 2 2018-07-04 : 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 34 typedef CPpmd7_Context * CTX_PTR; 35 36 struct CPpmd7_Node_; 37 38 typedef 39 #ifdef PPMD_32BIT 40 struct CPpmd7_Node_ * 41 #else 42 UInt32 43 #endif 44 CPpmd7_Node_Ref; 45 46 typedef struct CPpmd7_Node_ 47 { 48 UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ 49 UInt16 NU; 50 CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ 51 CPpmd7_Node_Ref Prev; 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 60 void Ppmd7_Construct(CPpmd7 *p) 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 98 BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) 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); 165 CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[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 283 static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) 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); 340 p->DummySee.Shift = PPMD_PERIOD_BITS; 341 p->DummySee.Summ = 0; /* unused */ 342 p->DummySee.Count = 64; /* unused */ 343 } 344 345 static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip) 346 { 347 CPpmd_State upState; 348 CTX_PTR c = p->MinContext; 349 CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); 350 CPpmd_State *ps[PPMD7_MAX_ORDER]; 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 { 463 p->MinContext = p->MaxContext = CreateSuccessors(p, True); 464 if (p->MinContext == 0) 465 { 466 RestartModel(p); 467 return; 468 } 469 SetSuccessor(p->FoundState, REF(p->MinContext)); 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 672 void Ppmd7_Update1(CPpmd7 *p) 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 687 void Ppmd7_Update1_0(CPpmd7 *p) 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 697 void Ppmd7_UpdateBin(CPpmd7 *p) 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 705 void Ppmd7_Update2(CPpmd7 *p) 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 } 713