1baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing System;
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace SevenZip.Compression.RangeCoder
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class Encoder
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const uint kTopValue = (1 << 24);
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		System.IO.Stream Stream;
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public UInt64 Low;
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint Range;
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		uint _cacheSize;
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		byte _cache;
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		long StartPosition;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void SetStream(System.IO.Stream stream)
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream = stream;
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void ReleaseStream()
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream = null;
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init()
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			StartPosition = Stream.Position;
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Low = 0;
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range = 0xFFFFFFFF;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_cacheSize = 1;
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_cache = 0;
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void FlushData()
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = 0; i < 5; i++)
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				ShiftLow();
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void FlushStream()
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream.Flush();
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void CloseStream()
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream.Close();
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Encode(uint start, uint size, uint total)
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Low += start * (Range /= total);
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range *= size;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (Range < kTopValue)
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range <<= 8;
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				ShiftLow();
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void ShiftLow()
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				byte temp = _cache;
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				do
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Stream.WriteByte((byte)(temp + (Low >> 32)));
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					temp = 0xFF;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				while (--_cacheSize != 0);
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_cache = (byte)(((uint)Low) >> 24);
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_cacheSize++;
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Low = ((uint)Low) << 8;
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void EncodeDirectBits(uint v, int numTotalBits)
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = numTotalBits - 1; i >= 0; i--)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range >>= 1;
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (((v >> i) & 1) == 1)
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Low += Range;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (Range < kTopValue)
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Range <<= 8;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					ShiftLow();
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void EncodeBit(uint size0, int numTotalBits, uint symbol)
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint newBound = (Range >> numTotalBits) * size0;
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (symbol == 0)
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range = newBound;
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Low += newBound;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range -= newBound;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (Range < kTopValue)
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range <<= 8;
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				ShiftLow();
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public long GetProcessedSizeAdd()
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return _cacheSize +
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Stream.Position - StartPosition + 4;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			// (long)Stream.GetProcessedSize();
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class Decoder
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const uint kTopValue = (1 << 24);
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint Range;
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint Code;
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public System.IO.Stream Stream;
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init(System.IO.Stream stream)
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			// Stream.Init(stream);
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream = stream;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Code = 0;
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range = 0xFFFFFFFF;
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = 0; i < 5; i++)
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Code = (Code << 8) | (byte)Stream.ReadByte();
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void ReleaseStream()
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			// Stream.ReleaseStream();
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream = null;
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void CloseStream()
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Stream.Close();
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Normalize()
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (Range < kTopValue)
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Code = (Code << 8) | (byte)Stream.ReadByte();
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range <<= 8;
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Normalize2()
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (Range < kTopValue)
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Code = (Code << 8) | (byte)Stream.ReadByte();
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range <<= 8;
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint GetThreshold(uint total)
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return Code / (Range /= total);
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Decode(uint start, uint size, uint total)
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Code -= start * Range;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range *= size;
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Normalize();
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint DecodeDirectBits(int numTotalBits)
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint range = Range;
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint code = Code;
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint result = 0;
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = numTotalBits; i > 0; i--)
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				range >>= 1;
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				/*
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				result <<= 1;
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (code >= range)
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					code -= range;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					result |= 1;
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				*/
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				uint t = (code - range) >> 31;
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				code -= range & (t - 1);
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				result = (result << 1) | (1 - t);
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (range < kTopValue)
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					code = (code << 8) | (byte)Stream.ReadByte();
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					range <<= 8;
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Range = range;
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Code = code;
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return result;
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint DecodeBit(uint size0, int numTotalBits)
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint newBound = (Range >> numTotalBits) * size0;
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint symbol;
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (Code < newBound)
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				symbol = 0;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range = newBound;
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				symbol = 1;
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Code -= newBound;
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Range -= newBound;
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Normalize();
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return symbol;
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
235