summaryrefslogtreecommitdiffstats
path: root/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Encoder.java
blob: 2273e92e50d0f4f9cfe84a90d2eb2b5e84eaa5df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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]; 
	}
}