Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'multiarc/src/formats/7z/C/Ppmd8.c')
-rwxr-xr-x[-rw-r--r--]multiarc/src/formats/7z/C/Ppmd8.c1116
1 files changed, 765 insertions, 351 deletions
diff --git a/multiarc/src/formats/7z/C/Ppmd8.c b/multiarc/src/formats/7z/C/Ppmd8.c
index 58141633..fda8b88a 100644..100755
--- a/multiarc/src/formats/7z/C/Ppmd8.c
+++ b/multiarc/src/formats/7z/C/Ppmd8.c
@@ -1,5 +1,5 @@
/* Ppmd8.c -- PPMdI codec
-2018-07-04 : Igor Pavlov : Public domain
+2021-04-13 : Igor Pavlov : Public domain
This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "Precomp.h"
@@ -8,7 +8,12 @@ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "Ppmd8.h"
-const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
+
+
+
+MY_ALIGN(16)
+static const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
+MY_ALIGN(16)
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
#define MAX_FREQ 124
@@ -16,13 +21,10 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])
-#define I2U(indx) (p->Indx2Units[indx])
+#define I2U(indx) ((unsigned)p->Indx2Units[indx])
-#ifdef PPMD_32BIT
- #define REF(ptr) (ptr)
-#else
- #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
-#endif
+
+#define REF(ptr) Ppmd_GetRef(p, ptr)
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
@@ -35,34 +37,23 @@ typedef CPpmd8_Context * CTX_PTR;
struct CPpmd8_Node_;
-typedef
- #ifdef PPMD_32BIT
- struct CPpmd8_Node_ *
- #else
- UInt32
- #endif
- CPpmd8_Node_Ref;
+typedef Ppmd_Ref_Type(struct CPpmd8_Node_) CPpmd8_Node_Ref;
typedef struct CPpmd8_Node_
{
UInt32 Stamp;
+
CPpmd8_Node_Ref Next;
UInt32 NU;
} CPpmd8_Node;
-#ifdef PPMD_32BIT
- #define NODE(ptr) (ptr)
-#else
- #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs)))
-#endif
-
-#define EMPTY_NODE 0xFFFFFFFF
+#define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd8_Node)
void Ppmd8_Construct(CPpmd8 *p)
{
unsigned i, k, m;
- p->Base = 0;
+ p->Base = NULL;
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{
@@ -78,39 +69,51 @@ void Ppmd8_Construct(CPpmd8 *p)
for (i = 0; i < 5; i++)
p->NS2Indx[i] = (Byte)i;
+
for (m = i, k = 1; i < 260; i++)
{
p->NS2Indx[i] = (Byte)m;
if (--k == 0)
k = (++m) - 4;
}
+
+ memcpy(p->ExpEscape, PPMD8_kExpEscape, 16);
}
+
void Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc)
{
ISzAlloc_Free(alloc, p->Base);
p->Size = 0;
- p->Base = 0;
+ p->Base = NULL;
}
+
BoolInt Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc)
{
if (!p->Base || p->Size != size)
{
Ppmd8_Free(p, alloc);
- p->AlignOffset =
- #ifdef PPMD_32BIT
- (4 - size) & 3;
- #else
- 4 - (size & 3);
- #endif
- if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == 0)
+ p->AlignOffset = (4 - size) & 3;
+ if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL)
return False;
p->Size = size;
}
return True;
}
+
+
+// ---------- Internal Memory Allocator ----------
+
+
+
+
+
+
+#define EMPTY_NODE 0xFFFFFFFF
+
+
static void InsertNode(CPpmd8 *p, void *node, unsigned indx)
{
((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;
@@ -120,14 +123,17 @@ static void InsertNode(CPpmd8 *p, void *node, unsigned indx)
p->Stamps[indx]++;
}
+
static void *RemoveNode(CPpmd8 *p, unsigned indx)
{
CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);
p->FreeList[indx] = node->Next;
p->Stamps[indx]--;
+
return node;
}
+
static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
{
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
@@ -140,51 +146,96 @@ static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
InsertNode(p, ptr, i);
}
+
+
+
+
+
+
+
+
+
+
+
+
+
static void GlueFreeBlocks(CPpmd8 *p)
{
- CPpmd8_Node_Ref head = 0;
- CPpmd8_Node_Ref *prev = &head;
- unsigned i;
+ /*
+ we use first UInt32 field of 12-bytes UNITs as record type stamp
+ CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0xFF
+ CPpmd8_Context { Byte NumStats; Byte Flags; UInt16 SummFreq; : Flags != 0xFF ???
+ CPpmd8_Node { UInt32 Stamp : Stamp == 0xFFFFFFFF for free record
+ : Stamp == 0 for guard
+ Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd8_Context record
+ */
+ CPpmd8_Node_Ref n;
p->GlueCount = 1 << 13;
memset(p->Stamps, 0, sizeof(p->Stamps));
- /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end.
- All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */
+ /* we set guard NODE at LoUnit */
if (p->LoUnit != p->HiUnit)
- ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
+ ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0;
- /* Glue free blocks */
- for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
- CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];
- p->FreeList[i] = 0;
- while (next != 0)
+ /* Glue free blocks */
+ CPpmd8_Node_Ref *prev = &n;
+ unsigned i;
+ for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
- CPpmd8_Node *node = NODE(next);
- if (node->NU != 0)
+
+ CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];
+ p->FreeList[i] = 0;
+ while (next != 0)
{
- CPpmd8_Node *node2;
+ CPpmd8_Node *node = NODE(next);
+ UInt32 nu = node->NU;
*prev = next;
- prev = &(node->Next);
- while ((node2 = node + node->NU)->Stamp == EMPTY_NODE)
+ next = node->Next;
+ if (nu != 0)
{
- node->NU += node2->NU;
- node2->NU = 0;
+ CPpmd8_Node *node2;
+ prev = &(node->Next);
+ while ((node2 = node + nu)->Stamp == EMPTY_NODE)
+ {
+ nu += node2->NU;
+ node2->NU = 0;
+ node->NU = nu;
+ }
}
}
- next = node->Next;
}
+
+ *prev = 0;
}
- *prev = 0;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* Fill lists of free blocks */
- while (head != 0)
+ while (n != 0)
{
- CPpmd8_Node *node = NODE(head);
- unsigned nu;
- head = node->Next;
- nu = node->NU;
+ CPpmd8_Node *node = NODE(n);
+ UInt32 nu = node->NU;
+ unsigned i;
+ n = node->Next;
if (nu == 0)
continue;
for (; nu > 128; nu -= 128, node += 128)
@@ -192,57 +243,70 @@ static void GlueFreeBlocks(CPpmd8 *p)
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
- InsertNode(p, node + k, nu - k - 1);
+ InsertNode(p, node + k, (unsigned)nu - k - 1);
}
InsertNode(p, node, i);
}
}
+
+MY_NO_INLINE
static void *AllocUnitsRare(CPpmd8 *p, unsigned indx)
{
unsigned i;
- void *retVal;
+
if (p->GlueCount == 0)
{
GlueFreeBlocks(p);
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
}
+
i = indx;
+
do
{
if (++i == PPMD_NUM_INDEXES)
{
UInt32 numBytes = U2B(I2U(indx));
+ Byte *us = p->UnitsStart;
p->GlueCount--;
- return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
+ return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : (NULL);
}
}
while (p->FreeList[i] == 0);
- retVal = RemoveNode(p, i);
- SplitBlock(p, retVal, i, indx);
- return retVal;
+
+ {
+ void *block = RemoveNode(p, i);
+ SplitBlock(p, block, i, indx);
+ return block;
+ }
}
+
static void *AllocUnits(CPpmd8 *p, unsigned indx)
{
- UInt32 numBytes;
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
- numBytes = U2B(I2U(indx));
- if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
{
- void *retVal = p->LoUnit;
- p->LoUnit += numBytes;
- return retVal;
+ UInt32 numBytes = U2B(I2U(indx));
+ Byte *lo = p->LoUnit;
+ if ((UInt32)(p->HiUnit - lo) >= numBytes)
+ {
+ p->LoUnit = lo + numBytes;
+ return lo;
+ }
}
return AllocUnitsRare(p, indx);
}
+
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
+
+
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
unsigned i0 = U2I(oldNU);
@@ -260,11 +324,13 @@ static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU
return oldPtr;
}
+
static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)
{
InsertNode(p, ptr, U2I(nu));
}
+
static void SpecialFreeUnit(CPpmd8 *p, void *ptr)
{
if ((Byte *)ptr != p->UnitsStart)
@@ -272,77 +338,91 @@ static void SpecialFreeUnit(CPpmd8 *p, void *ptr)
else
{
#ifdef PPMD8_FREEZE_SUPPORT
- *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */
+ *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts() */
#endif
p->UnitsStart += UNIT_SIZE;
}
}
+
+/*
static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)
{
unsigned indx = U2I(nu);
void *ptr;
- if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx])
+ if ((Byte *)oldPtr > p->UnitsStart + (1 << 14) || REF(oldPtr) > p->FreeList[indx])
return oldPtr;
ptr = RemoveNode(p, indx);
MyMem12Cpy(ptr, oldPtr, nu);
- if ((Byte*)oldPtr != p->UnitsStart)
+ if ((Byte *)oldPtr != p->UnitsStart)
InsertNode(p, oldPtr, indx);
else
p->UnitsStart += U2B(I2U(indx));
return ptr;
}
+*/
static void ExpandTextArea(CPpmd8 *p)
{
UInt32 count[PPMD_NUM_INDEXES];
unsigned i;
+
memset(count, 0, sizeof(count));
if (p->LoUnit != p->HiUnit)
- ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
+ ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0;
{
- CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart;
- for (; node->Stamp == EMPTY_NODE; node += node->NU)
+ CPpmd8_Node *node = (CPpmd8_Node *)(void *)p->UnitsStart;
+ while (node->Stamp == EMPTY_NODE)
{
+ UInt32 nu = node->NU;
node->Stamp = 0;
- count[U2I(node->NU)]++;
+ count[U2I(nu)]++;
+ node += nu;
}
p->UnitsStart = (Byte *)node;
}
for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
- CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i];
- while (count[i] != 0)
+ UInt32 cnt = count[i];
+ if (cnt == 0)
+ continue;
{
- CPpmd8_Node *node = NODE(*next);
- while (node->Stamp == 0)
+ CPpmd8_Node_Ref *prev = (CPpmd8_Node_Ref *)&p->FreeList[i];
+ CPpmd8_Node_Ref n = *prev;
+ p->Stamps[i] -= cnt;
+ for (;;)
{
- *next = node->Next;
- node = NODE(*next);
- p->Stamps[i]--;
- if (--count[i] == 0)
+ CPpmd8_Node *node = NODE(n);
+ n = node->Next;
+ if (node->Stamp != 0)
+ {
+ prev = &node->Next;
+ continue;
+ }
+ *prev = n;
+ if (--cnt == 0)
break;
}
- next = &node->Next;
}
}
}
-#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
+#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
{
- (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
- (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
+ Ppmd_SET_SUCCESSOR(p, v);
}
#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
-static void RestartModel(CPpmd8 *p)
+MY_NO_INLINE
+static
+void RestartModel(CPpmd8 *p)
{
- unsigned i, k, m, r;
+ unsigned i, k, m;
memset(p->FreeList, 0, sizeof(p->FreeList));
memset(p->Stamps, 0, sizeof(p->Stamps));
@@ -355,30 +435,47 @@ static void RestartModel(CPpmd8 *p)
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
p->PrevSuccess = 0;
- p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
- p->MinContext->Suffix = 0;
- p->MinContext->NumStats = 255;
- p->MinContext->Flags = 0;
- p->MinContext->SummFreq = 256 + 1;
- p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
- p->LoUnit += U2B(256 / 2);
- p->MinContext->Stats = REF(p->FoundState);
- for (i = 0; i < 256; i++)
{
- CPpmd_State *s = &p->FoundState[i];
- s->Symbol = (Byte)i;
- s->Freq = 1;
- SetSuccessor(s, 0);
+ CPpmd8_Context *mc = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
+ CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
+
+ p->LoUnit += U2B(256 / 2);
+ p->MaxContext = p->MinContext = mc;
+ p->FoundState = s;
+ mc->Flags = 0;
+ mc->NumStats = 256 - 1;
+ mc->Union2.SummFreq = 256 + 1;
+ mc->Union4.Stats = REF(s);
+ mc->Suffix = 0;
+
+ for (i = 0; i < 256; i++, s++)
+ {
+ s->Symbol = (Byte)i;
+ s->Freq = 1;
+ SetSuccessor(s, 0);
+ }
}
+
+
+
+
+
+
+
+
+
+
+
for (i = m = 0; m < 25; m++)
{
while (p->NS2Indx[i] == m)
i++;
for (k = 0; k < 8; k++)
{
- UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));
+ unsigned r;
UInt16 *dest = p->BinSumm[m] + k;
+ UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));
for (r = 0; r < 64; r += 8)
dest[r] = val;
}
@@ -386,50 +483,104 @@ static void RestartModel(CPpmd8 *p)
for (i = m = 0; m < 24; m++)
{
+ unsigned summ;
+ CPpmd_See *s;
while (p->NS2Indx[(size_t)i + 3] == m + 3)
i++;
- for (k = 0; k < 32; k++)
+ s = p->See[m];
+ summ = ((2 * i + 5) << (PPMD_PERIOD_BITS - 4));
+ for (k = 0; k < 32; k++, s++)
{
- CPpmd_See *s = &p->See[m][k];
- s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4));
+ s->Summ = (UInt16)summ;
+ s->Shift = (PPMD_PERIOD_BITS - 4);
s->Count = 7;
}
}
+
+ p->DummySee.Summ = 0; /* unused */
+ p->DummySee.Shift = PPMD_PERIOD_BITS;
+ p->DummySee.Count = 64; /* unused */
}
+
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)
{
p->MaxOrder = maxOrder;
p->RestoreMethod = restoreMethod;
RestartModel(p);
- p->DummySee.Shift = PPMD_PERIOD_BITS;
- p->DummySee.Summ = 0; /* unused */
- p->DummySee.Count = 64; /* unused */
}
+
+#define FLAG_RESCALED (1 << 2)
+// #define FLAG_SYM_HIGH (1 << 3)
+#define FLAG_PREV_HIGH (1 << 4)
+
+#define HiBits_Prepare(sym) ((unsigned)(sym) + 0xC0)
+
+#define HiBits_Convert_3(flags) (((flags) >> (8 - 3)) & (1 << 3))
+#define HiBits_Convert_4(flags) (((flags) >> (8 - 4)) & (1 << 4))
+
+#define PPMD8_HiBitsFlag_3(sym) HiBits_Convert_3(HiBits_Prepare(sym))
+#define PPMD8_HiBitsFlag_4(sym) HiBits_Convert_4(HiBits_Prepare(sym))
+
+// #define PPMD8_HiBitsFlag_3(sym) (0x08 * ((sym) >= 0x40))
+// #define PPMD8_HiBitsFlag_4(sym) (0x10 * ((sym) >= 0x40))
+
+/*
+Refresh() is called when we remove some symbols (successors) in context.
+It increases Escape_Freq for sum of all removed symbols.
+*/
+
static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)
{
unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
- ctx->Stats = REF(s);
- #ifdef PPMD8_FREEZE_SUPPORT
- /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */
- scale |= (ctx->SummFreq >= ((UInt32)1 << 15));
- #endif
- flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
- escFreq = ctx->SummFreq - s->Freq;
- sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));
+ ctx->Union4.Stats = REF(s);
+
+ // #ifdef PPMD8_FREEZE_SUPPORT
+ /*
+ (ctx->Union2.SummFreq >= ((UInt32)1 << 15)) can be in FREEZE mode for some files.
+ It's not good for range coder. So new versions of support fix:
+ - original PPMdI code rev.1
+ + original PPMdI code rev.2
+ - 7-Zip default ((PPMD8_FREEZE_SUPPORT is not defined)
+ + 7-Zip (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE)
+ if we use that fixed line, we can lose compatibility with some files created before fix
+ if we don't use that fixed line, the program can work incorrectly in FREEZE mode in rare case.
+ */
+ // if (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE)
+ {
+ scale |= (ctx->Union2.SummFreq >= ((UInt32)1 << 15));
+ }
+ // #endif
+
+
+
+ flags = HiBits_Prepare(s->Symbol);
+ {
+ unsigned freq = s->Freq;
+ escFreq = ctx->Union2.SummFreq - freq;
+ freq = (freq + scale) >> scale;
+ sumFreq = freq;
+ s->Freq = (Byte)freq;
+ }
+
do
{
- escFreq -= (++s)->Freq;
- sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale));
- flags |= 0x08 * (s->Symbol >= 0x40);
+ unsigned freq = (++s)->Freq;
+ escFreq -= freq;
+ freq = (freq + scale) >> scale;
+ sumFreq += freq;
+ s->Freq = (Byte)freq;
+ flags |= HiBits_Prepare(s->Symbol);
}
while (--i);
- ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));
- ctx->Flags = (Byte)flags;
+
+ ctx->Union2.SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));
+ ctx->Flags = (Byte)((ctx->Flags & (FLAG_PREV_HIGH + FLAG_RESCALED * scale)) + HiBits_Convert_3(flags));
}
+
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
{
CPpmd_State tmp = *t1;
@@ -437,98 +588,169 @@ static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
*t2 = tmp;
}
+
+/*
+CutOff() reduces contexts:
+ It conversts Successors at MaxOrder to another Contexts to NULL-Successors
+ It removes RAW-Successors and NULL-Successors that are not Order-0
+ and it removes contexts when it has no Successors.
+ if the (Union4.Stats) is close to (UnitsStart), it moves it up.
+*/
+
static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order)
{
- int i;
- unsigned tmp;
- CPpmd_State *s;
+ int ns = ctx->NumStats;
+ unsigned nu;
+ CPpmd_State *stats;
- if (!ctx->NumStats)
+ if (ns == 0)
{
- s = ONE_STATE(ctx);
- if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart)
+ CPpmd_State *s = ONE_STATE(ctx);
+ CPpmd_Void_Ref successor = SUCCESSOR(s);
+ if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart)
{
if (order < p->MaxOrder)
- SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
+ successor = CutOff(p, CTX(successor), order + 1);
else
- SetSuccessor(s, 0);
- if (SUCCESSOR(s) || order <= 9) /* O_BOUND */
+ successor = 0;
+ SetSuccessor(s, successor);
+ if (successor || order <= 9) /* O_BOUND */
return REF(ctx);
}
SpecialFreeUnit(p, ctx);
return 0;
}
- ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1));
+ nu = ((unsigned)ns + 2) >> 1;
+ // ctx->Union4.Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), nu));
+ {
+ unsigned indx = U2I(nu);
+ stats = STATS(ctx);
- for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--)
- if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart)
+ if ((UInt32)((Byte *)stats - p->UnitsStart) <= (1 << 14)
+ && (CPpmd_Void_Ref)ctx->Union4.Stats <= p->FreeList[indx])
{
- CPpmd_State *s2 = STATS(ctx) + (i--);
- SetSuccessor(s, 0);
- SwapStates(s, s2);
+ void *ptr = RemoveNode(p, indx);
+ ctx->Union4.Stats = STATS_REF(ptr);
+ MyMem12Cpy(ptr, (const void *)stats, nu);
+ if ((Byte *)stats != p->UnitsStart)
+ InsertNode(p, stats, indx);
+ else
+ p->UnitsStart += U2B(I2U(indx));
+ stats = ptr;
}
- else if (order < p->MaxOrder)
- SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
- else
- SetSuccessor(s, 0);
-
- if (i != ctx->NumStats && order)
+ }
+
+ {
+ CPpmd_State *s = stats + (unsigned)ns;
+ do
+ {
+ CPpmd_Void_Ref successor = SUCCESSOR(s);
+ if ((Byte *)Ppmd8_GetPtr(p, successor) < p->UnitsStart)
+ {
+ CPpmd_State *s2 = stats + (unsigned)(ns--);
+ if (order)
+ {
+ if (s != s2)
+ *s = *s2;
+ }
+ else
+ {
+ SwapStates(s, s2);
+ SetSuccessor(s2, 0);
+ }
+ }
+ else
+ {
+ if (order < p->MaxOrder)
+ SetSuccessor(s, CutOff(p, CTX(successor), order + 1));
+ else
+ SetSuccessor(s, 0);
+ }
+ }
+ while (--s >= stats);
+ }
+
+ if (ns != ctx->NumStats && order)
{
- ctx->NumStats = (Byte)i;
- s = STATS(ctx);
- if (i < 0)
+ if (ns < 0)
{
- FreeUnits(p, s, tmp);
+ FreeUnits(p, stats, nu);
SpecialFreeUnit(p, ctx);
return 0;
}
- if (i == 0)
+ ctx->NumStats = (Byte)ns;
+ if (ns == 0)
{
- ctx->Flags = (Byte)((ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
- *ONE_STATE(ctx) = *s;
- FreeUnits(p, s, tmp);
- /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */
- ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3);
+ const Byte sym = stats->Symbol;
+ ctx->Flags = (Byte)((ctx->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(sym));
+ // *ONE_STATE(ctx) = *stats;
+ ctx->Union2.State2.Symbol = sym;
+ ctx->Union2.State2.Freq = (Byte)(((unsigned)stats->Freq + 11) >> 3);
+ ctx->Union4.State4.Successor_0 = stats->Successor_0;
+ ctx->Union4.State4.Successor_1 = stats->Successor_1;
+ FreeUnits(p, stats, nu);
}
else
- Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i);
+ {
+ Refresh(p, ctx, nu, ctx->Union2.SummFreq > 16 * (unsigned)ns);
+ }
}
+
return REF(ctx);
}
+
+
#ifdef PPMD8_FREEZE_SUPPORT
+
+/*
+RemoveBinContexts()
+ It conversts Successors at MaxOrder to another Contexts to NULL-Successors
+ It changes RAW-Successors to NULL-Successors
+ removes Bin Context without Successor, if suffix of that context is also binary.
+*/
+
static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order)
{
- CPpmd_State *s;
if (!ctx->NumStats)
{
- s = ONE_STATE(ctx);
- if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
- SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
+ CPpmd_State *s = ONE_STATE(ctx);
+ CPpmd_Void_Ref successor = SUCCESSOR(s);
+ if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder)
+ successor = RemoveBinContexts(p, CTX(successor), order + 1);
else
- SetSuccessor(s, 0);
+ successor = 0;
+ SetSuccessor(s, successor);
/* Suffix context can be removed already, since different (high-order)
Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */
- if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))
+ if (!successor && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))
{
FreeUnits(p, ctx, 1);
return 0;
}
- else
- return REF(ctx);
}
-
- for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--)
- if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
- SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
- else
- SetSuccessor(s, 0);
+ else
+ {
+ CPpmd_State *s = STATS(ctx) + ctx->NumStats;
+ do
+ {
+ CPpmd_Void_Ref successor = SUCCESSOR(s);
+ if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder)
+ SetSuccessor(s, RemoveBinContexts(p, CTX(successor), order + 1));
+ else
+ SetSuccessor(s, 0);
+ }
+ while (--s >= STATS(ctx));
+ }
return REF(ctx);
}
+
#endif
+
+
static UInt32 GetUsedMemory(const CPpmd8 *p)
{
UInt32 v = 0;
@@ -544,7 +766,8 @@ static UInt32 GetUsedMemory(const CPpmd8 *p)
#define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)
#endif
-static void RestoreModel(CPpmd8 *p, CTX_PTR c1
+
+static void RestoreModel(CPpmd8 *p, CTX_PTR ctxError
#ifdef PPMD8_FREEZE_SUPPORT
, CTX_PTR fSuccessor
#endif
@@ -553,36 +776,55 @@ static void RestoreModel(CPpmd8 *p, CTX_PTR c1
CTX_PTR c;
CPpmd_State *s;
RESET_TEXT(0);
- for (c = p->MaxContext; c != c1; c = SUFFIX(c))
+
+ // we go here in cases of error of allocation for context (c1)
+ // Order(MinContext) < Order(ctxError) <= Order(MaxContext)
+
+ // We remove last symbol from each of contexts [p->MaxContext ... ctxError) contexts
+ // So we rollback all created (symbols) before error.
+ for (c = p->MaxContext; c != ctxError; c = SUFFIX(c))
if (--(c->NumStats) == 0)
{
s = STATS(c);
- c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
- *ONE_STATE(c) = *s;
+ c->Flags = (Byte)((c->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(s->Symbol));
+ // *ONE_STATE(c) = *s;
+ c->Union2.State2.Symbol = s->Symbol;
+ c->Union2.State2.Freq = (Byte)(((unsigned)s->Freq + 11) >> 3);
+ c->Union4.State4.Successor_0 = s->Successor_0;
+ c->Union4.State4.Successor_1 = s->Successor_1;
+
SpecialFreeUnit(p, s);
- ONE_STATE(c)->Freq = (Byte)(((unsigned)ONE_STATE(c)->Freq + 11) >> 3);
}
else
- Refresh(p, c, (c->NumStats+3) >> 1, 0);
+ {
+ /* Refresh() can increase Escape_Freq on value of Freq of last symbol, that was added before error.
+ so the largest possible increase for Escape_Freq is (8) from value before ModelUpoadet() */
+ Refresh(p, c, ((unsigned)c->NumStats + 3) >> 1, 0);
+ }
+ // increase Escape Freq for context [ctxError ... p->MinContext)
for (; c != p->MinContext; c = SUFFIX(c))
- if (!c->NumStats)
- ONE_STATE(c)->Freq = (Byte)(ONE_STATE(c)->Freq - (ONE_STATE(c)->Freq >> 1));
- else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats)
- Refresh(p, c, (c->NumStats + 2) >> 1, 1);
+ if (c->NumStats == 0)
+ {
+ // ONE_STATE(c)
+ c->Union2.State2.Freq = (Byte)(((unsigned)c->Union2.State2.Freq + 1) >> 1);
+ }
+ else if ((c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 4)) > 128 + 4 * c->NumStats)
+ Refresh(p, c, ((unsigned)c->NumStats + 2) >> 1, 1);
#ifdef PPMD8_FREEZE_SUPPORT
if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
{
p->MaxContext = fSuccessor;
- p->GlueCount += !(p->Stamps[1] & 1);
+ p->GlueCount += !(p->Stamps[1] & 1); // why?
}
else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)
{
while (p->MaxContext->Suffix)
p->MaxContext = SUFFIX(p->MaxContext);
RemoveBinContexts(p, p->MaxContext, 0);
- p->RestoreMethod++;
+ // we change the current mode to (PPMD8_RESTORE_METHOD_FREEZE + 1)
+ p->RestoreMethod = PPMD8_RESTORE_METHOD_FREEZE + 1;
p->GlueCount = 0;
p->OrderFall = p->MaxOrder;
}
@@ -603,16 +845,19 @@ static void RestoreModel(CPpmd8 *p, CTX_PTR c1
p->GlueCount = 0;
p->OrderFall = p->MaxOrder;
}
+ p->MinContext = p->MaxContext;
}
+
+
+MY_NO_INLINE
static CTX_PTR CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, CTX_PTR c)
{
- CPpmd_State upState;
- Byte flags;
+
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
- /* fixed over Shkarin's code. Maybe it could work without + 1 too. */
- CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
+ Byte newSym, newFreq, flags;
unsigned numPs = 0;
+ CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; /* fixed over Shkarin's code. Maybe it could work without + 1 too. */
if (!skip)
ps[numPs++] = p->FoundState;
@@ -622,19 +867,13 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, CTX_PT
CPpmd_Void_Ref successor;
CPpmd_State *s;
c = SUFFIX(c);
- if (s1)
- {
- s = s1;
- s1 = NULL;
- }
+
+ if (s1) { s = s1; s1 = NULL; }
else if (c->NumStats != 0)
{
- for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
- if (s->Freq < MAX_FREQ - 9)
- {
- s->Freq++;
- c->SummFreq++;
- }
+ Byte sym = p->FoundState->Symbol;
+ for (s = STATS(c); s->Symbol != sym; s++);
+ if (s->Freq < MAX_FREQ - 9) { s->Freq++; c->Union2.SummFreq++; }
}
else
{
@@ -644,36 +883,54 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, CTX_PT
successor = SUCCESSOR(s);
if (successor != upBranch)
{
+
c = CTX(successor);
if (numPs == 0)
+ {
+
+
return c;
+ }
break;
}
ps[numPs++] = s;
}
- upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch);
- SetSuccessor(&upState, upBranch + 1);
- flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40));
-
+
+
+
+
+ newSym = *(const Byte *)Ppmd8_GetPtr(p, upBranch);
+ upBranch++;
+ flags = (Byte)(PPMD8_HiBitsFlag_4(p->FoundState->Symbol) + PPMD8_HiBitsFlag_3(newSym));
+
if (c->NumStats == 0)
- upState.Freq = ONE_STATE(c)->Freq;
+ newFreq = c->Union2.State2.Freq;
else
{
UInt32 cf, s0;
CPpmd_State *s;
- for (s = STATS(c); s->Symbol != upState.Symbol; s++);
- cf = s->Freq - 1;
- s0 = c->SummFreq - c->NumStats - cf;
- upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
+ for (s = STATS(c); s->Symbol != newSym; s++);
+ cf = (UInt32)s->Freq - 1;
+ s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf;
+ /*
+
+
+ max(newFreq)= (s->Freq - 1), when (s0 == 1)
+
+
+ */
+ newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
}
+
+
do
{
- /* Create Child */
- CTX_PTR c1; /* = AllocContext(p); */
+ CTX_PTR c1;
+ /* = AllocContext(p); */
if (p->HiUnit != p->LoUnit)
- c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
+ c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE);
else if (p->FreeList[0] != 0)
c1 = (CTX_PTR)RemoveNode(p, 0);
else
@@ -682,9 +939,11 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, CTX_PT
if (!c1)
return NULL;
}
- c1->NumStats = 0;
c1->Flags = flags;
- *ONE_STATE(c1) = upState;
+ c1->NumStats = 0;
+ c1->Union2.State2.Symbol = newSym;
+ c1->Union2.State2.Freq = newFreq;
+ SetSuccessor(ONE_STATE(c1), upBranch);
c1->Suffix = REF(c);
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
@@ -694,6 +953,7 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, CTX_PT
return c;
}
+
static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
{
CPpmd_State *s = NULL;
@@ -739,8 +999,8 @@ static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
do { s++; } while (s->Symbol != p->FoundState->Symbol);
if (s->Freq < MAX_FREQ - 9)
{
- s->Freq += 2;
- c->SummFreq += 2;
+ s->Freq = (Byte)(s->Freq + 2);
+ c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);
}
}
else
@@ -776,33 +1036,42 @@ static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
p->FoundState = s;
successor = CreateSuccessors(p, False, NULL, c);
- if (successor == NULL)
+ if (!successor)
SetSuccessor(s, 0);
else
SetSuccessor(s, REF(successor));
p->FoundState = s2;
}
- if (p->OrderFall == 1 && c1 == p->MaxContext)
{
- SetSuccessor(p->FoundState, SUCCESSOR(s));
- p->Text--;
+ CPpmd_Void_Ref successor = SUCCESSOR(s);
+ if (p->OrderFall == 1 && c1 == p->MaxContext)
+ {
+ SetSuccessor(p->FoundState, successor);
+ p->Text--;
+ }
+ if (successor == 0)
+ return NULL;
+ return CTX(successor);
}
- if (SUCCESSOR(s) == 0)
- return NULL;
- return CTX(SUCCESSOR(s));
}
-static void UpdateModel(CPpmd8 *p)
+
+
+void Ppmd8_UpdateModel(CPpmd8 *p);
+MY_NO_INLINE
+void Ppmd8_UpdateModel(CPpmd8 *p)
{
- CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
+ CPpmd_Void_Ref maxSuccessor, minSuccessor = SUCCESSOR(p->FoundState);
CTX_PTR c;
unsigned s0, ns, fFreq = p->FoundState->Freq;
Byte flag, fSymbol = p->FoundState->Symbol;
+ {
CPpmd_State *s = NULL;
-
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
{
+ /* Update Freqs in Suffix Context */
+
c = SUFFIX(p->MinContext);
if (c->NumStats == 0)
@@ -813,91 +1082,134 @@ static void UpdateModel(CPpmd8 *p)
}
else
{
+ Byte sym = p->FoundState->Symbol;
s = STATS(c);
- if (s->Symbol != p->FoundState->Symbol)
+
+ if (s->Symbol != sym)
{
- do { s++; } while (s->Symbol != p->FoundState->Symbol);
+ do
+ {
+
+ s++;
+ }
+ while (s->Symbol != sym);
+
if (s[0].Freq >= s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
s--;
}
}
+
if (s->Freq < MAX_FREQ - 9)
{
- s->Freq += 2;
- c->SummFreq += 2;
+ s->Freq = (Byte)(s->Freq + 2);
+ c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);
}
}
}
c = p->MaxContext;
- if (p->OrderFall == 0 && fSuccessor)
+ if (p->OrderFall == 0 && minSuccessor)
{
CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext);
- if (cs == 0)
+ if (!cs)
{
SetSuccessor(p->FoundState, 0);
- RESTORE_MODEL(c, CTX(fSuccessor));
- }
- else
- {
- SetSuccessor(p->FoundState, REF(cs));
- p->MaxContext = cs;
+ RESTORE_MODEL(c, CTX(minSuccessor));
+ return;
}
+ SetSuccessor(p->FoundState, REF(cs));
+ p->MinContext = p->MaxContext = cs;
return;
}
- *p->Text++ = p->FoundState->Symbol;
- successor = REF(p->Text);
- if (p->Text >= p->UnitsStart)
+
+
+
{
- RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */
- return;
+ Byte *text = p->Text;
+ *text++ = p->FoundState->Symbol;
+ p->Text = text;
+ if (text >= p->UnitsStart)
+ {
+ RESTORE_MODEL(c, CTX(minSuccessor)); /* check it */
+ return;
+ }
+ maxSuccessor = REF(text);
}
-
- if (!fSuccessor)
+
+ if (!minSuccessor)
{
CTX_PTR cs = ReduceOrder(p, s, p->MinContext);
- if (cs == NULL)
+ if (!cs)
{
- RESTORE_MODEL(c, 0);
+ RESTORE_MODEL(c, NULL);
return;
}
- fSuccessor = REF(cs);
+ minSuccessor = REF(cs);
}
- else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart)
+ else if ((Byte *)Ppmd8_GetPtr(p, minSuccessor) < p->UnitsStart)
{
CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext);
- if (cs == NULL)
+ if (!cs)
{
- RESTORE_MODEL(c, 0);
+ RESTORE_MODEL(c, NULL);
return;
}
- fSuccessor = REF(cs);
+ minSuccessor = REF(cs);
}
if (--p->OrderFall == 0)
{
- successor = fSuccessor;
+ maxSuccessor = minSuccessor;
p->Text -= (p->MaxContext != p->MinContext);
}
#ifdef PPMD8_FREEZE_SUPPORT
else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
{
- successor = fSuccessor;
+ maxSuccessor = minSuccessor;
RESET_TEXT(0);
p->OrderFall = 0;
}
#endif
+ }
+
+
+
+
+
+
+
+
+
+
- s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq;
- flag = (Byte)(0x08 * (fSymbol >= 0x40));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flag = (Byte)(PPMD8_HiBitsFlag_3(fSymbol));
+ s0 = p->MinContext->Union2.SummFreq - (ns = p->MinContext->NumStats) - fFreq;
for (; c != p->MinContext; c = SUFFIX(c))
{
unsigned ns1;
- UInt32 cf, sf;
+ UInt32 sum;
+
if ((ns1 = c->NumStats) != 0)
{
if ((ns1 & 1) != 0)
@@ -911,91 +1223,133 @@ static void UpdateModel(CPpmd8 *p)
void *oldPtr;
if (!ptr)
{
- RESTORE_MODEL(c, CTX(fSuccessor));
+ RESTORE_MODEL(c, CTX(minSuccessor));
return;
}
oldPtr = STATS(c);
MyMem12Cpy(ptr, oldPtr, oldNU);
InsertNode(p, oldPtr, i);
- c->Stats = STATS_REF(ptr);
+ c->Union4.Stats = STATS_REF(ptr);
}
}
- c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns));
+ sum = c->Union2.SummFreq;
+ /* max increase of Escape_Freq is 1 here.
+ an average increase is 1/3 per symbol */
+ sum += (3 * ns1 + 1 < ns);
+ /* original PPMdH uses 16-bit variable for (sum) here.
+ But (sum < ???). Do we need to truncate (sum) to 16-bit */
+ // sum = (UInt16)sum;
}
else
{
- CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0);
- if (!s2)
+
+ CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
+ if (!s)
{
- RESTORE_MODEL(c, CTX(fSuccessor));
+ RESTORE_MODEL(c, CTX(minSuccessor));
return;
}
- *s2 = *ONE_STATE(c);
- c->Stats = REF(s2);
- if (s2->Freq < MAX_FREQ / 4 - 1)
- s2->Freq <<= 1;
- else
- s2->Freq = MAX_FREQ - 4;
- c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2));
- }
- cf = 2 * fFreq * (c->SummFreq + 6);
- sf = (UInt32)s0 + c->SummFreq;
- if (cf < 6 * sf)
- {
- cf = 1 + (cf > sf) + (cf >= 4 * sf);
- c->SummFreq += 4;
- }
- else
- {
- cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);
- c->SummFreq = (UInt16)(c->SummFreq + cf);
+ {
+ unsigned freq = c->Union2.State2.Freq;
+ // s = *ONE_STATE(c);
+ s->Symbol = c->Union2.State2.Symbol;
+ s->Successor_0 = c->Union4.State4.Successor_0;
+ s->Successor_1 = c->Union4.State4.Successor_1;
+ // SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of
+ // (Successor_0 and Successor_1) in LE/BE.
+ c->Union4.Stats = REF(s);
+ if (freq < MAX_FREQ / 4 - 1)
+ freq <<= 1;
+ else
+ freq = MAX_FREQ - 4;
+
+ s->Freq = (Byte)freq;
+
+ sum = freq + p->InitEsc + (ns > 2); // Ppmd8 (> 2)
+ }
}
+
{
- CPpmd_State *s2 = STATS(c) + ns1 + 1;
- SetSuccessor(s2, successor);
- s2->Symbol = fSymbol;
- s2->Freq = (Byte)cf;
- c->Flags |= flag;
+ CPpmd_State *s = STATS(c) + ns1 + 1;
+ UInt32 cf = 2 * (sum + 6) * (UInt32)fFreq;
+ UInt32 sf = (UInt32)s0 + sum;
+ s->Symbol = fSymbol;
c->NumStats = (Byte)(ns1 + 1);
+ SetSuccessor(s, maxSuccessor);
+ c->Flags |= flag;
+ if (cf < 6 * sf)
+ {
+ cf = (unsigned)1 + (cf > sf) + (cf >= 4 * sf);
+ sum += 4;
+ /* It can add (1, 2, 3) to Escape_Freq */
+ }
+ else
+ {
+ cf = (unsigned)4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);
+ sum += cf;
+ }
+
+ c->Union2.SummFreq = (UInt16)sum;
+ s->Freq = (Byte)cf;
}
+
}
- p->MaxContext = p->MinContext = CTX(fSuccessor);
+ p->MaxContext = p->MinContext = CTX(minSuccessor);
}
+
+
+MY_NO_INLINE
static void Rescale(CPpmd8 *p)
{
unsigned i, adder, sumFreq, escFreq;
CPpmd_State *stats = STATS(p->MinContext);
CPpmd_State *s = p->FoundState;
+
+ /* Sort the list by Freq */
+ if (s != stats)
{
CPpmd_State tmp = *s;
- for (; s != stats; s--)
+ do
s[0] = s[-1];
+ while (--s != stats);
*s = tmp;
}
- escFreq = p->MinContext->SummFreq - s->Freq;
- s->Freq += 4;
- adder = (p->OrderFall != 0
- #ifdef PPMD8_FREEZE_SUPPORT
- || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE
- #endif
- );
- s->Freq = (Byte)((s->Freq + adder) >> 1);
+
sumFreq = s->Freq;
+ escFreq = p->MinContext->Union2.SummFreq - sumFreq;
+
+
+
+
+
+ adder = (p->OrderFall != 0);
+
+ #ifdef PPMD8_FREEZE_SUPPORT
+ adder |= (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE);
+ #endif
+
+ sumFreq = (sumFreq + 4 + adder) >> 1;
i = p->MinContext->NumStats;
+ s->Freq = (Byte)sumFreq;
+
do
{
- escFreq -= (++s)->Freq;
- s->Freq = (Byte)((s->Freq + adder) >> 1);
- sumFreq += s->Freq;
- if (s[0].Freq > s[-1].Freq)
+ unsigned freq = (++s)->Freq;
+ escFreq -= freq;
+ freq = (freq + adder) >> 1;
+ sumFreq += freq;
+ s->Freq = (Byte)freq;
+ if (freq > s[-1].Freq)
{
+ CPpmd_State tmp = *s;
CPpmd_State *s1 = s;
- CPpmd_State tmp = *s1;
do
+ {
s1[0] = s1[-1];
- while (--s1 != stats && tmp.Freq > s1[-1].Freq);
+ }
+ while (--s1 != stats && freq > s1[-1].Freq);
*s1 = tmp;
}
}
@@ -1003,49 +1357,89 @@ static void Rescale(CPpmd8 *p)
if (s->Freq == 0)
{
- unsigned numStats = p->MinContext->NumStats;
- unsigned n0, n1;
- do { i++; } while ((--s)->Freq == 0);
+ /* Remove all items with Freq == 0 */
+ CPpmd8_Context *mc;
+ unsigned numStats, numStatsNew, n0, n1;
+
+ i = 0; do { i++; } while ((--s)->Freq == 0);
+
+
+
+
escFreq += i;
- p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i);
- if (p->MinContext->NumStats == 0)
+ mc = p->MinContext;
+ numStats = mc->NumStats;
+ numStatsNew = numStats - i;
+ mc->NumStats = (Byte)(numStatsNew);
+ n0 = (numStats + 2) >> 1;
+
+ if (numStatsNew == 0)
{
- CPpmd_State tmp = *stats;
- tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq);
- if (tmp.Freq > MAX_FREQ / 3)
- tmp.Freq = MAX_FREQ / 3;
- InsertNode(p, stats, U2I((numStats + 2) >> 1));
- p->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40));
- *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
+
+ unsigned freq = (2 * (unsigned)stats->Freq + escFreq - 1) / escFreq;
+ if (freq > MAX_FREQ / 3)
+ freq = MAX_FREQ / 3;
+ mc->Flags = (Byte)((mc->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(stats->Symbol));
+
+
+
+
+
+ s = ONE_STATE(mc);
+ *s = *stats;
+ s->Freq = (Byte)freq;
+ p->FoundState = s;
+ InsertNode(p, stats, U2I(n0));
return;
}
- n0 = (numStats + 2) >> 1;
- n1 = (p->MinContext->NumStats + 2) >> 1;
+
+ n1 = (numStatsNew + 2) >> 1;
if (n0 != n1)
- p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
- p->MinContext->Flags &= ~0x08;
- p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40);
- i = p->MinContext->NumStats;
- do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i);
+ mc->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
+ {
+ // here we are for max order only. So Ppmd8_MakeEscFreq() doesn't use mc->Flags
+ // but we still need current (Flags & FLAG_PREV_HIGH), if we will convert context to 1-symbol context later.
+ /*
+ unsigned flags = HiBits_Prepare((s = STATS(mc))->Symbol);
+ i = mc->NumStats;
+ do { flags |= HiBits_Prepare((++s)->Symbol); } while (--i);
+ mc->Flags = (Byte)((mc->Flags & ~FLAG_SYM_HIGH) + HiBits_Convert_3(flags));
+ */
+ }
+ }
+
+
+
+
+
+
+ {
+ CPpmd8_Context *mc = p->MinContext;
+ mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
+ mc->Flags |= FLAG_RESCALED;
+ p->FoundState = STATS(mc);
}
- p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
- p->MinContext->Flags |= 0x4;
- p->FoundState = STATS(p->MinContext);
}
+
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
{
CPpmd_See *see;
- if (p->MinContext->NumStats != 0xFF)
+ const CPpmd8_Context *mc = p->MinContext;
+ unsigned numStats = mc->NumStats;
+ if (numStats != 0xFF)
{
- see = p->See[(size_t)(unsigned)p->NS2Indx[(size_t)(unsigned)p->MinContext->NumStats + 2] - 3] +
- (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +
- 2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats <
- ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +
- p->MinContext->Flags;
+ // (3 <= numStats + 2 <= 256) (3 <= NS2Indx[3] and NS2Indx[256] === 26)
+ see = p->See[(size_t)(unsigned)p->NS2Indx[(size_t)numStats + 2] - 3]
+ + (mc->Union2.SummFreq > 11 * (numStats + 1))
+ + 2 * (unsigned)(2 * numStats < ((unsigned)SUFFIX(mc)->NumStats + numMasked1))
+ + mc->Flags;
+
{
- unsigned r = (see->Summ >> see->Shift);
- see->Summ = (UInt16)(see->Summ - r);
+ // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
+ unsigned summ = (UInt16)see->Summ; // & 0xFFFF
+ unsigned r = (summ >> see->Shift);
+ see->Summ = (UInt16)(summ - r);
*escFreq = r + (r == 0);
}
}
@@ -1057,67 +1451,87 @@ CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
return see;
}
+
static void NextContext(CPpmd8 *p)
{
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
- if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart)
- p->MinContext = p->MaxContext = c;
+ if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)
+ p->MaxContext = p->MinContext = c;
else
- {
- UpdateModel(p);
- p->MinContext = p->MaxContext;
- }
+ Ppmd8_UpdateModel(p);
}
+
void Ppmd8_Update1(CPpmd8 *p)
{
CPpmd_State *s = p->FoundState;
- s->Freq += 4;
- p->MinContext->SummFreq += 4;
- if (s[0].Freq > s[-1].Freq)
+ unsigned freq = s->Freq;
+ freq += 4;
+ p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);
+ s->Freq = (Byte)freq;
+ if (freq > s[-1].Freq)
{
- SwapStates(&s[0], &s[-1]);
+ SwapStates(s, &s[-1]);
p->FoundState = --s;
- if (s->Freq > MAX_FREQ)
+ if (freq > MAX_FREQ)
Rescale(p);
}
NextContext(p);
}
+
void Ppmd8_Update1_0(CPpmd8 *p)
{
- p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);
- p->RunLength += p->PrevSuccess;
- p->MinContext->SummFreq += 4;
- if ((p->FoundState->Freq += 4) > MAX_FREQ)
+ CPpmd_State *s = p->FoundState;
+ CPpmd8_Context *mc = p->MinContext;
+ unsigned freq = s->Freq;
+ unsigned summFreq = mc->Union2.SummFreq;
+ p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=)
+ p->RunLength += (int)p->PrevSuccess;
+ mc->Union2.SummFreq = (UInt16)(summFreq + 4);
+ freq += 4;
+ s->Freq = (Byte)freq;
+ if (freq > MAX_FREQ)
Rescale(p);
NextContext(p);
}
+
+/*
void Ppmd8_UpdateBin(CPpmd8 *p)
{
- p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));
+ unsigned freq = p->FoundState->Freq;
+ p->FoundState->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196)
p->PrevSuccess = 1;
p->RunLength++;
NextContext(p);
}
+*/
void Ppmd8_Update2(CPpmd8 *p)
{
- p->MinContext->SummFreq += 4;
- if ((p->FoundState->Freq += 4) > MAX_FREQ)
- Rescale(p);
+ CPpmd_State *s = p->FoundState;
+ unsigned freq = s->Freq;
+ freq += 4;
p->RunLength = p->InitRL;
- UpdateModel(p);
- p->MinContext = p->MaxContext;
+ p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);
+ s->Freq = (Byte)freq;
+ if (freq > MAX_FREQ)
+ Rescale(p);
+ Ppmd8_UpdateModel(p);
}
/* H->I changes:
NS2Indx
- GlewCount, and Glue method
+ GlueCount, and Glue method
BinSum
See / EscFreq
CreateSuccessors updates more suffix contexts
- UpdateModel consts.
+ Ppmd8_UpdateModel consts.
PrevSuccess Update
+
+Flags:
+ (1 << 2) - the Context was Rescaled
+ (1 << 3) - there is symbol in Stats with (sym >= 0x40) in
+ (1 << 4) - main symbol of context is (sym >= 0x40)
*/