1baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing System;
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace SevenZip.Compression.RangeCoder
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	struct BitEncoder
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const int kNumBitModelTotalBits = 11;
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		const int kNumMoveBits = 5;
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		const int kNumMoveReducingBits = 2;
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const int kNumBitPriceShiftBits = 6;
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		uint Prob;
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init() { Prob = kBitModelTotal >> 1; }
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void UpdateModel(uint symbol)
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (symbol == 0)
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob -= (Prob) >> kNumMoveBits;
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Encode(Encoder encoder, uint symbol)
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			// UpdateModel(symbol);
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (symbol == 0)
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				encoder.Range = newBound;
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				encoder.Low += newBound;
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				encoder.Range -= newBound;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob -= (Prob) >> kNumMoveBits;
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (encoder.Range < Encoder.kTopValue)
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				encoder.Range <<= 8;
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				encoder.ShiftLow();
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		static BitEncoder()
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = kNumBits - 1; i >= 0; i--)
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				UInt32 start = (UInt32)1 << (kNumBits - i - 1);
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				UInt32 end = (UInt32)1 << (kNumBits - i);
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (UInt32 j = start; j < end; j++)
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint GetPrice(uint symbol)
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	  public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	struct BitDecoder
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const int kNumBitModelTotalBits = 11;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		const int kNumMoveBits = 5;
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		uint Prob;
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void UpdateModel(int numMoveBits, uint symbol)
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (symbol == 0)
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob += (kBitModelTotal - Prob) >> numMoveBits;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob -= (Prob) >> numMoveBits;
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init() { Prob = kBitModelTotal >> 1; }
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public uint Decode(RangeCoder.Decoder rangeDecoder)
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (rangeDecoder.Code < newBound)
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				rangeDecoder.Range = newBound;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (rangeDecoder.Range < Decoder.kTopValue)
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeDecoder.Range <<= 8;
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return 0;
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				rangeDecoder.Range -= newBound;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				rangeDecoder.Code -= newBound;
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Prob -= (Prob) >> kNumMoveBits;
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (rangeDecoder.Range < Decoder.kTopValue)
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeDecoder.Range <<= 8;
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return 1;
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
118