package SevenZip.Compression.RangeCoder;
import java.io.IOException;
public class Encoder
{
static final int kTopMask = ~((1 << 24) - 1);
static final int kNumBitModelTotalBits = 11;
static final int kBitModelTotal = 1 << kNumBitModelTotalBits;
static final int kNumMoveBits = 5;
java.io.OutputStream Stream;
long Low;
int Range;
int _cacheSize;
int _cache;
long _position;
public void SetStream(java.io.OutputStream stream)
{
Stream = stream;
}
public void ReleaseStream()
{
Stream = null;
}
public void Init()
{
_position = 0;
Low = 0;
Range = -1;
_cacheSize = 1;
_cache = 0;
}
public void FlushData() throws IOException
{
for (int i = 0; i < 5; i++)
{
ShiftLow();
}
}
public void FlushStream() throws IOException
{
Stream.flush();
}
public void ShiftLow() throws IOException
{
final int LowHi = (int) (Low >>> 32);
if (LowHi != 0 || Low < 0xFF000000L)
{
_position += _cacheSize;
int temp = _cache;
do
{
Stream.write(temp + LowHi);
temp = 0xFF;
} while (--_cacheSize != 0);
_cache = (int) Low >>> 24;
}
_cacheSize++;
Low = (Low & 0xFFFFFF) << 8;
}
public void EncodeDirectBits(int v, int numTotalBits) throws IOException
{
for (int i = numTotalBits - 1; i >= 0; i--)
{
Range >>>= 1;
if ((v >>> i & 1) == 1)
{
Low += Range;
}
if ((Range & Encoder.kTopMask) == 0)
{
Range <<= 8;
ShiftLow();
}
}
}
public long GetProcessedSizeAdd()
{
return _cacheSize + _position + 4;
}
static final int kNumMoveReducingBits = 2;
public static final int kNumBitPriceShiftBits = 6;
public static void InitBitModels(short[] probs)
{
for (int i = 0; i < probs.length; i++)
{
probs[i] = kBitModelTotal >>> 1;
}
}
public void Encode(short[] probs, int index, int symbol) throws IOException
{
final int prob = probs[index];
final int newBound = (Range >>> kNumBitModelTotalBits) * prob;
if (symbol == 0)
{
Range = newBound;
probs[index] = (short) (prob + (kBitModelTotal - prob >>> kNumMoveBits));
}
else
{
Low += newBound & 0xFFFFFFFFL;
Range -= newBound;
probs[index] = (short) (prob - (prob >>> kNumMoveBits));
}
if ((Range & kTopMask) == 0)
{
Range <<= 8;
ShiftLow();
}
}
private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits];
static
{
final int kNumBits = kNumBitModelTotalBits - kNumMoveReducingBits;
for (int i = kNumBits - 1; i >= 0; i--)
{
final int start = 1 << kNumBits - i - 1;
final int end = 1 << kNumBits - i;
for (int j = start; j < end; j++)
{
ProbPrices[j] = (i << kNumBitPriceShiftBits)
+ (end - j << kNumBitPriceShiftBits >>> kNumBits - i
- 1);
}
}
}
static public int GetPrice(int Prob, int symbol)
{
return ProbPrices[((Prob - symbol ^ -symbol) & kBitModelTotal - 1) >>> kNumMoveReducingBits];
}
static public int GetPrice0(int Prob)
{
return ProbPrices[Prob >>> kNumMoveReducingBits];
}
static public int GetPrice1(int Prob)
{
return ProbPrices[kBitModelTotal - Prob >>> kNumMoveReducingBits];
}
}