📄 lzmaencoder.cpp
字号:
_isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK;}HRESULT CEncoder::MovePos(UInt32 num){ if (num == 0) return S_OK; _additionalOffset += num; return _matchFinder->Skip(num);}UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur){ _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; }/*Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal*/HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes){ if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return S_OK; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain, numDistancePairs)); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); lenRes = 1; return S_OK; } if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; UInt32 backOffset = reps[i] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) { repLens[i] = 0; continue; } UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } UInt32 *matchDistances = _matchDistances + 1; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)-1; lenRes = 1; return S_OK; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while(--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > matchDistances[offs]) offs += 2; for(; ; len++) { UInt32 distance = matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); COptimal &optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + kNumRepDistances; optimum.Prev1IsChar = false; } if (len == matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } UInt32 newLen, numDistancePairs; RINOK(ReadMatchDistances(newLen, numDistancePairs)); if(newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; const Byte currentByte = *data; const Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } /* if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) // speed optimization { // try Literal + rep0 UInt32 backOffset = reps[0] + 1; UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; for (temp = 1; temp < limit && data[temp] == data[(size_t)temp - backOffset]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 lenTestTemp = lenTest; UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while(startLen > matchDistances[offs]) offs += 2; UInt32 curBack = matchDistances[offs + 1]; UInt32 posSlot = GetPosSlot2(curBack); for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice; UInt32 lenToPosState = GetLenToPosState(lenTest); if (curBack < kNumFullDistances) curAndLenPrice += _distancesPrices[lenToPosState][curBack]; else curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -