Files
sharpcompress/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs
Adam Hathcock 896dfd6537 some AI changes
2026-04-28 08:32:44 +01:00

1303 lines
40 KiB
C#

#nullable disable
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Compressors.Rar;
using Decoder = SharpCompress.Compressors.LZMA.RangeCoder.Decoder;
namespace SharpCompress.Compressors.PPMd.H;
internal class ModelPpm
{
private void InitBlock()
{
for (var i = 0; i < 25; i++)
{
_see2Cont[i] = new See2Context[16];
}
for (var i2 = 0; i2 < 128; i2++)
{
_binSumm[i2] = new int[64];
}
}
public SubAllocator SubAlloc { get; } = new();
public virtual See2Context DummySee2Cont => _dummySee2Cont;
public virtual int InitRl => _initRl;
public virtual int EscCount
{
get => _escCount;
set => _escCount = value & 0xff;
}
public virtual int[] CharMask => _charMask;
public virtual int NumMasked
{
get => _numMasked;
set => _numMasked = value;
}
public virtual int PrevSuccess
{
get => _prevSuccess;
set => _prevSuccess = value & 0xff;
}
public virtual int InitEsc
{
get => _initEsc;
set => _initEsc = value;
}
public virtual int RunLength
{
get => _runLength;
set => _runLength = value;
}
public virtual int HiBitsFlag
{
get => _hiBitsFlag;
set => _hiBitsFlag = value & 0xff;
}
public virtual int[][] BinSumm => _binSumm;
internal RangeCoder Coder { get; private set; }
internal State FoundState { get; private set; }
public virtual byte[] Heap => SubAlloc.Heap;
public virtual int OrderFall => _orderFall;
public const int MAX_O = 64; /* maximum allowed model order */
public const int INT_BITS = 7;
public const int PERIOD_BITS = 7;
//UPGRADE_NOTE: Final was removed from the declaration of 'TOT_BITS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int TOT_BITS = INT_BITS + PERIOD_BITS;
//UPGRADE_NOTE: Final was removed from the declaration of 'INTERVAL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int INTERVAL = 1 << INT_BITS;
//UPGRADE_NOTE: Final was removed from the declaration of 'BIN_SCALE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int BIN_SCALE = 1 << TOT_BITS;
public const int MAX_FREQ = 124;
private readonly See2Context[][] _see2Cont = new See2Context[25][];
private See2Context _dummySee2Cont;
private PpmContext _minContext; //medContext
private PpmContext _maxContext;
private int _numMasked,
_initEsc,
_orderFall,
_maxOrder,
_runLength,
_initRl;
private readonly int[] _charMask = new int[256];
private readonly int[] _ns2Indx = new int[256];
private readonly int[] _ns2BsIndx = new int[256];
private readonly int[] _hb2Flag = new int[256];
// byte EscCount, PrevSuccess, HiBitsFlag;
private int _escCount,
_prevSuccess,
_hiBitsFlag;
private readonly int[][] _binSumm = new int[128][]; // binary SEE-contexts
private static readonly int[] INIT_BIN_ESC =
{
0x3CDD,
0x1F3F,
0x59BF,
0x48F3,
0x64A1,
0x5ABC,
0x6632,
0x6051,
};
// Temp fields
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly State _tempState1 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly State _tempState2 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly State _tempState3 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly State _tempState4 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly StateRef _tempStateRef1 = new();
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly StateRef _tempStateRef2 = new();
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly PpmContext _tempPpmContext1 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly PpmContext _tempPpmContext2 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly PpmContext _tempPpmContext3 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly PpmContext _tempPpmContext4 = new(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private readonly int[] _ps = new int[MAX_O];
public ModelPpm()
{
InitBlock();
_minContext = null;
_maxContext = null;
//medContext = null;
}
private void RestartModelRare()
{
new Span<int>(_charMask).Clear();
SubAlloc.InitSubAllocator();
_initRl = -(_maxOrder < 12 ? _maxOrder : 12) - 1;
var addr = SubAlloc.AllocContext();
_minContext.Address = addr;
_maxContext.Address = addr;
_minContext.SetSuffix(0);
_orderFall = _maxOrder;
_minContext.NumStats = 256;
_minContext.FreqData.SummFreq = _minContext.NumStats + 1;
addr = SubAlloc.AllocUnits(256 / 2);
FoundState.Address = addr;
_minContext.FreqData.SetStats(addr);
var state = new State(SubAlloc.Heap);
addr = _minContext.FreqData.GetStats();
_runLength = _initRl;
_prevSuccess = 0;
for (var i = 0; i < 256; i++)
{
state.Address = addr + (i * State.SIZE);
state.Symbol = i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (var i = 0; i < 128; i++)
{
for (var k = 0; k < 8; k++)
{
for (var m = 0; m < 64; m += 8)
{
_binSumm[i][k + m] = BIN_SCALE - (INIT_BIN_ESC[k] / (i + 2));
}
}
}
for (var i = 0; i < 25; i++)
{
for (var k = 0; k < 16; k++)
{
_see2Cont[i][k].Initialize((5 * i) + 10);
}
}
}
private void StartModelRare(int maxOrder)
{
int i,
k,
m,
step;
_escCount = 1;
_maxOrder = maxOrder;
RestartModelRare();
// Bug Fixed
_ns2BsIndx[0] = 0;
_ns2BsIndx[1] = 2;
for (var j = 0; j < 9; j++)
{
_ns2BsIndx[2 + j] = 4;
}
for (var j = 0; j < 256 - 11; j++)
{
_ns2BsIndx[11 + j] = 6;
}
for (i = 0; i < 3; i++)
{
_ns2Indx[i] = i;
}
for (m = i, k = 1, step = 1; i < 256; i++)
{
_ns2Indx[i] = m;
if ((--k) == 0)
{
k = ++step;
m++;
}
}
for (var j = 0; j < 0x40; j++)
{
_hb2Flag[j] = 0;
}
for (var j = 0; j < 0x100 - 0x40; j++)
{
_hb2Flag[0x40 + j] = 0x08;
}
_dummySee2Cont.Shift = PERIOD_BITS;
}
private void ClearMask()
{
_escCount = 1;
new Span<int>(_charMask).Clear();
}
internal bool DecodeInit(IRarUnpack unpackRead, int escChar)
{
var maxOrder = unpackRead.Char & 0xff;
var reset = ((maxOrder & 0x20) != 0);
var maxMb = 0;
if (reset)
{
maxMb = unpackRead.Char;
}
else
{
if (SubAlloc.GetAllocatedMemory() == 0)
{
return (false);
}
}
if ((maxOrder & 0x40) != 0)
{
escChar = unpackRead.Char;
unpackRead.PpmEscChar = escChar;
}
Coder = new RangeCoder(unpackRead);
if (reset)
{
maxOrder = (maxOrder & 0x1f) + 1;
if (maxOrder > 16)
{
maxOrder = 16 + ((maxOrder - 16) * 3);
}
if (maxOrder == 1)
{
SubAlloc.StopSubAllocator();
return (false);
}
SubAlloc.StartSubAllocator((maxMb + 1) << 20);
_minContext = new PpmContext(Heap);
//medContext = new PPMContext(Heap);
_maxContext = new PpmContext(Heap);
FoundState = new State(Heap);
_dummySee2Cont = new See2Context();
for (var i = 0; i < 25; i++)
{
for (var j = 0; j < 16; j++)
{
_see2Cont[i][j] = new See2Context();
}
}
StartModelRare(maxOrder);
}
return (_minContext.Address != 0);
}
internal async ValueTask<bool> DecodeInitAsync(
IRarUnpack unpackRead,
int escChar,
CancellationToken cancellationToken = default
)
{
var maxOrder =
await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false) & 0xff;
var reset = ((maxOrder & 0x20) != 0);
var maxMb = 0;
if (reset)
{
maxMb = await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false);
}
else
{
if (SubAlloc.GetAllocatedMemory() == 0)
{
return false;
}
}
if ((maxOrder & 0x40) != 0)
{
escChar = await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false);
unpackRead.PpmEscChar = escChar;
}
Coder = new RangeCoder();
await Coder.InitAsync(unpackRead, cancellationToken).ConfigureAwait(false);
if (reset)
{
maxOrder = (maxOrder & 0x1f) + 1;
if (maxOrder > 16)
{
maxOrder = 16 + ((maxOrder - 16) * 3);
}
if (maxOrder == 1)
{
SubAlloc.StopSubAllocator();
return false;
}
SubAlloc.StartSubAllocator((maxMb + 1) << 20);
_minContext = new PpmContext(Heap);
_maxContext = new PpmContext(Heap);
FoundState = new State(Heap);
_dummySee2Cont = new See2Context();
for (var i = 0; i < 25; i++)
{
for (var j = 0; j < 16; j++)
{
_see2Cont[i][j] = new See2Context();
}
}
StartModelRare(maxOrder);
}
return _minContext.Address != 0;
}
public virtual int DecodeChar()
{
// Debug
//subAlloc.dumpHeap();
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return (-1);
}
if (_minContext.NumStats != 1)
{
if (
_minContext.FreqData.GetStats() <= SubAlloc.PText
|| _minContext.FreqData.GetStats() > SubAlloc.HeapEnd
)
{
return (-1);
}
if (!_minContext.DecodeSymbol1(this))
{
return (-1);
}
}
else
{
_minContext.DecodeBinSymbol(this);
}
Coder.Decode();
while (FoundState.Address == 0)
{
Coder.AriDecNormalize();
do
{
_orderFall++;
_minContext.Address = _minContext.GetSuffix(); // =MinContext->Suffix;
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return (-1);
}
} while (_minContext.NumStats == _numMasked);
if (!_minContext.DecodeSymbol2(this))
{
return (-1);
}
Coder.Decode();
}
var symbol = FoundState.Symbol;
if ((_orderFall == 0) && FoundState.GetSuccessor() > SubAlloc.PText)
{
// MinContext=MaxContext=FoundState->Successor;
var addr = FoundState.GetSuccessor();
_minContext.Address = addr;
_maxContext.Address = addr;
}
else
{
UpdateModel();
//this.foundState.Address=foundState.Address);//TODO just 4 debugging
if (_escCount == 0)
{
ClearMask();
}
}
Coder.AriDecNormalize(); // ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return (symbol);
}
public virtual async ValueTask<int> DecodeCharAsync(
CancellationToken cancellationToken = default
)
{
// Debug
//subAlloc.dumpHeap();
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return (-1);
}
if (_minContext.NumStats != 1)
{
if (
_minContext.FreqData.GetStats() <= SubAlloc.PText
|| _minContext.FreqData.GetStats() > SubAlloc.HeapEnd
)
{
return (-1);
}
if (!_minContext.DecodeSymbol1(this))
{
return (-1);
}
}
else
{
_minContext.DecodeBinSymbol(this);
}
Coder.Decode();
while (FoundState.Address == 0)
{
await Coder.AriDecNormalizeAsync(cancellationToken).ConfigureAwait(false);
do
{
_orderFall++;
_minContext.Address = _minContext.GetSuffix(); // =MinContext->Suffix;
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return (-1);
}
} while (_minContext.NumStats == _numMasked);
if (!_minContext.DecodeSymbol2(this))
{
return (-1);
}
Coder.Decode();
}
var symbol = FoundState.Symbol;
if ((_orderFall == 0) && FoundState.GetSuccessor() > SubAlloc.PText)
{
// MinContext=MaxContext=FoundState->Successor;
var addr = FoundState.GetSuccessor();
_minContext.Address = addr;
_maxContext.Address = addr;
}
else
{
UpdateModel();
//this.foundState.Address=foundState.Address);//TODO just 4 debugging
if (_escCount == 0)
{
ClearMask();
}
}
await Coder.AriDecNormalizeAsync(cancellationToken).ConfigureAwait(false); // ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return (symbol);
}
public virtual See2Context[][] GetSee2Cont() => _see2Cont;
public virtual void IncEscCount(int dEscCount) => EscCount += dEscCount;
public virtual void IncRunLength(int dRunLength) => RunLength += dRunLength;
public virtual int[] GetHb2Flag() => _hb2Flag;
public virtual int[] GetNs2BsIndx() => _ns2BsIndx;
public virtual int[] GetNs2Indx() => _ns2Indx;
private int CreateSuccessors(bool skip, State p1)
{
//State upState = tempState1.Initialize(null);
var upState = _tempStateRef2;
var tempState = _tempState1.Initialize(Heap);
// PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
var pc = _tempPpmContext1.Initialize(Heap);
pc.Address = _minContext.Address;
var upBranch = _tempPpmContext2.Initialize(Heap);
upBranch.Address = FoundState.GetSuccessor();
// STATE * p, * ps[MAX_O], ** pps=ps;
var p = _tempState2.Initialize(Heap);
var pps = 0;
var noLoop = false;
if (!skip)
{
_ps[pps++] = FoundState.Address; // *pps++ = FoundState;
if (pc.GetSuffix() == 0)
{
noLoop = true;
}
}
if (!noLoop)
{
var loopEntry = false;
if (p1.Address != 0)
{
p.Address = p1.Address;
pc.Address = pc.GetSuffix(); // =pc->Suffix;
loopEntry = true;
}
do
{
if (!loopEntry)
{
pc.Address = pc.GetSuffix(); // pc=pc->Suffix;
if (pc.NumStats != 1)
{
p.Address = pc.FreqData.GetStats(); // p=pc->U.Stats
if (p.Symbol != FoundState.Symbol)
{
do
{
p.IncrementAddress();
} while (p.Symbol != FoundState.Symbol);
}
}
else
{
p.Address = pc.GetOneState().Address; // p=&(pc->OneState);
}
} // LOOP_ENTRY:
loopEntry = false;
if (p.GetSuccessor() != upBranch.Address)
{
pc.Address = p.GetSuccessor(); // =p->Successor;
break;
}
_ps[pps++] = p.Address;
} while (pc.GetSuffix() != 0);
} // NO_LOOP:
if (pps == 0)
{
return pc.Address;
}
upState.Symbol = Heap[upBranch.Address]; // UpState.Symbol=*(byte*)
// UpBranch;
// UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
upState.SetSuccessor(upBranch.Address + 1); //TODO check if +1 necessary
if (pc.NumStats != 1)
{
if (pc.Address <= SubAlloc.PText)
{
return (0);
}
p.Address = pc.FreqData.GetStats();
if (p.Symbol != upState.Symbol)
{
do
{
p.IncrementAddress();
} while (p.Symbol != upState.Symbol);
}
var cf = p.Freq - 1;
var s0 = pc.FreqData.SummFreq - pc.NumStats - cf;
// UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
upState.Freq =
1
+ ((2 * cf <= s0) ? (5 * cf > s0 ? 1 : 0) : (((2 * cf) + (3 * s0) - 1) / (2 * s0)));
}
else
{
upState.Freq = pc.GetOneState().Freq; // UpState.Freq=pc->OneState.Freq;
}
do
{
// pc = pc->createChild(this,*--pps,UpState);
tempState.Address = _ps[--pps];
pc.Address = pc.CreateChild(this, tempState, upState);
if (pc.Address == 0)
{
return 0;
}
} while (pps != 0);
return pc.Address;
}
private void UpdateModelRestart()
{
RestartModelRare();
_escCount = 0;
}
private void UpdateModel()
{
//System.out.println("ModelPPM.updateModel()");
// STATE fs = *FoundState, *p = NULL;
var fs = _tempStateRef1;
fs.Values = FoundState;
var p = _tempState3.Initialize(Heap);
var tempState = _tempState4.Initialize(Heap);
var pc = _tempPpmContext3.Initialize(Heap);
var successor = _tempPpmContext4.Initialize(Heap);
int ns1,
ns,
cf,
sf,
s0;
pc.Address = _minContext.GetSuffix();
if (fs.Freq < MAX_FREQ / 4 && pc.Address != 0)
{
if (pc.NumStats != 1)
{
p.Address = pc.FreqData.GetStats();
if (p.Symbol != fs.Symbol)
{
do
{
p.IncrementAddress();
} while (p.Symbol != fs.Symbol);
tempState.Address = p.Address - State.SIZE;
if (p.Freq >= tempState.Freq)
{
State.PpmdSwap(p, tempState);
p.DecrementAddress();
}
}
if (p.Freq < MAX_FREQ - 9)
{
p.IncrementFreq(2);
pc.FreqData.IncrementSummFreq(2);
}
}
else
{
p.Address = pc.GetOneState().Address;
if (p.Freq < 32)
{
p.IncrementFreq(1);
}
}
}
if (_orderFall == 0)
{
FoundState.SetSuccessor(CreateSuccessors(true, p));
_minContext.Address = FoundState.GetSuccessor();
_maxContext.Address = FoundState.GetSuccessor();
if (_minContext.Address == 0)
{
UpdateModelRestart();
return;
}
return;
}
SubAlloc.Heap[SubAlloc.PText] = (byte)fs.Symbol;
SubAlloc.IncPText();
successor.Address = SubAlloc.PText;
if (SubAlloc.PText >= SubAlloc.FakeUnitsStart)
{
UpdateModelRestart();
return;
}
// // Debug
// subAlloc.dumpHeap();
if (fs.GetSuccessor() != 0)
{
if (fs.GetSuccessor() <= SubAlloc.PText)
{
fs.SetSuccessor(CreateSuccessors(false, p));
if (fs.GetSuccessor() == 0)
{
UpdateModelRestart();
return;
}
}
if (--_orderFall == 0)
{
successor.Address = fs.GetSuccessor();
if (_maxContext.Address != _minContext.Address)
{
SubAlloc.DecPText(1);
}
}
}
else
{
FoundState.SetSuccessor(successor.Address);
fs.SetSuccessor(_minContext);
}
// // Debug
// subAlloc.dumpHeap();
ns = _minContext.NumStats;
s0 = _minContext.FreqData.SummFreq - (ns) - (fs.Freq - 1);
for (
pc.Address = _maxContext.Address;
pc.Address != _minContext.Address;
pc.Address = pc.GetSuffix()
)
{
if ((ns1 = pc.NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
//System.out.println(ns1);
pc.FreqData.SetStats(
SubAlloc.ExpandUnits(pc.FreqData.GetStats(), Utility.URShift(ns1, 1))
);
if (pc.FreqData.GetStats() == 0)
{
UpdateModelRestart();
return;
}
}
// bug fixed
// int sum = ((2 * ns1 < ns) ? 1 : 0) +
// 2 * ((4 * ((ns1 <= ns) ? 1 : 0)) & ((pc.getFreqData()
// .getSummFreq() <= 8 * ns1) ? 1 : 0));
var sum =
((2 * ns1 < ns) ? 1 : 0)
+ (
2
* (((4 * ns1 <= ns) ? 1 : 0) & ((pc.FreqData.SummFreq <= 8 * ns1) ? 1 : 0))
);
pc.FreqData.IncrementSummFreq(sum);
}
else
{
p.Address = SubAlloc.AllocUnits(1);
if (p.Address == 0)
{
UpdateModelRestart();
return;
}
p.SetValues(pc.GetOneState());
pc.FreqData.SetStats(p);
if (p.Freq < (MAX_FREQ / 4) - 1)
{
p.IncrementFreq(p.Freq);
}
else
{
p.Freq = MAX_FREQ - 4;
}
pc.FreqData.SummFreq = (p.Freq + _initEsc + (ns > 3 ? 1 : 0));
}
cf = 2 * fs.Freq * (pc.FreqData.SummFreq + 6);
sf = s0 + pc.FreqData.SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf ? 1 : 0) + (cf >= 4 * sf ? 1 : 0);
pc.FreqData.IncrementSummFreq(3);
}
else
{
cf = 4 + (cf >= 9 * sf ? 1 : 0) + (cf >= 12 * sf ? 1 : 0) + (cf >= 15 * sf ? 1 : 0);
pc.FreqData.IncrementSummFreq(cf);
}
p.Address = pc.FreqData.GetStats() + (ns1 * State.SIZE);
p.SetSuccessor(successor);
p.Symbol = fs.Symbol;
p.Freq = cf;
pc.NumStats = ++ns1;
}
var address = fs.GetSuccessor();
_maxContext.Address = address;
_minContext.Address = address;
//TODO-----debug
// int pos = minContext.getFreqData().getStats();
// State a = new State(getHeap());
// a.Address=pos);
// pos+=State.size;
// a.Address=pos);
//--dbg end
}
// Debug
public override string ToString()
{
var buffer = new StringBuilder();
buffer.Append("ModelPPM[");
buffer.Append("\n numMasked=");
buffer.Append(_numMasked);
buffer.Append("\n initEsc=");
buffer.Append(_initEsc);
buffer.Append("\n orderFall=");
buffer.Append(_orderFall);
buffer.Append("\n maxOrder=");
buffer.Append(_maxOrder);
buffer.Append("\n runLength=");
buffer.Append(_runLength);
buffer.Append("\n initRL=");
buffer.Append(_initRl);
buffer.Append("\n escCount=");
buffer.Append(_escCount);
buffer.Append("\n prevSuccess=");
buffer.Append(_prevSuccess);
buffer.Append("\n foundState=");
buffer.Append(FoundState);
buffer.Append("\n coder=");
buffer.Append(Coder);
buffer.Append("\n subAlloc=");
buffer.Append(SubAlloc);
buffer.Append("\n]");
return buffer.ToString();
}
// Debug
// public void dumpHeap() {
// subAlloc.dumpHeap();
// }
internal bool DecodeInit(Stream stream, int maxOrder, int maxMemory)
{
if (stream != null)
{
Coder = new RangeCoder(stream);
}
if (maxOrder == 1)
{
SubAlloc.StopSubAllocator();
return (false);
}
SubAlloc.StartSubAllocator(maxMemory);
_minContext = new PpmContext(Heap);
//medContext = new PPMContext(Heap);
_maxContext = new PpmContext(Heap);
FoundState = new State(Heap);
_dummySee2Cont = new See2Context();
for (var i = 0; i < 25; i++)
{
for (var j = 0; j < 16; j++)
{
_see2Cont[i][j] = new See2Context();
}
}
StartModelRare(maxOrder);
return (_minContext.Address != 0);
}
internal async ValueTask<bool> DecodeInitAsync(
Stream stream,
int maxOrder,
int maxMemory,
CancellationToken cancellationToken = default
)
{
if (stream != null)
{
Coder = new RangeCoder();
await Coder.InitAsync(stream, cancellationToken).ConfigureAwait(false);
}
if (maxOrder == 1)
{
SubAlloc.StopSubAllocator();
return (false);
}
SubAlloc.StartSubAllocator(maxMemory);
_minContext = new PpmContext(Heap);
//medContext = new PPMContext(Heap);
_maxContext = new PpmContext(Heap);
FoundState = new State(Heap);
_dummySee2Cont = new See2Context();
for (var i = 0; i < 25; i++)
{
for (var j = 0; j < 16; j++)
{
_see2Cont[i][j] = new See2Context();
}
}
StartModelRare(maxOrder);
return (_minContext.Address != 0);
}
internal void NextContext()
{
var addr = FoundState.GetSuccessor();
if (_orderFall == 0 && addr > SubAlloc.PText)
{
_minContext.Address = addr;
_maxContext.Address = addr;
}
else
{
UpdateModel();
}
}
public int DecodeChar(Decoder decoder)
{
if (_minContext.NumStats != 1)
{
var s = _tempState1.Initialize(Heap);
s.Address = _minContext.FreqData.GetStats();
int i;
int count,
hiCnt;
if (
(count = (int)decoder.GetThreshold((uint)_minContext.FreqData.SummFreq))
< (hiCnt = s.Freq)
)
{
byte symbol;
decoder.Decode(0, (uint)s.Freq);
symbol = (byte)s.Symbol;
_minContext.update1_0(this, s.Address);
NextContext();
return symbol;
}
_prevSuccess = 0;
i = _minContext.NumStats - 1;
do
{
s.IncrementAddress();
if ((hiCnt += s.Freq) > count)
{
byte symbol;
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
symbol = (byte)s.Symbol;
_minContext.Update1(this, s.Address);
NextContext();
return symbol;
}
} while (--i > 0);
if (count >= _minContext.FreqData.SummFreq)
{
return -2;
}
_hiBitsFlag = _hb2Flag[FoundState.Symbol];
decoder.Decode((uint)hiCnt, (uint)(_minContext.FreqData.SummFreq - hiCnt));
for (i = 0; i < 256; i++)
{
_charMask[i] = -1;
}
_charMask[s.Symbol] = 0;
i = _minContext.NumStats - 1;
do
{
s.DecrementAddress();
_charMask[s.Symbol] = 0;
} while (--i > 0);
}
else
{
var rs = _tempState1.Initialize(Heap);
rs.Address = _minContext.GetOneState().Address;
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
var off1 = rs.Freq - 1;
var off2 = _minContext.GetArrayIndex(this, rs);
var bs = _binSumm[off1][off2];
if (decoder.DecodeBit((uint)bs, 14) == 0)
{
byte symbol;
_binSumm[off1][off2] =
(bs + INTERVAL - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
FoundState.Address = rs.Address;
symbol = (byte)rs.Symbol;
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
_prevSuccess = 1;
IncRunLength(1);
NextContext();
return symbol;
}
bs = (bs - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
_binSumm[off1][off2] = bs;
_initEsc = PpmContext.EXP_ESCAPE[Utility.URShift(bs, 10)];
int i;
for (i = 0; i < 256; i++)
{
_charMask[i] = -1;
}
_charMask[rs.Symbol] = 0;
_prevSuccess = 0;
}
for (; ; )
{
var s = _tempState1.Initialize(Heap);
int i;
int count,
hiCnt;
See2Context see;
int num,
numMasked = _minContext.NumStats;
do
{
_orderFall++;
_minContext.Address = _minContext.GetSuffix();
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return -1;
}
} while (_minContext.NumStats == numMasked);
hiCnt = 0;
s.Address = _minContext.FreqData.GetStats();
i = 0;
num = _minContext.NumStats - numMasked;
do
{
var k = _charMask[s.Symbol];
hiCnt += s.Freq & k;
_minContext._ps[i] = s.Address;
s.IncrementAddress();
i -= k;
} while (i != num);
see = _minContext.MakeEscFreq(this, numMasked, out var freqSum);
freqSum += hiCnt;
count = (int)decoder.GetThreshold((uint)freqSum);
if (count < hiCnt)
{
byte symbol;
var ps = _tempState2.Initialize(Heap);
for (
hiCnt = 0, i = 0, ps.Address = _minContext._ps[i];
(hiCnt += ps.Freq) <= count;
i++, ps.Address = _minContext._ps[i]
)
{
;
}
s.Address = ps.Address;
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
see.Update();
symbol = (byte)s.Symbol;
_minContext.Update2(this, s.Address);
UpdateModel();
return symbol;
}
if (count >= freqSum)
{
return -2;
}
decoder.Decode((uint)hiCnt, (uint)(freqSum - hiCnt));
see.Summ += freqSum;
do
{
s.Address = _minContext._ps[--i];
_charMask[s.Symbol] = 0;
} while (i != 0);
}
}
public async ValueTask<int> DecodeCharAsync(
Decoder decoder,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
if (_minContext.NumStats != 1)
{
var s = _tempState1.Initialize(Heap);
s.Address = _minContext.FreqData.GetStats();
int i;
int count,
hiCnt;
if (
(count = (int)decoder.GetThreshold((uint)_minContext.FreqData.SummFreq))
< (hiCnt = s.Freq)
)
{
byte symbol;
await decoder.DecodeAsync(0, (uint)s.Freq, cancellationToken).ConfigureAwait(false);
symbol = (byte)s.Symbol;
_minContext.update1_0(this, s.Address);
NextContext();
return symbol;
}
_prevSuccess = 0;
i = _minContext.NumStats - 1;
do
{
s.IncrementAddress();
if ((hiCnt += s.Freq) > count)
{
byte symbol;
await decoder
.DecodeAsync((uint)(hiCnt - s.Freq), (uint)s.Freq, cancellationToken)
.ConfigureAwait(false);
symbol = (byte)s.Symbol;
_minContext.Update1(this, s.Address);
NextContext();
return symbol;
}
} while (--i > 0);
if (count >= _minContext.FreqData.SummFreq)
{
return -2;
}
_hiBitsFlag = _hb2Flag[FoundState.Symbol];
await decoder
.DecodeAsync(
(uint)hiCnt,
(uint)(_minContext.FreqData.SummFreq - hiCnt),
cancellationToken
)
.ConfigureAwait(false);
for (i = 0; i < 256; i++)
{
_charMask[i] = -1;
}
_charMask[s.Symbol] = 0;
i = _minContext.NumStats - 1;
do
{
s.DecrementAddress();
_charMask[s.Symbol] = 0;
} while (--i > 0);
}
else
{
var rs = _tempState1.Initialize(Heap);
rs.Address = _minContext.GetOneState().Address;
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
var off1 = rs.Freq - 1;
var off2 = _minContext.GetArrayIndex(this, rs);
var bs = _binSumm[off1][off2];
if (
await decoder.DecodeBitAsync((uint)bs, 14, cancellationToken).ConfigureAwait(false)
== 0
)
{
byte symbol;
_binSumm[off1][off2] =
(bs + INTERVAL - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
FoundState.Address = rs.Address;
symbol = (byte)rs.Symbol;
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
_prevSuccess = 1;
IncRunLength(1);
NextContext();
return symbol;
}
bs = (bs - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
_binSumm[off1][off2] = bs;
_initEsc = PpmContext.EXP_ESCAPE[Utility.URShift(bs, 10)];
int i;
for (i = 0; i < 256; i++)
{
_charMask[i] = -1;
}
_charMask[rs.Symbol] = 0;
_prevSuccess = 0;
}
for (; ; )
{
var s = _tempState1.Initialize(Heap);
int i;
int count,
hiCnt;
See2Context see;
int num,
numMasked = _minContext.NumStats;
do
{
_orderFall++;
_minContext.Address = _minContext.GetSuffix();
if (_minContext.Address <= SubAlloc.PText || _minContext.Address > SubAlloc.HeapEnd)
{
return -1;
}
} while (_minContext.NumStats == numMasked);
hiCnt = 0;
s.Address = _minContext.FreqData.GetStats();
i = 0;
num = _minContext.NumStats - numMasked;
do
{
var k = _charMask[s.Symbol];
hiCnt += s.Freq & k;
_minContext._ps[i] = s.Address;
s.IncrementAddress();
i -= k;
} while (i != num);
see = _minContext.MakeEscFreq(this, numMasked, out var freqSum);
freqSum += hiCnt;
count = (int)decoder.GetThreshold((uint)freqSum);
if (count < hiCnt)
{
byte symbol;
var ps = _tempState2.Initialize(Heap);
for (
hiCnt = 0, i = 0, ps.Address = _minContext._ps[i];
(hiCnt += ps.Freq) <= count;
i++, ps.Address = _minContext._ps[i]
)
{
;
}
s.Address = ps.Address;
await decoder
.DecodeAsync((uint)(hiCnt - s.Freq), (uint)s.Freq, cancellationToken)
.ConfigureAwait(false);
see.Update();
symbol = (byte)s.Symbol;
_minContext.Update2(this, s.Address);
UpdateModel();
return symbol;
}
if (count >= freqSum)
{
return -2;
}
await decoder
.DecodeAsync((uint)hiCnt, (uint)(freqSum - hiCnt), cancellationToken)
.ConfigureAwait(false);
see.Summ += freqSum;
do
{
s.Address = _minContext._ps[--i];
_charMask[s.Symbol] = 0;
} while (i != 0);
}
}
}