1 package SevenZip.Compression.RangeCoder;
2 import java.io.IOException;
3 
4 public 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 
SetStream(java.io.OutputStream stream)21 	public void SetStream(java.io.OutputStream stream)
22 	{
23 		Stream = stream;
24 	}
25 
ReleaseStream()26 	public void ReleaseStream()
27 	{
28 		Stream = null;
29 	}
30 
Init()31 	public void Init()
32 	{
33 		_position = 0;
34 		Low = 0;
35 		Range = -1;
36 		_cacheSize = 1;
37 		_cache = 0;
38 	}
39 
FlushData()40 	public void FlushData() throws IOException
41 	{
42 		for (int i = 0; i < 5; i++)
43 			ShiftLow();
44 	}
45 
FlushStream()46 	public void FlushStream() throws IOException
47 	{
48 		Stream.flush();
49 	}
50 
ShiftLow()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 
EncodeDirectBits(int v, int numTotalBits)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 
GetProcessedSizeAdd()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 
InitBitModels(short []probs)96 	public static void InitBitModels(short []probs)
97 	{
98 		for (int i = 0; i < probs.length; i++)
99 			probs[i] = (kBitModelTotal >>> 1);
100 	}
101 
Encode(short []probs, int index, int symbol)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 
GetPrice(int Prob, int symbol)139 	static public int GetPrice(int Prob, int symbol)
140 	{
141 		return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits];
142 	}
GetPrice0(int Prob)143 	static public int GetPrice0(int Prob)
144 	{
145 		return ProbPrices[Prob >>> kNumMoveReducingBits];
146 	}
GetPrice1(int Prob)147 	static public int GetPrice1(int Prob)
148 	{
149 		return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits];
150 	}
151 }
152