aboutsummaryrefslogtreecommitdiff
path: root/C/Ppmd7.c
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2023-06-21 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2023-12-17 14:59:19 +0500
commit5b39dc76f1bc82f941d5c800ab9f34407a06b53a (patch)
treefe5e17420300b715021a76328444088d32047963 /C/Ppmd7.c
parent93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (diff)
download7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.gz
7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.bz2
7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.zip
23.0123.01
Diffstat (limited to 'C/Ppmd7.c')
-rw-r--r--C/Ppmd7.c186
1 files changed, 102 insertions, 84 deletions
diff --git a/C/Ppmd7.c b/C/Ppmd7.c
index cf401cb..6e1307e 100644
--- a/C/Ppmd7.c
+++ b/C/Ppmd7.c
@@ -1,5 +1,5 @@
1/* Ppmd7.c -- PPMdH codec 1/* Ppmd7.c -- PPMdH codec
22021-04-13 : Igor Pavlov : Public domain 22023-04-02 : Igor Pavlov : Public domain
3This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ 3This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4 4
5#include "Precomp.h" 5#include "Precomp.h"
@@ -14,7 +14,7 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
14MY_ALIGN(16) 14MY_ALIGN(16)
15static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; 15static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
16MY_ALIGN(16) 16MY_ALIGN(16)
17static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; 17static const UInt16 PPMD7_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
18 18
19#define MAX_FREQ 124 19#define MAX_FREQ 124
20#define UNIT_SIZE 12 20#define UNIT_SIZE 12
@@ -33,7 +33,7 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x
33#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) 33#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
34#define SUFFIX(ctx) CTX((ctx)->Suffix) 34#define SUFFIX(ctx) CTX((ctx)->Suffix)
35 35
36typedef CPpmd7_Context * CTX_PTR; 36typedef CPpmd7_Context * PPMD7_CTX_PTR;
37 37
38struct CPpmd7_Node_; 38struct CPpmd7_Node_;
39 39
@@ -107,14 +107,14 @@ BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
107// ---------- Internal Memory Allocator ---------- 107// ---------- Internal Memory Allocator ----------
108 108
109/* We can use CPpmd7_Node in list of free units (as in Ppmd8) 109/* We can use CPpmd7_Node in list of free units (as in Ppmd8)
110 But we still need one additional list walk pass in GlueFreeBlocks(). 110 But we still need one additional list walk pass in Ppmd7_GlueFreeBlocks().
111 So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in InsertNode() / RemoveNode() 111 So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in Ppmd7_InsertNode() / Ppmd7_RemoveNode()
112*/ 112*/
113 113
114#define EMPTY_NODE 0 114#define EMPTY_NODE 0
115 115
116 116
117static void InsertNode(CPpmd7 *p, void *node, unsigned indx) 117static void Ppmd7_InsertNode(CPpmd7 *p, void *node, unsigned indx)
118{ 118{
119 *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; 119 *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
120 // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx]; 120 // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx];
@@ -124,7 +124,7 @@ static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
124} 124}
125 125
126 126
127static void *RemoveNode(CPpmd7 *p, unsigned indx) 127static void *Ppmd7_RemoveNode(CPpmd7 *p, unsigned indx)
128{ 128{
129 CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); 129 CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
130 p->FreeList[indx] = *node; 130 p->FreeList[indx] = *node;
@@ -134,32 +134,32 @@ static void *RemoveNode(CPpmd7 *p, unsigned indx)
134} 134}
135 135
136 136
137static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) 137static void Ppmd7_SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
138{ 138{
139 unsigned i, nu = I2U(oldIndx) - I2U(newIndx); 139 unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
140 ptr = (Byte *)ptr + U2B(I2U(newIndx)); 140 ptr = (Byte *)ptr + U2B(I2U(newIndx));
141 if (I2U(i = U2I(nu)) != nu) 141 if (I2U(i = U2I(nu)) != nu)
142 { 142 {
143 unsigned k = I2U(--i); 143 unsigned k = I2U(--i);
144 InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); 144 Ppmd7_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
145 } 145 }
146 InsertNode(p, ptr, i); 146 Ppmd7_InsertNode(p, ptr, i);
147} 147}
148 148
149 149
150/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ 150/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */
151 151
152typedef union _CPpmd7_Node_Union 152typedef union
153{ 153{
154 CPpmd7_Node Node; 154 CPpmd7_Node Node;
155 CPpmd7_Node_Ref NextRef; 155 CPpmd7_Node_Ref NextRef;
156} CPpmd7_Node_Union; 156} CPpmd7_Node_Union;
157 157
158/* Original PPmdH (Ppmd7) code uses doubly linked list in GlueFreeBlocks() 158/* Original PPmdH (Ppmd7) code uses doubly linked list in Ppmd7_GlueFreeBlocks()
159 we use single linked list similar to Ppmd8 code */ 159 we use single linked list similar to Ppmd8 code */
160 160
161 161
162static void GlueFreeBlocks(CPpmd7 *p) 162static void Ppmd7_GlueFreeBlocks(CPpmd7 *p)
163{ 163{
164 /* 164 /*
165 we use first UInt16 field of 12-bytes UNITs as record type stamp 165 we use first UInt16 field of 12-bytes UNITs as record type stamp
@@ -239,27 +239,27 @@ static void GlueFreeBlocks(CPpmd7 *p)
239 if (nu == 0) 239 if (nu == 0)
240 continue; 240 continue;
241 for (; nu > 128; nu -= 128, node += 128) 241 for (; nu > 128; nu -= 128, node += 128)
242 InsertNode(p, node, PPMD_NUM_INDEXES - 1); 242 Ppmd7_InsertNode(p, node, PPMD_NUM_INDEXES - 1);
243 if (I2U(i = U2I(nu)) != nu) 243 if (I2U(i = U2I(nu)) != nu)
244 { 244 {
245 unsigned k = I2U(--i); 245 unsigned k = I2U(--i);
246 InsertNode(p, node + k, (unsigned)nu - k - 1); 246 Ppmd7_InsertNode(p, node + k, (unsigned)nu - k - 1);
247 } 247 }
248 InsertNode(p, node, i); 248 Ppmd7_InsertNode(p, node, i);
249 } 249 }
250} 250}
251 251
252 252
253MY_NO_INLINE 253Z7_NO_INLINE
254static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) 254static void *Ppmd7_AllocUnitsRare(CPpmd7 *p, unsigned indx)
255{ 255{
256 unsigned i; 256 unsigned i;
257 257
258 if (p->GlueCount == 0) 258 if (p->GlueCount == 0)
259 { 259 {
260 GlueFreeBlocks(p); 260 Ppmd7_GlueFreeBlocks(p);
261 if (p->FreeList[indx] != 0) 261 if (p->FreeList[indx] != 0)
262 return RemoveNode(p, indx); 262 return Ppmd7_RemoveNode(p, indx);
263 } 263 }
264 264
265 i = indx; 265 i = indx;
@@ -277,17 +277,17 @@ static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
277 while (p->FreeList[i] == 0); 277 while (p->FreeList[i] == 0);
278 278
279 { 279 {
280 void *block = RemoveNode(p, i); 280 void *block = Ppmd7_RemoveNode(p, i);
281 SplitBlock(p, block, i, indx); 281 Ppmd7_SplitBlock(p, block, i, indx);
282 return block; 282 return block;
283 } 283 }
284} 284}
285 285
286 286
287static void *AllocUnits(CPpmd7 *p, unsigned indx) 287static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx)
288{ 288{
289 if (p->FreeList[indx] != 0) 289 if (p->FreeList[indx] != 0)
290 return RemoveNode(p, indx); 290 return Ppmd7_RemoveNode(p, indx);
291 { 291 {
292 UInt32 numBytes = U2B(I2U(indx)); 292 UInt32 numBytes = U2B(I2U(indx));
293 Byte *lo = p->LoUnit; 293 Byte *lo = p->LoUnit;
@@ -297,11 +297,11 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
297 return lo; 297 return lo;
298 } 298 }
299 } 299 }
300 return AllocUnitsRare(p, indx); 300 return Ppmd7_AllocUnitsRare(p, indx);
301} 301}
302 302
303 303
304#define MyMem12Cpy(dest, src, num) \ 304#define MEM_12_CPY(dest, src, num) \
305 { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ 305 { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
306 do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } 306 do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
307 307
@@ -315,12 +315,12 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU
315 return oldPtr; 315 return oldPtr;
316 if (p->FreeList[i1] != 0) 316 if (p->FreeList[i1] != 0)
317 { 317 {
318 void *ptr = RemoveNode(p, i1); 318 void *ptr = Ppmd7_RemoveNode(p, i1);
319 MyMem12Cpy(ptr, oldPtr, newNU); 319 MEM_12_CPY(ptr, oldPtr, newNU)
320 InsertNode(p, oldPtr, i0); 320 Ppmd7_InsertNode(p, oldPtr, i0);
321 return ptr; 321 return ptr;
322 } 322 }
323 SplitBlock(p, oldPtr, i0, i1); 323 Ppmd7_SplitBlock(p, oldPtr, i0, i1);
324 return oldPtr; 324 return oldPtr;
325} 325}
326*/ 326*/
@@ -329,14 +329,14 @@ static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU
329#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) 329#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
330static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) 330static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
331{ 331{
332 Ppmd_SET_SUCCESSOR(p, v); 332 Ppmd_SET_SUCCESSOR(p, v)
333} 333}
334 334
335 335
336 336
337MY_NO_INLINE 337Z7_NO_INLINE
338static 338static
339void RestartModel(CPpmd7 *p) 339void Ppmd7_RestartModel(CPpmd7 *p)
340{ 340{
341 unsigned i, k; 341 unsigned i, k;
342 342
@@ -352,8 +352,8 @@ void RestartModel(CPpmd7 *p)
352 p->PrevSuccess = 0; 352 p->PrevSuccess = 0;
353 353
354 { 354 {
355 CPpmd7_Context *mc = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ 355 CPpmd7_Context *mc = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
356 CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ 356 CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd7_AllocUnits(p, PPMD_NUM_INDEXES - 1); */
357 357
358 p->LoUnit += U2B(256 / 2); 358 p->LoUnit += U2B(256 / 2);
359 p->MaxContext = p->MinContext = mc; 359 p->MaxContext = p->MinContext = mc;
@@ -391,7 +391,7 @@ void RestartModel(CPpmd7 *p)
391 { 391 {
392 unsigned m; 392 unsigned m;
393 UInt16 *dest = p->BinSumm[i] + k; 393 UInt16 *dest = p->BinSumm[i] + k;
394 UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); 394 const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD7_kInitBinEsc[k] / (i + 2));
395 for (m = 0; m < 64; m += 8) 395 for (m = 0; m < 64; m += 8)
396 dest[m] = val; 396 dest[m] = val;
397 } 397 }
@@ -423,13 +423,13 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
423{ 423{
424 p->MaxOrder = maxOrder; 424 p->MaxOrder = maxOrder;
425 425
426 RestartModel(p); 426 Ppmd7_RestartModel(p);
427} 427}
428 428
429 429
430 430
431/* 431/*
432 CreateSuccessors() 432 Ppmd7_CreateSuccessors()
433 It's called when (FoundState->Successor) is RAW-Successor, 433 It's called when (FoundState->Successor) is RAW-Successor,
434 that is the link to position in Raw text. 434 that is the link to position in Raw text.
435 So we create Context records and write the links to 435 So we create Context records and write the links to
@@ -445,10 +445,10 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
445 also it can return pointer to real context of same order, 445 also it can return pointer to real context of same order,
446*/ 446*/
447 447
448MY_NO_INLINE 448Z7_NO_INLINE
449static CTX_PTR CreateSuccessors(CPpmd7 *p) 449static PPMD7_CTX_PTR Ppmd7_CreateSuccessors(CPpmd7 *p)
450{ 450{
451 CTX_PTR c = p->MinContext; 451 PPMD7_CTX_PTR c = p->MinContext;
452 CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); 452 CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
453 Byte newSym, newFreq; 453 Byte newSym, newFreq;
454 unsigned numPs = 0; 454 unsigned numPs = 0;
@@ -522,15 +522,15 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p)
522 522
523 do 523 do
524 { 524 {
525 CTX_PTR c1; 525 PPMD7_CTX_PTR c1;
526 /* = AllocContext(p); */ 526 /* = AllocContext(p); */
527 if (p->HiUnit != p->LoUnit) 527 if (p->HiUnit != p->LoUnit)
528 c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); 528 c1 = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE);
529 else if (p->FreeList[0] != 0) 529 else if (p->FreeList[0] != 0)
530 c1 = (CTX_PTR)RemoveNode(p, 0); 530 c1 = (PPMD7_CTX_PTR)Ppmd7_RemoveNode(p, 0);
531 else 531 else
532 { 532 {
533 c1 = (CTX_PTR)AllocUnitsRare(p, 0); 533 c1 = (PPMD7_CTX_PTR)Ppmd7_AllocUnitsRare(p, 0);
534 if (!c1) 534 if (!c1)
535 return NULL; 535 return NULL;
536 } 536 }
@@ -550,16 +550,16 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p)
550 550
551 551
552 552
553#define SwapStates(s) \ 553#define SWAP_STATES(s) \
554 { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } 554 { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; }
555 555
556 556
557void Ppmd7_UpdateModel(CPpmd7 *p); 557void Ppmd7_UpdateModel(CPpmd7 *p);
558MY_NO_INLINE 558Z7_NO_INLINE
559void Ppmd7_UpdateModel(CPpmd7 *p) 559void Ppmd7_UpdateModel(CPpmd7 *p)
560{ 560{
561 CPpmd_Void_Ref maxSuccessor, minSuccessor; 561 CPpmd_Void_Ref maxSuccessor, minSuccessor;
562 CTX_PTR c, mc; 562 PPMD7_CTX_PTR c, mc;
563 unsigned s0, ns; 563 unsigned s0, ns;
564 564
565 565
@@ -592,7 +592,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
592 592
593 if (s[0].Freq >= s[-1].Freq) 593 if (s[0].Freq >= s[-1].Freq)
594 { 594 {
595 SwapStates(s); 595 SWAP_STATES(s)
596 s--; 596 s--;
597 } 597 }
598 } 598 }
@@ -610,10 +610,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
610 { 610 {
611 /* MAX ORDER context */ 611 /* MAX ORDER context */
612 /* (FoundState->Successor) is RAW-Successor. */ 612 /* (FoundState->Successor) is RAW-Successor. */
613 p->MaxContext = p->MinContext = CreateSuccessors(p); 613 p->MaxContext = p->MinContext = Ppmd7_CreateSuccessors(p);
614 if (!p->MinContext) 614 if (!p->MinContext)
615 { 615 {
616 RestartModel(p); 616 Ppmd7_RestartModel(p);
617 return; 617 return;
618 } 618 }
619 SetSuccessor(p->FoundState, REF(p->MinContext)); 619 SetSuccessor(p->FoundState, REF(p->MinContext));
@@ -629,7 +629,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
629 p->Text = text; 629 p->Text = text;
630 if (text >= p->UnitsStart) 630 if (text >= p->UnitsStart)
631 { 631 {
632 RestartModel(p); 632 Ppmd7_RestartModel(p);
633 return; 633 return;
634 } 634 }
635 maxSuccessor = REF(text); 635 maxSuccessor = REF(text);
@@ -645,10 +645,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
645 if (minSuccessor <= maxSuccessor) 645 if (minSuccessor <= maxSuccessor)
646 { 646 {
647 // minSuccessor is RAW-Successor. So we will create real contexts records: 647 // minSuccessor is RAW-Successor. So we will create real contexts records:
648 CTX_PTR cs = CreateSuccessors(p); 648 PPMD7_CTX_PTR cs = Ppmd7_CreateSuccessors(p);
649 if (!cs) 649 if (!cs)
650 { 650 {
651 RestartModel(p); 651 Ppmd7_RestartModel(p);
652 return; 652 return;
653 } 653 }
654 minSuccessor = REF(cs); 654 minSuccessor = REF(cs);
@@ -715,16 +715,16 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
715 unsigned i = U2I(oldNU); 715 unsigned i = U2I(oldNU);
716 if (i != U2I((size_t)oldNU + 1)) 716 if (i != U2I((size_t)oldNU + 1))
717 { 717 {
718 void *ptr = AllocUnits(p, i + 1); 718 void *ptr = Ppmd7_AllocUnits(p, i + 1);
719 void *oldPtr; 719 void *oldPtr;
720 if (!ptr) 720 if (!ptr)
721 { 721 {
722 RestartModel(p); 722 Ppmd7_RestartModel(p);
723 return; 723 return;
724 } 724 }
725 oldPtr = STATS(c); 725 oldPtr = STATS(c);
726 MyMem12Cpy(ptr, oldPtr, oldNU); 726 MEM_12_CPY(ptr, oldPtr, oldNU)
727 InsertNode(p, oldPtr, i); 727 Ppmd7_InsertNode(p, oldPtr, i);
728 c->Union4.Stats = STATS_REF(ptr); 728 c->Union4.Stats = STATS_REF(ptr);
729 } 729 }
730 } 730 }
@@ -739,10 +739,10 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
739 else 739 else
740 { 740 {
741 // instead of One-symbol context we create 2-symbol context 741 // instead of One-symbol context we create 2-symbol context
742 CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); 742 CPpmd_State *s = (CPpmd_State*)Ppmd7_AllocUnits(p, 0);
743 if (!s) 743 if (!s)
744 { 744 {
745 RestartModel(p); 745 Ppmd7_RestartModel(p);
746 return; 746 return;
747 } 747 }
748 { 748 {
@@ -795,8 +795,8 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
795 795
796 796
797 797
798MY_NO_INLINE 798Z7_NO_INLINE
799static void Rescale(CPpmd7 *p) 799static void Ppmd7_Rescale(CPpmd7 *p)
800{ 800{
801 unsigned i, adder, sumFreq, escFreq; 801 unsigned i, adder, sumFreq, escFreq;
802 CPpmd_State *stats = STATS(p->MinContext); 802 CPpmd_State *stats = STATS(p->MinContext);
@@ -885,7 +885,7 @@ static void Rescale(CPpmd7 *p)
885 *s = *stats; 885 *s = *stats;
886 s->Freq = (Byte)freq; // (freq <= 260 / 4) 886 s->Freq = (Byte)freq; // (freq <= 260 / 4)
887 p->FoundState = s; 887 p->FoundState = s;
888 InsertNode(p, stats, U2I(n0)); 888 Ppmd7_InsertNode(p, stats, U2I(n0));
889 return; 889 return;
890 } 890 }
891 891
@@ -899,13 +899,13 @@ static void Rescale(CPpmd7 *p)
899 { 899 {
900 if (p->FreeList[i1] != 0) 900 if (p->FreeList[i1] != 0)
901 { 901 {
902 void *ptr = RemoveNode(p, i1); 902 void *ptr = Ppmd7_RemoveNode(p, i1);
903 p->MinContext->Union4.Stats = STATS_REF(ptr); 903 p->MinContext->Union4.Stats = STATS_REF(ptr);
904 MyMem12Cpy(ptr, (const void *)stats, n1); 904 MEM_12_CPY(ptr, (const void *)stats, n1)
905 InsertNode(p, stats, i0); 905 Ppmd7_InsertNode(p, stats, i0);
906 } 906 }
907 else 907 else
908 SplitBlock(p, stats, i0, i1); 908 Ppmd7_SplitBlock(p, stats, i0, i1);
909 } 909 }
910 } 910 }
911 } 911 }
@@ -948,9 +948,9 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
948} 948}
949 949
950 950
951static void NextContext(CPpmd7 *p) 951static void Ppmd7_NextContext(CPpmd7 *p)
952{ 952{
953 CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); 953 PPMD7_CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
954 if (p->OrderFall == 0 && (const Byte *)c > p->Text) 954 if (p->OrderFall == 0 && (const Byte *)c > p->Text)
955 p->MaxContext = p->MinContext = c; 955 p->MaxContext = p->MinContext = c;
956 else 956 else
@@ -967,12 +967,12 @@ void Ppmd7_Update1(CPpmd7 *p)
967 s->Freq = (Byte)freq; 967 s->Freq = (Byte)freq;
968 if (freq > s[-1].Freq) 968 if (freq > s[-1].Freq)
969 { 969 {
970 SwapStates(s); 970 SWAP_STATES(s)
971 p->FoundState = --s; 971 p->FoundState = --s;
972 if (freq > MAX_FREQ) 972 if (freq > MAX_FREQ)
973 Rescale(p); 973 Ppmd7_Rescale(p);
974 } 974 }
975 NextContext(p); 975 Ppmd7_NextContext(p);
976} 976}
977 977
978 978
@@ -988,8 +988,8 @@ void Ppmd7_Update1_0(CPpmd7 *p)
988 freq += 4; 988 freq += 4;
989 s->Freq = (Byte)freq; 989 s->Freq = (Byte)freq;
990 if (freq > MAX_FREQ) 990 if (freq > MAX_FREQ)
991 Rescale(p); 991 Ppmd7_Rescale(p);
992 NextContext(p); 992 Ppmd7_NextContext(p);
993} 993}
994 994
995 995
@@ -1000,7 +1000,7 @@ void Ppmd7_UpdateBin(CPpmd7 *p)
1000 p->FoundState->Freq = (Byte)(freq + (freq < 128)); 1000 p->FoundState->Freq = (Byte)(freq + (freq < 128));
1001 p->PrevSuccess = 1; 1001 p->PrevSuccess = 1;
1002 p->RunLength++; 1002 p->RunLength++;
1003 NextContext(p); 1003 Ppmd7_NextContext(p);
1004} 1004}
1005*/ 1005*/
1006 1006
@@ -1013,7 +1013,7 @@ void Ppmd7_Update2(CPpmd7 *p)
1013 p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); 1013 p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);
1014 s->Freq = (Byte)freq; 1014 s->Freq = (Byte)freq;
1015 if (freq > MAX_FREQ) 1015 if (freq > MAX_FREQ)
1016 Rescale(p); 1016 Ppmd7_Rescale(p);
1017 Ppmd7_UpdateModel(p); 1017 Ppmd7_UpdateModel(p);
1018} 1018}
1019 1019
@@ -1042,8 +1042,8 @@ Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record.
1042The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors. 1042The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors.
1043The code doesn't free UNITs allocated for CPpmd7_Context records. 1043The code doesn't free UNITs allocated for CPpmd7_Context records.
1044 1044
1045The code calls RestartModel(), when there is no free memory for allocation. 1045The code calls Ppmd7_RestartModel(), when there is no free memory for allocation.
1046And RestartModel() changes the state to orignal start state, with full free block. 1046And Ppmd7_RestartModel() changes the state to orignal start state, with full free block.
1047 1047
1048 1048
1049The code allocates UNITs with the following order: 1049The code allocates UNITs with the following order:
@@ -1051,14 +1051,14 @@ The code allocates UNITs with the following order:
1051Allocation of 1 UNIT for Context record 1051Allocation of 1 UNIT for Context record
1052 - from free space (HiUnit) down to (LoUnit) 1052 - from free space (HiUnit) down to (LoUnit)
1053 - from FreeList[0] 1053 - from FreeList[0]
1054 - AllocUnitsRare() 1054 - Ppmd7_AllocUnitsRare()
1055 1055
1056AllocUnits() for CPpmd_State vectors: 1056Ppmd7_AllocUnits() for CPpmd_State vectors:
1057 - from FreeList[i] 1057 - from FreeList[i]
1058 - from free space (LoUnit) up to (HiUnit) 1058 - from free space (LoUnit) up to (HiUnit)
1059 - AllocUnitsRare() 1059 - Ppmd7_AllocUnitsRare()
1060 1060
1061AllocUnitsRare() 1061Ppmd7_AllocUnitsRare()
1062 - if (GlueCount == 0) 1062 - if (GlueCount == 0)
1063 { Glue lists, GlueCount = 255, allocate from FreeList[i]] } 1063 { Glue lists, GlueCount = 255, allocate from FreeList[i]] }
1064 - loop for all higher sized FreeList[...] lists 1064 - loop for all higher sized FreeList[...] lists
@@ -1093,8 +1093,8 @@ The PPMd code tries to fulfill the condition:
1093We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124) 1093We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124)
1094So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol. 1094So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol.
1095If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7. 1095If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7.
1096SummFreq and Escape_Freq can be changed in Rescale() and *Update*() functions. 1096SummFreq and Escape_Freq can be changed in Ppmd7_Rescale() and *Update*() functions.
1097Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Rescale() for 1097Ppmd7_Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Ppmd7_Rescale() for
1098max-order context. 1098max-order context.
1099 1099
1100When the PPMd code still break (Total <= RC::Range) condition in range coder, 1100When the PPMd code still break (Total <= RC::Range) condition in range coder,
@@ -1102,3 +1102,21 @@ we have two ways to resolve that problem:
1102 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases. 1102 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases.
1103 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value. 1103 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value.
1104*/ 1104*/
1105
1106#undef MAX_FREQ
1107#undef UNIT_SIZE
1108#undef U2B
1109#undef U2I
1110#undef I2U
1111#undef I2U_UInt16
1112#undef REF
1113#undef STATS_REF
1114#undef CTX
1115#undef STATS
1116#undef ONE_STATE
1117#undef SUFFIX
1118#undef NODE
1119#undef EMPTY_NODE
1120#undef MEM_12_CPY
1121#undef SUCCESSOR
1122#undef SWAP_STATES