1baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpackage SevenZip.Compression.LZMA;
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport SevenZip.Compression.RangeCoder.BitTreeEncoder;
4baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport SevenZip.Compression.LZMA.Base;
5baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport SevenZip.Compression.LZ.BinTree;
6baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport SevenZip.ICodeProgress;
7baa3858d3f5d128a5c8466b700098109edcad5f2repo syncimport java.io.IOException;
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
9baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic class Encoder
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static final int EMatchFinderTypeBT2 = 0;
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static final int EMatchFinderTypeBT4 = 1;
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kIfinityPrice = 0xFFFFFFF;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static byte[] g_FastPos = new byte[1 << 11];
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int kFastSlots = 22;
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int c = 2;
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		g_FastPos[0] = 0;
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		g_FastPos[1] = 1;
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int slotFast = 2; slotFast < kFastSlots; slotFast++)
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int k = (1 << ((slotFast >> 1) - 1));
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int j = 0; j < k; j++, c++)
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				g_FastPos[c] = (byte)slotFast;
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static int GetPosSlot(int pos)
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (pos < (1 << 11))
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return g_FastPos[pos];
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (pos < (1 << 21))
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return (g_FastPos[pos >> 10] + 20);
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return (g_FastPos[pos >> 20] + 40);
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static int GetPosSlot2(int pos)
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (pos < (1 << 17))
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return (g_FastPos[pos >> 6] + 12);
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (pos < (1 << 27))
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return (g_FastPos[pos >> 16] + 32);
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return (g_FastPos[pos >> 26] + 52);
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _state = Base.StateInit();
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	byte _previousByte;
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] _repDistances = new int[Base.kNumRepDistances];
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void BaseInit()
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_state = Base.StateInit();
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_previousByte = 0;
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < Base.kNumRepDistances; i++)
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_repDistances[i] = 0;
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kDefaultDictionaryLogSize = 22;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kNumFastBytesDefault = 0x20;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class LiteralEncoder
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		class Encoder2
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			short[] m_Encoders = new short[0x300];
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); }
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int context = 1;
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (int i = 7; i >= 0; i--)
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int bit = ((symbol >> i) & 1);
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeEncoder.Encode(m_Encoders, context, bit);
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					context = (context << 1) | bit;
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int context = 1;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				boolean same = true;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (int i = 7; i >= 0; i--)
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int bit = ((symbol >> i) & 1);
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int state = context;
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (same)
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int matchBit = ((matchByte >> i) & 1);
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state += ((1 + matchBit) << 8);
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						same = (matchBit == bit);
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeEncoder.Encode(m_Encoders, state, bit);
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					context = (context << 1) | bit;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			public int GetPrice(boolean matchMode, byte matchByte, byte symbol)
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int price = 0;
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int context = 1;
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int i = 7;
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (matchMode)
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					for (; i >= 0; i--)
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int matchBit = (matchByte >> i) & 1;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int bit = (symbol >> i) & 1;
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit);
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						context = (context << 1) | bit;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (matchBit != bit)
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							i--;
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							break;
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (; i >= 0; i--)
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int bit = (symbol >> i) & 1;
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					context = (context << 1) | bit;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return price;
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Encoder2[] m_Coders;
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int m_NumPrevBits;
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int m_NumPosBits;
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int m_PosMask;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Create(int numPosBits, int numPrevBits)
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return;
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			m_NumPosBits = numPosBits;
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			m_PosMask = (1 << numPosBits) - 1;
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			m_NumPrevBits = numPrevBits;
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			m_Coders = new Encoder2[numStates];
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = 0; i < numStates; i++)
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				m_Coders[i] = new Encoder2();
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init()
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int i = 0; i < numStates; i++)
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				m_Coders[i].Init();
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public Encoder2 GetSubCoder(int pos, byte prevByte)
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; }
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class LenEncoder
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		short[] _choice = new short[2];
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits);
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public LenEncoder()
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Init(int numPosStates)
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice);
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int posState = 0; posState < numPosStates; posState++)
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_lowCoder[posState].Init();
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_midCoder[posState].Init();
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_highCoder.Init();
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (symbol < Base.kNumLowLenSymbols)
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				rangeEncoder.Encode(_choice, 0, 0);
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_lowCoder[posState].Encode(rangeEncoder, symbol);
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				symbol -= Base.kNumLowLenSymbols;
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				rangeEncoder.Encode(_choice, 0, 1);
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (symbol < Base.kNumMidLenSymbols)
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeEncoder.Encode(_choice, 1, 0);
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_midCoder[posState].Encode(rangeEncoder, symbol);
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					rangeEncoder.Encode(_choice, 1, 1);
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void SetPrices(int posState, int numSymbols, int[] prices, int st)
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]);
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]);
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]);
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]);
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int i = 0;
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (i = 0; i < Base.kNumLowLenSymbols; i++)
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (i >= numSymbols)
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					return;
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (i >= numSymbols)
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					return;
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (; i < numSymbols; i++)
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	};
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class LenPriceTableEncoder extends LenEncoder
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax];
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int _tableSize;
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int[] _counters = new int[Base.kNumPosStatesEncodingMax];
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void SetTableSize(int tableSize) { _tableSize = tableSize; }
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int GetPrice(int symbol, int posState)
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return _prices[posState * Base.kNumLenSymbols + symbol];
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		void UpdateTable(int posState)
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_counters[posState] = _tableSize;
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void UpdateTables(int numPosStates)
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int posState = 0; posState < numPosStates; posState++)
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				UpdateTable(posState);
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			super.Encode(rangeEncoder, symbol, posState);
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (--_counters[posState] == 0)
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				UpdateTable(posState);
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	static final int kNumOpts = 1 << 12;
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	class Optimal
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int State;
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public boolean Prev1IsChar;
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public boolean Prev2;
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int PosPrev2;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int BackPrev2;
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int Price;
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int PosPrev;
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int BackPrev;
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int Backs0;
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int Backs1;
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int Backs2;
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public int Backs3;
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; }
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		public boolean IsShortRep() { return (BackPrev == 0); }
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	};
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	Optimal[] _optimum = new Optimal[kNumOpts];
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	SevenZip.Compression.LZ.BinTree _matchFinder = null;
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isRep = new short[Base.kNumStates];
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isRepG0 = new short[Base.kNumStates];
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isRepG1 = new short[Base.kNumStates];
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isRepG2 = new short[Base.kNumStates];
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex];
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits);
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	LiteralEncoder _literalEncoder = new LiteralEncoder();
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] _matchDistances = new int[Base.kMatchMaxLen*2+2];
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _numFastBytes = kNumFastBytesDefault;
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _longestMatchLength;
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _numDistancePairs;
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _additionalOffset;
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _optimumEndIndex;
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _optimumCurrentIndex;
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	boolean _longestMatchWasFound;
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)];
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits];
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] _alignPrices = new int[Base.kAlignTableSize];
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _alignPriceCount;
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _distTableSize = (kDefaultDictionaryLogSize * 2);
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _posStateBits = 2;
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _posStateMask = (4 - 1);
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _numLiteralPosStateBits = 0;
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _numLiteralContextBits = 3;
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _dictionarySize = (1 << kDefaultDictionaryLogSize);
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _dictionarySizePrev = -1;
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _numFastBytesPrev = -1;
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	long nowPos64;
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	boolean _finished;
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	java.io.InputStream _inStream;
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _matchFinderType = EMatchFinderTypeBT4;
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	boolean _writeEndMark = false;
359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	boolean _needReleaseMFStream = false;
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void Create()
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_matchFinder == null)
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree();
367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int numHashBytes = 4;
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (_matchFinderType == EMatchFinderTypeBT2)
369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				numHashBytes = 2;
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			bt.SetType(numHashBytes);
371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder = bt;
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return;
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_dictionarySizePrev = _dictionarySize;
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_numFastBytesPrev = _numFastBytes;
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public Encoder()
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < kNumOpts; i++)
385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[i] = new Optimal();
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < Base.kNumLenToPosStates; i++)
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void SetWriteEndMarkerMode(boolean writeEndMarker)
391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_writeEndMark = writeEndMarker;
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void Init()
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		BaseInit();
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.Init();
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch);
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long);
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep);
403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0);
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1);
405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2);
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders);
407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_literalEncoder.Init();
415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < Base.kNumLenToPosStates; i++)
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_posSlotEncoder[i].Init();
417baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
418baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_lenEncoder.Init(1 << _posStateBits);
421baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_repMatchLenEncoder.Init(1 << _posStateBits);
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
423baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_posAlignEncoder.Init();
424baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
425baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_longestMatchWasFound = false;
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimumEndIndex = 0;
427baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimumCurrentIndex = 0;
428baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_additionalOffset = 0;
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
430baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int ReadMatchDistances() throws java.io.IOException
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int lenRes = 0;
434baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_numDistancePairs = _matchFinder.GetMatches(_matchDistances);
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_numDistancePairs > 0)
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			lenRes = _matchDistances[_numDistancePairs - 2];
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (lenRes == _numFastBytes)
439baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1],
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Base.kMatchMaxLen - lenRes);
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_additionalOffset++;
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return lenRes;
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
445baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
446baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void MovePos(int num) throws java.io.IOException
447baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
448baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (num > 0)
449baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
450baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder.Skip(num);
451baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_additionalOffset += num;
452baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
453baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
454baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
455baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int GetRepLen1Price(int state, int posState)
456baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
457baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) +
458baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
459baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
460baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
461baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int GetPureRepPrice(int repIndex, int state, int posState)
462baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
463baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int price;
464baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (repIndex == 0)
465baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
466baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]);
467baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
468baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
469baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		else
470baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
471baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]);
472baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (repIndex == 1)
473baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]);
474baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
475baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
476baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]);
477baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2);
478baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
479baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
480baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return price;
481baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
482baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
483baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int GetRepPrice(int repIndex, int len, int state, int posState)
484baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
485baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
486baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return price + GetPureRepPrice(repIndex, state, posState);
487baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
488baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
489baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int GetPosLenPrice(int pos, int len, int posState)
490baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
491baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int price;
492baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int lenToPosState = Base.GetLenToPosState(len);
493baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (pos < Base.kNumFullDistances)
494baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
495baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		else
496baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
497baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_alignPrices[pos & Base.kAlignMask];
498baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
499baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
500baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
501baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int Backward(int cur)
502baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
503baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimumEndIndex = cur;
504baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int posMem = _optimum[cur].PosPrev;
505baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int backMem = _optimum[cur].BackPrev;
506baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		do
507baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
508baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (_optimum[cur].Prev1IsChar)
509baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
510baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_optimum[posMem].MakeAsChar();
511baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_optimum[posMem].PosPrev = posMem - 1;
512baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_optimum[cur].Prev2)
513baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
514baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_optimum[posMem - 1].Prev1IsChar = false;
515baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
516baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
517baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
518baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
519baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posPrev = posMem;
520baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int backCur = backMem;
521baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
522baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backMem = _optimum[posPrev].BackPrev;
523baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			posMem = _optimum[posPrev].PosPrev;
524baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
525baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[posPrev].BackPrev = backCur;
526baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[posPrev].PosPrev = cur;
527baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			cur = posPrev;
528baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
529baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		while (cur > 0);
530baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		backRes = _optimum[0].BackPrev;
531baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimumCurrentIndex = _optimum[0].PosPrev;
532baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return _optimumCurrentIndex;
533baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
534baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
535baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] reps = new int[Base.kNumRepDistances];
536baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] repLens = new int[Base.kNumRepDistances];
537baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int backRes;
538baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
539baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int GetOptimum(int position) throws IOException
540baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
541baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_optimumEndIndex != _optimumCurrentIndex)
542baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
543baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
544baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = _optimum[_optimumCurrentIndex].BackPrev;
545baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
546baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return lenRes;
547baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
548baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimumCurrentIndex = _optimumEndIndex = 0;
549baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
550baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int lenMain, numDistancePairs;
551baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (!_longestMatchWasFound)
552baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
553baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			lenMain = ReadMatchDistances();
554baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
555baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		else
556baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
557baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			lenMain = _longestMatchLength;
558baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_longestMatchWasFound = false;
559baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
560baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		numDistancePairs = _numDistancePairs;
561baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
562baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
563baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (numAvailableBytes < 2)
564baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
565baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = -1;
566baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return 1;
567baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
568baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (numAvailableBytes > Base.kMatchMaxLen)
569baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			numAvailableBytes = Base.kMatchMaxLen;
570baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
571baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int repMaxIndex = 0;
572baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int i;
573baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (i = 0; i < Base.kNumRepDistances; i++)
574baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
575baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			reps[i] = _repDistances[i];
576baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
577baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (repLens[i] > repLens[repMaxIndex])
578baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				repMaxIndex = i;
579baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
580baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (repLens[repMaxIndex] >= _numFastBytes)
581baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
582baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = repMaxIndex;
583baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int lenRes = repLens[repMaxIndex];
584baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			MovePos(lenRes - 1);
585baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return lenRes;
586baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
587baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
588baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (lenMain >= _numFastBytes)
589baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
590baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
591baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			MovePos(lenMain - 1);
592baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return lenMain;
593baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
594baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
595baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		byte currentByte = _matchFinder.GetIndexByte(0 - 1);
596baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1);
597baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
598baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
599baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
600baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = -1;
601baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return 1;
602baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
603baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
604baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[0].State = _state;
605baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
606baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int posState = (position & _posStateMask);
607baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
608baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) +
609baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte);
610baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[1].MakeAsChar();
611baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
612baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]);
613baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]);
614baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
615baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (matchByte == currentByte)
616baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
617baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
618baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (shortRepPrice < _optimum[1].Price)
619baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
620baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_optimum[1].Price = shortRepPrice;
621baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_optimum[1].MakeAsShortRep();
622baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
623baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
624baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
625baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
626baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
627baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (lenEnd < 2)
628baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
629baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			backRes = _optimum[1].BackPrev;
630baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return 1;
631baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
632baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
633baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[1].PosPrev = 0;
634baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
635baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[0].Backs0 = reps[0];
636baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[0].Backs1 = reps[1];
637baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[0].Backs2 = reps[2];
638baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_optimum[0].Backs3 = reps[3];
639baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
640baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int len = lenEnd;
641baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		do
642baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[len--].Price = kIfinityPrice;
643baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		while (len >= 2);
644baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
645baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (i = 0; i < Base.kNumRepDistances; i++)
646baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
647baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int repLen = repLens[i];
648baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (repLen < 2)
649baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				continue;
650baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int price = repMatchPrice + GetPureRepPrice(i, _state, posState);
651baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			do
652baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
653baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
654baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Optimal optimum = _optimum[repLen];
655baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (curAndLenPrice < optimum.Price)
656baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
657baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.Price = curAndLenPrice;
658baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.PosPrev = 0;
659baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.BackPrev = i;
660baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.Prev1IsChar = false;
661baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
662baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
663baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (--repLen >= 2);
664baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
665baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
666baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]);
667baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
668baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
669baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (len <= lenMain)
670baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
671baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int offs = 0;
672baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (len > _matchDistances[offs])
673baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				offs += 2;
674baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (; ; len++)
675baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
676baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int distance = _matchDistances[offs + 1];
677baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
678baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Optimal optimum = _optimum[len];
679baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (curAndLenPrice < optimum.Price)
680baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
681baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.Price = curAndLenPrice;
682baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.PosPrev = 0;
683baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.BackPrev = distance + Base.kNumRepDistances;
684baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					optimum.Prev1IsChar = false;
685baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
686baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (len == _matchDistances[offs])
687baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
688baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					offs += 2;
689baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (offs == numDistancePairs)
690baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						break;
691baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
692baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
693baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
694baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
695baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int cur = 0;
696baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
697baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		while (true)
698baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
699baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			cur++;
700baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (cur == lenEnd)
701baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return Backward(cur);
702baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int newLen = ReadMatchDistances();
703baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			numDistancePairs = _numDistancePairs;
704baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (newLen >= _numFastBytes)
705baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
706baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
707baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_longestMatchLength = newLen;
708baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_longestMatchWasFound = true;
709baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return Backward(cur);
710baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
711baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			position++;
712baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posPrev = _optimum[cur].PosPrev;
713baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int state;
714baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (_optimum[cur].Prev1IsChar)
715baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
716baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				posPrev--;
717baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_optimum[cur].Prev2)
718baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
719baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					state = _optimum[_optimum[cur].PosPrev2].State;
720baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
721baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state = Base.StateUpdateRep(state);
722baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else
723baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state = Base.StateUpdateMatch(state);
724baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
725baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
726baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					state = _optimum[posPrev].State;
727baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				state = Base.StateUpdateChar(state);
728baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
729baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
730baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				state = _optimum[posPrev].State;
731baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (posPrev == cur - 1)
732baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
733baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_optimum[cur].IsShortRep())
734baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					state = Base.StateUpdateShortRep(state);
735baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
736baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					state = Base.StateUpdateChar(state);
737baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
738baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
739baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
740baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int pos;
741baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
742baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
743baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					posPrev = _optimum[cur].PosPrev2;
744baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					pos = _optimum[cur].BackPrev2;
745baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					state = Base.StateUpdateRep(state);
746baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
747baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
748baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
749baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					pos = _optimum[cur].BackPrev;
750baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (pos < Base.kNumRepDistances)
751baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state = Base.StateUpdateRep(state);
752baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else
753baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state = Base.StateUpdateMatch(state);
754baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
755baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Optimal opt = _optimum[posPrev];
756baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (pos < Base.kNumRepDistances)
757baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
758baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (pos == 0)
759baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
760baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[0] = opt.Backs0;
761baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[1] = opt.Backs1;
762baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[2] = opt.Backs2;
763baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[3] = opt.Backs3;
764baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
765baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else if (pos == 1)
766baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
767baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[0] = opt.Backs1;
768baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[1] = opt.Backs0;
769baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[2] = opt.Backs2;
770baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[3] = opt.Backs3;
771baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
772baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else if (pos == 2)
773baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
774baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[0] = opt.Backs2;
775baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[1] = opt.Backs0;
776baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[2] = opt.Backs1;
777baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[3] = opt.Backs3;
778baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
779baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else
780baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
781baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[0] = opt.Backs3;
782baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[1] = opt.Backs0;
783baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[2] = opt.Backs1;
784baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						reps[3] = opt.Backs2;
785baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
786baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
787baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
788baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
789baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					reps[0] = (pos - Base.kNumRepDistances);
790baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					reps[1] = opt.Backs0;
791baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					reps[2] = opt.Backs1;
792baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					reps[3] = opt.Backs2;
793baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
794baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
795baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[cur].State = state;
796baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[cur].Backs0 = reps[0];
797baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[cur].Backs1 = reps[1];
798baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[cur].Backs2 = reps[2];
799baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_optimum[cur].Backs3 = reps[3];
800baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int curPrice = _optimum[cur].Price;
801baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
802baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			currentByte = _matchFinder.GetIndexByte(0 - 1);
803baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1);
804baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
805baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			posState = (position & _posStateMask);
806baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
807baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int curAnd1Price = curPrice +
808baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) +
809baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
810baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				GetPrice(!Base.StateIsCharState(state), matchByte, currentByte);
811baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
812baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Optimal nextOptimum = _optimum[cur + 1];
813baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
814baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			boolean nextIsChar = false;
815baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (curAnd1Price < nextOptimum.Price)
816baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
817baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				nextOptimum.Price = curAnd1Price;
818baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				nextOptimum.PosPrev = cur;
819baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				nextOptimum.MakeAsChar();
820baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				nextIsChar = true;
821baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
822baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
823baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]);
824baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]);
825baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
826baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (matchByte == currentByte &&
827baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
828baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
829baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
830baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (shortRepPrice <= nextOptimum.Price)
831baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
832baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					nextOptimum.Price = shortRepPrice;
833baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					nextOptimum.PosPrev = cur;
834baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					nextOptimum.MakeAsShortRep();
835baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					nextIsChar = true;
836baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
837baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
838baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
839baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
840baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull);
841baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			numAvailableBytes = numAvailableBytesFull;
842baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
843baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (numAvailableBytes < 2)
844baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				continue;
845baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (numAvailableBytes > _numFastBytes)
846baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				numAvailableBytes = _numFastBytes;
847baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (!nextIsChar && matchByte != currentByte)
848baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
849baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				// try Literal + rep0
850baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int t = Math.min(numAvailableBytesFull - 1, _numFastBytes);
851baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
852baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (lenTest2 >= 2)
853baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
854baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int state2 = Base.StateUpdateChar(state);
855baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
856baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int posStateNext = (position + 1) & _posStateMask;
857baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int nextRepMatchPrice = curAnd1Price +
858baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
859baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
860baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
861baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int offset = cur + 1 + lenTest2;
862baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						while (lenEnd < offset)
863baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_optimum[++lenEnd].Price = kIfinityPrice;
864baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int curAndLenPrice = nextRepMatchPrice + GetRepPrice(
865baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								0, lenTest2, state2, posStateNext);
866baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						Optimal optimum = _optimum[offset];
867baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (curAndLenPrice < optimum.Price)
868baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
869baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							optimum.Price = curAndLenPrice;
870baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							optimum.PosPrev = cur + 1;
871baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							optimum.BackPrev = 0;
872baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							optimum.Prev1IsChar = true;
873baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							optimum.Prev2 = false;
874baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
875baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
876baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
877baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
878baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
879baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int startLen = 2; // speed optimization
880baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
881baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
882baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
883baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
884baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (lenTest < 2)
885baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					continue;
886baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int lenTestTemp = lenTest;
887baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				do
888baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
889baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					while (lenEnd < cur + lenTest)
890baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_optimum[++lenEnd].Price = kIfinityPrice;
891baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
892baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Optimal optimum = _optimum[cur + lenTest];
893baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (curAndLenPrice < optimum.Price)
894baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
895baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.Price = curAndLenPrice;
896baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.PosPrev = cur;
897baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.BackPrev = repIndex;
898baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.Prev1IsChar = false;
899baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
900baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
901baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				while (--lenTest >= 2);
902baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				lenTest = lenTestTemp;
903baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
904baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (repIndex == 0)
905baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					startLen = lenTest + 1;
906baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
907baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				// if (_maxMode)
908baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (lenTest < numAvailableBytesFull)
909baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
910baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
911baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);
912baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (lenTest2 >= 2)
913baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
914baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int state2 = Base.StateUpdateRep(state);
915baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
916baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int posStateNext = (position + lenTest) & _posStateMask;
917baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int curAndLenCharPrice =
918baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
919baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
920baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								_literalEncoder.GetSubCoder(position + lenTest,
921baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								_matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true,
922baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								_matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)),
923baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								_matchFinder.GetIndexByte(lenTest - 1));
924baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						state2 = Base.StateUpdateChar(state2);
925baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						posStateNext = (position + lenTest + 1) & _posStateMask;
926baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
927baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
928baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
929baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						// for(; lenTest2 >= 2; lenTest2--)
930baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
931baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							int offset = lenTest + 1 + lenTest2;
932baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							while (lenEnd < cur + offset)
933baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								_optimum[++lenEnd].Price = kIfinityPrice;
934baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
935baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							Optimal optimum = _optimum[cur + offset];
936baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							if (curAndLenPrice < optimum.Price)
937baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							{
938baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.Price = curAndLenPrice;
939baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.PosPrev = cur + lenTest + 1;
940baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.BackPrev = 0;
941baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.Prev1IsChar = true;
942baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.Prev2 = true;
943baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.PosPrev2 = cur;
944baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum.BackPrev2 = repIndex;
945baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							}
946baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
947baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
948baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
949baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
950baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
951baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (newLen > numAvailableBytes)
952baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
953baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				newLen = numAvailableBytes;
954baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
955baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_matchDistances[numDistancePairs] = newLen;
956baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				numDistancePairs += 2;
957baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
958baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (newLen >= startLen)
959baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
960baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]);
961baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				while (lenEnd < cur + newLen)
962baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_optimum[++lenEnd].Price = kIfinityPrice;
963baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
964baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				int offs = 0;
965baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				while (startLen > _matchDistances[offs])
966baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					offs += 2;
967baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
968baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				for (int lenTest = startLen; ; lenTest++)
969baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
970baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int curBack = _matchDistances[offs + 1];
971baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
972baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Optimal optimum = _optimum[cur + lenTest];
973baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (curAndLenPrice < optimum.Price)
974baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
975baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.Price = curAndLenPrice;
976baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.PosPrev = cur;
977baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.BackPrev = curBack + Base.kNumRepDistances;
978baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						optimum.Prev1IsChar = false;
979baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
980baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
981baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (lenTest == _matchDistances[offs])
982baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
983baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (lenTest < numAvailableBytesFull)
984baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
985baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
986baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t);
987baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							if (lenTest2 >= 2)
988baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							{
989baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int state2 = Base.StateUpdateMatch(state);
990baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
991baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int posStateNext = (position + lenTest) & _posStateMask;
992baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int curAndLenCharPrice = curAndLenPrice +
993baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
994baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									_literalEncoder.GetSubCoder(position + lenTest,
995baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									_matchFinder.GetIndexByte(lenTest - 1 - 1)).
996baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									GetPrice(true,
997baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									_matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1),
998baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									_matchFinder.GetIndexByte(lenTest - 1));
999baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								state2 = Base.StateUpdateChar(state2);
1000baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								posStateNext = (position + lenTest + 1) & _posStateMask;
1001baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
1002baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
1003baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1004baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								int offset = lenTest + 1 + lenTest2;
1005baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								while (lenEnd < cur + offset)
1006baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									_optimum[++lenEnd].Price = kIfinityPrice;
1007baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
1008baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								optimum = _optimum[cur + offset];
1009baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								if (curAndLenPrice < optimum.Price)
1010baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								{
1011baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.Price = curAndLenPrice;
1012baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.PosPrev = cur + lenTest + 1;
1013baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.BackPrev = 0;
1014baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.Prev1IsChar = true;
1015baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.Prev2 = true;
1016baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.PosPrev2 = cur;
1017baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									optimum.BackPrev2 = curBack + Base.kNumRepDistances;
1018baa3858d3f5d128a5c8466b700098109edcad5f2repo sync								}
1019baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							}
1020baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
1021baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						offs += 2;
1022baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (offs == numDistancePairs)
1023baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							break;
1024baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1025baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1026baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1027baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1028baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1029baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1030baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	boolean ChangePair(int smallDist, int bigDist)
1031baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1032baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int kDif = 7;
1033baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif));
1034baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1035baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1036baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void WriteEndMarker(int posState) throws IOException
1037baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1038baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (!_writeEndMark)
1039baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return;
1040baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1041baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1);
1042baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.Encode(_isRep, _state, 0);
1043baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_state = Base.StateUpdateMatch(_state);
1044baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int len = Base.kMatchMinLen;
1045baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1046baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int posSlot = (1 << Base.kNumPosSlotBits) - 1;
1047baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int lenToPosState = Base.GetLenToPosState(len);
1048baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
1049baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int footerBits = 30;
1050baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int posReduced = (1 << footerBits) - 1;
1051baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
1052baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
1053baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1054baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1055baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void Flush(int nowPos) throws IOException
1056baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1057baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		ReleaseMFStream();
1058baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		WriteEndMarker(nowPos & _posStateMask);
1059baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.FlushData();
1060baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_rangeEncoder.FlushStream();
1061baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1062baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1063baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException
1064baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1065baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		inSize[0] = 0;
1066baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		outSize[0] = 0;
1067baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		finished[0] = true;
1068baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1069baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_inStream != null)
1070baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1071baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder.SetStream(_inStream);
1072baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder.Init();
1073baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_needReleaseMFStream = true;
1074baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_inStream = null;
1075baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1076baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1077baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_finished)
1078baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return;
1079baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_finished = true;
1080baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1081baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1082baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		long progressPosValuePrev = nowPos64;
1083baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (nowPos64 == 0)
1084baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1085baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (_matchFinder.GetNumAvailableBytes() == 0)
1086baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
1087baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				Flush((int)nowPos64);
1088baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				return;
1089baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1090baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1091baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			ReadMatchDistances();
1092baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posState = (int)(nowPos64) & _posStateMask;
1093baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0);
1094baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_state = Base.StateUpdateChar(_state);
1095baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset);
1096baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
1097baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_previousByte = curByte;
1098baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_additionalOffset--;
1099baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			nowPos64++;
1100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_matchFinder.GetNumAvailableBytes() == 0)
1102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			Flush((int)nowPos64);
1104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return;
1105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		while (true)
1107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int len = GetOptimum((int)nowPos64);
1110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int pos = backRes;
1111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posState = ((int)nowPos64) & _posStateMask;
1112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int complexState = (_state << Base.kNumPosStatesBitsMax) + posState;
1113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (len == 1 && pos == -1)
1114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
1115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_rangeEncoder.Encode(_isMatch, complexState, 0);
1116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset));
1117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte);
1118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (!Base.StateIsCharState(_state))
1119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset));
1121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
1122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
1124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					subCoder.Encode(_rangeEncoder, curByte);
1125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_previousByte = curByte;
1126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_state = Base.StateUpdateChar(_state);
1127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			else
1129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
1130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_rangeEncoder.Encode(_isMatch, complexState, 1);
1131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (pos < Base.kNumRepDistances)
1132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_rangeEncoder.Encode(_isRep, _state, 1);
1134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (pos == 0)
1135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
1136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_rangeEncoder.Encode(_isRepG0, _state, 0);
1137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (len == 1)
1138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.Encode(_isRep0Long, complexState, 0);
1139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						else
1140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.Encode(_isRep0Long, complexState, 1);
1141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else
1143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
1144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_rangeEncoder.Encode(_isRepG0, _state, 1);
1145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (pos == 1)
1146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.Encode(_isRepG1, _state, 0);
1147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						else
1148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
1149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.Encode(_isRepG1, _state, 1);
1150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.Encode(_isRepG2, _state, pos - 2);
1151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
1152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (len == 1)
1154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_state = Base.StateUpdateShortRep(_state);
1155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					else
1156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
1157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_state = Base.StateUpdateRep(_state);
1159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int distance = _repDistances[pos];
1161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (pos != 0)
1162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
1163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						for (int i = pos; i >= 1; i--)
1164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_repDistances[i] = _repDistances[i - 1];
1165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_repDistances[0] = distance;
1166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				else
1169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_rangeEncoder.Encode(_isRep, _state, 0);
1171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_state = Base.StateUpdateMatch(_state);
1172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					pos -= Base.kNumRepDistances;
1174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int posSlot = GetPosSlot(pos);
1175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int lenToPosState = Base.GetLenToPosState(len);
1176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
1177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					if (posSlot >= Base.kStartPosModelIndex)
1179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					{
1180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int footerBits = (int)((posSlot >> 1) - 1);
1181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int baseVal = ((2 | (posSlot & 1)) << footerBits);
1182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						int posReduced = pos - baseVal;
1183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						if (posSlot < Base.kEndPosModelIndex)
1185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							BitTreeEncoder.ReverseEncode(_posEncoders,
1186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync									baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
1187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						else
1188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						{
1189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
1190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
1191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync							_alignPriceCount++;
1192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						}
1193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					}
1194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					int distance = pos;
1195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					for (int i = Base.kNumRepDistances - 1; i >= 1; i--)
1196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync						_repDistances[i] = _repDistances[i - 1];
1197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_repDistances[0] = distance;
1198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_matchPriceCount++;
1199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset);
1201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_additionalOffset -= len;
1203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			nowPos64 += len;
1204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			if (_additionalOffset == 0)
1205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
1206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				// if (!_fastMode)
1207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_matchPriceCount >= (1 << 7))
1208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					FillDistancesPrices();
1209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_alignPriceCount >= Base.kAlignTableSize)
1210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					FillAlignPrices();
1211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				inSize[0] = nowPos64;
1212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				outSize[0] = _rangeEncoder.GetProcessedSizeAdd();
1213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (_matchFinder.GetNumAvailableBytes() == 0)
1214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					Flush((int)nowPos64);
1216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					return;
1217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (nowPos64 - progressPosValuePrev >= (1 << 12))
1220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					_finished = false;
1222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					finished[0] = false;
1223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					return;
1224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void ReleaseMFStream()
1230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_matchFinder != null && _needReleaseMFStream)
1232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder.ReleaseStream();
1234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_needReleaseMFStream = false;
1235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void SetOutStream(java.io.OutputStream outStream)
1239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{ _rangeEncoder.SetStream(outStream); }
1240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void ReleaseOutStream()
1241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{ _rangeEncoder.ReleaseStream(); }
1242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void ReleaseStreams()
1244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		ReleaseMFStream();
1246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		ReleaseOutStream();
1247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream,
1250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			long inSize, long outSize)
1251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_inStream = inStream;
1253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_finished = false;
1254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Create();
1255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		SetOutStream(outStream);
1256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		Init();
1257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		// if (!_fastMode)
1259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			FillDistancesPrices();
1261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			FillAlignPrices();
1262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_lenEncoder.UpdateTables(1 << _posStateBits);
1266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_repMatchLenEncoder.UpdateTables(1 << _posStateBits);
1268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		nowPos64 = 0;
1270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1];
1273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void Code(java.io.InputStream inStream, java.io.OutputStream outStream,
1274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			long inSize, long outSize, ICodeProgress progress) throws IOException
1275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_needReleaseMFStream = false;
1277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		try
1278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			SetStreams(inStream, outStream, inSize, outSize);
1280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			while (true)
1281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			{
1282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				CodeOneBlock(processedInSize, processedOutSize, finished);
1286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (finished[0])
1287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					return;
1288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				if (progress != null)
1289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				{
1290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync					progress.SetProgress(processedInSize[0], processedOutSize[0]);
1291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				}
1292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			}
1293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		finally
1295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			ReleaseStreams();
1297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public static final int kPropSize = 5;
1301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	byte[] properties = new byte[kPropSize];
1302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException
1304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
1306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < 4; i++)
1307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			properties[1 + i] = (byte)(_dictionarySize >> (8 * i));
1308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		outStream.write(properties, 0, kPropSize);
1309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int[] tempPrices = new int[Base.kNumFullDistances];
1312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	int _matchPriceCount;
1313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void FillDistancesPrices()
1315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
1317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posSlot = GetPosSlot(i);
1319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int footerBits = (int)((posSlot >> 1) - 1);
1320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int baseVal = ((2 | (posSlot & 1)) << footerBits);
1321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
1322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				baseVal - posSlot - 1, footerBits, i - baseVal);
1323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
1326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int posSlot;
1328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
1329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int st = (lenToPosState << Base.kNumPosSlotBits);
1331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (posSlot = 0; posSlot < _distTableSize; posSlot++)
1332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
1333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
1334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits);
1335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int st2 = lenToPosState * Base.kNumFullDistances;
1337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			int i;
1338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (i = 0; i < Base.kStartPosModelIndex; i++)
1339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_distancesPrices[st2 + i] = _posSlotPrices[st + i];
1340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			for (; i < Base.kNumFullDistances; i++)
1341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
1342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_matchPriceCount = 0;
1344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	void FillAlignPrices()
1347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (int i = 0; i < Base.kAlignTableSize; i++)
1349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
1350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_alignPriceCount = 0;
1351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public boolean SetAlgorithm(int algorithm)
1355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		/*
1357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_fastMode = (algorithm == 0);
1358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_maxMode = (algorithm >= 2);
1359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		*/
1360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return true;
1361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public boolean SetDictionarySize(int dictionarySize)
1364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int kDicLogSizeMaxCompress = 29;
1366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress))
1367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return false;
1368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_dictionarySize = dictionarySize;
1369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int dicLogSize;
1370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ;
1371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_distTableSize = dicLogSize * 2;
1372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return true;
1373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public boolean SetNumFastBytes(int numFastBytes)
1376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
1378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return false;
1379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_numFastBytes = numFastBytes;
1380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return true;
1381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public boolean SetMatchFinder(int matchFinderIndex)
1384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (matchFinderIndex < 0 || matchFinderIndex > 2)
1386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return false;
1387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		int matchFinderIndexPrev = _matchFinderType;
1388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_matchFinderType = matchFinderIndex;
1389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
1390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		{
1391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_dictionarySizePrev = -1;
1392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			_matchFinder = null;
1393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		}
1394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return true;
1395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public boolean SetLcLpPb(int lc, int lp, int pb)
1398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		if (
1400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax ||
1401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				lc < 0 || lc > Base.kNumLitContextBitsMax ||
1402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync				pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax)
1403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync			return false;
1404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_numLiteralPosStateBits = lp;
1405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_numLiteralContextBits = lc;
1406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_posStateBits = pb;
1407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_posStateMask = ((1) << _posStateBits) - 1;
1408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		return true;
1409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	public void SetEndMarkerMode(boolean endMarkerMode)
1412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	{
1413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync		_writeEndMark = endMarkerMode;
1414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync	}
1415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
1416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1417