1baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpackage SevenZip.Compression.RangeCoder;
2baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport java.io.IOException;
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
4baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic class Encoder
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kTopMask = ~((1 << 24) - 1);
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kNumBitModelTotalBits = 11;
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kNumMoveBits = 5;
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	java.io.OutputStream Stream;
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	long Low;
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int Range;
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _cacheSize;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _cache;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	long _position;
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void SetStream(java.io.OutputStream stream)
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Stream = stream;
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void ReleaseStream()
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Stream = null;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void Init()
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_position = 0;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Low = 0;
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Range = -1;
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_cacheSize = 1;
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_cache = 0;
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void FlushData() throws IOException
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < 5; i++)
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			ShiftLow();
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void FlushStream() throws IOException
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Stream.flush();
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void ShiftLow() throws IOException
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int LowHi = (int)(Low >>> 32);
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (LowHi != 0 || Low < 0xFF000000L)
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_position += _cacheSize;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int temp = _cache;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			do
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Stream.write(temp + LowHi);
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				temp = 0xFF;
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while(--_cacheSize != 0);
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_cache = (((int)Low) >>> 24);
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_cacheSize++;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Low = (Low & 0xFFFFFF) << 8;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void EncodeDirectBits(int v, int numTotalBits) throws IOException
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = numTotalBits - 1; i >= 0; i--)
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range >>>= 1;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (((v >>> i) & 1) == 1)
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Low += Range;
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if ((Range & Encoder.kTopMask) == 0)
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range <<= 8;
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				ShiftLow();
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public long GetProcessedSizeAdd()
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return _cacheSize + _position + 4;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kNumMoveReducingBits = 2;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static final int kNumBitPriceShiftBits = 6;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static void InitBitModels(short []probs)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < probs.length; i++)
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			probs[i] = (kBitModelTotal >>> 1);
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void Encode(short []probs, int index, int symbol) throws IOException
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int prob = probs[index];
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int newBound = (Range >>> kNumBitModelTotalBits) * prob;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (symbol == 0)
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range = newBound;
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		else
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Low += (newBound & 0xFFFFFFFFL);
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range -= newBound;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if ((Range & kTopMask) == 0)
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range <<= 8;
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			ShiftLow();
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits];
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = kNumBits - 1; i >= 0; i--)
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int start = 1 << (kNumBits - i - 1);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int end = 1 << (kNumBits - i);
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int j = start; j < end; j++)
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				ProbPrices[j] = (i << kNumBitPriceShiftBits) +
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1));
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static public int GetPrice(int Prob, int symbol)
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits];
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static public int GetPrice0(int Prob)
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return ProbPrices[Prob >>> kNumMoveReducingBits];
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static public int GetPrice1(int Prob)
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits];
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
152