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 {
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 {
int prob = probs[index];
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 {
int kNumBits = (kNumBitModelTotalBits-kNumMoveReducingBits);
for (int i = kNumBits-1; i>=0; i--) {
int start = 1<<(kNumBits-i-1);
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];
}
}