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]; } }