2013-04-07 10:58:58 +01:00
using System.Text ;
using System.IO ;
using SharpCompress.Compressor.Rar ;
namespace SharpCompress.Compressor.PPMd.H
{
internal class ModelPPM
{
private void InitBlock ( )
{
for ( int i = 0 ; i < 25 ; i + + )
{
SEE2Cont [ i ] = new SEE2Context [ 16 ] ;
}
for ( int i2 = 0 ; i2 < 128 ; i2 + + )
{
binSumm [ i2 ] = new int [ 64 ] ;
}
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
public SubAllocator SubAlloc
{
2013-04-28 12:32:55 +01:00
get { return subAlloc ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual SEE2Context DummySEE2Cont
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return dummySEE2Cont ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int InitRL
{
get { return initRL ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int EscCount
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return escCount ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . escCount = value & 0xff ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int [ ] CharMask
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return charMask ; }
}
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
public virtual int NumMasked
{
get { return numMasked ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . numMasked = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int PrevSuccess
{
get { return prevSuccess ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . prevSuccess = value & 0xff ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int InitEsc
{
get { return initEsc ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . initEsc = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int RunLength
{
get { return runLength ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . runLength = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int HiBitsFlag
{
get { return hiBitsFlag ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . hiBitsFlag = value & 0xff ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int [ ] [ ] BinSumm
{
get { return binSumm ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
internal RangeCoder Coder
{
2013-04-28 12:32:55 +01:00
get { return coder ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
internal State FoundState
{
2013-04-28 12:32:55 +01:00
get { return foundState ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual byte [ ] Heap
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return subAlloc . Heap ; }
}
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
public virtual int OrderFall
{
get { return orderFall ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
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 SEE2Context [ ] [ ] SEE2Cont = new SEE2Context [ 25 ] [ ] ;
private SEE2Context dummySEE2Cont ;
private PPMContext minContext ; //medContext
private PPMContext maxContext ;
private State foundState ; // found next state transition
private int numMasked , initEsc , orderFall , maxOrder , runLength , initRL ;
private int [ ] charMask = new int [ 256 ] ;
private int [ ] NS2Indx = new int [ 256 ] ;
private int [ ] NS2BSIndx = new int [ 256 ] ;
private int [ ] HB2Flag = new int [ 256 ] ;
// byte EscCount, PrevSuccess, HiBitsFlag;
private int escCount , prevSuccess , hiBitsFlag ;
private int [ ] [ ] binSumm = new int [ 128 ] [ ] ; // binary SEE-contexts
private RangeCoder coder ;
private SubAllocator subAlloc = new SubAllocator ( ) ;
2013-04-28 12:32:55 +01:00
private static int [ ] InitBinEsc = new int [ ] { 0x3CDD , 0x1F3F , 0x59BF , 0x48F3 , 0x64A1 , 0x5ABC , 0x6632 , 0x6051 } ;
2013-04-07 10:58:58 +01:00
// 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 State tempState1 = new State ( 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 State tempState2 = new State ( 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 State tempState3 = new State ( 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 State tempState4 = new State ( 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 StateRef tempStateRef1 = new StateRef ( ) ;
//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 StateRef tempStateRef2 = new StateRef ( ) ;
//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 PPMContext tempPPMContext1 = new PPMContext ( 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 PPMContext tempPPMContext2 = new PPMContext ( 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 PPMContext tempPPMContext3 = new PPMContext ( 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 PPMContext tempPPMContext4 = new PPMContext ( 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 int [ ] ps = new int [ MAX_O ] ;
public ModelPPM ( )
{
InitBlock ( ) ;
minContext = null ;
maxContext = null ;
//medContext = null;
}
private void restartModelRare ( )
{
Utility . Fill ( charMask , 0 ) ;
subAlloc . initSubAllocator ( ) ;
initRL = - ( maxOrder < 12 ? maxOrder : 12 ) - 1 ;
int addr = subAlloc . allocContext ( ) ;
minContext . Address = addr ;
maxContext . Address = addr ;
minContext . setSuffix ( 0 ) ;
orderFall = maxOrder ;
minContext . NumStats = 256 ;
minContext . FreqData . SummFreq = minContext . NumStats + 1 ;
2013-04-28 12:32:55 +01:00
addr = subAlloc . allocUnits ( 256 / 2 ) ;
2013-04-07 10:58:58 +01:00
foundState . Address = addr ;
minContext . FreqData . SetStats ( addr ) ;
State state = new State ( subAlloc . Heap ) ;
addr = minContext . FreqData . GetStats ( ) ;
runLength = initRL ;
prevSuccess = 0 ;
for ( int i = 0 ; i < 256 ; i + + )
{
2013-04-28 12:32:55 +01:00
state . Address = addr + i * State . Size ;
2013-04-07 10:58:58 +01:00
state . Symbol = i ;
state . Freq = 1 ;
state . SetSuccessor ( 0 ) ;
}
for ( int i = 0 ; i < 128 ; i + + )
{
for ( int k = 0 ; k < 8 ; k + + )
{
for ( int m = 0 ; m < 64 ; m + = 8 )
{
2013-04-28 12:32:55 +01:00
binSumm [ i ] [ k + m ] = BIN_SCALE - InitBinEsc [ k ] / ( i + 2 ) ;
2013-04-07 10:58:58 +01:00
}
}
}
for ( int i = 0 ; i < 25 ; i + + )
{
for ( int k = 0 ; k < 16 ; k + + )
{
2013-04-28 12:32:55 +01:00
SEE2Cont [ i ] [ k ] . Initialize ( 5 * i + 10 ) ;
2013-04-07 10:58:58 +01:00
}
}
}
private void startModelRare ( int MaxOrder )
{
int i , k , m , Step ;
escCount = 1 ;
this . maxOrder = MaxOrder ;
restartModelRare ( ) ;
// Bug Fixed
NS2BSIndx [ 0 ] = 0 ;
NS2BSIndx [ 1 ] = 2 ;
for ( int j = 0 ; j < 9 ; j + + )
{
NS2BSIndx [ 2 + j ] = 4 ;
}
for ( int 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 ( int j = 0 ; j < 0x40 ; j + + )
{
HB2Flag [ j ] = 0 ;
}
for ( int j = 0 ; j < 0x100 - 0x40 ; j + + )
{
HB2Flag [ 0x40 + j ] = 0x08 ;
}
dummySEE2Cont . Shift = PERIOD_BITS ;
}
private void clearMask ( )
{
escCount = 1 ;
Utility . Fill ( charMask , 0 ) ;
}
internal bool decodeInit ( Unpack unpackRead , int escChar )
{
int MaxOrder = unpackRead . Char & 0xff ;
bool reset = ( ( MaxOrder & 0x20 ) ! = 0 ) ;
int 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 )
{
2013-04-28 12:32:55 +01:00
MaxOrder = 16 + ( MaxOrder - 16 ) * 3 ;
2013-04-07 10:58:58 +01:00
}
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 ( int i = 0 ; i < 25 ; i + + )
{
for ( int 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 )
{
2013-04-28 12:32:55 +01:00
if ( minContext . FreqData . GetStats ( ) < = subAlloc . PText | |
minContext . FreqData . GetStats ( ) > subAlloc . HeapEnd )
2013-04-07 10:58:58 +01:00
{
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 ) ;
}
2013-04-28 12:32:55 +01:00
} while ( minContext . NumStats = = numMasked ) ;
2013-04-07 10:58:58 +01:00
if ( ! minContext . decodeSymbol2 ( this ) )
{
return ( - 1 ) ;
}
coder . Decode ( ) ;
}
int Symbol = foundState . Symbol ;
if ( ( orderFall = = 0 ) & & foundState . GetSuccessor ( ) > subAlloc . PText )
{
// MinContext=MaxContext=FoundState->Successor;
int 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 SEE2Context [ ] [ ] getSEE2Cont ( )
{
return SEE2Cont ;
}
public virtual void incEscCount ( int dEscCount )
{
EscCount = EscCount + dEscCount ;
}
public virtual void incRunLength ( int dRunLength )
{
RunLength = RunLength + dRunLength ;
}
public virtual int [ ] getHB2Flag ( )
{
return HB2Flag ;
}
public virtual int [ ] getNS2BSIndx ( )
{
return NS2BSIndx ;
}
public virtual int [ ] getNS2Indx ( )
{
return NS2Indx ;
}
private int createSuccessors ( bool Skip , State p1 )
{
//State upState = tempState1.Initialize(null);
StateRef upState = tempStateRef2 ;
State tempState = tempState1 . Initialize ( Heap ) ;
// PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
PPMContext pc = tempPPMContext1 . Initialize ( Heap ) ;
pc . Address = minContext . Address ;
PPMContext upBranch = tempPPMContext2 . Initialize ( Heap ) ;
upBranch . Address = foundState . GetSuccessor ( ) ;
// STATE * p, * ps[MAX_O], ** pps=ps;
State p = tempState2 . Initialize ( Heap ) ;
int pps = 0 ;
bool noLoop = false ;
if ( ! Skip )
{
ps [ pps + + ] = foundState . Address ; // *pps++ = FoundState;
if ( pc . getSuffix ( ) = = 0 )
{
noLoop = true ;
}
}
if ( ! noLoop )
{
bool 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 ( ) ;
2013-04-28 12:32:55 +01:00
} while ( p . Symbol ! = foundState . Symbol ) ;
2013-04-07 10:58:58 +01:00
}
}
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 ;
2013-04-28 12:32:55 +01:00
} while ( pc . getSuffix ( ) ! = 0 ) ;
2013-04-07 10:58:58 +01:00
} // 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 ( ) ;
2013-04-28 12:32:55 +01:00
} while ( p . Symbol ! = upState . Symbol ) ;
2013-04-07 10:58:58 +01:00
}
int cf = p . Freq - 1 ;
int s0 = pc . FreqData . SummFreq - pc . NumStats - cf ;
// UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
2013-04-28 12:32:55 +01:00
upState . Freq = 1 + ( ( 2 * cf < = s0 ) ? ( 5 * cf > s0 ? 1 : 0 ) : ( ( 2 * cf + 3 * s0 - 1 ) / ( 2 * s0 ) ) ) ;
2013-04-07 10:58:58 +01:00
}
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 ;
}
2013-04-28 12:32:55 +01:00
} while ( pps ! = 0 ) ;
2013-04-07 10:58:58 +01:00
return pc . Address ;
}
private void updateModelRestart ( )
{
restartModelRare ( ) ;
escCount = 0 ;
}
private void updateModel ( )
{
//System.out.println("ModelPPM.updateModel()");
// STATE fs = *FoundState, *p = NULL;
StateRef fs = tempStateRef1 ;
fs . Values = foundState ;
State p = tempState3 . Initialize ( Heap ) ;
State tempState = tempState4 . Initialize ( Heap ) ;
PPMContext pc = tempPPMContext3 . Initialize ( Heap ) ;
PPMContext successor = tempPPMContext4 . Initialize ( Heap ) ;
int ns1 , ns , cf , sf , s0 ;
pc . Address = minContext . getSuffix ( ) ;
2013-04-28 12:32:55 +01:00
if ( fs . Freq < MAX_FREQ / 4 & & pc . Address ! = 0 )
2013-04-07 10:58:58 +01:00
{
if ( pc . NumStats ! = 1 )
{
p . Address = pc . FreqData . GetStats ( ) ;
if ( p . Symbol ! = fs . Symbol )
{
do
{
p . IncrementAddress ( ) ;
2013-04-28 12:32:55 +01:00
} while ( p . Symbol ! = fs . Symbol ) ;
2013-04-07 10:58:58 +01:00
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 ;
}
2013-04-28 12:32:55 +01:00
subAlloc . Heap [ subAlloc . PText ] = ( byte ) fs . Symbol ;
2013-04-07 10:58:58 +01:00
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));
2013-04-28 12:32:55 +01:00
int sum = ( ( 2 * ns1 < ns ) ? 1 : 0 ) +
2 * ( ( ( 4 * ns1 < = ns ) ? 1 : 0 ) & ( ( pc . FreqData . SummFreq < = 8 * ns1 ) ? 1 : 0 ) ) ;
2013-04-07 10:58:58 +01:00
pc . FreqData . IncrementSummFreq ( sum ) ;
}
else
{
p . Address = subAlloc . allocUnits ( 1 ) ;
if ( p . Address = = 0 )
{
updateModelRestart ( ) ;
return ;
}
p . SetValues ( pc . getOneState ( ) ) ;
pc . FreqData . SetStats ( p ) ;
2013-04-28 12:32:55 +01:00
if ( p . Freq < MAX_FREQ / 4 - 1 )
2013-04-07 10:58:58 +01:00
{
p . IncrementFreq ( p . Freq ) ;
}
else
{
p . Freq = MAX_FREQ - 4 ;
}
pc . FreqData . SummFreq = ( p . Freq + initEsc + ( ns > 3 ? 1 : 0 ) ) ;
}
2013-04-28 12:32:55 +01:00
cf = 2 * fs . Freq * ( pc . FreqData . SummFreq + 6 ) ;
2013-04-07 10:58:58 +01:00
sf = s0 + pc . FreqData . SummFreq ;
2013-04-28 12:32:55 +01:00
if ( cf < 6 * sf )
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
cf = 1 + ( cf > sf ? 1 : 0 ) + ( cf > = 4 * sf ? 1 : 0 ) ;
2013-04-07 10:58:58 +01:00
pc . FreqData . IncrementSummFreq ( 3 ) ;
}
else
{
2013-04-28 12:32:55 +01:00
cf = 4 + ( cf > = 9 * sf ? 1 : 0 ) + ( cf > = 12 * sf ? 1 : 0 ) + ( cf > = 15 * sf ? 1 : 0 ) ;
2013-04-07 10:58:58 +01:00
pc . FreqData . IncrementSummFreq ( cf ) ;
}
2013-04-28 12:32:55 +01:00
p . Address = pc . FreqData . GetStats ( ) + ns1 * State . Size ;
2013-04-07 10:58:58 +01:00
p . SetSuccessor ( successor ) ;
p . Symbol = fs . Symbol ;
p . Freq = cf ;
pc . NumStats = + + ns1 ;
}
int 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
return ;
}
// Debug
public override System . String ToString ( )
{
StringBuilder 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 ( int i = 0 ; i < 25 ; i + + )
{
for ( int j = 0 ; j < 16 ; j + + )
{
SEE2Cont [ i ] [ j ] = new SEE2Context ( ) ;
}
}
startModelRare ( maxOrder ) ;
return ( minContext . Address ! = 0 ) ;
}
internal void nextContext ( )
{
int addr = foundState . GetSuccessor ( ) ;
if ( orderFall = = 0 & & addr > subAlloc . PText )
{
minContext . Address = addr ;
maxContext . Address = addr ;
}
else
updateModel ( ) ;
}
public int decodeChar ( LZMA . RangeCoder . Decoder decoder )
{
if ( minContext . NumStats ! = 1 )
{
State s = tempState1 . Initialize ( Heap ) ;
s . Address = minContext . FreqData . GetStats ( ) ;
int i ;
int count , hiCnt ;
2013-04-28 12:32:55 +01:00
if ( ( count = ( int ) decoder . GetThreshold ( ( uint ) minContext . FreqData . SummFreq ) ) < ( hiCnt = s . Freq ) )
2013-04-07 10:58:58 +01:00
{
byte symbol ;
2013-04-28 12:32:55 +01:00
decoder . Decode ( 0 , ( uint ) s . Freq ) ;
symbol = ( byte ) s . Symbol ;
2013-04-07 10:58:58 +01:00
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 ;
2013-04-28 12:32:55 +01:00
decoder . Decode ( ( uint ) ( hiCnt - s . Freq ) , ( uint ) s . Freq ) ;
symbol = ( byte ) s . Symbol ;
2013-04-07 10:58:58 +01:00
minContext . update1 ( this , s . Address ) ;
nextContext ( ) ;
return symbol ;
}
2013-04-28 12:32:55 +01:00
} while ( - - i > 0 ) ;
2013-04-07 10:58:58 +01:00
if ( count > = minContext . FreqData . SummFreq )
return - 2 ;
hiBitsFlag = HB2Flag [ foundState . Symbol ] ;
2013-04-28 12:32:55 +01:00
decoder . Decode ( ( uint ) hiCnt , ( uint ) ( minContext . FreqData . SummFreq - hiCnt ) ) ;
2013-04-07 10:58:58 +01:00
for ( i = 0 ; i < 256 ; i + + )
charMask [ i ] = - 1 ;
charMask [ s . Symbol ] = 0 ;
i = minContext . NumStats - 1 ;
do
{
s . DecrementAddress ( ) ;
charMask [ s . Symbol ] = 0 ;
2013-04-28 12:32:55 +01:00
} while ( - - i > 0 ) ;
2013-04-07 10:58:58 +01:00
}
else
{
State rs = tempState1 . Initialize ( Heap ) ;
rs . Address = minContext . getOneState ( ) . Address ;
hiBitsFlag = getHB2Flag ( ) [ foundState . Symbol ] ;
int off1 = rs . Freq - 1 ;
int off2 = minContext . getArrayIndex ( this , rs ) ;
int bs = binSumm [ off1 ] [ off2 ] ;
2013-04-28 12:32:55 +01:00
if ( decoder . DecodeBit ( ( uint ) bs , 14 ) = = 0 )
2013-04-07 10:58:58 +01:00
{
byte symbol ;
binSumm [ off1 ] [ off2 ] = ( bs + INTERVAL - minContext . getMean ( bs , PERIOD_BITS , 2 ) ) & 0xFFFF ;
foundState . Address = rs . Address ;
2013-04-28 12:32:55 +01:00
symbol = ( byte ) rs . Symbol ;
2013-04-07 10:58:58 +01:00
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 . ExpEscape [ Utility . URShift ( bs , 10 ) ] ;
int i ;
for ( i = 0 ; i < 256 ; i + + )
charMask [ i ] = - 1 ;
charMask [ rs . Symbol ] = 0 ;
prevSuccess = 0 ;
}
for ( ; ; )
{
State s = tempState1 . Initialize ( Heap ) ;
int i ;
int freqSum , 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 ;
2013-04-28 12:32:55 +01:00
} while ( minContext . NumStats = = numMasked ) ;
2013-04-07 10:58:58 +01:00
hiCnt = 0 ;
s . Address = minContext . FreqData . GetStats ( ) ;
i = 0 ;
num = minContext . NumStats - numMasked ;
do
{
int k = charMask [ s . Symbol ] ;
hiCnt + = s . Freq & k ;
minContext . ps [ i ] = s . Address ;
s . IncrementAddress ( ) ;
i - = k ;
2013-04-28 12:32:55 +01:00
} while ( i ! = num ) ;
2013-04-07 10:58:58 +01:00
see = minContext . makeEscFreq ( this , numMasked , out freqSum ) ;
freqSum + = hiCnt ;
2013-04-28 12:32:55 +01:00
count = ( int ) decoder . GetThreshold ( ( uint ) freqSum ) ;
2013-04-07 10:58:58 +01:00
if ( count < hiCnt )
{
byte symbol ;
State ps = tempState2 . Initialize ( Heap ) ;
2013-04-28 12:32:55 +01:00
for ( hiCnt = 0 , i = 0 , ps . Address = minContext . ps [ i ] ;
( hiCnt + = ps . Freq ) < = count ;
i + + , ps . Address = minContext . ps [ i ] ) ;
2013-04-07 10:58:58 +01:00
s . Address = ps . Address ;
2013-04-28 12:32:55 +01:00
decoder . Decode ( ( uint ) ( hiCnt - s . Freq ) , ( uint ) s . Freq ) ;
2013-04-07 10:58:58 +01:00
see . update ( ) ;
2013-04-28 12:32:55 +01:00
symbol = ( byte ) s . Symbol ;
2013-04-07 10:58:58 +01:00
minContext . update2 ( this , s . Address ) ;
updateModel ( ) ;
return symbol ;
}
if ( count > = freqSum )
return - 2 ;
2013-04-28 12:32:55 +01:00
decoder . Decode ( ( uint ) hiCnt , ( uint ) ( freqSum - hiCnt ) ) ;
2013-04-07 10:58:58 +01:00
see . Summ = see . Summ + freqSum ;
do
{
s . Address = minContext . ps [ - - i ] ;
charMask [ s . Symbol ] = 0 ;
2013-04-28 12:32:55 +01:00
} while ( i ! = 0 ) ;
2013-04-07 10:58:58 +01:00
}
}
}
}