tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Encoder.java (42261B)


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