Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '7zip/Compress/LZMA/LZMAEncoder.cpp')
-rwxr-xr-x7zip/Compress/LZMA/LZMAEncoder.cpp692
1 files changed, 359 insertions, 333 deletions
diff --git a/7zip/Compress/LZMA/LZMAEncoder.cpp b/7zip/Compress/LZMA/LZMAEncoder.cpp
index a88020f6..4a5ba0e8 100755
--- a/7zip/Compress/LZMA/LZMAEncoder.cpp
+++ b/7zip/Compress/LZMA/LZMAEncoder.cpp
@@ -11,18 +11,16 @@
// #define COMPRESS_MF_BT
// #define COMPRESS_MF_BT4
-#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC)
+#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC)
#define COMPRESS_MF_BT
-#define COMPRESS_MF_PAT
#define COMPRESS_MF_HC
#endif
#ifdef COMPRESS_MF_BT
-#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B)
+#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4)
#define COMPRESS_MF_BT2
#define COMPRESS_MF_BT3
#define COMPRESS_MF_BT4
-#define COMPRESS_MF_BT4B
#endif
#ifdef COMPRESS_MF_BT2
#include "../LZ/BinTree/BinTree2.h"
@@ -33,21 +31,9 @@
#ifdef COMPRESS_MF_BT4
#include "../LZ/BinTree/BinTree4.h"
#endif
-#ifdef COMPRESS_MF_BT4B
-#include "../LZ/BinTree/BinTree4b.h"
-#endif
-#endif
-
-#ifdef COMPRESS_MF_PAT
-#include "../LZ/Patricia/Pat2.h"
-#include "../LZ/Patricia/Pat2H.h"
-#include "../LZ/Patricia/Pat3H.h"
-#include "../LZ/Patricia/Pat4H.h"
-#include "../LZ/Patricia/Pat2R.h"
#endif
#ifdef COMPRESS_MF_HC
-#include "../LZ/HashChain/HC3.h"
#include "../LZ/HashChain/HC4.h"
#endif
@@ -58,7 +44,7 @@
namespace NCompress {
namespace NLZMA {
-const int kDefaultDictionaryLogSize = 20;
+const int kDefaultDictionaryLogSize = 22;
const UInt32 kNumFastBytesDefault = 0x20;
enum
@@ -66,13 +52,6 @@ enum
kBT2,
kBT3,
kBT4,
- kBT4B,
- kPat2,
- kPat2H,
- kPat3H,
- kPat4H,
- kPat2R,
- kHC3,
kHC4
};
@@ -81,17 +60,10 @@ static const wchar_t *kMatchFinderIDs[] =
L"BT2",
L"BT3",
L"BT4",
- L"BT4B",
- L"PAT2",
- L"PAT2H",
- L"PAT3H",
- L"PAT4H",
- L"PAT2R",
- L"HC3",
L"HC4"
};
-Byte g_FastPos[1024];
+Byte g_FastPos[1 << 11];
class CFastPosInit
{
@@ -99,7 +71,7 @@ public:
CFastPosInit() { Init(); }
void Init()
{
- const Byte kFastSlots = 20;
+ const Byte kFastSlots = 22;
int c = 2;
g_FastPos[0] = 0;
g_FastPos[1] = 1;
@@ -222,22 +194,27 @@ void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32
}
}
-UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const
+void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const
{
- if(symbol < kNumLowSymbols)
- return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol);
- UInt32 price = _choice.GetPrice1();
- if(symbol < kNumLowSymbols + kNumMidSymbols)
+ UInt32 a0 = _choice.GetPrice0();
+ UInt32 a1 = _choice.GetPrice1();
+ UInt32 b0 = a1 + _choice2.GetPrice0();
+ UInt32 b1 = a1 + _choice2.GetPrice1();
+ UInt32 i = 0;
+ for (i = 0; i < kNumLowSymbols; i++)
{
- price += _choice2.GetPrice0();
- price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols);
+ if (i >= numSymbols)
+ return;
+ prices[i] = a0 + _lowCoder[posState].GetPrice(i);
}
- else
+ for (; i < kNumLowSymbols + kNumMidSymbols; i++)
{
- price += _choice2.GetPrice1();
- price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols);
+ if (i >= numSymbols)
+ return;
+ prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);
}
- return price;
+ for (; i < numSymbols; i++)
+ prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);
}
}
@@ -257,7 +234,7 @@ CEncoder::CEncoder():
#endif
_writeEndMark(false)
{
- _maxMode = false;
+ // _maxMode = false;
_fastMode = false;
}
@@ -272,50 +249,24 @@ HRESULT CEncoder::Create()
#ifdef COMPRESS_MF_BT
#ifdef COMPRESS_MF_BT2
case kBT2:
- _matchFinder = new NBT2::CMatchFinderBinTree;
+ _matchFinder = new NBT2::CMatchFinder;
break;
#endif
#ifdef COMPRESS_MF_BT3
case kBT3:
- _matchFinder = new NBT3::CMatchFinderBinTree;
+ _matchFinder = new NBT3::CMatchFinder;
break;
#endif
#ifdef COMPRESS_MF_BT4
case kBT4:
- _matchFinder = new NBT4::CMatchFinderBinTree;
- break;
- #endif
- #ifdef COMPRESS_MF_BT4B
- case kBT4B:
- _matchFinder = new NBT4B::CMatchFinderBinTree;
+ _matchFinder = new NBT4::CMatchFinder;
break;
#endif
#endif
- #ifdef COMPRESS_MF_PAT
- case kPat2:
- _matchFinder = new NPat2::CPatricia;
- break;
- case kPat2H:
- _matchFinder = new NPat2H::CPatricia;
- break;
- case kPat3H:
- _matchFinder = new NPat3H::CPatricia;
- break;
- case kPat4H:
- _matchFinder = new NPat4H::CPatricia;
- break;
- case kPat2R:
- _matchFinder = new NPat2R::CPatricia;
- break;
- #endif
-
#ifdef COMPRESS_MF_HC
- case kHC3:
- _matchFinder = new NHC3::CMatchFinderHC;
- break;
case kHC4:
- _matchFinder = new NHC4::CMatchFinderHC;
+ _matchFinder = new NHC4::CMatchFinder;
break;
#endif
}
@@ -323,7 +274,7 @@ HRESULT CEncoder::Create()
return E_OUTOFMEMORY;
#ifdef COMPRESS_MF_MT
- if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4)))
+ if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4)))
{
CMatchFinderMT *mfSpec = new CMatchFinderMT;
if (mfSpec == 0)
@@ -341,8 +292,7 @@ HRESULT CEncoder::Create()
if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
return S_OK;
- RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes,
- kMatchMaxLen * 2 + 1 - _numFastBytes));
+ RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes
_dictionarySizePrev = _dictionarySize;
_numFastBytesPrev = _numFastBytes;
return S_OK;
@@ -396,7 +346,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
return E_INVALIDARG;
UInt32 maximize = prop.ulVal;
_fastMode = (maximize == 0);
- _maxMode = (maximize >= 2);
+ // _maxMode = (maximize >= 2);
break;
}
case NCoderPropID::kMatchFinder:
@@ -432,7 +382,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
#endif
case NCoderPropID::kDictionarySize:
{
- const int kDicLogSizeMaxCompress = 28;
+ const int kDicLogSizeMaxCompress = 30;
if (prop.vt != VT_UI4)
return E_INVALIDARG;
UInt32 dictionarySize = prop.ulVal;
@@ -536,8 +486,6 @@ HRESULT CEncoder::Init()
_literalEncoder.Init();
- // _repMatchLenEncoder.Init();
-
{
for(UInt32 i = 0; i < kNumLenToPosStates; i++)
_posSlotEncoder[i].Init();
@@ -562,13 +510,10 @@ HRESULT CEncoder::Init()
HRESULT CEncoder::MovePos(UInt32 num)
{
- for (;num != 0; num--)
- {
- _matchFinder->DummyLongestMatch();
- RINOK(_matchFinder->MovePos());
- _additionalOffset++;
- }
- return S_OK;
+ if (num == 0)
+ return S_OK;
+ _additionalOffset += num;
+ return _matchFinder->Skip(num);
}
UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
@@ -606,16 +551,6 @@ UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
}
/*
-inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit)
-{
- back++;
- for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++);
- return i;
-}
-*/
-
-
-/*
Out:
(lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
*/
@@ -630,20 +565,30 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
_optimumCurrentIndex = optimum.PosPrev;
return S_OK;
}
- _optimumCurrentIndex = 0;
- _optimumEndIndex = 0; // test it;
+ _optimumCurrentIndex = _optimumEndIndex = 0;
- UInt32 lenMain;
+ UInt32 lenMain, numDistancePairs;
if (!_longestMatchWasFound)
{
- RINOK(ReadMatchDistances(lenMain));
+ 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];
@@ -652,8 +597,17 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
for(i = 0; i < kNumRepDistances; i++)
{
reps[i] = _repDistances[i];
- repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen);
- if (i == 0 || repLens[i] > repLens[repMaxIndex])
+ 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)
@@ -663,31 +617,31 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
return MovePos(lenRes - 1);
}
+ UInt32 *matchDistances = _matchDistances + 1;
if(lenMain >= _numFastBytes)
{
- backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
+ backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
lenRes = lenMain;
return MovePos(lenMain - 1);
}
- Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
+ Byte currentByte = *data;
+ Byte matchByte = data[(size_t)0 - reps[0] - 1];
- _optimum[0].State = _state;
+ if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ backRes = (UInt32)-1;
+ lenRes = 1;
+ return S_OK;
+ }
- Byte matchByte;
-
- matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1);
+ _optimum[0].State = _state;
UInt32 posState = (position & _posStateMask);
_optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
- _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte);
+ _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);
_optimum[1].MakeAsChar();
- _optimum[1].PosPrev = 0;
-
- for (i = 0; i < kNumRepDistances; i++)
- _optimum[0].Backs[i] = reps[i];
-
UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
@@ -700,55 +654,75 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
_optimum[1].MakeAsShortRep();
}
}
- if(lenMain < 2)
+ UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+ if(lenEnd < 2)
{
backRes = _optimum[1].BackPrev;
lenRes = 1;
return S_OK;
}
-
- UInt32 normalMatchPrice = matchPrice +
- _isRep[_state.Index].GetPrice0();
+ _optimum[1].PosPrev = 0;
+ for (i = 0; i < kNumRepDistances; i++)
+ _optimum[0].Backs[i] = reps[i];
- if (lenMain <= repLens[repMaxIndex])
- lenMain = 0;
+ UInt32 len = lenEnd;
+ do
+ _optimum[len--].Price = kIfinityPrice;
+ while (len >= 2);
- UInt32 len;
- for(len = 2; len <= lenMain; len++)
+ for(i = 0; i < kNumRepDistances; i++)
{
- _optimum[len].PosPrev = 0;
- _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
- _optimum[len].Price = normalMatchPrice +
- GetPosLenPrice(_matchDistances[len], len, posState);
- _optimum[len].Prev1IsChar = false;
+ 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);
}
- if (lenMain < repLens[repMaxIndex])
- lenMain = repLens[repMaxIndex];
-
- for (; len <= lenMain; len++)
- _optimum[len].Price = kIfinityPrice;
+ UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
- for(i = 0; i < kNumRepDistances; i++)
+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ if (len <= lenMain)
{
- UInt32 repLen = repLens[i];
- for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++)
+ UInt32 offs = 0;
+ while (len > matchDistances[offs])
+ offs += 2;
+ for(; ; len++)
{
- UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState);
- COptimal &optimum = _optimum[lenTest];
+ 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 = i;
+ optimum.BackPrev = distance + kNumRepDistances;
optimum.Prev1IsChar = false;
}
+ if (len == matchDistances[offs])
+ {
+ offs += 2;
+ if (offs == numDistancePairs)
+ break;
+ }
}
}
UInt32 cur = 0;
- UInt32 lenEnd = lenMain;
while(true)
{
@@ -758,6 +732,16 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
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;
@@ -785,11 +769,6 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
state.UpdateShortRep();
else
state.UpdateChar();
- /*
- if (curOptimum.Prev1IsChar)
- for(int i = 0; i < kNumRepDistances; i++)
- reps[i] = _optimum[posPrev].Backs[i];
- */
}
else
{
@@ -828,27 +807,16 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
curOptimum.State = state;
for(UInt32 i = 0; i < kNumRepDistances; i++)
curOptimum.Backs[i] = reps[i];
- UInt32 newLen;
- RINOK(ReadMatchDistances(newLen));
- if(newLen >= _numFastBytes)
- {
- _longestMatchLength = newLen;
- _longestMatchWasFound = true;
- lenRes = Backward(backRes, cur);
- return S_OK;
- }
UInt32 curPrice = curOptimum.Price;
- // Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
- // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1);
const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
- Byte currentByte = *data;
- Byte matchByte = data[(size_t)0 - reps[0] - 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.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte);
+ _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte);
COptimal &nextOptimum = _optimum[cur + 1];
@@ -873,11 +841,11 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
nextOptimum.Price = shortRepPrice;
nextOptimum.PosPrev = cur;
nextOptimum.MakeAsShortRep();
- // nextIsChar = false;
+ nextIsChar = true;
}
}
/*
- if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
+ if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
continue;
*/
@@ -889,14 +857,14 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
continue;
if (numAvailableBytes > _numFastBytes)
numAvailableBytes = _numFastBytes;
- if (numAvailableBytes >= 3 && !nextIsChar)
+ 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 < numAvailableBytes; temp++)
- if (data[temp] != data[(size_t)temp - backOffset])
- break;
+ for (temp = 1; temp < limit &&
+ data[temp] == data[(size_t)temp - backOffset]; temp++);
UInt32 lenTest2 = temp - 1;
if (lenTest2 >= 2)
{
@@ -908,11 +876,12 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
_isRep[state2.Index].GetPrice1();
// for (; lenTest2 >= 2; lenTest2--)
{
- while(lenEnd < cur + 1 + lenTest2)
+ UInt32 offset = cur + 1 + lenTest2;
+ while(lenEnd < offset)
_optimum[++lenEnd].Price = kIfinityPrice;
UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[cur + 1 + lenTest2];
+ COptimal &optimum = _optimum[offset];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
@@ -924,6 +893,8 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
}
}
}
+
+ UInt32 startLen = 2; // speed optimization
for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
{
// UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
@@ -932,15 +903,15 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
data[1] != data[(size_t)1 - backOffset])
continue;
UInt32 lenTest;
- for (lenTest = 2; lenTest < numAvailableBytes; lenTest++)
- if (data[lenTest] != data[(size_t)lenTest - backOffset])
- break;
+ 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
{
- while(lenEnd < cur + lenTest)
- _optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+ UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);
COptimal &optimum = _optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
@@ -952,14 +923,16 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
}
while(--lenTest >= 2);
lenTest = lenTestTemp;
-
- if (_maxMode)
+
+ if (repIndex == 0)
+ startLen = lenTest + 1;
+
+ // if (_maxMode)
{
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
- for (; lenTest2 < limit; lenTest2++)
- if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
- break;
+ for (; lenTest2 < limit &&
+ data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);
lenTest2 -= lenTest + 1;
if (lenTest2 >= 2)
{
@@ -967,23 +940,24 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
state2.UpdateRep();
UInt32 posStateNext = (position + lenTest) & _posStateMask;
UInt32 curAndLenCharPrice =
- repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
+ price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) +
_isMatch[state2.Index][posStateNext].GetPrice0() +
- _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
+ _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 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
- UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+ UInt32 nextRepMatchPrice = curAndLenCharPrice +
+ _isMatch[state2.Index][posStateNext].GetPrice1() +
+ _isRep[state2.Index].GetPrice1();
// for(; lenTest2 >= 2; lenTest2--)
{
- UInt32 offset = lenTest + 1 + lenTest2;
- while(lenEnd < cur + offset)
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ while(lenEnd < offset)
_optimum[++lenEnd].Price = kIfinityPrice;
UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[cur + offset];
+ COptimal &optimum = _optimum[offset];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
@@ -1001,20 +975,34 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
// for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
if (newLen > numAvailableBytes)
+ {
newLen = numAvailableBytes;
- if (newLen >= 2)
+ for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
+ matchDistances[numDistancePairs] = newLen;
+ numDistancePairs += 2;
+ }
+ if (newLen >= startLen)
{
- if (newLen == 2 && _matchDistances[2] >= 0x80)
- continue;
- UInt32 normalMatchPrice = matchPrice +
- _isRep[state.Index].GetPrice0();
+ UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
while(lenEnd < cur + newLen)
_optimum[++lenEnd].Price = kIfinityPrice;
- for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
+ 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 curBack = _matchDistances[lenTest];
- UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+ 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);
+
COptimal &optimum = _optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
@@ -1024,15 +1012,14 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
optimum.Prev1IsChar = false;
}
- if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1]))
+ if (/*_maxMode && */lenTest == matchDistances[offs])
{
// Try Match + Literal + Rep0
UInt32 backOffset = curBack + 1;
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
- for (; lenTest2 < limit; lenTest2++)
- if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
- break;
+ for (; lenTest2 < limit &&
+ data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);
lenTest2 -= lenTest + 1;
if (lenTest2 >= 2)
{
@@ -1041,21 +1028,21 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
UInt32 posStateNext = (position + lenTest) & _posStateMask;
UInt32 curAndLenCharPrice = curAndLenPrice +
_isMatch[state2.Index][posStateNext].GetPrice0() +
- _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
+ _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 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
- UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+ posStateNext = (posStateNext + 1) & _posStateMask;
+ UInt32 nextRepMatchPrice = curAndLenCharPrice +
+ _isMatch[state2.Index][posStateNext].GetPrice1() +
+ _isRep[state2.Index].GetPrice1();
// for(; lenTest2 >= 2; lenTest2--)
{
- UInt32 offset = lenTest + 1 + lenTest2;
- while(lenEnd < cur + offset)
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ while(lenEnd < offset)
_optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
- 0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[cur + offset];
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+ COptimal &optimum = _optimum[offset];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
@@ -1068,6 +1055,12 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
}
}
}
+ offs += 2;
+ if (offs == numDistancePairs)
+ break;
+ curBack = matchDistances[offs + 1];
+ if (curBack >= kNumFullDistances)
+ posSlot = GetPosSlot2(curBack);
}
}
}
@@ -1076,67 +1069,103 @@ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
{
- const int kDif = 7;
- return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif));
+ return ((bigDist >> 7) > smallDist);
}
-HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes)
+HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs)
{
- lenRes = _matchFinder->GetLongestMatch(_matchDistances);
- if (lenRes == _numFastBytes)
- lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes],
- kMatchMaxLen - lenRes);
+ lenRes = 0;
+ RINOK(_matchFinder->GetMatches(_matchDistances));
+ numDistancePairs = _matchDistances[0];
+ if (numDistancePairs > 0)
+ {
+ lenRes = _matchDistances[1 + numDistancePairs - 2];
+ if (lenRes == _numFastBytes)
+ lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1],
+ kMatchMaxLen - lenRes);
+ }
_additionalOffset++;
- return _matchFinder->MovePos();
+ return S_OK;
}
HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
{
- UInt32 lenMain;
+ UInt32 lenMain, numDistancePairs;
if (!_longestMatchWasFound)
{
- RINOK(ReadMatchDistances(lenMain));
+ RINOK(ReadMatchDistances(lenMain, numDistancePairs));
}
else
{
lenMain = _longestMatchLength;
+ numDistancePairs = _numDistancePairs;
_longestMatchWasFound = false;
}
+
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
+ UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;
+ if (numAvailableBytes > kMatchMaxLen)
+ numAvailableBytes = kMatchMaxLen;
+ if (numAvailableBytes < 2)
+ {
+ backRes = (UInt32)(-1);
+ lenRes = 1;
+ return S_OK;
+ }
+
UInt32 repLens[kNumRepDistances];
UInt32 repMaxIndex = 0;
+
for(UInt32 i = 0; i < kNumRepDistances; i++)
{
- repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
- if (i == 0 || repLens[i] > repLens[repMaxIndex])
+ UInt32 backOffset = _repDistances[i] + 1;
+ if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset])
+ {
+ repLens[i] = 0;
+ continue;
+ }
+ UInt32 len;
+ for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);
+ if(len >= _numFastBytes)
+ {
+ backRes = i;
+ lenRes = len;
+ return MovePos(lenRes - 1);
+ }
+ repLens[i] = len;
+ if (len > 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[_numFastBytes] + kNumRepDistances;
+ backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
lenRes = lenMain;
return MovePos(lenMain - 1);
}
- while (lenMain > 2)
+
+ UInt32 backMain;
+ if (lenMain >= 2)
{
- if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))
- break;
- lenMain--;
+ backMain = matchDistances[numDistancePairs - 1];
+ while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
+ {
+ if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
+ break;
+ numDistancePairs -= 2;
+ lenMain = matchDistances[numDistancePairs - 2];
+ backMain = matchDistances[numDistancePairs - 1];
+ }
+ if (lenMain == 2 && backMain >= 0x80)
+ lenMain = 1;
}
- if (lenMain == 2 && _matchDistances[2] >= 0x80)
- lenMain = 1;
- UInt32 backMain = _matchDistances[lenMain];
if (repLens[repMaxIndex] >= 2)
{
if (repLens[repMaxIndex] + 1 >= lenMain ||
- repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12)))
+ repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
+ repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
{
backRes = repMaxIndex;
lenRes = repLens[repMaxIndex];
@@ -1144,30 +1173,36 @@ HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRe
}
}
-
- if (lenMain >= 2)
+ if (lenMain >= 2 && numAvailableBytes > 2)
{
- RINOK(ReadMatchDistances(_longestMatchLength));
- if (_longestMatchLength >= 2 &&
- (
- (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) ||
- _longestMatchLength == lenMain + 1 &&
- !ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
- _longestMatchLength > lenMain + 1 ||
- _longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
- ChangePair(_matchDistances[lenMain - 1], backMain)
- )
- )
+ RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs));
+ if (_longestMatchLength >= 2)
{
- _longestMatchWasFound = true;
- backRes = UInt32(-1);
- lenRes = 1;
- return S_OK;
+ UInt32 newDistance = matchDistances[_numDistancePairs - 1];
+ if (_longestMatchLength >= lenMain && newDistance < backMain ||
+ _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
+ _longestMatchLength > lenMain + 1 ||
+ _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
+ {
+ _longestMatchWasFound = true;
+ backRes = UInt32(-1);
+ lenRes = 1;
+ return S_OK;
+ }
}
+ data++;
+ numAvailableBytes--;
for(UInt32 i = 0; i < kNumRepDistances; i++)
{
- UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
- if (repLen >= 2 && repLen + 1 >= lenMain)
+ UInt32 backOffset = _repDistances[i] + 1;
+ if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset])
+ {
+ repLens[i] = 0;
+ continue;
+ }
+ UInt32 len;
+ for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);
+ if (len + 1 >= lenMain)
{
_longestMatchWasFound = true;
backRes = UInt32(-1);
@@ -1209,7 +1244,7 @@ void CEncoder::WriteEndMarker(UInt32 posState)
_isRep[_state.Index].Encode(&_rangeEncoder, 0);
_state.UpdateMatch();
UInt32 len = kMatchMinLen; // kMatchMaxLen;
- _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
UInt32 lenToPosState = GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
@@ -1261,7 +1296,6 @@ HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
if (!_fastMode)
{
- FillPosSlotPrices();
FillDistancesPrices();
FillAlignPrices();
}
@@ -1271,7 +1305,6 @@ HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
_repMatchLenEncoder.UpdateTables(1 << _posStateBits);
- lastPosSlotFillingPos = 0;
nowPos64 = 0;
return S_OK;
}
@@ -1280,7 +1313,8 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
{
if (_inStream != 0)
{
- RINOK(_matchFinder->Init(_inStream));
+ RINOK(_matchFinder->SetStream(_inStream));
+ RINOK(_matchFinder->Init());
_needReleaseMFStream = true;
_inStream = 0;
}
@@ -1291,14 +1325,12 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
return S_OK;
_finished = true;
-
- UInt64 progressPosValuePrev = nowPos64;
if (nowPos64 == 0)
{
if (_matchFinder->GetNumAvailableBytes() == 0)
return Flush(UInt32(nowPos64));
- UInt32 len; // it's not used
- RINOK(ReadMatchDistances(len));
+ UInt32 len, numDistancePairs;
+ RINOK(ReadMatchDistances(len, numDistancePairs));
UInt32 posState = UInt32(nowPos64) & _posStateMask;
_isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
_state.UpdateChar();
@@ -1308,37 +1340,40 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
_additionalOffset--;
nowPos64++;
}
+
+ UInt32 nowPos32 = (UInt32)nowPos64;
+ UInt32 progressPosValuePrev = nowPos32;
+
if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush(UInt32(nowPos64));
+ return Flush(nowPos32);
+
while(true)
{
#ifdef _NO_EXCEPTIONS
if (_rangeEncoder.Stream.ErrorCode != S_OK)
return _rangeEncoder.Stream.ErrorCode;
#endif
- UInt32 pos;
- UInt32 posState = UInt32(nowPos64) & _posStateMask;
-
- UInt32 len;
+ UInt32 pos, len;
HRESULT result;
if (_fastMode)
- result = GetOptimumFast(UInt32(nowPos64), pos, len);
+ result = GetOptimumFast(nowPos32, pos, len);
else
- result = GetOptimum(UInt32(nowPos64), pos, len);
+ result = GetOptimum(nowPos32, pos, len);
RINOK(result);
+ UInt32 posState = nowPos32 & _posStateMask;
if(len == 1 && pos == 0xFFFFFFFF)
{
_isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
- CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte);
- if(!_state.IsCharState())
+ CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);
+ if(_state.IsCharState())
+ subCoder->Encode(&_rangeEncoder, curByte);
+ else
{
Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
}
- else
- subCoder->Encode(&_rangeEncoder, curByte);
_state.UpdateChar();
_previousByte = curByte;
}
@@ -1351,13 +1386,11 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
if(pos == 0)
{
_isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
- if(len == 1)
- _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0);
- else
- _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1);
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));
}
else
{
+ UInt32 distance = _repDistances[pos];
_isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
if (pos == 1)
_isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
@@ -1365,34 +1398,29 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
{
_isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
_isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
+ if (pos == 3)
+ _repDistances[3] = _repDistances[2];
+ _repDistances[2] = _repDistances[1];
}
+ _repDistances[1] = _repDistances[0];
+ _repDistances[0] = distance;
}
if (len == 1)
_state.UpdateShortRep();
else
{
- _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
_state.UpdateRep();
}
-
-
- UInt32 distance = _repDistances[pos];
- if (pos != 0)
- {
- for(UInt32 i = pos; i >= 1; i--)
- _repDistances[i] = _repDistances[i - 1];
- _repDistances[0] = distance;
- }
}
else
{
_isRep[_state.Index].Encode(&_rangeEncoder, 0);
_state.UpdateMatch();
- _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
pos -= kNumRepDistances;
UInt32 posSlot = GetPosSlot(pos);
- UInt32 lenToPosState = GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
+ _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);
if (posSlot >= kStartPosModelIndex)
{
@@ -1407,35 +1435,35 @@ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
{
_rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
_posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
- if (!_fastMode)
- if (--_alignPriceCount == 0)
- FillAlignPrices();
+ _alignPriceCount++;
}
}
- UInt32 distance = pos;
- for(UInt32 i = kNumRepDistances - 1; i >= 1; i--)
- _repDistances[i] = _repDistances[i - 1];
- _repDistances[0] = distance;
+ _repDistances[3] = _repDistances[2];
+ _repDistances[2] = _repDistances[1];
+ _repDistances[1] = _repDistances[0];
+ _repDistances[0] = pos;
+ _matchPriceCount++;
}
_previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
}
_additionalOffset -= len;
- nowPos64 += len;
- if (!_fastMode)
- if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))
- {
- FillPosSlotPrices();
- FillDistancesPrices();
- lastPosSlotFillingPos = nowPos64;
- }
+ nowPos32 += len;
if (_additionalOffset == 0)
{
- *inSize = nowPos64;
- *outSize = _rangeEncoder.GetProcessedSize();
+ if (!_fastMode)
+ {
+ if (_matchPriceCount >= (1 << 7))
+ FillDistancesPrices();
+ if (_alignPriceCount >= kAlignTableSize)
+ FillAlignPrices();
+ }
if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush(UInt32(nowPos64));
- if (nowPos64 - progressPosValuePrev >= (1 << 12))
+ return Flush(nowPos32);
+ if (nowPos32 - progressPosValuePrev >= (1 << 14))
{
+ nowPos64 += nowPos32 - progressPosValuePrev;
+ *inSize = nowPos64;
+ *outSize = _rangeEncoder.GetProcessedSize();
_finished = false;
*finished = 0;
return S_OK;
@@ -1460,45 +1488,43 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
#endif
}
-void CEncoder::FillPosSlotPrices()
+void CEncoder::FillDistancesPrices()
{
- for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
- {
- UInt32 posSlot;
- for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++)
- _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot);
- for (; posSlot < _distTableSize; posSlot++)
- _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) +
- ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
+ UInt32 tempPrices[kNumFullDistances];
+ for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot(i);
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
+ base - posSlot - 1, footerBits, i - base);
}
-}
-void CEncoder::FillDistancesPrices()
-{
for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
{
+ UInt32 posSlot;
+ NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];
+ UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];
+ for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+ posSlotPrices[posSlot] = encoder.GetPrice(posSlot);
+ for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
+
+ UInt32 *distancesPrices = _distancesPrices[lenToPosState];
UInt32 i;
for (i = 0; i < kStartPosModelIndex; i++)
- _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
+ distancesPrices[i] = posSlotPrices[i];
for (; i < kNumFullDistances; i++)
- {
- UInt32 posSlot = GetPosSlot(i);
- UInt32 footerBits = ((posSlot >> 1) - 1);
- UInt32 base = ((2 | (posSlot & 1)) << footerBits);
-
- _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
- NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
- base - posSlot - 1, footerBits, i - base);
-
- }
+ distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];
}
+ _matchPriceCount = 0;
}
void CEncoder::FillAlignPrices()
{
for (UInt32 i = 0; i < kAlignTableSize; i++)
_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
- _alignPriceCount = kAlignTableSize;
+ _alignPriceCount = 0;
}
}}