package sevenzip.compression.rangecoder; import java.io.IOException; /** * Range decoder. */ public class Decoder { static final int kTopMask = ~((1<<24)-1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1<<kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i<5; i++) { Code = (Code<<8)|Stream.read(); } } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i!=0; i--) { Range >>>= 1; int t = ((Code-Range)>>>31); Code -= Range&(t-1); result = (result<<1)|(1-t); if ((Range&kTopMask)==0) { Code = (Code<<8)|Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short[] probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range>>>kNumBitModelTotalBits)*prob; int result = 0; if ((Code^0x80000000)<(newBound^0x80000000)) { Range = newBound; probs[index] = (short) (prob+((kBitModelTotal-prob)>>>kNumMoveBits)); if ((Range&kTopMask)==0) { Code = (Code<<8)|Stream.read(); Range <<= 8; } } else { Range -= newBound; Code -= newBound; probs[index] = (short) (prob-((prob)>>>kNumMoveBits)); if ((Range&kTopMask)==0) { Code = (Code<<8)|Stream.read(); Range <<= 8; } result = 1; } return result; } public static void InitBitModels(short[] probs) { for (int i = 0; i<probs.length; i++) { probs[i] = (kBitModelTotal>>>1); } } }