1 package SevenZip.Compression.LZMA;
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;
11 public static final int EMatchFinderTypeBT2 = 0;
12 public static final int EMatchFinderTypeBT4 = 1;
17 static final int kIfinityPrice = 0xFFFFFFF;
19 static byte[] g_FastPos = new byte[1 << 11];
27 for (int slotFast = 2; slotFast < kFastSlots; slotFast++)
29 int k = (1 << ((slotFast >> 1) - 1));
30 for (int j = 0; j < k; j++, c++)
31 g_FastPos[c] = (byte)slotFast;
35 static int GetPosSlot(int pos)
38 return g_FastPos[pos];
40 return (g_FastPos[pos >> 10] + 20);
41 return (g_FastPos[pos >> 20] + 40);
44 static int GetPosSlot2(int pos)
47 return (g_FastPos[pos >> 6] + 12);
49 return (g_FastPos[pos >> 16] + 32);
50 return (g_FastPos[pos >> 26] + 52);
53 int _state = Base.StateInit();
55 int[] _repDistances = new int[Base.kNumRepDistances];
59 _state = Base.StateInit();
61 for (int i = 0; i < Base.kNumRepDistances; i++)
65 static final int kDefaultDictionaryLogSize = 22;
66 static final int kNumFastBytesDefault = 0x20;
72 short[] m_Encoders = new short[0x300];
74 public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); }
78 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException
81 for (int i = 7; i >= 0; i--)
83 int bit = ((symbol >> i) & 1);
84 rangeEncoder.Encode(m_Encoders, context, bit);
85 context = (context << 1) | bit;
89 public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException
93 for (int i = 7; i >= 0; i--)
95 int bit = ((symbol >> i) & 1);
99 int matchBit = ((matchByte >> i) & 1);
100 state += ((1 + matchBit) << 8);
101 same = (matchBit == bit);
103 rangeEncoder.Encode(m_Encoders, state, bit);
104 context = (context << 1) | bit;
108 public int GetPrice(boolean matchMode, byte matchByte, byte symbol)
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;
130 int bit = (symbol >> i) & 1;
131 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit);
132 context = (context << 1) | bit;
143 public void Create(int numPosBits, int numPrevBits)
145 if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
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();
158 int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
159 for (int i = 0; i < numStates; i++)
163 public Encoder2 GetSubCoder(int pos, byte prevByte)
164 { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; }
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);
177 for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
179 _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
180 _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
184 public void Init(int numPosStates)
186 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice);
188 for (int posState = 0; posState < numPosStates; posState++)
190 _lowCoder[posState].Init();
191 _midCoder[posState].Init();
196 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
198 if (symbol < Base.kNumLowLenSymbols)
200 rangeEncoder.Encode(_choice, 0, 0);
201 _lowCoder[posState].Encode(rangeEncoder, symbol);
205 symbol -= Base.kNumLowLenSymbols;
206 rangeEncoder.Encode(_choice, 0, 1);
207 if (symbol < Base.kNumMidLenSymbols)
209 rangeEncoder.Encode(_choice, 1, 0);
210 _midCoder[posState].Encode(rangeEncoder, symbol);
214 rangeEncoder.Encode(_choice, 1, 1);
215 _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
220 public void SetPrices(int posState, int numSymbols, int[] prices, int st)
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]);
227 for (i = 0; i < Base.kNumLowLenSymbols; i++)
231 prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
233 for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
237 prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
239 for (; i < numSymbols; i++)
240 prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
244 public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
246 class LenPriceTableEncoder extends LenEncoder
248 int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax];
250 int[] _counters = new int[Base.kNumPosStatesEncodingMax];
252 public void SetTableSize(int tableSize) { _tableSize = tableSize; }
254 public int GetPrice(int symbol, int posState)
256 return _prices[posState * Base.kNumLenSymbols + symbol];
259 void UpdateTable(int posState)
261 SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
262 _counters[posState] = _tableSize;
265 public void UpdateTables(int numPosStates)
267 for (int posState = 0; posState < numPosStates; posState++)
268 UpdateTable(posState);
271 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
273 super.Encode(rangeEncoder, symbol, posState);
274 if (--_counters[posState] == 0)
275 UpdateTable(posState);
279 static final int kNumOpts = 1 << 12;
284 public boolean Prev1IsChar;
285 public boolean Prev2;
288 public int BackPrev2;
299 public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; }
300 public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
301 public boolean IsShortRep() { return (BackPrev == 0); }
303 Optimal[] _optimum = new Optimal[kNumOpts];
304 SevenZip.Compression.LZ.BinTree _matchFinder = null;
305 SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();
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];
314 BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
316 short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex];
317 BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits);
319 LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
320 LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
322 LiteralEncoder _literalEncoder = new LiteralEncoder();
324 int[] _matchDistances = new int[Base.kMatchMaxLen*2+2];
326 int _numFastBytes = kNumFastBytesDefault;
327 int _longestMatchLength;
328 int _numDistancePairs;
330 int _additionalOffset;
332 int _optimumEndIndex;
333 int _optimumCurrentIndex;
335 boolean _longestMatchWasFound;
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;
342 int _distTableSize = (kDefaultDictionaryLogSize * 2);
344 int _posStateBits = 2;
345 int _posStateMask = (4 - 1);
346 int _numLiteralPosStateBits = 0;
347 int _numLiteralContextBits = 3;
349 int _dictionarySize = (1 << kDefaultDictionaryLogSize);
350 int _dictionarySizePrev = -1;
351 int _numFastBytesPrev = -1;
355 java.io.InputStream _inStream;
357 int _matchFinderType = EMatchFinderTypeBT4;
358 boolean _writeEndMark = false;
360 boolean _needReleaseMFStream = false;
364 if (_matchFinder == null)
366 SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree();
367 int numHashBytes = 4;
368 if (_matchFinderType == EMatchFinderTypeBT2)
370 bt.SetType(numHashBytes);
373 _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
375 if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
377 _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
378 _dictionarySizePrev = _dictionarySize;
379 _numFastBytesPrev = _numFastBytes;
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);
390 void SetWriteEndMarkerMode(boolean writeEndMarker)
392 _writeEndMark = writeEndMarker;
398 _rangeEncoder.Init();
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);
414 _literalEncoder.Init();
415 for (int i = 0; i < Base.kNumLenToPosStates; i++)
416 _posSlotEncoder[i].Init();
420 _lenEncoder.Init(1 << _posStateBits);
421 _repMatchLenEncoder.Init(1 << _posStateBits);
423 _posAlignEncoder.Init();
425 _longestMatchWasFound = false;
426 _optimumEndIndex = 0;
427 _optimumCurrentIndex = 0;
428 _additionalOffset = 0;
431 int ReadMatchDistances() throws java.io.IOException
434 _numDistancePairs = _matchFinder.GetMatches(_matchDistances);
435 if (_numDistancePairs > 0)
437 lenRes = _matchDistances[_numDistancePairs - 2];
438 if (lenRes == _numFastBytes)
439 lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1],
440 Base.kMatchMaxLen - lenRes);
446 void MovePos(int num) throws java.io.IOException
450 _matchFinder.Skip(num);
451 _additionalOffset += num;
455 int GetRepLen1Price(int state, int posState)
457 return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) +
458 SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
461 int GetPureRepPrice(int repIndex, int state, int posState)
466 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]);
467 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
471 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]);
473 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]);
476 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]);
477 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2);
483 int GetRepPrice(int repIndex, int len, int state, int posState)
485 int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
486 return price + GetPureRepPrice(repIndex, state, posState);
489 int GetPosLenPrice(int pos, int len, int posState)
492 int lenToPosState = Base.GetLenToPosState(len);
493 if (pos < Base.kNumFullDistances)
494 price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
496 price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
497 _alignPrices[pos & Base.kAlignMask];
498 return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
501 int Backward(int cur)
503 _optimumEndIndex = cur;
504 int posMem = _optimum[cur].PosPrev;
505 int backMem = _optimum[cur].BackPrev;
508 if (_optimum[cur].Prev1IsChar)
510 _optimum[posMem].MakeAsChar();
511 _optimum[posMem].PosPrev = posMem - 1;
512 if (_optimum[cur].Prev2)
514 _optimum[posMem - 1].Prev1IsChar = false;
515 _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
516 _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
519 int posPrev = posMem;
520 int backCur = backMem;
522 backMem = _optimum[posPrev].BackPrev;
523 posMem = _optimum[posPrev].PosPrev;
525 _optimum[posPrev].BackPrev = backCur;
526 _optimum[posPrev].PosPrev = cur;
530 backRes = _optimum[0].BackPrev;
531 _optimumCurrentIndex = _optimum[0].PosPrev;
532 return _optimumCurrentIndex;
535 int[] reps = new int[Base.kNumRepDistances];
536 int[] repLens = new int[Base.kNumRepDistances];
539 int GetOptimum(int position) throws IOException
541 if (_optimumEndIndex != _optimumCurrentIndex)
543 int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
544 backRes = _optimum[_optimumCurrentIndex].BackPrev;
545 _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
548 _optimumCurrentIndex = _optimumEndIndex = 0;
550 int lenMain, numDistancePairs;
551 if (!_longestMatchWasFound)
553 lenMain = ReadMatchDistances();
557 lenMain = _longestMatchLength;
558 _longestMatchWasFound = false;
560 numDistancePairs = _numDistancePairs;
562 int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
563 if (numAvailableBytes < 2)
568 if (numAvailableBytes > Base.kMatchMaxLen)
569 numAvailableBytes = Base.kMatchMaxLen;
573 for (i = 0; i < Base.kNumRepDistances; i++)
575 reps[i] = _repDistances[i];
576 repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
577 if (repLens[i] > repLens[repMaxIndex])
580 if (repLens[repMaxIndex] >= _numFastBytes)
582 backRes = repMaxIndex;
583 int lenRes = repLens[repMaxIndex];
588 if (lenMain >= _numFastBytes)
590 backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
591 MovePos(lenMain - 1);
595 byte currentByte = _matchFinder.GetIndexByte(0 - 1);
596 byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1);
598 if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
604 _optimum[0].State = _state;
606 int posState = (position & _posStateMask);
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();
612 int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]);
613 int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]);
615 if (matchByte == currentByte)
617 int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
618 if (shortRepPrice < _optimum[1].Price)
620 _optimum[1].Price = shortRepPrice;
621 _optimum[1].MakeAsShortRep();
625 int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
629 backRes = _optimum[1].BackPrev;
633 _optimum[1].PosPrev = 0;
635 _optimum[0].Backs0 = reps[0];
636 _optimum[0].Backs1 = reps[1];
637 _optimum[0].Backs2 = reps[2];
638 _optimum[0].Backs3 = reps[3];
642 _optimum[len--].Price = kIfinityPrice;
645 for (i = 0; i < Base.kNumRepDistances; i++)
647 int repLen = repLens[i];
650 int price = repMatchPrice + GetPureRepPrice(i, _state, posState);
653 int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
654 Optimal optimum = _optimum[repLen];
655 if (curAndLenPrice < optimum.Price)
657 optimum.Price = curAndLenPrice;
659 optimum.BackPrev = i;
660 optimum.Prev1IsChar = false;
663 while (--repLen >= 2);
666 int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]);
668 len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
672 while (len > _matchDistances[offs])
676 int distance = _matchDistances[offs + 1];
677 int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
678 Optimal optimum = _optimum[len];
679 if (curAndLenPrice < optimum.Price)
681 optimum.Price = curAndLenPrice;
683 optimum.BackPrev = distance + Base.kNumRepDistances;
684 optimum.Prev1IsChar = false;
686 if (len == _matchDistances[offs])
689 if (offs == numDistancePairs)
701 return Backward(cur);
702 int newLen = ReadMatchDistances();
703 numDistancePairs = _numDistancePairs;
704 if (newLen >= _numFastBytes)
707 _longestMatchLength = newLen;
708 _longestMatchWasFound = true;
709 return Backward(cur);
712 int posPrev = _optimum[cur].PosPrev;
714 if (_optimum[cur].Prev1IsChar)
717 if (_optimum[cur].Prev2)
719 state = _optimum[_optimum[cur].PosPrev2].State;
720 if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
721 state = Base.StateUpdateRep(state);
723 state = Base.StateUpdateMatch(state);
726 state = _optimum[posPrev].State;
727 state = Base.StateUpdateChar(state);
730 state = _optimum[posPrev].State;
731 if (posPrev == cur - 1)
733 if (_optimum[cur].IsShortRep())
734 state = Base.StateUpdateShortRep(state);
736 state = Base.StateUpdateChar(state);
741 if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
743 posPrev = _optimum[cur].PosPrev2;
744 pos = _optimum[cur].BackPrev2;
745 state = Base.StateUpdateRep(state);
749 pos = _optimum[cur].BackPrev;
750 if (pos < Base.kNumRepDistances)
751 state = Base.StateUpdateRep(state);
753 state = Base.StateUpdateMatch(state);
755 Optimal opt = _optimum[posPrev];
756 if (pos < Base.kNumRepDistances)
760 reps[0] = opt.Backs0;
761 reps[1] = opt.Backs1;
762 reps[2] = opt.Backs2;
763 reps[3] = opt.Backs3;
767 reps[0] = opt.Backs1;
768 reps[1] = opt.Backs0;
769 reps[2] = opt.Backs2;
770 reps[3] = opt.Backs3;
774 reps[0] = opt.Backs2;
775 reps[1] = opt.Backs0;
776 reps[2] = opt.Backs1;
777 reps[3] = opt.Backs3;
781 reps[0] = opt.Backs3;
782 reps[1] = opt.Backs0;
783 reps[2] = opt.Backs1;
784 reps[3] = opt.Backs2;
789 reps[0] = (pos - Base.kNumRepDistances);
790 reps[1] = opt.Backs0;
791 reps[2] = opt.Backs1;
792 reps[3] = opt.Backs2;
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;
802 currentByte = _matchFinder.GetIndexByte(0 - 1);
803 matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1);
805 posState = (position & _posStateMask);
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);
812 Optimal nextOptimum = _optimum[cur + 1];
814 boolean nextIsChar = false;
815 if (curAnd1Price < nextOptimum.Price)
817 nextOptimum.Price = curAnd1Price;
818 nextOptimum.PosPrev = cur;
819 nextOptimum.MakeAsChar();
823 matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]);
824 repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]);
826 if (matchByte == currentByte &&
827 !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
829 int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
830 if (shortRepPrice <= nextOptimum.Price)
832 nextOptimum.Price = shortRepPrice;
833 nextOptimum.PosPrev = cur;
834 nextOptimum.MakeAsShortRep();
839 int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
840 numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull);
841 numAvailableBytes = numAvailableBytesFull;
843 if (numAvailableBytes < 2)
845 if (numAvailableBytes > _numFastBytes)
846 numAvailableBytes = _numFastBytes;
847 if (!nextIsChar && matchByte != currentByte)
849 // try Literal + rep0
850 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes);
851 int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
854 int state2 = Base.StateUpdateChar(state);
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]);
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)
869 optimum.Price = curAndLenPrice;
870 optimum.PosPrev = cur + 1;
871 optimum.BackPrev = 0;
872 optimum.Prev1IsChar = true;
873 optimum.Prev2 = false;
879 int startLen = 2; // speed optimization
881 for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
883 int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
886 int lenTestTemp = lenTest;
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)
895 optimum.Price = curAndLenPrice;
896 optimum.PosPrev = cur;
897 optimum.BackPrev = repIndex;
898 optimum.Prev1IsChar = false;
901 while (--lenTest >= 2);
902 lenTest = lenTestTemp;
905 startLen = lenTest + 1;
908 if (lenTest < numAvailableBytesFull)
910 int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
911 int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);
914 int state2 = Base.StateUpdateRep(state);
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]);
929 // for(; lenTest2 >= 2; lenTest2--)
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)
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;
951 if (newLen > numAvailableBytes)
953 newLen = numAvailableBytes;
954 for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
955 _matchDistances[numDistancePairs] = newLen;
956 numDistancePairs += 2;
958 if (newLen >= startLen)
960 normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]);
961 while (lenEnd < cur + newLen)
962 _optimum[++lenEnd].Price = kIfinityPrice;
965 while (startLen > _matchDistances[offs])
968 for (int lenTest = startLen; ; lenTest++)
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)
975 optimum.Price = curAndLenPrice;
976 optimum.PosPrev = cur;
977 optimum.BackPrev = curBack + Base.kNumRepDistances;
978 optimum.Prev1IsChar = false;
981 if (lenTest == _matchDistances[offs])
983 if (lenTest < numAvailableBytesFull)
985 int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
986 int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t);
989 int state2 = Base.StateUpdateMatch(state);
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)).
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]);
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)
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;
1022 if (offs == numDistancePairs)
1030 boolean ChangePair(int smallDist, int bigDist)
1033 return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif));
1036 void WriteEndMarker(int posState) throws IOException
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);
1055 void Flush(int nowPos) throws IOException
1058 WriteEndMarker(nowPos & _posStateMask);
1059 _rangeEncoder.FlushData();
1060 _rangeEncoder.FlushStream();
1063 public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException
1069 if (_inStream != null)
1071 _matchFinder.SetStream(_inStream);
1072 _matchFinder.Init();
1073 _needReleaseMFStream = true;
1082 long progressPosValuePrev = nowPos64;
1085 if (_matchFinder.GetNumAvailableBytes() == 0)
1087 Flush((int)nowPos64);
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--;
1101 if (_matchFinder.GetNumAvailableBytes() == 0)
1103 Flush((int)nowPos64);
1109 int len = GetOptimum((int)nowPos64);
1111 int posState = ((int)nowPos64) & _posStateMask;
1112 int complexState = (_state << Base.kNumPosStatesBitsMax) + posState;
1113 if (len == 1 && pos == -1)
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))
1120 byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset));
1121 subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
1124 subCoder.Encode(_rangeEncoder, curByte);
1125 _previousByte = curByte;
1126 _state = Base.StateUpdateChar(_state);
1130 _rangeEncoder.Encode(_isMatch, complexState, 1);
1131 if (pos < Base.kNumRepDistances)
1133 _rangeEncoder.Encode(_isRep, _state, 1);
1136 _rangeEncoder.Encode(_isRepG0, _state, 0);
1138 _rangeEncoder.Encode(_isRep0Long, complexState, 0);
1140 _rangeEncoder.Encode(_isRep0Long, complexState, 1);
1144 _rangeEncoder.Encode(_isRepG0, _state, 1);
1146 _rangeEncoder.Encode(_isRepG1, _state, 0);
1149 _rangeEncoder.Encode(_isRepG1, _state, 1);
1150 _rangeEncoder.Encode(_isRepG2, _state, pos - 2);
1154 _state = Base.StateUpdateShortRep(_state);
1157 _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1158 _state = Base.StateUpdateRep(_state);
1160 int distance = _repDistances[pos];
1163 for (int i = pos; i >= 1; i--)
1164 _repDistances[i] = _repDistances[i - 1];
1165 _repDistances[0] = distance;
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);
1178 if (posSlot >= Base.kStartPosModelIndex)
1180 int footerBits = (int)((posSlot >> 1) - 1);
1181 int baseVal = ((2 | (posSlot & 1)) << footerBits);
1182 int posReduced = pos - baseVal;
1184 if (posSlot < Base.kEndPosModelIndex)
1185 BitTreeEncoder.ReverseEncode(_posEncoders,
1186 baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
1189 _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
1190 _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
1195 for (int i = Base.kNumRepDistances - 1; i >= 1; i--)
1196 _repDistances[i] = _repDistances[i - 1];
1197 _repDistances[0] = distance;
1200 _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset);
1202 _additionalOffset -= len;
1204 if (_additionalOffset == 0)
1207 if (_matchPriceCount >= (1 << 7))
1208 FillDistancesPrices();
1209 if (_alignPriceCount >= Base.kAlignTableSize)
1211 inSize[0] = nowPos64;
1212 outSize[0] = _rangeEncoder.GetProcessedSizeAdd();
1213 if (_matchFinder.GetNumAvailableBytes() == 0)
1215 Flush((int)nowPos64);
1219 if (nowPos64 - progressPosValuePrev >= (1 << 12))
1222 finished[0] = false;
1229 void ReleaseMFStream()
1231 if (_matchFinder != null && _needReleaseMFStream)
1233 _matchFinder.ReleaseStream();
1234 _needReleaseMFStream = false;
1238 void SetOutStream(java.io.OutputStream outStream)
1239 { _rangeEncoder.SetStream(outStream); }
1240 void ReleaseOutStream()
1241 { _rangeEncoder.ReleaseStream(); }
1243 void ReleaseStreams()
1249 void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream,
1250 long inSize, long outSize)
1252 _inStream = inStream;
1255 SetOutStream(outStream);
1260 FillDistancesPrices();
1264 _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1265 _lenEncoder.UpdateTables(1 << _posStateBits);
1266 _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1267 _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
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
1276 _needReleaseMFStream = false;
1279 SetStreams(inStream, outStream, inSize, outSize);
1285 CodeOneBlock(processedInSize, processedOutSize, finished);
1288 if (progress != null)
1290 progress.SetProgress(processedInSize[0], processedOutSize[0]);
1300 public static final int kPropSize = 5;
1301 byte[] properties = new byte[kPropSize];
1303 public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException
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);
1311 int[] tempPrices = new int[Base.kNumFullDistances];
1312 int _matchPriceCount;
1314 void FillDistancesPrices()
1316 for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
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);
1325 for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
1328 BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
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);
1336 int st2 = lenToPosState * Base.kNumFullDistances;
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];
1343 _matchPriceCount = 0;
1346 void FillAlignPrices()
1348 for (int i = 0; i < Base.kAlignTableSize; i++)
1349 _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
1350 _alignPriceCount = 0;
1354 public boolean SetAlgorithm(int algorithm)
1357 _fastMode = (algorithm == 0);
1358 _maxMode = (algorithm >= 2);
1363 public boolean SetDictionarySize(int dictionarySize)
1365 int kDicLogSizeMaxCompress = 29;
1366 if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress))
1368 _dictionarySize = dictionarySize;
1370 for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ;
1371 _distTableSize = dicLogSize * 2;
1375 public boolean SeNumFastBytes(int numFastBytes)
1377 if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
1379 _numFastBytes = numFastBytes;
1383 public boolean SetMatchFinder(int matchFinderIndex)
1385 if (matchFinderIndex < 0 || matchFinderIndex > 2)
1387 int matchFinderIndexPrev = _matchFinderType;
1388 _matchFinderType = matchFinderIndex;
1389 if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
1391 _dictionarySizePrev = -1;
1392 _matchFinder = null;
1397 public boolean SetLcLpPb(int lc, int lp, int pb)
1400 lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax ||
1401 lc < 0 || lc > Base.kNumLitContextBitsMax ||
1402 pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax)
1404 _numLiteralPosStateBits = lp;
1405 _numLiteralContextBits = lc;
1407 _posStateMask = ((1) << _posStateBits) - 1;
1411 public void SetEndMarkerMode(boolean endMarkerMode)
1413 _writeEndMark = endMarkerMode;