16c95142eSMartin Matuska /* Ppmd7.c -- PPMdH codec 26c95142eSMartin Matuska 2010-03-12 : Igor Pavlov : Public domain 36c95142eSMartin Matuska This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 46c95142eSMartin Matuska 56c95142eSMartin Matuska #include "archive_platform.h" 66c95142eSMartin Matuska 7c3afd20fSMartin Matuska #include <stdlib.h> 86c95142eSMartin Matuska 96c95142eSMartin Matuska #include "archive_ppmd7_private.h" 106c95142eSMartin Matuska 116c95142eSMartin Matuska #ifdef PPMD_32BIT 126c95142eSMartin Matuska #define Ppmd7_GetPtr(p, ptr) (ptr) 136c95142eSMartin Matuska #define Ppmd7_GetContext(p, ptr) (ptr) 146c95142eSMartin Matuska #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) 156c95142eSMartin Matuska #else 166c95142eSMartin Matuska #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) 176c95142eSMartin Matuska #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) 186c95142eSMartin Matuska #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) 196c95142eSMartin Matuska #endif 206c95142eSMartin Matuska 216c95142eSMartin Matuska #define Ppmd7_GetBinSumm(p) \ 226c95142eSMartin Matuska &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ 236c95142eSMartin Matuska p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ 246c95142eSMartin Matuska (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ 256c95142eSMartin Matuska 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ 266c95142eSMartin Matuska ((p->RunLength >> 26) & 0x20)] 276c95142eSMartin Matuska 286c95142eSMartin Matuska #define kTopValue (1 << 24) 296c95142eSMartin Matuska #define MAX_FREQ 124 306c95142eSMartin Matuska #define UNIT_SIZE 12 316c95142eSMartin Matuska 326c95142eSMartin Matuska #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) 336c95142eSMartin Matuska #define U2I(nu) (p->Units2Indx[(nu) - 1]) 346c95142eSMartin Matuska #define I2U(indx) (p->Indx2Units[indx]) 356c95142eSMartin Matuska 366c95142eSMartin Matuska #ifdef PPMD_32BIT 376c95142eSMartin Matuska #define REF(ptr) (ptr) 386c95142eSMartin Matuska #else 396c95142eSMartin Matuska #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) 406c95142eSMartin Matuska #endif 416c95142eSMartin Matuska 426c95142eSMartin Matuska #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) 436c95142eSMartin Matuska 446c95142eSMartin Matuska #define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) 456c95142eSMartin Matuska #define STATS(ctx) Ppmd7_GetStats(p, ctx) 466c95142eSMartin Matuska #define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) 476c95142eSMartin Matuska #define SUFFIX(ctx) CTX((ctx)->Suffix) 486c95142eSMartin Matuska 496c95142eSMartin Matuska static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; 506c95142eSMartin Matuska static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 516c95142eSMartin Matuska 526c95142eSMartin Matuska typedef CPpmd7_Context * CTX_PTR; 536c95142eSMartin Matuska 546c95142eSMartin Matuska struct CPpmd7_Node_; 556c95142eSMartin Matuska 566c95142eSMartin Matuska typedef 576c95142eSMartin Matuska #ifdef PPMD_32BIT 586c95142eSMartin Matuska struct CPpmd7_Node_ * 596c95142eSMartin Matuska #else 606c95142eSMartin Matuska UInt32 616c95142eSMartin Matuska #endif 626c95142eSMartin Matuska CPpmd7_Node_Ref; 636c95142eSMartin Matuska 646c95142eSMartin Matuska typedef struct CPpmd7_Node_ 656c95142eSMartin Matuska { 666c95142eSMartin Matuska UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ 676c95142eSMartin Matuska UInt16 NU; 686c95142eSMartin Matuska CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ 696c95142eSMartin Matuska CPpmd7_Node_Ref Prev; 706c95142eSMartin Matuska } CPpmd7_Node; 716c95142eSMartin Matuska 726c95142eSMartin Matuska #ifdef PPMD_32BIT 736c95142eSMartin Matuska #define NODE(ptr) (ptr) 746c95142eSMartin Matuska #else 756c95142eSMartin Matuska #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) 766c95142eSMartin Matuska #endif 776c95142eSMartin Matuska 786c95142eSMartin Matuska static void Ppmd7_Update1(CPpmd7 *p); 796c95142eSMartin Matuska static void Ppmd7_Update1_0(CPpmd7 *p); 806c95142eSMartin Matuska static void Ppmd7_Update2(CPpmd7 *p); 816c95142eSMartin Matuska static void Ppmd7_UpdateBin(CPpmd7 *p); 826c95142eSMartin Matuska static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, 836c95142eSMartin Matuska UInt32 *scale); 846c95142eSMartin Matuska 856c95142eSMartin Matuska /* ----------- Base ----------- */ 866c95142eSMartin Matuska 876c95142eSMartin Matuska static void Ppmd7_Construct(CPpmd7 *p) 886c95142eSMartin Matuska { 896c95142eSMartin Matuska unsigned i, k, m; 906c95142eSMartin Matuska 916c95142eSMartin Matuska p->Base = 0; 926c95142eSMartin Matuska 936c95142eSMartin Matuska for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) 946c95142eSMartin Matuska { 956c95142eSMartin Matuska unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); 966c95142eSMartin Matuska do { p->Units2Indx[k++] = (Byte)i; } while(--step); 976c95142eSMartin Matuska p->Indx2Units[i] = (Byte)k; 986c95142eSMartin Matuska } 996c95142eSMartin Matuska 1006c95142eSMartin Matuska p->NS2BSIndx[0] = (0 << 1); 1016c95142eSMartin Matuska p->NS2BSIndx[1] = (1 << 1); 1026c95142eSMartin Matuska memset(p->NS2BSIndx + 2, (2 << 1), 9); 1036c95142eSMartin Matuska memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); 1046c95142eSMartin Matuska 1056c95142eSMartin Matuska for (i = 0; i < 3; i++) 1066c95142eSMartin Matuska p->NS2Indx[i] = (Byte)i; 1076c95142eSMartin Matuska for (m = i, k = 1; i < 256; i++) 1086c95142eSMartin Matuska { 1096c95142eSMartin Matuska p->NS2Indx[i] = (Byte)m; 1106c95142eSMartin Matuska if (--k == 0) 1116c95142eSMartin Matuska k = (++m) - 2; 1126c95142eSMartin Matuska } 1136c95142eSMartin Matuska 1146c95142eSMartin Matuska memset(p->HB2Flag, 0, 0x40); 1156c95142eSMartin Matuska memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); 1166c95142eSMartin Matuska } 1176c95142eSMartin Matuska 118a2a3407cSMartin Matuska static void Ppmd7_Free(CPpmd7 *p) 1196c95142eSMartin Matuska { 120a2a3407cSMartin Matuska free(p->Base); 1216c95142eSMartin Matuska p->Size = 0; 1226c95142eSMartin Matuska p->Base = 0; 1236c95142eSMartin Matuska } 1246c95142eSMartin Matuska 125a2a3407cSMartin Matuska static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size) 1266c95142eSMartin Matuska { 1276c95142eSMartin Matuska if (p->Base == 0 || p->Size != size) 1286c95142eSMartin Matuska { 129f061a221SMartin Matuska /* RestartModel() below assumes that p->Size >= UNIT_SIZE 130f061a221SMartin Matuska (see the calculation of m->MinContext). */ 131f061a221SMartin Matuska if (size < UNIT_SIZE) { 132f061a221SMartin Matuska return False; 133f061a221SMartin Matuska } 134a2a3407cSMartin Matuska Ppmd7_Free(p); 1356c95142eSMartin Matuska p->AlignOffset = 1366c95142eSMartin Matuska #ifdef PPMD_32BIT 1376c95142eSMartin Matuska (4 - size) & 3; 1386c95142eSMartin Matuska #else 1396c95142eSMartin Matuska 4 - (size & 3); 1406c95142eSMartin Matuska #endif 141*bd66c1b4SMartin Matuska if ((p->Base = malloc(p->AlignOffset + size 1426c95142eSMartin Matuska #ifndef PPMD_32BIT 1436c95142eSMartin Matuska + UNIT_SIZE 1446c95142eSMartin Matuska #endif 1456c95142eSMartin Matuska )) == 0) 1466c95142eSMartin Matuska return False; 1476c95142eSMartin Matuska p->Size = size; 1486c95142eSMartin Matuska } 1496c95142eSMartin Matuska return True; 1506c95142eSMartin Matuska } 1516c95142eSMartin Matuska 1526c95142eSMartin Matuska static void InsertNode(CPpmd7 *p, void *node, unsigned indx) 1536c95142eSMartin Matuska { 1546c95142eSMartin Matuska *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; 1556c95142eSMartin Matuska p->FreeList[indx] = REF(node); 1566c95142eSMartin Matuska } 1576c95142eSMartin Matuska 1586c95142eSMartin Matuska static void *RemoveNode(CPpmd7 *p, unsigned indx) 1596c95142eSMartin Matuska { 1606c95142eSMartin Matuska CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); 1616c95142eSMartin Matuska p->FreeList[indx] = *node; 1626c95142eSMartin Matuska return node; 1636c95142eSMartin Matuska } 1646c95142eSMartin Matuska 1656c95142eSMartin Matuska static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) 1666c95142eSMartin Matuska { 1676c95142eSMartin Matuska unsigned i, nu = I2U(oldIndx) - I2U(newIndx); 1686c95142eSMartin Matuska ptr = (Byte *)ptr + U2B(I2U(newIndx)); 1696c95142eSMartin Matuska if (I2U(i = U2I(nu)) != nu) 1706c95142eSMartin Matuska { 1716c95142eSMartin Matuska unsigned k = I2U(--i); 1726c95142eSMartin Matuska InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); 1736c95142eSMartin Matuska } 1746c95142eSMartin Matuska InsertNode(p, ptr, i); 1756c95142eSMartin Matuska } 1766c95142eSMartin Matuska 1776c95142eSMartin Matuska static void GlueFreeBlocks(CPpmd7 *p) 1786c95142eSMartin Matuska { 1796c95142eSMartin Matuska #ifdef PPMD_32BIT 1806c95142eSMartin Matuska CPpmd7_Node headItem; 1816c95142eSMartin Matuska CPpmd7_Node_Ref head = &headItem; 1826c95142eSMartin Matuska #else 1836c95142eSMartin Matuska CPpmd7_Node_Ref head = p->AlignOffset + p->Size; 1846c95142eSMartin Matuska #endif 1856c95142eSMartin Matuska 1866c95142eSMartin Matuska CPpmd7_Node_Ref n = head; 1876c95142eSMartin Matuska unsigned i; 1886c95142eSMartin Matuska 1896c95142eSMartin Matuska p->GlueCount = 255; 1906c95142eSMartin Matuska 1916c95142eSMartin Matuska /* create doubly-linked list of free blocks */ 1926c95142eSMartin Matuska for (i = 0; i < PPMD_NUM_INDEXES; i++) 1936c95142eSMartin Matuska { 1946c95142eSMartin Matuska UInt16 nu = I2U(i); 1956c95142eSMartin Matuska CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; 1966c95142eSMartin Matuska p->FreeList[i] = 0; 1976c95142eSMartin Matuska while (next != 0) 1986c95142eSMartin Matuska { 1996c95142eSMartin Matuska CPpmd7_Node *node = NODE(next); 2006c95142eSMartin Matuska node->Next = n; 2016c95142eSMartin Matuska n = NODE(n)->Prev = next; 2026c95142eSMartin Matuska next = *(const CPpmd7_Node_Ref *)node; 2036c95142eSMartin Matuska node->Stamp = 0; 2046c95142eSMartin Matuska node->NU = (UInt16)nu; 2056c95142eSMartin Matuska } 2066c95142eSMartin Matuska } 2076c95142eSMartin Matuska NODE(head)->Stamp = 1; 2086c95142eSMartin Matuska NODE(head)->Next = n; 2096c95142eSMartin Matuska NODE(n)->Prev = head; 2106c95142eSMartin Matuska if (p->LoUnit != p->HiUnit) 2116c95142eSMartin Matuska ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; 2126c95142eSMartin Matuska 2136c95142eSMartin Matuska /* Glue free blocks */ 2146c95142eSMartin Matuska while (n != head) 2156c95142eSMartin Matuska { 2166c95142eSMartin Matuska CPpmd7_Node *node = NODE(n); 2176c95142eSMartin Matuska UInt32 nu = (UInt32)node->NU; 2186c95142eSMartin Matuska for (;;) 2196c95142eSMartin Matuska { 2206c95142eSMartin Matuska CPpmd7_Node *node2 = NODE(n) + nu; 2216c95142eSMartin Matuska nu += node2->NU; 2226c95142eSMartin Matuska if (node2->Stamp != 0 || nu >= 0x10000) 2236c95142eSMartin Matuska break; 2246c95142eSMartin Matuska NODE(node2->Prev)->Next = node2->Next; 2256c95142eSMartin Matuska NODE(node2->Next)->Prev = node2->Prev; 2266c95142eSMartin Matuska node->NU = (UInt16)nu; 2276c95142eSMartin Matuska } 2286c95142eSMartin Matuska n = node->Next; 2296c95142eSMartin Matuska } 2306c95142eSMartin Matuska 2316c95142eSMartin Matuska /* Fill lists of free blocks */ 2326c95142eSMartin Matuska for (n = NODE(head)->Next; n != head;) 2336c95142eSMartin Matuska { 2346c95142eSMartin Matuska CPpmd7_Node *node = NODE(n); 2356c95142eSMartin Matuska unsigned nu; 2366c95142eSMartin Matuska CPpmd7_Node_Ref next = node->Next; 2376c95142eSMartin Matuska for (nu = node->NU; nu > 128; nu -= 128, node += 128) 2386c95142eSMartin Matuska InsertNode(p, node, PPMD_NUM_INDEXES - 1); 2396c95142eSMartin Matuska if (I2U(i = U2I(nu)) != nu) 2406c95142eSMartin Matuska { 2416c95142eSMartin Matuska unsigned k = I2U(--i); 2426c95142eSMartin Matuska InsertNode(p, node + k, nu - k - 1); 2436c95142eSMartin Matuska } 2446c95142eSMartin Matuska InsertNode(p, node, i); 2456c95142eSMartin Matuska n = next; 2466c95142eSMartin Matuska } 2476c95142eSMartin Matuska } 2486c95142eSMartin Matuska 2496c95142eSMartin Matuska static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) 2506c95142eSMartin Matuska { 2516c95142eSMartin Matuska unsigned i; 2526c95142eSMartin Matuska void *retVal; 2536c95142eSMartin Matuska if (p->GlueCount == 0) 2546c95142eSMartin Matuska { 2556c95142eSMartin Matuska GlueFreeBlocks(p); 2566c95142eSMartin Matuska if (p->FreeList[indx] != 0) 2576c95142eSMartin Matuska return RemoveNode(p, indx); 2586c95142eSMartin Matuska } 2596c95142eSMartin Matuska i = indx; 2606c95142eSMartin Matuska do 2616c95142eSMartin Matuska { 2626c95142eSMartin Matuska if (++i == PPMD_NUM_INDEXES) 2636c95142eSMartin Matuska { 2646c95142eSMartin Matuska UInt32 numBytes = U2B(I2U(indx)); 2656c95142eSMartin Matuska p->GlueCount--; 2666c95142eSMartin Matuska return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); 2676c95142eSMartin Matuska } 2686c95142eSMartin Matuska } 2696c95142eSMartin Matuska while (p->FreeList[i] == 0); 2706c95142eSMartin Matuska retVal = RemoveNode(p, i); 2716c95142eSMartin Matuska SplitBlock(p, retVal, i, indx); 2726c95142eSMartin Matuska return retVal; 2736c95142eSMartin Matuska } 2746c95142eSMartin Matuska 2756c95142eSMartin Matuska static void *AllocUnits(CPpmd7 *p, unsigned indx) 2766c95142eSMartin Matuska { 2776c95142eSMartin Matuska UInt32 numBytes; 2786c95142eSMartin Matuska if (p->FreeList[indx] != 0) 2796c95142eSMartin Matuska return RemoveNode(p, indx); 2806c95142eSMartin Matuska numBytes = U2B(I2U(indx)); 2816c95142eSMartin Matuska if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) 2826c95142eSMartin Matuska { 2836c95142eSMartin Matuska void *retVal = p->LoUnit; 2846c95142eSMartin Matuska p->LoUnit += numBytes; 2856c95142eSMartin Matuska return retVal; 2866c95142eSMartin Matuska } 2876c95142eSMartin Matuska return AllocUnitsRare(p, indx); 2886c95142eSMartin Matuska } 2896c95142eSMartin Matuska 2906c95142eSMartin Matuska #define MyMem12Cpy(dest, src, num) \ 2916c95142eSMartin Matuska { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ 2926c95142eSMartin Matuska do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } 2936c95142eSMartin Matuska 2946c95142eSMartin Matuska static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) 2956c95142eSMartin Matuska { 2966c95142eSMartin Matuska unsigned i0 = U2I(oldNU); 2976c95142eSMartin Matuska unsigned i1 = U2I(newNU); 2986c95142eSMartin Matuska if (i0 == i1) 2996c95142eSMartin Matuska return oldPtr; 3006c95142eSMartin Matuska if (p->FreeList[i1] != 0) 3016c95142eSMartin Matuska { 3026c95142eSMartin Matuska void *ptr = RemoveNode(p, i1); 3036c95142eSMartin Matuska MyMem12Cpy(ptr, oldPtr, newNU); 3046c95142eSMartin Matuska InsertNode(p, oldPtr, i0); 3056c95142eSMartin Matuska return ptr; 3066c95142eSMartin Matuska } 3076c95142eSMartin Matuska SplitBlock(p, oldPtr, i0, i1); 3086c95142eSMartin Matuska return oldPtr; 3096c95142eSMartin Matuska } 3106c95142eSMartin Matuska 3116c95142eSMartin Matuska #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) 3126c95142eSMartin Matuska 3136c95142eSMartin Matuska static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) 3146c95142eSMartin Matuska { 3156c95142eSMartin Matuska (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); 3166c95142eSMartin Matuska (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); 3176c95142eSMartin Matuska } 3186c95142eSMartin Matuska 3196c95142eSMartin Matuska static void RestartModel(CPpmd7 *p) 3206c95142eSMartin Matuska { 3216c95142eSMartin Matuska unsigned i, k, m; 3226c95142eSMartin Matuska 3236c95142eSMartin Matuska memset(p->FreeList, 0, sizeof(p->FreeList)); 3246c95142eSMartin Matuska p->Text = p->Base + p->AlignOffset; 3256c95142eSMartin Matuska p->HiUnit = p->Text + p->Size; 3266c95142eSMartin Matuska p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; 3276c95142eSMartin Matuska p->GlueCount = 0; 3286c95142eSMartin Matuska 3296c95142eSMartin Matuska p->OrderFall = p->MaxOrder; 3306c95142eSMartin Matuska p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; 3316c95142eSMartin Matuska p->PrevSuccess = 0; 3326c95142eSMartin Matuska 3336c95142eSMartin Matuska p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ 3346c95142eSMartin Matuska p->MinContext->Suffix = 0; 3356c95142eSMartin Matuska p->MinContext->NumStats = 256; 3366c95142eSMartin Matuska p->MinContext->SummFreq = 256 + 1; 3376c95142eSMartin Matuska p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ 3386c95142eSMartin Matuska p->LoUnit += U2B(256 / 2); 3396c95142eSMartin Matuska p->MinContext->Stats = REF(p->FoundState); 3406c95142eSMartin Matuska for (i = 0; i < 256; i++) 3416c95142eSMartin Matuska { 3426c95142eSMartin Matuska CPpmd_State *s = &p->FoundState[i]; 3436c95142eSMartin Matuska s->Symbol = (Byte)i; 3446c95142eSMartin Matuska s->Freq = 1; 3456c95142eSMartin Matuska SetSuccessor(s, 0); 3466c95142eSMartin Matuska } 3476c95142eSMartin Matuska 3486c95142eSMartin Matuska for (i = 0; i < 128; i++) 3496c95142eSMartin Matuska for (k = 0; k < 8; k++) 3506c95142eSMartin Matuska { 3516c95142eSMartin Matuska UInt16 *dest = p->BinSumm[i] + k; 3526c95142eSMartin Matuska UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); 3536c95142eSMartin Matuska for (m = 0; m < 64; m += 8) 3546c95142eSMartin Matuska dest[m] = val; 3556c95142eSMartin Matuska } 3566c95142eSMartin Matuska 3576c95142eSMartin Matuska for (i = 0; i < 25; i++) 3586c95142eSMartin Matuska for (k = 0; k < 16; k++) 3596c95142eSMartin Matuska { 3606c95142eSMartin Matuska CPpmd_See *s = &p->See[i][k]; 3616c95142eSMartin Matuska s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); 3626c95142eSMartin Matuska s->Count = 4; 3636c95142eSMartin Matuska } 3646c95142eSMartin Matuska } 3656c95142eSMartin Matuska 3666c95142eSMartin Matuska static void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) 3676c95142eSMartin Matuska { 3686c95142eSMartin Matuska p->MaxOrder = maxOrder; 3696c95142eSMartin Matuska RestartModel(p); 3706c95142eSMartin Matuska p->DummySee.Shift = PPMD_PERIOD_BITS; 3716c95142eSMartin Matuska p->DummySee.Summ = 0; /* unused */ 3726c95142eSMartin Matuska p->DummySee.Count = 64; /* unused */ 3736c95142eSMartin Matuska } 3746c95142eSMartin Matuska 3756c95142eSMartin Matuska static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) 3766c95142eSMartin Matuska { 3776c95142eSMartin Matuska CPpmd_State upState; 3786c95142eSMartin Matuska CTX_PTR c = p->MinContext; 3796c95142eSMartin Matuska CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); 3806c95142eSMartin Matuska CPpmd_State *ps[PPMD7_MAX_ORDER]; 3816c95142eSMartin Matuska unsigned numPs = 0; 3826c95142eSMartin Matuska 3836c95142eSMartin Matuska if (!skip) 3846c95142eSMartin Matuska ps[numPs++] = p->FoundState; 3856c95142eSMartin Matuska 3866c95142eSMartin Matuska while (c->Suffix) 3876c95142eSMartin Matuska { 3886c95142eSMartin Matuska CPpmd_Void_Ref successor; 3896c95142eSMartin Matuska CPpmd_State *s; 3906c95142eSMartin Matuska c = SUFFIX(c); 3916c95142eSMartin Matuska if (c->NumStats != 1) 3926c95142eSMartin Matuska { 3936c95142eSMartin Matuska for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); 3946c95142eSMartin Matuska } 3956c95142eSMartin Matuska else 3966c95142eSMartin Matuska s = ONE_STATE(c); 3976c95142eSMartin Matuska successor = SUCCESSOR(s); 3986c95142eSMartin Matuska if (successor != upBranch) 3996c95142eSMartin Matuska { 4006c95142eSMartin Matuska c = CTX(successor); 4016c95142eSMartin Matuska if (numPs == 0) 4026c95142eSMartin Matuska return c; 4036c95142eSMartin Matuska break; 4046c95142eSMartin Matuska } 4056c95142eSMartin Matuska ps[numPs++] = s; 4066c95142eSMartin Matuska } 4076c95142eSMartin Matuska 4086c95142eSMartin Matuska upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); 4096c95142eSMartin Matuska SetSuccessor(&upState, upBranch + 1); 4106c95142eSMartin Matuska 4116c95142eSMartin Matuska if (c->NumStats == 1) 4126c95142eSMartin Matuska upState.Freq = ONE_STATE(c)->Freq; 4136c95142eSMartin Matuska else 4146c95142eSMartin Matuska { 4156c95142eSMartin Matuska UInt32 cf, s0; 4166c95142eSMartin Matuska CPpmd_State *s; 4176c95142eSMartin Matuska for (s = STATS(c); s->Symbol != upState.Symbol; s++); 4186c95142eSMartin Matuska cf = s->Freq - 1; 4196c95142eSMartin Matuska s0 = c->SummFreq - c->NumStats - cf; 4206c95142eSMartin Matuska upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); 4216c95142eSMartin Matuska } 4226c95142eSMartin Matuska 423fd082e96SMartin Matuska while (numPs != 0) 4246c95142eSMartin Matuska { 4256c95142eSMartin Matuska /* Create Child */ 4266c95142eSMartin Matuska CTX_PTR c1; /* = AllocContext(p); */ 4276c95142eSMartin Matuska if (p->HiUnit != p->LoUnit) 4286c95142eSMartin Matuska c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); 4296c95142eSMartin Matuska else if (p->FreeList[0] != 0) 4306c95142eSMartin Matuska c1 = (CTX_PTR)RemoveNode(p, 0); 4316c95142eSMartin Matuska else 4326c95142eSMartin Matuska { 4336c95142eSMartin Matuska c1 = (CTX_PTR)AllocUnitsRare(p, 0); 4346c95142eSMartin Matuska if (!c1) 4356c95142eSMartin Matuska return NULL; 4366c95142eSMartin Matuska } 4376c95142eSMartin Matuska c1->NumStats = 1; 4386c95142eSMartin Matuska *ONE_STATE(c1) = upState; 4396c95142eSMartin Matuska c1->Suffix = REF(c); 4406c95142eSMartin Matuska SetSuccessor(ps[--numPs], REF(c1)); 4416c95142eSMartin Matuska c = c1; 4426c95142eSMartin Matuska } 4436c95142eSMartin Matuska 4446c95142eSMartin Matuska return c; 4456c95142eSMartin Matuska } 4466c95142eSMartin Matuska 4476c95142eSMartin Matuska static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) 4486c95142eSMartin Matuska { 4496c95142eSMartin Matuska CPpmd_State tmp = *t1; 4506c95142eSMartin Matuska *t1 = *t2; 4516c95142eSMartin Matuska *t2 = tmp; 4526c95142eSMartin Matuska } 4536c95142eSMartin Matuska 4546c95142eSMartin Matuska static void UpdateModel(CPpmd7 *p) 4556c95142eSMartin Matuska { 4566c95142eSMartin Matuska CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); 4576c95142eSMartin Matuska CTX_PTR c; 4586c95142eSMartin Matuska unsigned s0, ns; 4596c95142eSMartin Matuska 4606c95142eSMartin Matuska if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) 4616c95142eSMartin Matuska { 4626c95142eSMartin Matuska c = SUFFIX(p->MinContext); 4636c95142eSMartin Matuska 4646c95142eSMartin Matuska if (c->NumStats == 1) 4656c95142eSMartin Matuska { 4666c95142eSMartin Matuska CPpmd_State *s = ONE_STATE(c); 4676c95142eSMartin Matuska if (s->Freq < 32) 4686c95142eSMartin Matuska s->Freq++; 4696c95142eSMartin Matuska } 4706c95142eSMartin Matuska else 4716c95142eSMartin Matuska { 4726c95142eSMartin Matuska CPpmd_State *s = STATS(c); 4736c95142eSMartin Matuska if (s->Symbol != p->FoundState->Symbol) 4746c95142eSMartin Matuska { 4756c95142eSMartin Matuska do { s++; } while (s->Symbol != p->FoundState->Symbol); 4766c95142eSMartin Matuska if (s[0].Freq >= s[-1].Freq) 4776c95142eSMartin Matuska { 4786c95142eSMartin Matuska SwapStates(&s[0], &s[-1]); 4796c95142eSMartin Matuska s--; 4806c95142eSMartin Matuska } 4816c95142eSMartin Matuska } 4826c95142eSMartin Matuska if (s->Freq < MAX_FREQ - 9) 4836c95142eSMartin Matuska { 4846c95142eSMartin Matuska s->Freq += 2; 4856c95142eSMartin Matuska c->SummFreq += 2; 4866c95142eSMartin Matuska } 4876c95142eSMartin Matuska } 4886c95142eSMartin Matuska } 4896c95142eSMartin Matuska 4906c95142eSMartin Matuska if (p->OrderFall == 0) 4916c95142eSMartin Matuska { 4926c95142eSMartin Matuska p->MinContext = p->MaxContext = CreateSuccessors(p, True); 4936c95142eSMartin Matuska if (p->MinContext == 0) 4946c95142eSMartin Matuska { 4956c95142eSMartin Matuska RestartModel(p); 4966c95142eSMartin Matuska return; 4976c95142eSMartin Matuska } 4986c95142eSMartin Matuska SetSuccessor(p->FoundState, REF(p->MinContext)); 4996c95142eSMartin Matuska return; 5006c95142eSMartin Matuska } 5016c95142eSMartin Matuska 5026c95142eSMartin Matuska *p->Text++ = p->FoundState->Symbol; 5036c95142eSMartin Matuska successor = REF(p->Text); 5046c95142eSMartin Matuska if (p->Text >= p->UnitsStart) 5056c95142eSMartin Matuska { 5066c95142eSMartin Matuska RestartModel(p); 5076c95142eSMartin Matuska return; 5086c95142eSMartin Matuska } 5096c95142eSMartin Matuska 5106c95142eSMartin Matuska if (fSuccessor) 5116c95142eSMartin Matuska { 5126c95142eSMartin Matuska if (fSuccessor <= successor) 5136c95142eSMartin Matuska { 5146c95142eSMartin Matuska CTX_PTR cs = CreateSuccessors(p, False); 5156c95142eSMartin Matuska if (cs == NULL) 5166c95142eSMartin Matuska { 5176c95142eSMartin Matuska RestartModel(p); 5186c95142eSMartin Matuska return; 5196c95142eSMartin Matuska } 5206c95142eSMartin Matuska fSuccessor = REF(cs); 5216c95142eSMartin Matuska } 5226c95142eSMartin Matuska if (--p->OrderFall == 0) 5236c95142eSMartin Matuska { 5246c95142eSMartin Matuska successor = fSuccessor; 5256c95142eSMartin Matuska p->Text -= (p->MaxContext != p->MinContext); 5266c95142eSMartin Matuska } 5276c95142eSMartin Matuska } 5286c95142eSMartin Matuska else 5296c95142eSMartin Matuska { 5306c95142eSMartin Matuska SetSuccessor(p->FoundState, successor); 5316c95142eSMartin Matuska fSuccessor = REF(p->MinContext); 5326c95142eSMartin Matuska } 5336c95142eSMartin Matuska 5346c95142eSMartin Matuska s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); 5356c95142eSMartin Matuska 5366c95142eSMartin Matuska for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) 5376c95142eSMartin Matuska { 5386c95142eSMartin Matuska unsigned ns1; 5396c95142eSMartin Matuska UInt32 cf, sf; 5406c95142eSMartin Matuska if ((ns1 = c->NumStats) != 1) 5416c95142eSMartin Matuska { 5426c95142eSMartin Matuska if ((ns1 & 1) == 0) 5436c95142eSMartin Matuska { 5446c95142eSMartin Matuska /* Expand for one UNIT */ 5456c95142eSMartin Matuska unsigned oldNU = ns1 >> 1; 5466c95142eSMartin Matuska unsigned i = U2I(oldNU); 5476c95142eSMartin Matuska if (i != U2I(oldNU + 1)) 5486c95142eSMartin Matuska { 5496c95142eSMartin Matuska void *ptr = AllocUnits(p, i + 1); 5506c95142eSMartin Matuska void *oldPtr; 5516c95142eSMartin Matuska if (!ptr) 5526c95142eSMartin Matuska { 5536c95142eSMartin Matuska RestartModel(p); 5546c95142eSMartin Matuska return; 5556c95142eSMartin Matuska } 5566c95142eSMartin Matuska oldPtr = STATS(c); 5576c95142eSMartin Matuska MyMem12Cpy(ptr, oldPtr, oldNU); 5586c95142eSMartin Matuska InsertNode(p, oldPtr, i); 5596c95142eSMartin Matuska c->Stats = STATS_REF(ptr); 5606c95142eSMartin Matuska } 5616c95142eSMartin Matuska } 5626c95142eSMartin Matuska c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); 5636c95142eSMartin Matuska } 5646c95142eSMartin Matuska else 5656c95142eSMartin Matuska { 5666c95142eSMartin Matuska CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); 5676c95142eSMartin Matuska if (!s) 5686c95142eSMartin Matuska { 5696c95142eSMartin Matuska RestartModel(p); 5706c95142eSMartin Matuska return; 5716c95142eSMartin Matuska } 5726c95142eSMartin Matuska *s = *ONE_STATE(c); 5736c95142eSMartin Matuska c->Stats = REF(s); 5746c95142eSMartin Matuska if (s->Freq < MAX_FREQ / 4 - 1) 5756c95142eSMartin Matuska s->Freq <<= 1; 5766c95142eSMartin Matuska else 5776c95142eSMartin Matuska s->Freq = MAX_FREQ - 4; 5786c95142eSMartin Matuska c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); 5796c95142eSMartin Matuska } 5806c95142eSMartin Matuska cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); 5816c95142eSMartin Matuska sf = (UInt32)s0 + c->SummFreq; 5826c95142eSMartin Matuska if (cf < 6 * sf) 5836c95142eSMartin Matuska { 5846c95142eSMartin Matuska cf = 1 + (cf > sf) + (cf >= 4 * sf); 5856c95142eSMartin Matuska c->SummFreq += 3; 5866c95142eSMartin Matuska } 5876c95142eSMartin Matuska else 5886c95142eSMartin Matuska { 5896c95142eSMartin Matuska cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); 5906c95142eSMartin Matuska c->SummFreq = (UInt16)(c->SummFreq + cf); 5916c95142eSMartin Matuska } 5926c95142eSMartin Matuska { 5936c95142eSMartin Matuska CPpmd_State *s = STATS(c) + ns1; 5946c95142eSMartin Matuska SetSuccessor(s, successor); 5956c95142eSMartin Matuska s->Symbol = p->FoundState->Symbol; 5966c95142eSMartin Matuska s->Freq = (Byte)cf; 5976c95142eSMartin Matuska c->NumStats = (UInt16)(ns1 + 1); 5986c95142eSMartin Matuska } 5996c95142eSMartin Matuska } 6006c95142eSMartin Matuska p->MaxContext = p->MinContext = CTX(fSuccessor); 6016c95142eSMartin Matuska } 6026c95142eSMartin Matuska 6036c95142eSMartin Matuska static void Rescale(CPpmd7 *p) 6046c95142eSMartin Matuska { 6056c95142eSMartin Matuska unsigned i, adder, sumFreq, escFreq; 6066c95142eSMartin Matuska CPpmd_State *stats = STATS(p->MinContext); 6076c95142eSMartin Matuska CPpmd_State *s = p->FoundState; 6086c95142eSMartin Matuska { 6096c95142eSMartin Matuska CPpmd_State tmp = *s; 6106c95142eSMartin Matuska for (; s != stats; s--) 6116c95142eSMartin Matuska s[0] = s[-1]; 6126c95142eSMartin Matuska *s = tmp; 6136c95142eSMartin Matuska } 6146c95142eSMartin Matuska escFreq = p->MinContext->SummFreq - s->Freq; 6156c95142eSMartin Matuska s->Freq += 4; 6166c95142eSMartin Matuska adder = (p->OrderFall != 0); 6176c95142eSMartin Matuska s->Freq = (Byte)((s->Freq + adder) >> 1); 6186c95142eSMartin Matuska sumFreq = s->Freq; 6196c95142eSMartin Matuska 6206c95142eSMartin Matuska i = p->MinContext->NumStats - 1; 6216c95142eSMartin Matuska do 6226c95142eSMartin Matuska { 6236c95142eSMartin Matuska escFreq -= (++s)->Freq; 6246c95142eSMartin Matuska s->Freq = (Byte)((s->Freq + adder) >> 1); 6256c95142eSMartin Matuska sumFreq += s->Freq; 6266c95142eSMartin Matuska if (s[0].Freq > s[-1].Freq) 6276c95142eSMartin Matuska { 6286c95142eSMartin Matuska CPpmd_State *s1 = s; 6296c95142eSMartin Matuska CPpmd_State tmp = *s1; 6306c95142eSMartin Matuska do 6316c95142eSMartin Matuska s1[0] = s1[-1]; 6326c95142eSMartin Matuska while (--s1 != stats && tmp.Freq > s1[-1].Freq); 6336c95142eSMartin Matuska *s1 = tmp; 6346c95142eSMartin Matuska } 6356c95142eSMartin Matuska } 6366c95142eSMartin Matuska while (--i); 6376c95142eSMartin Matuska 6386c95142eSMartin Matuska if (s->Freq == 0) 6396c95142eSMartin Matuska { 6406c95142eSMartin Matuska unsigned numStats = p->MinContext->NumStats; 6416c95142eSMartin Matuska unsigned n0, n1; 6426c95142eSMartin Matuska do { i++; } while ((--s)->Freq == 0); 6436c95142eSMartin Matuska escFreq += i; 6446c95142eSMartin Matuska p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); 6456c95142eSMartin Matuska if (p->MinContext->NumStats == 1) 6466c95142eSMartin Matuska { 6476c95142eSMartin Matuska CPpmd_State tmp = *stats; 6486c95142eSMartin Matuska do 6496c95142eSMartin Matuska { 6506c95142eSMartin Matuska tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); 6516c95142eSMartin Matuska escFreq >>= 1; 6526c95142eSMartin Matuska } 6536c95142eSMartin Matuska while (escFreq > 1); 6546c95142eSMartin Matuska InsertNode(p, stats, U2I(((numStats + 1) >> 1))); 6556c95142eSMartin Matuska *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; 6566c95142eSMartin Matuska return; 6576c95142eSMartin Matuska } 6586c95142eSMartin Matuska n0 = (numStats + 1) >> 1; 6596c95142eSMartin Matuska n1 = (p->MinContext->NumStats + 1) >> 1; 6606c95142eSMartin Matuska if (n0 != n1) 6616c95142eSMartin Matuska p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); 6626c95142eSMartin Matuska } 6636c95142eSMartin Matuska p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); 6646c95142eSMartin Matuska p->FoundState = STATS(p->MinContext); 6656c95142eSMartin Matuska } 6666c95142eSMartin Matuska 6676c95142eSMartin Matuska static CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) 6686c95142eSMartin Matuska { 6696c95142eSMartin Matuska CPpmd_See *see; 6706c95142eSMartin Matuska unsigned nonMasked = p->MinContext->NumStats - numMasked; 6716c95142eSMartin Matuska if (p->MinContext->NumStats != 256) 6726c95142eSMartin Matuska { 6736c95142eSMartin Matuska see = p->See[p->NS2Indx[nonMasked - 1]] + 6746c95142eSMartin Matuska (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + 6756c95142eSMartin Matuska 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + 6766c95142eSMartin Matuska 4 * (numMasked > nonMasked) + 6776c95142eSMartin Matuska p->HiBitsFlag; 6786c95142eSMartin Matuska { 6796c95142eSMartin Matuska unsigned r = (see->Summ >> see->Shift); 6806c95142eSMartin Matuska see->Summ = (UInt16)(see->Summ - r); 6816c95142eSMartin Matuska *escFreq = r + (r == 0); 6826c95142eSMartin Matuska } 6836c95142eSMartin Matuska } 6846c95142eSMartin Matuska else 6856c95142eSMartin Matuska { 6866c95142eSMartin Matuska see = &p->DummySee; 6876c95142eSMartin Matuska *escFreq = 1; 6886c95142eSMartin Matuska } 6896c95142eSMartin Matuska return see; 6906c95142eSMartin Matuska } 6916c95142eSMartin Matuska 6926c95142eSMartin Matuska static void NextContext(CPpmd7 *p) 6936c95142eSMartin Matuska { 6946c95142eSMartin Matuska CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); 6956c95142eSMartin Matuska if (p->OrderFall == 0 && (Byte *)c > p->Text) 6966c95142eSMartin Matuska p->MinContext = p->MaxContext = c; 6976c95142eSMartin Matuska else 6986c95142eSMartin Matuska UpdateModel(p); 6996c95142eSMartin Matuska } 7006c95142eSMartin Matuska 7016c95142eSMartin Matuska static void Ppmd7_Update1(CPpmd7 *p) 7026c95142eSMartin Matuska { 7036c95142eSMartin Matuska CPpmd_State *s = p->FoundState; 7046c95142eSMartin Matuska s->Freq += 4; 7056c95142eSMartin Matuska p->MinContext->SummFreq += 4; 7066c95142eSMartin Matuska if (s[0].Freq > s[-1].Freq) 7076c95142eSMartin Matuska { 7086c95142eSMartin Matuska SwapStates(&s[0], &s[-1]); 7096c95142eSMartin Matuska p->FoundState = --s; 7106c95142eSMartin Matuska if (s->Freq > MAX_FREQ) 7116c95142eSMartin Matuska Rescale(p); 7126c95142eSMartin Matuska } 7136c95142eSMartin Matuska NextContext(p); 7146c95142eSMartin Matuska } 7156c95142eSMartin Matuska 7166c95142eSMartin Matuska static void Ppmd7_Update1_0(CPpmd7 *p) 7176c95142eSMartin Matuska { 7186c95142eSMartin Matuska p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); 7196c95142eSMartin Matuska p->RunLength += p->PrevSuccess; 7206c95142eSMartin Matuska p->MinContext->SummFreq += 4; 7216c95142eSMartin Matuska if ((p->FoundState->Freq += 4) > MAX_FREQ) 7226c95142eSMartin Matuska Rescale(p); 7236c95142eSMartin Matuska NextContext(p); 7246c95142eSMartin Matuska } 7256c95142eSMartin Matuska 7266c95142eSMartin Matuska static void Ppmd7_UpdateBin(CPpmd7 *p) 7276c95142eSMartin Matuska { 7286c95142eSMartin Matuska p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); 7296c95142eSMartin Matuska p->PrevSuccess = 1; 7306c95142eSMartin Matuska p->RunLength++; 7316c95142eSMartin Matuska NextContext(p); 7326c95142eSMartin Matuska } 7336c95142eSMartin Matuska 7346c95142eSMartin Matuska static void Ppmd7_Update2(CPpmd7 *p) 7356c95142eSMartin Matuska { 7366c95142eSMartin Matuska p->MinContext->SummFreq += 4; 7376c95142eSMartin Matuska if ((p->FoundState->Freq += 4) > MAX_FREQ) 7386c95142eSMartin Matuska Rescale(p); 7396c95142eSMartin Matuska p->RunLength = p->InitRL; 7406c95142eSMartin Matuska UpdateModel(p); 7416c95142eSMartin Matuska } 7426c95142eSMartin Matuska 7436c95142eSMartin Matuska /* ---------- Decode ---------- */ 7446c95142eSMartin Matuska 7456c95142eSMartin Matuska static Bool Ppmd_RangeDec_Init(CPpmd7z_RangeDec *p) 7466c95142eSMartin Matuska { 7476c95142eSMartin Matuska unsigned i; 7486c95142eSMartin Matuska p->Low = p->Bottom = 0; 7496c95142eSMartin Matuska p->Range = 0xFFFFFFFF; 7506c95142eSMartin Matuska for (i = 0; i < 4; i++) 7516c95142eSMartin Matuska p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); 7526c95142eSMartin Matuska return (p->Code < 0xFFFFFFFF); 7536c95142eSMartin Matuska } 7546c95142eSMartin Matuska 7556c95142eSMartin Matuska static Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) 7566c95142eSMartin Matuska { 7576c95142eSMartin Matuska if (p->Stream->Read((void *)p->Stream) != 0) 7586c95142eSMartin Matuska return False; 7596c95142eSMartin Matuska return Ppmd_RangeDec_Init(p); 7606c95142eSMartin Matuska } 7616c95142eSMartin Matuska 7626c95142eSMartin Matuska static Bool PpmdRAR_RangeDec_Init(CPpmd7z_RangeDec *p) 7636c95142eSMartin Matuska { 7646c95142eSMartin Matuska if (!Ppmd_RangeDec_Init(p)) 7656c95142eSMartin Matuska return False; 7666c95142eSMartin Matuska p->Bottom = 0x8000; 7676c95142eSMartin Matuska return True; 7686c95142eSMartin Matuska } 7696c95142eSMartin Matuska 7706c95142eSMartin Matuska static UInt32 Range_GetThreshold(void *pp, UInt32 total) 7716c95142eSMartin Matuska { 7726c95142eSMartin Matuska CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 7736c95142eSMartin Matuska return (p->Code - p->Low) / (p->Range /= total); 7746c95142eSMartin Matuska } 7756c95142eSMartin Matuska 7766c95142eSMartin Matuska static void Range_Normalize(CPpmd7z_RangeDec *p) 7776c95142eSMartin Matuska { 7786c95142eSMartin Matuska while (1) 7796c95142eSMartin Matuska { 7806c95142eSMartin Matuska if((p->Low ^ (p->Low + p->Range)) >= kTopValue) 7816c95142eSMartin Matuska { 7826c95142eSMartin Matuska if(p->Range >= p->Bottom) 7836c95142eSMartin Matuska break; 7846c95142eSMartin Matuska else 785fd082e96SMartin Matuska p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1); 7866c95142eSMartin Matuska } 7876c95142eSMartin Matuska p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); 7886c95142eSMartin Matuska p->Range <<= 8; 7896c95142eSMartin Matuska p->Low <<= 8; 7906c95142eSMartin Matuska } 7916c95142eSMartin Matuska } 7926c95142eSMartin Matuska 7936c95142eSMartin Matuska static void Range_Decode_7z(void *pp, UInt32 start, UInt32 size) 7946c95142eSMartin Matuska { 7956c95142eSMartin Matuska CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 7966c95142eSMartin Matuska p->Code -= start * p->Range; 7976c95142eSMartin Matuska p->Range *= size; 7986c95142eSMartin Matuska Range_Normalize(p); 7996c95142eSMartin Matuska } 8006c95142eSMartin Matuska 8016c95142eSMartin Matuska static void Range_Decode_RAR(void *pp, UInt32 start, UInt32 size) 8026c95142eSMartin Matuska { 8036c95142eSMartin Matuska CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 8046c95142eSMartin Matuska p->Low += start * p->Range; 8056c95142eSMartin Matuska p->Range *= size; 8066c95142eSMartin Matuska Range_Normalize(p); 8076c95142eSMartin Matuska } 8086c95142eSMartin Matuska 8096c95142eSMartin Matuska static UInt32 Range_DecodeBit_7z(void *pp, UInt32 size0) 8106c95142eSMartin Matuska { 8116c95142eSMartin Matuska CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 8126c95142eSMartin Matuska UInt32 newBound = (p->Range >> 14) * size0; 8136c95142eSMartin Matuska UInt32 symbol; 8146c95142eSMartin Matuska if (p->Code < newBound) 8156c95142eSMartin Matuska { 8166c95142eSMartin Matuska symbol = 0; 8176c95142eSMartin Matuska p->Range = newBound; 8186c95142eSMartin Matuska } 8196c95142eSMartin Matuska else 8206c95142eSMartin Matuska { 8216c95142eSMartin Matuska symbol = 1; 8226c95142eSMartin Matuska p->Code -= newBound; 8236c95142eSMartin Matuska p->Range -= newBound; 8246c95142eSMartin Matuska } 8256c95142eSMartin Matuska Range_Normalize(p); 8266c95142eSMartin Matuska return symbol; 8276c95142eSMartin Matuska } 8286c95142eSMartin Matuska 8296c95142eSMartin Matuska static UInt32 Range_DecodeBit_RAR(void *pp, UInt32 size0) 8306c95142eSMartin Matuska { 8316c95142eSMartin Matuska CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; 8326c95142eSMartin Matuska UInt32 bit, value = p->p.GetThreshold(p, PPMD_BIN_SCALE); 8336c95142eSMartin Matuska if(value < size0) 8346c95142eSMartin Matuska { 8356c95142eSMartin Matuska bit = 0; 8366c95142eSMartin Matuska p->p.Decode(p, 0, size0); 8376c95142eSMartin Matuska } 8386c95142eSMartin Matuska else 8396c95142eSMartin Matuska { 8406c95142eSMartin Matuska bit = 1; 8416c95142eSMartin Matuska p->p.Decode(p, size0, PPMD_BIN_SCALE - size0); 8426c95142eSMartin Matuska } 8436c95142eSMartin Matuska return bit; 8446c95142eSMartin Matuska } 8456c95142eSMartin Matuska 8466c95142eSMartin Matuska static void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) 8476c95142eSMartin Matuska { 8486c95142eSMartin Matuska p->p.GetThreshold = Range_GetThreshold; 8496c95142eSMartin Matuska p->p.Decode = Range_Decode_7z; 8506c95142eSMartin Matuska p->p.DecodeBit = Range_DecodeBit_7z; 8516c95142eSMartin Matuska } 8526c95142eSMartin Matuska 8536c95142eSMartin Matuska static void PpmdRAR_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) 8546c95142eSMartin Matuska { 8556c95142eSMartin Matuska p->p.GetThreshold = Range_GetThreshold; 8566c95142eSMartin Matuska p->p.Decode = Range_Decode_RAR; 8576c95142eSMartin Matuska p->p.DecodeBit = Range_DecodeBit_RAR; 8586c95142eSMartin Matuska } 8596c95142eSMartin Matuska 8606c95142eSMartin Matuska #define MASK(sym) ((signed char *)charMask)[sym] 8616c95142eSMartin Matuska 8626c95142eSMartin Matuska static int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc) 8636c95142eSMartin Matuska { 8646c95142eSMartin Matuska size_t charMask[256 / sizeof(size_t)]; 8656c95142eSMartin Matuska if (p->MinContext->NumStats != 1) 8666c95142eSMartin Matuska { 8676c95142eSMartin Matuska CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 8686c95142eSMartin Matuska unsigned i; 8696c95142eSMartin Matuska UInt32 count, hiCnt; 8706c95142eSMartin Matuska if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) 8716c95142eSMartin Matuska { 8726c95142eSMartin Matuska Byte symbol; 8736c95142eSMartin Matuska rc->Decode(rc, 0, s->Freq); 8746c95142eSMartin Matuska p->FoundState = s; 8756c95142eSMartin Matuska symbol = s->Symbol; 8766c95142eSMartin Matuska Ppmd7_Update1_0(p); 8776c95142eSMartin Matuska return symbol; 8786c95142eSMartin Matuska } 8796c95142eSMartin Matuska p->PrevSuccess = 0; 8806c95142eSMartin Matuska i = p->MinContext->NumStats - 1; 8816c95142eSMartin Matuska do 8826c95142eSMartin Matuska { 8836c95142eSMartin Matuska if ((hiCnt += (++s)->Freq) > count) 8846c95142eSMartin Matuska { 8856c95142eSMartin Matuska Byte symbol; 8866c95142eSMartin Matuska rc->Decode(rc, hiCnt - s->Freq, s->Freq); 8876c95142eSMartin Matuska p->FoundState = s; 8886c95142eSMartin Matuska symbol = s->Symbol; 8896c95142eSMartin Matuska Ppmd7_Update1(p); 8906c95142eSMartin Matuska return symbol; 8916c95142eSMartin Matuska } 8926c95142eSMartin Matuska } 8936c95142eSMartin Matuska while (--i); 8946c95142eSMartin Matuska if (count >= p->MinContext->SummFreq) 8956c95142eSMartin Matuska return -2; 8966c95142eSMartin Matuska p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 8976c95142eSMartin Matuska rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); 8986c95142eSMartin Matuska PPMD_SetAllBitsIn256Bytes(charMask); 8996c95142eSMartin Matuska MASK(s->Symbol) = 0; 9006c95142eSMartin Matuska i = p->MinContext->NumStats - 1; 9016c95142eSMartin Matuska do { MASK((--s)->Symbol) = 0; } while (--i); 9026c95142eSMartin Matuska } 9036c95142eSMartin Matuska else 9046c95142eSMartin Matuska { 9056c95142eSMartin Matuska UInt16 *prob = Ppmd7_GetBinSumm(p); 9066c95142eSMartin Matuska if (rc->DecodeBit(rc, *prob) == 0) 9076c95142eSMartin Matuska { 9086c95142eSMartin Matuska Byte symbol; 9096c95142eSMartin Matuska *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 9106c95142eSMartin Matuska symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; 9116c95142eSMartin Matuska Ppmd7_UpdateBin(p); 9126c95142eSMartin Matuska return symbol; 9136c95142eSMartin Matuska } 9146c95142eSMartin Matuska *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 9156c95142eSMartin Matuska p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 9166c95142eSMartin Matuska PPMD_SetAllBitsIn256Bytes(charMask); 9176c95142eSMartin Matuska MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; 9186c95142eSMartin Matuska p->PrevSuccess = 0; 9196c95142eSMartin Matuska } 9206c95142eSMartin Matuska for (;;) 9216c95142eSMartin Matuska { 9226c95142eSMartin Matuska CPpmd_State *ps[256], *s; 9236c95142eSMartin Matuska UInt32 freqSum, count, hiCnt; 9246c95142eSMartin Matuska CPpmd_See *see; 9256c95142eSMartin Matuska unsigned i, num, numMasked = p->MinContext->NumStats; 9266c95142eSMartin Matuska do 9276c95142eSMartin Matuska { 9286c95142eSMartin Matuska p->OrderFall++; 9296c95142eSMartin Matuska if (!p->MinContext->Suffix) 9306c95142eSMartin Matuska return -1; 9316c95142eSMartin Matuska p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 9326c95142eSMartin Matuska } 9336c95142eSMartin Matuska while (p->MinContext->NumStats == numMasked); 9346c95142eSMartin Matuska hiCnt = 0; 9356c95142eSMartin Matuska s = Ppmd7_GetStats(p, p->MinContext); 9366c95142eSMartin Matuska i = 0; 9376c95142eSMartin Matuska num = p->MinContext->NumStats - numMasked; 9386c95142eSMartin Matuska do 9396c95142eSMartin Matuska { 9406c95142eSMartin Matuska int k = (int)(MASK(s->Symbol)); 9416c95142eSMartin Matuska hiCnt += (s->Freq & k); 9426c95142eSMartin Matuska ps[i] = s++; 9436c95142eSMartin Matuska i -= k; 9446c95142eSMartin Matuska } 9456c95142eSMartin Matuska while (i != num); 9466c95142eSMartin Matuska 9476c95142eSMartin Matuska see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); 9486c95142eSMartin Matuska freqSum += hiCnt; 9496c95142eSMartin Matuska count = rc->GetThreshold(rc, freqSum); 9506c95142eSMartin Matuska 9516c95142eSMartin Matuska if (count < hiCnt) 9526c95142eSMartin Matuska { 9536c95142eSMartin Matuska Byte symbol; 9546c95142eSMartin Matuska CPpmd_State **pps = ps; 9556c95142eSMartin Matuska for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); 9566c95142eSMartin Matuska s = *pps; 9576c95142eSMartin Matuska rc->Decode(rc, hiCnt - s->Freq, s->Freq); 9586c95142eSMartin Matuska Ppmd_See_Update(see); 9596c95142eSMartin Matuska p->FoundState = s; 9606c95142eSMartin Matuska symbol = s->Symbol; 9616c95142eSMartin Matuska Ppmd7_Update2(p); 9626c95142eSMartin Matuska return symbol; 9636c95142eSMartin Matuska } 9646c95142eSMartin Matuska if (count >= freqSum) 9656c95142eSMartin Matuska return -2; 9666c95142eSMartin Matuska rc->Decode(rc, hiCnt, freqSum - hiCnt); 9676c95142eSMartin Matuska see->Summ = (UInt16)(see->Summ + freqSum); 9686c95142eSMartin Matuska do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); 9696c95142eSMartin Matuska } 9706c95142eSMartin Matuska } 9716c95142eSMartin Matuska 9726c95142eSMartin Matuska /* ---------- Encode ---------- Ppmd7Enc.c */ 9736c95142eSMartin Matuska 9746c95142eSMartin Matuska #define kTopValue (1 << 24) 9756c95142eSMartin Matuska 9766c95142eSMartin Matuska static void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) 9776c95142eSMartin Matuska { 9786c95142eSMartin Matuska p->Low = 0; 9796c95142eSMartin Matuska p->Range = 0xFFFFFFFF; 9806c95142eSMartin Matuska p->Cache = 0; 9816c95142eSMartin Matuska p->CacheSize = 1; 9826c95142eSMartin Matuska } 9836c95142eSMartin Matuska 9846c95142eSMartin Matuska static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) 9856c95142eSMartin Matuska { 9866c95142eSMartin Matuska if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) 9876c95142eSMartin Matuska { 9886c95142eSMartin Matuska Byte temp = p->Cache; 9896c95142eSMartin Matuska do 9906c95142eSMartin Matuska { 9916c95142eSMartin Matuska p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); 9926c95142eSMartin Matuska temp = 0xFF; 9936c95142eSMartin Matuska } 9946c95142eSMartin Matuska while(--p->CacheSize != 0); 9956c95142eSMartin Matuska p->Cache = (Byte)((UInt32)p->Low >> 24); 9966c95142eSMartin Matuska } 9976c95142eSMartin Matuska p->CacheSize++; 998acc60b03SMartin Matuska p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF; 9996c95142eSMartin Matuska } 10006c95142eSMartin Matuska 10016c95142eSMartin Matuska static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) 10026c95142eSMartin Matuska { 1003f9762417SMartin Matuska p->Low += (UInt64)start * (UInt64)(p->Range /= total); 10046c95142eSMartin Matuska p->Range *= size; 10056c95142eSMartin Matuska while (p->Range < kTopValue) 10066c95142eSMartin Matuska { 10076c95142eSMartin Matuska p->Range <<= 8; 10086c95142eSMartin Matuska RangeEnc_ShiftLow(p); 10096c95142eSMartin Matuska } 10106c95142eSMartin Matuska } 10116c95142eSMartin Matuska 10126c95142eSMartin Matuska static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) 10136c95142eSMartin Matuska { 10146c95142eSMartin Matuska p->Range = (p->Range >> 14) * size0; 10156c95142eSMartin Matuska while (p->Range < kTopValue) 10166c95142eSMartin Matuska { 10176c95142eSMartin Matuska p->Range <<= 8; 10186c95142eSMartin Matuska RangeEnc_ShiftLow(p); 10196c95142eSMartin Matuska } 10206c95142eSMartin Matuska } 10216c95142eSMartin Matuska 10226c95142eSMartin Matuska static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) 10236c95142eSMartin Matuska { 10246c95142eSMartin Matuska UInt32 newBound = (p->Range >> 14) * size0; 10256c95142eSMartin Matuska p->Low += newBound; 10266c95142eSMartin Matuska p->Range -= newBound; 10276c95142eSMartin Matuska while (p->Range < kTopValue) 10286c95142eSMartin Matuska { 10296c95142eSMartin Matuska p->Range <<= 8; 10306c95142eSMartin Matuska RangeEnc_ShiftLow(p); 10316c95142eSMartin Matuska } 10326c95142eSMartin Matuska } 10336c95142eSMartin Matuska 10346c95142eSMartin Matuska static void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) 10356c95142eSMartin Matuska { 10366c95142eSMartin Matuska unsigned i; 10376c95142eSMartin Matuska for (i = 0; i < 5; i++) 10386c95142eSMartin Matuska RangeEnc_ShiftLow(p); 10396c95142eSMartin Matuska } 10406c95142eSMartin Matuska 10416c95142eSMartin Matuska 10426c95142eSMartin Matuska #define MASK(sym) ((signed char *)charMask)[sym] 10436c95142eSMartin Matuska 10446c95142eSMartin Matuska static void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) 10456c95142eSMartin Matuska { 10466c95142eSMartin Matuska size_t charMask[256 / sizeof(size_t)]; 10476c95142eSMartin Matuska if (p->MinContext->NumStats != 1) 10486c95142eSMartin Matuska { 10496c95142eSMartin Matuska CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); 10506c95142eSMartin Matuska UInt32 sum; 10516c95142eSMartin Matuska unsigned i; 10526c95142eSMartin Matuska if (s->Symbol == symbol) 10536c95142eSMartin Matuska { 10546c95142eSMartin Matuska RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); 10556c95142eSMartin Matuska p->FoundState = s; 10566c95142eSMartin Matuska Ppmd7_Update1_0(p); 10576c95142eSMartin Matuska return; 10586c95142eSMartin Matuska } 10596c95142eSMartin Matuska p->PrevSuccess = 0; 10606c95142eSMartin Matuska sum = s->Freq; 10616c95142eSMartin Matuska i = p->MinContext->NumStats - 1; 10626c95142eSMartin Matuska do 10636c95142eSMartin Matuska { 10646c95142eSMartin Matuska if ((++s)->Symbol == symbol) 10656c95142eSMartin Matuska { 10666c95142eSMartin Matuska RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); 10676c95142eSMartin Matuska p->FoundState = s; 10686c95142eSMartin Matuska Ppmd7_Update1(p); 10696c95142eSMartin Matuska return; 10706c95142eSMartin Matuska } 10716c95142eSMartin Matuska sum += s->Freq; 10726c95142eSMartin Matuska } 10736c95142eSMartin Matuska while (--i); 10746c95142eSMartin Matuska 10756c95142eSMartin Matuska p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; 10766c95142eSMartin Matuska PPMD_SetAllBitsIn256Bytes(charMask); 10776c95142eSMartin Matuska MASK(s->Symbol) = 0; 10786c95142eSMartin Matuska i = p->MinContext->NumStats - 1; 10796c95142eSMartin Matuska do { MASK((--s)->Symbol) = 0; } while (--i); 10806c95142eSMartin Matuska RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); 10816c95142eSMartin Matuska } 10826c95142eSMartin Matuska else 10836c95142eSMartin Matuska { 10846c95142eSMartin Matuska UInt16 *prob = Ppmd7_GetBinSumm(p); 10856c95142eSMartin Matuska CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); 10866c95142eSMartin Matuska if (s->Symbol == symbol) 10876c95142eSMartin Matuska { 10886c95142eSMartin Matuska RangeEnc_EncodeBit_0(rc, *prob); 10896c95142eSMartin Matuska *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); 10906c95142eSMartin Matuska p->FoundState = s; 10916c95142eSMartin Matuska Ppmd7_UpdateBin(p); 10926c95142eSMartin Matuska return; 10936c95142eSMartin Matuska } 10946c95142eSMartin Matuska else 10956c95142eSMartin Matuska { 10966c95142eSMartin Matuska RangeEnc_EncodeBit_1(rc, *prob); 10976c95142eSMartin Matuska *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); 10986c95142eSMartin Matuska p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; 10996c95142eSMartin Matuska PPMD_SetAllBitsIn256Bytes(charMask); 11006c95142eSMartin Matuska MASK(s->Symbol) = 0; 11016c95142eSMartin Matuska p->PrevSuccess = 0; 11026c95142eSMartin Matuska } 11036c95142eSMartin Matuska } 11046c95142eSMartin Matuska for (;;) 11056c95142eSMartin Matuska { 11066c95142eSMartin Matuska UInt32 escFreq; 11076c95142eSMartin Matuska CPpmd_See *see; 11086c95142eSMartin Matuska CPpmd_State *s; 11096c95142eSMartin Matuska UInt32 sum; 11106c95142eSMartin Matuska unsigned i, numMasked = p->MinContext->NumStats; 11116c95142eSMartin Matuska do 11126c95142eSMartin Matuska { 11136c95142eSMartin Matuska p->OrderFall++; 11146c95142eSMartin Matuska if (!p->MinContext->Suffix) 11156c95142eSMartin Matuska return; /* EndMarker (symbol = -1) */ 11166c95142eSMartin Matuska p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); 11176c95142eSMartin Matuska } 11186c95142eSMartin Matuska while (p->MinContext->NumStats == numMasked); 11196c95142eSMartin Matuska 11206c95142eSMartin Matuska see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); 11216c95142eSMartin Matuska s = Ppmd7_GetStats(p, p->MinContext); 11226c95142eSMartin Matuska sum = 0; 11236c95142eSMartin Matuska i = p->MinContext->NumStats; 11246c95142eSMartin Matuska do 11256c95142eSMartin Matuska { 11266c95142eSMartin Matuska int cur = s->Symbol; 11276c95142eSMartin Matuska if (cur == symbol) 11286c95142eSMartin Matuska { 11296c95142eSMartin Matuska UInt32 low = sum; 11306c95142eSMartin Matuska CPpmd_State *s1 = s; 11316c95142eSMartin Matuska do 11326c95142eSMartin Matuska { 11336c95142eSMartin Matuska sum += (s->Freq & (int)(MASK(s->Symbol))); 11346c95142eSMartin Matuska s++; 11356c95142eSMartin Matuska } 11366c95142eSMartin Matuska while (--i); 11376c95142eSMartin Matuska RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); 11386c95142eSMartin Matuska Ppmd_See_Update(see); 11396c95142eSMartin Matuska p->FoundState = s1; 11406c95142eSMartin Matuska Ppmd7_Update2(p); 11416c95142eSMartin Matuska return; 11426c95142eSMartin Matuska } 11436c95142eSMartin Matuska sum += (s->Freq & (int)(MASK(cur))); 11446c95142eSMartin Matuska MASK(cur) = 0; 11456c95142eSMartin Matuska s++; 11466c95142eSMartin Matuska } 11476c95142eSMartin Matuska while (--i); 11486c95142eSMartin Matuska 11496c95142eSMartin Matuska RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); 11506c95142eSMartin Matuska see->Summ = (UInt16)(see->Summ + sum + escFreq); 11516c95142eSMartin Matuska } 11526c95142eSMartin Matuska } 11536c95142eSMartin Matuska 11546c95142eSMartin Matuska const IPpmd7 __archive_ppmd7_functions = 11556c95142eSMartin Matuska { 11566c95142eSMartin Matuska &Ppmd7_Construct, 11576c95142eSMartin Matuska &Ppmd7_Alloc, 11586c95142eSMartin Matuska &Ppmd7_Free, 11596c95142eSMartin Matuska &Ppmd7_Init, 11606c95142eSMartin Matuska &Ppmd7z_RangeDec_CreateVTable, 11616c95142eSMartin Matuska &PpmdRAR_RangeDec_CreateVTable, 11626c95142eSMartin Matuska &Ppmd7z_RangeDec_Init, 11636c95142eSMartin Matuska &PpmdRAR_RangeDec_Init, 11646c95142eSMartin Matuska &Ppmd7_DecodeSymbol, 11656c95142eSMartin Matuska &Ppmd7z_RangeEnc_Init, 11666c95142eSMartin Matuska &Ppmd7z_RangeEnc_FlushData, 11676c95142eSMartin Matuska &Ppmd7_EncodeSymbol 11686c95142eSMartin Matuska }; 1169