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 "archive_platform.h" 6 7 #include <stdlib.h> 8 9 #include "archive_ppmd7_private.h" 10 11 #ifdef PPMD_32BIT 12 #define Ppmd7_GetPtr(p, ptr) (ptr) 13 #define Ppmd7_GetContext(p, ptr) (ptr) 14 #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) 15 #else 16 #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) 17 #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) 18 #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) 19 #endif 20 21 #define Ppmd7_GetBinSumm(p) \ 22 &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ 23 p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ 24 (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ 25 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ 26 ((p->RunLength >> 26) & 0x20)] 27 28 #define kTopValue (1 << 24) 29 #define MAX_FREQ 124 30 #define UNIT_SIZE 12 31 32 #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) 33 #define U2I(nu) (p->Units2Indx[(nu) - 1]) 34 #define I2U(indx) (p->Indx2Units[indx]) 35 36 #ifdef PPMD_32BIT 37 #define REF(ptr) (ptr) 38 #else 39 #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) 40 #endif 41 42 #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) 43 44 #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) 45 #define STATS(ctx) Ppmd7_GetStats(p, ctx) 46 #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) 47 #define SUFFIX(ctx) CTX((ctx)->Suffix) 48 49 static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; 50 static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 51 52 typedef CPpmd7_Context * CTX_PTR; 53 54 struct CPpmd7_Node_; 55 56 typedef 57 #ifdef PPMD_32BIT 58 struct CPpmd7_Node_ * 59 #else 60 UInt32 61 #endif 62 CPpmd7_Node_Ref; 63 64 typedef struct CPpmd7_Node_ 65 { 66 UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ 67 UInt16 NU; 68 CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ 69 CPpmd7_Node_Ref Prev; 70 } CPpmd7_Node; 71 72 #ifdef PPMD_32BIT 73 #define NODE(ptr) (ptr) 74 #else 75 #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) 76 #endif 77 78 static void Ppmd7_Update1(CPpmd7 *p); 79 static void Ppmd7_Update1_0(CPpmd7 *p); 80 static void Ppmd7_Update2(CPpmd7 *p); 81 static void Ppmd7_UpdateBin(CPpmd7 *p); 82 static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, 83 UInt32 *scale); 84 85 /* ----------- Base ----------- */ 86 87 static void Ppmd7_Construct(CPpmd7 *p) 88 { 89 unsigned i, k, m; 90 91 p->Base = 0; 92 93 for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) 94 { 95 unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); 96 do { p->Units2Indx[k++] = (Byte)i; } while(--step); 97 p->Indx2Units[i] = (Byte)k; 98 } 99 100 p->NS2BSIndx[0] = (0 << 1); 101 p->NS2BSIndx[1] = (1 << 1); 102 memset(p->NS2BSIndx + 2, (2 << 1), 9); 103 memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); 104 105 for (i = 0; i < 3; i++) 106 p->NS2Indx[i] = (Byte)i; 107 for (m = i, k = 1; i < 256; i++) 108 { 109 p->NS2Indx[i] = (Byte)m; 110 if (--k == 0) 111 k = (++m) - 2; 112 } 113 114 memset(p->HB2Flag, 0, 0x40); 115 memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); 116 } 117 118 static void Ppmd7_Free(CPpmd7 *p) 119 { 120 free(p->Base); 121 p->Size = 0; 122 p->Base = 0; 123 } 124 125 static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size) 126 { 127 if (p->Base == 0 || p->Size != size) 128 { 129 /* RestartModel() below assumes that p->Size >= UNIT_SIZE 130 (see the calculation of m->MinContext). */ 131 if (size < UNIT_SIZE) { 132 return False; 133 } 134 Ppmd7_Free(p); 135 p->AlignOffset = 136 #ifdef PPMD_32BIT 137 (4 - size) & 3; 138 #else 139 4 - (size & 3); 140 #endif 141 if ((p->Base = malloc(p->AlignOffset + size 142 #ifndef PPMD_32BIT 143 + UNIT_SIZE 144 #endif 145 )) == 0) 146 return False; 147 p->Size = size; 148 } 149 return True; 150 } 151 152 static void InsertNode(CPpmd7 *p, void *node, unsigned indx) 153 { 154 *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; 155 p->FreeList[indx] = REF(node); 156 } 157 158 static void *RemoveNode(CPpmd7 *p, unsigned indx) 159 { 160 CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); 161 p->FreeList[indx] = *node; 162 return node; 163 } 164 165 static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) 166 { 167 unsigned i, nu = I2U(oldIndx) - I2U(newIndx); 168 ptr = (Byte *)ptr + U2B(I2U(newIndx)); 169 if (I2U(i = U2I(nu)) != nu) 170 { 171 unsigned k = I2U(--i); 172 InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); 173 } 174 InsertNode(p, ptr, i); 175 } 176 177 static void GlueFreeBlocks(CPpmd7 *p) 178 { 179 #ifdef PPMD_32BIT 180 CPpmd7_Node headItem; 181 CPpmd7_Node_Ref head = &headItem; 182 #else 183 CPpmd7_Node_Ref head = p->AlignOffset + p->Size; 184 #endif 185 186 CPpmd7_Node_Ref n = head; 187 unsigned i; 188 189 p->GlueCount = 255; 190 191 /* create doubly-linked list of free blocks */ 192 for (i = 0; i < PPMD_NUM_INDEXES; i++) 193 { 194 UInt16 nu = I2U(i); 195 CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; 196 p->FreeList[i] = 0; 197 while (next != 0) 198 { 199 CPpmd7_Node *node = NODE(next); 200 node->Next = n; 201 n = NODE(n)->Prev = next; 202 next = *(const CPpmd7_Node_Ref *)node; 203 node->Stamp = 0; 204 node->NU = (UInt16)nu; 205 } 206 } 207 NODE(head)->Stamp = 1; 208 NODE(head)->Next = n; 209 NODE(n)->Prev = head; 210 if (p->LoUnit != p->HiUnit) 211 ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; 212 213 /* Glue free blocks */ 214 while (n != head) 215 { 216 CPpmd7_Node *node = NODE(n); 217 UInt32 nu = (UInt32)node->NU; 218 for (;;) 219 { 220 CPpmd7_Node *node2 = NODE(n) + nu; 221 nu += node2->NU; 222 if (node2->Stamp != 0 || nu >= 0x10000) 223 break; 224 NODE(node2->Prev)->Next = node2->Next; 225 NODE(node2->Next)->Prev = node2->Prev; 226 node->NU = (UInt16)nu; 227 } 228 n = node->Next; 229 } 230 231 /* Fill lists of free blocks */ 232 for (n = NODE(head)->Next; n != head;) 233 { 234 CPpmd7_Node *node = NODE(n); 235 unsigned nu; 236 CPpmd7_Node_Ref next = node->Next; 237 for (nu = node->NU; nu > 128; nu -= 128, node += 128) 238 InsertNode(p, node, PPMD_NUM_INDEXES - 1); 239 if (I2U(i = U2I(nu)) != nu) 240 { 241 unsigned k = I2U(--i); 242 InsertNode(p, node + k, nu - k - 1); 243 } 244 InsertNode(p, node, i); 245 n = next; 246 } 247 } 248 249 static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) 250 { 251 unsigned i; 252 void *retVal; 253 if (p->GlueCount == 0) 254 { 255 GlueFreeBlocks(p); 256 if (p->FreeList[indx] != 0) 257 return RemoveNode(p, indx); 258 } 259 i = indx; 260 do 261 { 262 if (++i == PPMD_NUM_INDEXES) 263 { 264 UInt32 numBytes = U2B(I2U(indx)); 265 p->GlueCount--; 266 return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); 267 } 268 } 269 while (p->FreeList[i] == 0); 270 retVal = RemoveNode(p, i); 271 SplitBlock(p, retVal, i, indx); 272 return retVal; 273 } 274 275 static void *AllocUnits(CPpmd7 *p, unsigned indx) 276 { 277 UInt32 numBytes; 278 if (p->FreeList[indx] != 0) 279 return RemoveNode(p, indx); 280 numBytes = U2B(I2U(indx)); 281 if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) 282 { 283 void *retVal = p->LoUnit; 284 p->LoUnit += numBytes; 285 return retVal; 286 } 287 return AllocUnitsRare(p, indx); 288 } 289 290 #define MyMem12Cpy(dest, src, num) do { \ 291 UInt32 *d = (UInt32 *)dest; \ 292 const UInt32 *s = (const UInt32 *)src; \ 293 UInt32 n = num; \ 294 do { \ 295 d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; \ 296 } while(--n); \ 297 } while (0) 298 299 static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) 300 { 301 unsigned i0 = U2I(oldNU); 302 unsigned i1 = U2I(newNU); 303 if (i0 == i1) 304 return oldPtr; 305 if (p->FreeList[i1] != 0) 306 { 307 void *ptr = RemoveNode(p, i1); 308 MyMem12Cpy(ptr, oldPtr, newNU); 309 InsertNode(p, oldPtr, i0); 310 return ptr; 311 } 312 SplitBlock(p, oldPtr, i0, i1); 313 return oldPtr; 314 } 315 316 #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) 317 318 static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) 319 { 320 (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); 321 (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); 322 } 323 324 static void RestartModel(CPpmd7 *p) 325 { 326 unsigned i, k, m; 327 328 memset(p->FreeList, 0, sizeof(p->FreeList)); 329 p->Text = p->Base + p->AlignOffset; 330 p->HiUnit = p->Text + p->Size; 331 p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; 332 p->GlueCount = 0; 333 334 p->OrderFall = p->MaxOrder; 335 p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; 336 p->PrevSuccess = 0; 337 338 p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ 339 p->MinContext->Suffix = 0; 340 p->MinContext->NumStats = 256; 341 p->MinContext->SummFreq = 256 + 1; 342 p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ 343 p->LoUnit += U2B(256 / 2); 344 p->MinContext->Stats = REF(p->FoundState); 345 for (i = 0; i < 256; i++) 346 { 347 CPpmd_State *s = &p->FoundState[i]; 348 s->Symbol = (Byte)i; 349 s->Freq = 1; 350 SetSuccessor(s, 0); 351 } 352 353 for (i = 0; i < 128; i++) 354 for (k = 0; k < 8; k++) 355 { 356 UInt16 *dest = p->BinSumm[i] + k; 357 UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); 358 for (m = 0; m < 64; m += 8) 359 dest[m] = val; 360 } 361 362 for (i = 0; i < 25; i++) 363 for (k = 0; k < 16; k++) 364 { 365 CPpmd_See *s = &p->See[i][k]; 366 s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); 367 s->Count = 4; 368 } 369 } 370 371 static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) 372 { 373 p->MaxOrder = maxOrder; 374 RestartModel(p); 375 p->DummySee.Shift = PPMD_PERIOD_BITS; 376 p->DummySee.Summ = 0; /* unused */ 377 p->DummySee.Count = 64; /* unused */ 378 } 379 380 static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) 381 { 382 CPpmd_State upState; 383 CTX_PTR c = p->MinContext; 384 CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); 385 CPpmd_State *ps[PPMD7_MAX_ORDER]; 386 unsigned numPs = 0; 387 388 if (!skip) 389 ps[numPs++] = p->FoundState; 390 391 while (c->Suffix) 392 { 393 CPpmd_Void_Ref successor; 394 CPpmd_State *s; 395 c = SUFFIX(c); 396 if (c->NumStats != 1) 397 { 398 for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); 399 } 400 else 401 s = ONE_STATE(c); 402 successor = SUCCESSOR(s); 403 if (successor != upBranch) 404 { 405 c = CTX(successor); 406 if (numPs == 0) 407 return c; 408 break; 409 } 410 ps[numPs++] = s; 411 } 412 413 upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); 414 SetSuccessor(&upState, upBranch + 1); 415 416 if (c->NumStats == 1) 417 upState.Freq = ONE_STATE(c)->Freq; 418 else 419 { 420 UInt32 cf, s0; 421 CPpmd_State *s; 422 for (s = STATS(c); s->Symbol != upState.Symbol; s++); 423 cf = s->Freq - 1; 424 s0 = c->SummFreq - c->NumStats - cf; 425 upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); 426 } 427 428 while (numPs != 0) 429 { 430 /* Create Child */ 431 CTX_PTR c1; /* = AllocContext(p); */ 432 if (p->HiUnit != p->LoUnit) 433 c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); 434 else if (p->FreeList[0] != 0) 435 c1 = (CTX_PTR)RemoveNode(p, 0); 436 else 437 { 438 c1 = (CTX_PTR)AllocUnitsRare(p, 0); 439 if (!c1) 440 return NULL; 441 } 442 c1->NumStats = 1; 443 *ONE_STATE(c1) = upState; 444 c1->Suffix = REF(c); 445 SetSuccessor(ps[--numPs], REF(c1)); 446 c = c1; 447 } 448 449 return c; 450 } 451 452 static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) 453 { 454 CPpmd_State tmp = *t1; 455 *t1 = *t2; 456 *t2 = tmp; 457 } 458 459 static void UpdateModel(CPpmd7 *p) 460 { 461 CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); 462 CTX_PTR c; 463 unsigned s0, ns; 464 465 if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) 466 { 467 c = SUFFIX(p->MinContext); 468 469 if (c->NumStats == 1) 470 { 471 CPpmd_State *s = ONE_STATE(c); 472 if (s->Freq < 32) 473 s->Freq++; 474 } 475 else 476 { 477 CPpmd_State *s = STATS(c); 478 if (s->Symbol != p->FoundState->Symbol) 479 { 480 do { s++; } while (s->Symbol != p->FoundState->Symbol); 481 if (s[0].Freq >= s[-1].Freq) 482 { 483 SwapStates(&s[0], &s[-1]); 484 s--; 485 } 486 } 487 if (s->Freq < MAX_FREQ - 9) 488 { 489 s->Freq += 2; 490 c->SummFreq += 2; 491 } 492 } 493 } 494 495 if (p->OrderFall == 0) 496 { 497 p->MinContext = p->MaxContext = CreateSuccessors(p, True); 498 if (p->MinContext == 0) 499 { 500 RestartModel(p); 501 return; 502 } 503 SetSuccessor(p->FoundState, REF(p->MinContext)); 504 return; 505 } 506 507 *p->Text++ = p->FoundState->Symbol; 508 successor = REF(p->Text); 509 if (p->Text >= p->UnitsStart) 510 { 511 RestartModel(p); 512 return; 513 } 514 515 if (fSuccessor) 516 { 517 if (fSuccessor <= successor) 518 { 519 CTX_PTR cs = CreateSuccessors(p, False); 520 if (cs == NULL) 521 { 522 RestartModel(p); 523 return; 524 } 525 fSuccessor = REF(cs); 526 } 527 if (--p->OrderFall == 0) 528 { 529 successor = fSuccessor; 530 p->Text -= (p->MaxContext != p->MinContext); 531 } 532 } 533 else 534 { 535 SetSuccessor(p->FoundState, successor); 536 fSuccessor = REF(p->MinContext); 537 } 538 539 s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); 540 541 for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) 542 { 543 unsigned ns1; 544 UInt32 cf, sf; 545 if ((ns1 = c->NumStats) != 1) 546 { 547 if ((ns1 & 1) == 0) 548 { 549 /* Expand for one UNIT */ 550 unsigned oldNU = ns1 >> 1; 551 unsigned i = U2I(oldNU); 552 if (i != U2I(oldNU + 1)) 553 { 554 void *ptr = AllocUnits(p, i + 1); 555 void *oldPtr; 556 if (!ptr) 557 { 558 RestartModel(p); 559 return; 560 } 561 oldPtr = STATS(c); 562 MyMem12Cpy(ptr, oldPtr, oldNU); 563 InsertNode(p, oldPtr, i); 564 c->Stats = STATS_REF(ptr); 565 } 566 } 567 c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); 568 } 569 else 570 { 571 CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); 572 if (!s) 573 { 574 RestartModel(p); 575 return; 576 } 577 *s = *ONE_STATE(c); 578 c->Stats = REF(s); 579 if (s->Freq < MAX_FREQ / 4 - 1) 580 s->Freq <<= 1; 581 else 582 s->Freq = MAX_FREQ - 4; 583 c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); 584 } 585 cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); 586 sf = (UInt32)s0 + c->SummFreq; 587 if (cf < 6 * sf) 588 { 589 cf = 1 + (cf > sf) + (cf >= 4 * sf); 590 c->SummFreq += 3; 591 } 592 else 593 { 594 cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); 595 c->SummFreq = (UInt16)(c->SummFreq + cf); 596 } 597 { 598 CPpmd_State *s = STATS(c) + ns1; 599 SetSuccessor(s, successor); 600 s->Symbol = p->FoundState->Symbol; 601 s->Freq = (Byte)cf; 602 c->NumStats = (UInt16)(ns1 + 1); 603 } 604 } 605 p->MaxContext = p->MinContext = CTX(fSuccessor); 606 } 607 608 static void Rescale(CPpmd7 *p) 609 { 610 unsigned i, adder, sumFreq, escFreq; 611 CPpmd_State *stats = STATS(p->MinContext); 612 CPpmd_State *s = p->FoundState; 613 { 614 CPpmd_State tmp = *s; 615 for (; s != stats; s--) 616 s[0] = s[-1]; 617 *s = tmp; 618 } 619 escFreq = p->MinContext->SummFreq - s->Freq; 620 s->Freq += 4; 621 adder = (p->OrderFall != 0); 622 s->Freq = (Byte)((s->Freq + adder) >> 1); 623 sumFreq = s->Freq; 624 625 i = p->MinContext->NumStats - 1; 626 do 627 { 628 escFreq -= (++s)->Freq; 629 s->Freq = (Byte)((s->Freq + adder) >> 1); 630 sumFreq += s->Freq; 631 if (s[0].Freq > s[-1].Freq) 632 { 633 CPpmd_State *s1 = s; 634 CPpmd_State tmp = *s1; 635 do 636 s1[0] = s1[-1]; 637 while (--s1 != stats && tmp.Freq > s1[-1].Freq); 638 *s1 = tmp; 639 } 640 } 641 while (--i); 642 643 if (s->Freq == 0) 644 { 645 unsigned numStats = p->MinContext->NumStats; 646 unsigned n0, n1; 647 do { i++; } while ((--s)->Freq == 0); 648 escFreq += i; 649 p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); 650 if (p->MinContext->NumStats == 1) 651 { 652 CPpmd_State tmp = *stats; 653 do 654 { 655 tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); 656 escFreq >>= 1; 657 } 658 while (escFreq > 1); 659 InsertNode(p, stats, U2I(((numStats + 1) >> 1))); 660 *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; 661 return; 662 } 663 n0 = (numStats + 1) >> 1; 664 n1 = (p->MinContext->NumStats + 1) >> 1; 665 if (n0 != n1) 666 p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); 667 } 668 p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); 669 p->FoundState = STATS(p->MinContext); 670 } 671 672 static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) 673 { 674 CPpmd_See *see; 675 unsigned nonMasked = p->MinContext->NumStats - numMasked; 676 if (p->MinContext->NumStats != 256) 677 { 678 see = p->See[p->NS2Indx[nonMasked - 1]] + 679 (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + 680 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + 681 4 * (numMasked > nonMasked) + 682 p->HiBitsFlag; 683 { 684 unsigned r = (see->Summ >> see->Shift); 685 see->Summ = (UInt16)(see->Summ - r); 686 *escFreq = r + (r == 0); 687 } 688 } 689 else 690 { 691 see = &p->DummySee; 692 *escFreq = 1; 693 } 694 return see; 695 } 696 697 static void NextContext(CPpmd7 *p) 698 { 699 CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); 700 if (p->OrderFall == 0 && (Byte *)c > p->Text) 701 p->MinContext = p->MaxContext = c; 702 else 703 UpdateModel(p); 704 } 705 706 static void Ppmd7_Update1(CPpmd7 *p) 707 { 708 CPpmd_State *s = p->FoundState; 709 s->Freq += 4; 710 p->MinContext->SummFreq += 4; 711 if (s[0].Freq > s[-1].Freq) 712 { 713 SwapStates(&s[0], &s[-1]); 714 p->FoundState = --s; 715 if (s->Freq > MAX_FREQ) 716 Rescale(p); 717 } 718 NextContext(p); 719 } 720 721 static void Ppmd7_Update1_0(CPpmd7 *p) 722 { 723 p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); 724 p->RunLength += p->PrevSuccess; 725 p->MinContext->SummFreq += 4; 726 if ((p->FoundState->Freq += 4) > MAX_FREQ) 727 Rescale(p); 728 NextContext(p); 729 } 730 731 static void Ppmd7_UpdateBin(CPpmd7 *p) 732 { 733 p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); 734 p->PrevSuccess = 1; 735 p->RunLength++; 736 NextContext(p); 737 } 738 739 static void Ppmd7_Update2(CPpmd7 *p) 740 { 741 p->MinContext->SummFreq += 4; 742 if ((p->FoundState->Freq += 4) > MAX_FREQ) 743 Rescale(p); 744 p->RunLength = p->InitRL; 745 UpdateModel(p); 746 } 747 748 /* ---------- Decode ---------- */ 749 750 static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p) 751 { 752 unsigned i; 753 p->Low = p->Bottom = 0; 754 p->Range = 0xFFFFFFFF; 755 for (i = 0; i < 4; i++) 756 p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); 757 return (p->Code < 0xFFFFFFFF); 758 } 759 760 static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) 761 { 762 if (p->Stream->Read((void *)p->Stream) != 0) 763 return False; 764 return Ppmd_RangeDec_Init(p); 765 } 766 767 static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p) 768 { 769 if (!Ppmd_RangeDec_Init(p)) 770 return False; 771 p->Bottom = 0x8000; 772 return True; 773 } 774 775 static UInt32 Range_GetThreshold(void *pp, UInt32 total) 776 { 777 CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 778 return (p->Code - p->Low) / (p->Range /= total); 779 } 780 781 static void Range_Normalize(CPpmd7z_RangeDec *p) 782 { 783 while (1) 784 { 785 if((p->Low ^ (p->Low + p->Range)) >= kTopValue) 786 { 787 if(p->Range >= p->Bottom) 788 break; 789 else 790 p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1); 791 } 792 p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); 793 p->Range <<= 8; 794 p->Low <<= 8; 795 } 796 } 797 798 static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size) 799 { 800 CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 801 p->Code -= start * p->Range; 802 p->Range *= size; 803 Range_Normalize(p); 804 } 805 806 static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size) 807 { 808 CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 809 p->Low += start * p->Range; 810 p->Range *= size; 811 Range_Normalize(p); 812 } 813 814 static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0) 815 { 816 CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 817 UInt32 newBound = (p->Range >> 14) * size0; 818 UInt32 symbol; 819 if (p->Code < newBound) 820 { 821 symbol = 0; 822 p->Range = newBound; 823 } 824 else 825 { 826 symbol = 1; 827 p->Code -= newBound; 828 p->Range -= newBound; 829 } 830 Range_Normalize(p); 831 return symbol; 832 } 833 834 static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0) 835 { 836 CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 837 UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE); 838 if(value < size0) 839 { 840 bit = 0; 841 p->p.Decode(p, 0, size0); 842 } 843 else 844 { 845 bit = 1; 846 p->p.Decode(p, size0, PPMD_BIN_SCALE - size0); 847 } 848 return bit; 849 } 850 851 static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) 852 { 853 p->p.GetThreshold = Range_GetThreshold; 854 p->p.Decode = Range_Decode_7z; 855 p->p.DecodeBit = Range_DecodeBit_7z; 856 } 857 858 static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) 859 { 860 p->p.GetThreshold = Range_GetThreshold; 861 p->p.Decode = Range_Decode_RAR; 862 p->p.DecodeBit = Range_DecodeBit_RAR; 863 } 864 865 #define MASK(sym) ((signed char *)charMask)[sym] 866 867 static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc) 868 { 869 size_t charMask[256 / sizeof(size_t)]; 870 if (p->MinContext->NumStats != 1) 871 { 872 CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 873 unsigned i; 874 UInt32 count, hiCnt; 875 if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) 876 { 877 Byte symbol; 878 rc->Decode(rc, 0, s->Freq); 879 p->FoundState = s; 880 symbol = s->Symbol; 881 Ppmd7_Update1_0(p); 882 return symbol; 883 } 884 p->PrevSuccess = 0; 885 i = p->MinContext->NumStats - 1; 886 do 887 { 888 if ((hiCnt += (++s)->Freq) > count) 889 { 890 Byte symbol; 891 rc->Decode(rc, hiCnt - s->Freq, s->Freq); 892 p->FoundState = s; 893 symbol = s->Symbol; 894 Ppmd7_Update1(p); 895 return symbol; 896 } 897 } 898 while (--i); 899 if (count >= p->MinContext->SummFreq) 900 return -2; 901 p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 902 rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); 903 PPMD_SetAllBitsIn256Bytes(charMask); 904 MASK(s->Symbol) = 0; 905 i = p->MinContext->NumStats - 1; 906 do { MASK((--s)->Symbol) = 0; } while (--i); 907 } 908 else 909 { 910 UInt16 *prob = Ppmd7_GetBinSumm(p); 911 if (rc->DecodeBit(rc, *prob) == 0) 912 { 913 Byte symbol; 914 *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 915 symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; 916 Ppmd7_UpdateBin(p); 917 return symbol; 918 } 919 *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 920 p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 921 PPMD_SetAllBitsIn256Bytes(charMask); 922 MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; 923 p->PrevSuccess = 0; 924 } 925 for (;;) 926 { 927 CPpmd_State *ps[256], *s; 928 UInt32 freqSum, count, hiCnt; 929 CPpmd_See *see; 930 unsigned i, num, numMasked = p->MinContext->NumStats; 931 do 932 { 933 p->OrderFall++; 934 if (!p->MinContext->Suffix) 935 return -1; 936 p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 937 } 938 while (p->MinContext->NumStats == numMasked); 939 hiCnt = 0; 940 s = Ppmd7_GetStats(p, p->MinContext); 941 i = 0; 942 num = p->MinContext->NumStats - numMasked; 943 do 944 { 945 int k = (int)(MASK(s->Symbol)); 946 hiCnt += (s->Freq & k); 947 ps[i] = s++; 948 i -= k; 949 } 950 while (i != num); 951 952 see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); 953 freqSum += hiCnt; 954 count = rc->GetThreshold(rc, freqSum); 955 956 if (count < hiCnt) 957 { 958 Byte symbol; 959 CPpmd_State **pps = ps; 960 for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); 961 s = *pps; 962 rc->Decode(rc, hiCnt - s->Freq, s->Freq); 963 Ppmd_See_Update(see); 964 p->FoundState = s; 965 symbol = s->Symbol; 966 Ppmd7_Update2(p); 967 return symbol; 968 } 969 if (count >= freqSum) 970 return -2; 971 rc->Decode(rc, hiCnt, freqSum - hiCnt); 972 see->Summ = (UInt16)(see->Summ + freqSum); 973 do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); 974 } 975 } 976 977 /* ---------- Encode ---------- Ppmd7Enc.c */ 978 979 #define kTopValue (1 << 24) 980 981 static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) 982 { 983 p->Low = 0; 984 p->Range = 0xFFFFFFFF; 985 p->Cache = 0; 986 p->CacheSize = 1; 987 } 988 989 static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) 990 { 991 if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) 992 { 993 Byte temp = p->Cache; 994 do 995 { 996 p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); 997 temp = 0xFF; 998 } 999 while(--p->CacheSize != 0); 1000 p->Cache = (Byte)((UInt32)p->Low >> 24); 1001 } 1002 p->CacheSize++; 1003 p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF; 1004 } 1005 1006 static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) 1007 { 1008 p->Low += (UInt64)start * (UInt64)(p->Range /= total); 1009 p->Range *= size; 1010 while (p->Range < kTopValue) 1011 { 1012 p->Range <<= 8; 1013 RangeEnc_ShiftLow(p); 1014 } 1015 } 1016 1017 static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) 1018 { 1019 p->Range = (p->Range >> 14) * size0; 1020 while (p->Range < kTopValue) 1021 { 1022 p->Range <<= 8; 1023 RangeEnc_ShiftLow(p); 1024 } 1025 } 1026 1027 static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) 1028 { 1029 UInt32 newBound = (p->Range >> 14) * size0; 1030 p->Low += newBound; 1031 p->Range -= newBound; 1032 while (p->Range < kTopValue) 1033 { 1034 p->Range <<= 8; 1035 RangeEnc_ShiftLow(p); 1036 } 1037 } 1038 1039 static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) 1040 { 1041 unsigned i; 1042 for (i = 0; i < 5; i++) 1043 RangeEnc_ShiftLow(p); 1044 } 1045 1046 1047 #define MASK(sym) ((signed char *)charMask)[sym] 1048 1049 static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) 1050 { 1051 size_t charMask[256 / sizeof(size_t)]; 1052 if (p->MinContext->NumStats != 1) 1053 { 1054 CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 1055 UInt32 sum; 1056 unsigned i; 1057 if (s->Symbol == symbol) 1058 { 1059 RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); 1060 p->FoundState = s; 1061 Ppmd7_Update1_0(p); 1062 return; 1063 } 1064 p->PrevSuccess = 0; 1065 sum = s->Freq; 1066 i = p->MinContext->NumStats - 1; 1067 do 1068 { 1069 if ((++s)->Symbol == symbol) 1070 { 1071 RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); 1072 p->FoundState = s; 1073 Ppmd7_Update1(p); 1074 return; 1075 } 1076 sum += s->Freq; 1077 } 1078 while (--i); 1079 1080 p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 1081 PPMD_SetAllBitsIn256Bytes(charMask); 1082 MASK(s->Symbol) = 0; 1083 i = p->MinContext->NumStats - 1; 1084 do { MASK((--s)->Symbol) = 0; } while (--i); 1085 RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); 1086 } 1087 else 1088 { 1089 UInt16 *prob = Ppmd7_GetBinSumm(p); 1090 CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); 1091 if (s->Symbol == symbol) 1092 { 1093 RangeEnc_EncodeBit_0(rc, *prob); 1094 *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 1095 p->FoundState = s; 1096 Ppmd7_UpdateBin(p); 1097 return; 1098 } 1099 else 1100 { 1101 RangeEnc_EncodeBit_1(rc, *prob); 1102 *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 1103 p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 1104 PPMD_SetAllBitsIn256Bytes(charMask); 1105 MASK(s->Symbol) = 0; 1106 p->PrevSuccess = 0; 1107 } 1108 } 1109 for (;;) 1110 { 1111 UInt32 escFreq; 1112 CPpmd_See *see; 1113 CPpmd_State *s; 1114 UInt32 sum; 1115 unsigned i, numMasked = p->MinContext->NumStats; 1116 do 1117 { 1118 p->OrderFall++; 1119 if (!p->MinContext->Suffix) 1120 return; /* EndMarker (symbol = -1) */ 1121 p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 1122 } 1123 while (p->MinContext->NumStats == numMasked); 1124 1125 see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); 1126 s = Ppmd7_GetStats(p, p->MinContext); 1127 sum = 0; 1128 i = p->MinContext->NumStats; 1129 do 1130 { 1131 int cur = s->Symbol; 1132 if (cur == symbol) 1133 { 1134 UInt32 low = sum; 1135 CPpmd_State *s1 = s; 1136 do 1137 { 1138 sum += (s->Freq & (int)(MASK(s->Symbol))); 1139 s++; 1140 } 1141 while (--i); 1142 RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); 1143 Ppmd_See_Update(see); 1144 p->FoundState = s1; 1145 Ppmd7_Update2(p); 1146 return; 1147 } 1148 sum += (s->Freq & (int)(MASK(cur))); 1149 MASK(cur) = 0; 1150 s++; 1151 } 1152 while (--i); 1153 1154 RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); 1155 see->Summ = (UInt16)(see->Summ + sum + escFreq); 1156 } 1157 } 1158 1159 const IPpmd7 __archive_ppmd7_functions = 1160 { 1161 &Ppmd7_Construct, 1162 &Ppmd7_Alloc, 1163 &Ppmd7_Free, 1164 &Ppmd7_Init, 1165 &Ppmd7z_RangeDec_CreateVTable, 1166 &PpmdRAR_RangeDec_CreateVTable, 1167 &Ppmd7z_RangeDec_Init, 1168 &PpmdRAR_RangeDec_Init, 1169 &Ppmd7_DecodeSymbol, 1170 &Ppmd7z_RangeEnc_Init, 1171 &Ppmd7z_RangeEnc_FlushData, 1172 &Ppmd7_EncodeSymbol 1173 }; 1174