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