1370b324cSopenharmony_ciusing System;
2370b324cSopenharmony_ci
3370b324cSopenharmony_cinamespace SevenZip.Compression.RangeCoder
4370b324cSopenharmony_ci{
5370b324cSopenharmony_ci	class Encoder
6370b324cSopenharmony_ci	{
7370b324cSopenharmony_ci		public const uint kTopValue = (1 << 24);
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci		System.IO.Stream Stream;
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci		public UInt64 Low;
12370b324cSopenharmony_ci		public uint Range;
13370b324cSopenharmony_ci		uint _cacheSize;
14370b324cSopenharmony_ci		byte _cache;
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci		long StartPosition;
17370b324cSopenharmony_ci
18370b324cSopenharmony_ci		public void SetStream(System.IO.Stream stream)
19370b324cSopenharmony_ci		{
20370b324cSopenharmony_ci			Stream = stream;
21370b324cSopenharmony_ci		}
22370b324cSopenharmony_ci
23370b324cSopenharmony_ci		public void ReleaseStream()
24370b324cSopenharmony_ci		{
25370b324cSopenharmony_ci			Stream = null;
26370b324cSopenharmony_ci		}
27370b324cSopenharmony_ci
28370b324cSopenharmony_ci		public void Init()
29370b324cSopenharmony_ci		{
30370b324cSopenharmony_ci			StartPosition = Stream.Position;
31370b324cSopenharmony_ci
32370b324cSopenharmony_ci			Low = 0;
33370b324cSopenharmony_ci			Range = 0xFFFFFFFF;
34370b324cSopenharmony_ci			_cacheSize = 1;
35370b324cSopenharmony_ci			_cache = 0;
36370b324cSopenharmony_ci		}
37370b324cSopenharmony_ci
38370b324cSopenharmony_ci		public void FlushData()
39370b324cSopenharmony_ci		{
40370b324cSopenharmony_ci			for (int i = 0; i < 5; i++)
41370b324cSopenharmony_ci				ShiftLow();
42370b324cSopenharmony_ci		}
43370b324cSopenharmony_ci
44370b324cSopenharmony_ci		public void FlushStream()
45370b324cSopenharmony_ci		{
46370b324cSopenharmony_ci			Stream.Flush();
47370b324cSopenharmony_ci		}
48370b324cSopenharmony_ci
49370b324cSopenharmony_ci		public void CloseStream()
50370b324cSopenharmony_ci		{
51370b324cSopenharmony_ci			Stream.Close();
52370b324cSopenharmony_ci		}
53370b324cSopenharmony_ci
54370b324cSopenharmony_ci		public void Encode(uint start, uint size, uint total)
55370b324cSopenharmony_ci		{
56370b324cSopenharmony_ci			Low += start * (Range /= total);
57370b324cSopenharmony_ci			Range *= size;
58370b324cSopenharmony_ci			while (Range < kTopValue)
59370b324cSopenharmony_ci			{
60370b324cSopenharmony_ci				Range <<= 8;
61370b324cSopenharmony_ci				ShiftLow();
62370b324cSopenharmony_ci			}
63370b324cSopenharmony_ci		}
64370b324cSopenharmony_ci
65370b324cSopenharmony_ci		public void ShiftLow()
66370b324cSopenharmony_ci		{
67370b324cSopenharmony_ci			if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
68370b324cSopenharmony_ci			{
69370b324cSopenharmony_ci				byte temp = _cache;
70370b324cSopenharmony_ci				do
71370b324cSopenharmony_ci				{
72370b324cSopenharmony_ci					Stream.WriteByte((byte)(temp + (Low >> 32)));
73370b324cSopenharmony_ci					temp = 0xFF;
74370b324cSopenharmony_ci				}
75370b324cSopenharmony_ci				while (--_cacheSize != 0);
76370b324cSopenharmony_ci				_cache = (byte)(((uint)Low) >> 24);
77370b324cSopenharmony_ci			}
78370b324cSopenharmony_ci			_cacheSize++;
79370b324cSopenharmony_ci			Low = ((uint)Low) << 8;
80370b324cSopenharmony_ci		}
81370b324cSopenharmony_ci
82370b324cSopenharmony_ci		public void EncodeDirectBits(uint v, int numTotalBits)
83370b324cSopenharmony_ci		{
84370b324cSopenharmony_ci			for (int i = numTotalBits - 1; i >= 0; i--)
85370b324cSopenharmony_ci			{
86370b324cSopenharmony_ci				Range >>= 1;
87370b324cSopenharmony_ci				if (((v >> i) & 1) == 1)
88370b324cSopenharmony_ci					Low += Range;
89370b324cSopenharmony_ci				if (Range < kTopValue)
90370b324cSopenharmony_ci				{
91370b324cSopenharmony_ci					Range <<= 8;
92370b324cSopenharmony_ci					ShiftLow();
93370b324cSopenharmony_ci				}
94370b324cSopenharmony_ci			}
95370b324cSopenharmony_ci		}
96370b324cSopenharmony_ci
97370b324cSopenharmony_ci		public void EncodeBit(uint size0, int numTotalBits, uint symbol)
98370b324cSopenharmony_ci		{
99370b324cSopenharmony_ci			uint newBound = (Range >> numTotalBits) * size0;
100370b324cSopenharmony_ci			if (symbol == 0)
101370b324cSopenharmony_ci				Range = newBound;
102370b324cSopenharmony_ci			else
103370b324cSopenharmony_ci			{
104370b324cSopenharmony_ci				Low += newBound;
105370b324cSopenharmony_ci				Range -= newBound;
106370b324cSopenharmony_ci			}
107370b324cSopenharmony_ci			while (Range < kTopValue)
108370b324cSopenharmony_ci			{
109370b324cSopenharmony_ci				Range <<= 8;
110370b324cSopenharmony_ci				ShiftLow();
111370b324cSopenharmony_ci			}
112370b324cSopenharmony_ci		}
113370b324cSopenharmony_ci
114370b324cSopenharmony_ci		public long GetProcessedSizeAdd()
115370b324cSopenharmony_ci		{
116370b324cSopenharmony_ci			return _cacheSize +
117370b324cSopenharmony_ci				Stream.Position - StartPosition + 4;
118370b324cSopenharmony_ci			// (long)Stream.GetProcessedSize();
119370b324cSopenharmony_ci		}
120370b324cSopenharmony_ci	}
121370b324cSopenharmony_ci
122370b324cSopenharmony_ci	class Decoder
123370b324cSopenharmony_ci	{
124370b324cSopenharmony_ci		public const uint kTopValue = (1 << 24);
125370b324cSopenharmony_ci		public uint Range;
126370b324cSopenharmony_ci		public uint Code;
127370b324cSopenharmony_ci		// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
128370b324cSopenharmony_ci		public System.IO.Stream Stream;
129370b324cSopenharmony_ci
130370b324cSopenharmony_ci		public void Init(System.IO.Stream stream)
131370b324cSopenharmony_ci		{
132370b324cSopenharmony_ci			// Stream.Init(stream);
133370b324cSopenharmony_ci			Stream = stream;
134370b324cSopenharmony_ci
135370b324cSopenharmony_ci			Code = 0;
136370b324cSopenharmony_ci			Range = 0xFFFFFFFF;
137370b324cSopenharmony_ci			for (int i = 0; i < 5; i++)
138370b324cSopenharmony_ci				Code = (Code << 8) | (byte)Stream.ReadByte();
139370b324cSopenharmony_ci		}
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci		public void ReleaseStream()
142370b324cSopenharmony_ci		{
143370b324cSopenharmony_ci			// Stream.ReleaseStream();
144370b324cSopenharmony_ci			Stream = null;
145370b324cSopenharmony_ci		}
146370b324cSopenharmony_ci
147370b324cSopenharmony_ci		public void CloseStream()
148370b324cSopenharmony_ci		{
149370b324cSopenharmony_ci			Stream.Close();
150370b324cSopenharmony_ci		}
151370b324cSopenharmony_ci
152370b324cSopenharmony_ci		public void Normalize()
153370b324cSopenharmony_ci		{
154370b324cSopenharmony_ci			while (Range < kTopValue)
155370b324cSopenharmony_ci			{
156370b324cSopenharmony_ci				Code = (Code << 8) | (byte)Stream.ReadByte();
157370b324cSopenharmony_ci				Range <<= 8;
158370b324cSopenharmony_ci			}
159370b324cSopenharmony_ci		}
160370b324cSopenharmony_ci
161370b324cSopenharmony_ci		public void Normalize2()
162370b324cSopenharmony_ci		{
163370b324cSopenharmony_ci			if (Range < kTopValue)
164370b324cSopenharmony_ci			{
165370b324cSopenharmony_ci				Code = (Code << 8) | (byte)Stream.ReadByte();
166370b324cSopenharmony_ci				Range <<= 8;
167370b324cSopenharmony_ci			}
168370b324cSopenharmony_ci		}
169370b324cSopenharmony_ci
170370b324cSopenharmony_ci		public uint GetThreshold(uint total)
171370b324cSopenharmony_ci		{
172370b324cSopenharmony_ci			return Code / (Range /= total);
173370b324cSopenharmony_ci		}
174370b324cSopenharmony_ci
175370b324cSopenharmony_ci		public void Decode(uint start, uint size, uint total)
176370b324cSopenharmony_ci		{
177370b324cSopenharmony_ci			Code -= start * Range;
178370b324cSopenharmony_ci			Range *= size;
179370b324cSopenharmony_ci			Normalize();
180370b324cSopenharmony_ci		}
181370b324cSopenharmony_ci
182370b324cSopenharmony_ci		public uint DecodeDirectBits(int numTotalBits)
183370b324cSopenharmony_ci		{
184370b324cSopenharmony_ci			uint range = Range;
185370b324cSopenharmony_ci			uint code = Code;
186370b324cSopenharmony_ci			uint result = 0;
187370b324cSopenharmony_ci			for (int i = numTotalBits; i > 0; i--)
188370b324cSopenharmony_ci			{
189370b324cSopenharmony_ci				range >>= 1;
190370b324cSopenharmony_ci				/*
191370b324cSopenharmony_ci				result <<= 1;
192370b324cSopenharmony_ci				if (code >= range)
193370b324cSopenharmony_ci				{
194370b324cSopenharmony_ci					code -= range;
195370b324cSopenharmony_ci					result |= 1;
196370b324cSopenharmony_ci				}
197370b324cSopenharmony_ci				*/
198370b324cSopenharmony_ci				uint t = (code - range) >> 31;
199370b324cSopenharmony_ci				code -= range & (t - 1);
200370b324cSopenharmony_ci				result = (result << 1) | (1 - t);
201370b324cSopenharmony_ci
202370b324cSopenharmony_ci				if (range < kTopValue)
203370b324cSopenharmony_ci				{
204370b324cSopenharmony_ci					code = (code << 8) | (byte)Stream.ReadByte();
205370b324cSopenharmony_ci					range <<= 8;
206370b324cSopenharmony_ci				}
207370b324cSopenharmony_ci			}
208370b324cSopenharmony_ci			Range = range;
209370b324cSopenharmony_ci			Code = code;
210370b324cSopenharmony_ci			return result;
211370b324cSopenharmony_ci		}
212370b324cSopenharmony_ci
213370b324cSopenharmony_ci		public uint DecodeBit(uint size0, int numTotalBits)
214370b324cSopenharmony_ci		{
215370b324cSopenharmony_ci			uint newBound = (Range >> numTotalBits) * size0;
216370b324cSopenharmony_ci			uint symbol;
217370b324cSopenharmony_ci			if (Code < newBound)
218370b324cSopenharmony_ci			{
219370b324cSopenharmony_ci				symbol = 0;
220370b324cSopenharmony_ci				Range = newBound;
221370b324cSopenharmony_ci			}
222370b324cSopenharmony_ci			else
223370b324cSopenharmony_ci			{
224370b324cSopenharmony_ci				symbol = 1;
225370b324cSopenharmony_ci				Code -= newBound;
226370b324cSopenharmony_ci				Range -= newBound;
227370b324cSopenharmony_ci			}
228370b324cSopenharmony_ci			Normalize();
229370b324cSopenharmony_ci			return symbol;
230370b324cSopenharmony_ci		}
231370b324cSopenharmony_ci
232370b324cSopenharmony_ci		// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
233370b324cSopenharmony_ci	}
234370b324cSopenharmony_ci}
235