upgraded to lzma sdk 4.43 for faster compression

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4772 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2006-10-16 08:46:36 +00:00
parent 51a96f2d75
commit 2cd2142ca3
42 changed files with 1900 additions and 1572 deletions

View file

@ -1,92 +1,54 @@
// BinTree.h
// #ifndef __BINTREE_H
// #define __BINTREE_H
#include "../LZInWindow.h"
#include "../IMatchFinder.h"
namespace BT_NAMESPACE {
typedef UInt32 CIndex;
const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
// #define HASH_ARRAY_2
// #ifdef HASH_ARRAY_2
// #define HASH_ARRAY_3
// #else
// #define HASH_ZIP
// #endif
struct CPair
{
CIndex Left;
CIndex Right;
};
/*
const int kNumBundleBits = 2;
const UInt32 kNumPairsInBundle = 1 << kNumBundleBits;
const UInt32 kBundleMask = kNumPairsInBundle - 1;
const UInt32 kNumBundleBytes = kNumPairsInBundle * sizeof(CPair);
struct CBundle
{
CPair Pairs[kNumPairsInBundle];
Byte Bytes[kNumBundleBytes];
};
*/
class CInTree: public CLZInWindow
class CMatchFinder:
public IMatchFinder,
public CLZInWindow,
public CMyUnknownImp,
public IMatchFinderSetNumPasses
{
UInt32 _cyclicBufferPos;
UInt32 _cyclicBufferSize;
UInt32 _historySize;
UInt32 _cyclicBufferSize; // it must be historySize + 1
UInt32 _matchMaxLen;
CIndex *_hash;
#ifdef HASH_ARRAY_2
CIndex *_hash2;
#ifdef HASH_ARRAY_3
CIndex *_hash3;
#endif
#endif
// CBundle *_son;
CPair *_son;
CIndex *_son;
UInt32 _hashMask;
UInt32 _cutValue;
UInt32 _hashSizeSum;
void NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue);
void Normalize();
void FreeThisClassMemory();
void FreeMemory();
MY_UNKNOWN_IMP
STDMETHOD(SetStream)(ISequentialInStream *inStream);
STDMETHOD_(void, ReleaseStream)();
STDMETHOD(Init)();
HRESULT MovePos();
STDMETHOD_(Byte, GetIndexByte)(Int32 index);
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
STDMETHOD_(UInt32, GetNumAvailableBytes)();
STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes);
STDMETHOD_(void, ChangeBufferPos)();
STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
STDMETHOD(GetMatches)(UInt32 *distances);
STDMETHOD(Skip)(UInt32 num);
public:
CInTree();
~CInTree();
HRESULT Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
UInt32 keepAddBufferAfter, UInt32 sizeReserv = (1<<17));
HRESULT Init(ISequentialInStream *stream);
void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
UInt32 GetLongestMatch(UInt32 *distances);
void DummyLongestMatch();
HRESULT MovePos()
{
_cyclicBufferPos++;
if (_cyclicBufferPos >= _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
return S_OK;
}
CMatchFinder();
virtual ~CMatchFinder();
virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; }
};
}
// #endif

View file

@ -1,16 +1,12 @@
// BinTree2.h
#ifndef __BINTREE2__H
#define __BINTREE2__H
#ifndef __BINTREE2_H
#define __BINTREE2_H
#undef BT_CLSID
#define BT_CLSID CLSID_CMatchFinderBT2
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT2
#include "BinTreeMF.h"
#include "BinTreeMFMain.h"
#include "BinTreeMain.h"
#undef BT_NAMESPACE
#endif

View file

@ -1,20 +1,16 @@
// BinTree3.h
#ifndef __BINTREE3__H
#define __BINTREE3__H
#ifndef __BINTREE3_H
#define __BINTREE3_H
#undef BT_CLSID
#define BT_CLSID CLSID_CMatchFinderBT3
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT3
#define HASH_ARRAY_2
#include "BinTreeMF.h"
#include "BinTreeMFMain.h"
#include "BinTreeMain.h"
#undef HASH_ARRAY_2
#endif
#undef BT_NAMESPACE
#endif

View file

@ -1,17 +1,16 @@
// BinTree3Z.h
#ifndef __BINTREE3Z__H
#define __BINTREE3Z__H
#ifndef __BINTREE3Z_H
#define __BINTREE3Z_H
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT3Z
#define HASH_ZIP
#include "BinTree.h"
// #include "BinTreeMain.h"
#include "BinTreeMain.h"
#undef HASH_ZIP
#endif
#undef BT_NAMESPACE
#endif

View file

@ -1,22 +1,18 @@
// BinTree4.h
#ifndef __BINTREE4__H
#define __BINTREE4__H
#ifndef __BINTREE4_H
#define __BINTREE4_H
#undef BT_CLSID
#define BT_CLSID CLSID_CMatchFinderBT4
#undef BT_NAMESPACE
#define BT_NAMESPACE NBT4
#define HASH_ARRAY_2
#define HASH_ARRAY_3
#include "BinTreeMF.h"
#include "BinTreeMFMain.h"
#include "BinTreeMain.h"
#undef HASH_ARRAY_2
#undef HASH_ARRAY_3
#endif
#undef BT_NAMESPACE
#endif

View file

@ -4,163 +4,187 @@
#include "../../../../Common/CRC.h"
#include "../../../../Common/Alloc.h"
#include "BinTree.h"
// #include <xmmintrin.h>
// It's for prefetch
// But prefetch doesn't give big gain in K8.
namespace BT_NAMESPACE {
#ifdef HASH_ARRAY_2
static const UInt32 kHash2Size = 1 << 10;
#define kNumHashDirectBytes 0
#ifdef HASH_ARRAY_3
static const UInt32 kNumHashDirectBytes = 0;
static const UInt32 kNumHashBytes = 4;
static const UInt32 kHash3Size = 1 << 18;
#ifdef HASH_BIG
static const UInt32 kHashSize = 1 << 23;
#else
static const UInt32 kHashSize = 1 << 20;
#endif
static const UInt32 kHash3Size = 1 << 16;
#else
static const UInt32 kNumHashDirectBytes = 3;
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
#endif
static const UInt32 kHashSize = 0;
static const UInt32 kMinMatchCheck = kNumHashBytes;
static const UInt32 kStartMaxLen = 1;
#else
#ifdef HASH_ZIP
static const UInt32 kNumHashDirectBytes = 0;
#define kNumHashDirectBytes 0
static const UInt32 kNumHashBytes = 3;
static const UInt32 kHashSize = 1 << 16;
static const UInt32 kMinMatchCheck = kNumHashBytes;
static const UInt32 kStartMaxLen = 1;
#else
static const UInt32 kNumHashDirectBytes = 2;
#define kNumHashDirectBytes 2
static const UInt32 kNumHashBytes = 2;
static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
static const UInt32 kMinMatchCheck = kNumHashBytes + 1;
static const UInt32 kStartMaxLen = 1;
#endif
#endif
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
static const UInt32 kHash3Offset = kHash2Size;
#endif
#endif
CInTree::CInTree():
_hash(0),
#ifdef HASH_ARRAY_2
_hash2(0),
#ifdef HASH_ARRAY_3
_hash3(0),
#endif
#endif
_son(0),
_cutValue(0xFF)
static const UInt32 kFixHashSize = 0
#ifdef HASH_ARRAY_2
+ kHash2Size
#ifdef HASH_ARRAY_3
+ kHash3Size
#endif
#endif
;
CMatchFinder::CMatchFinder():
_hash(0)
{
}
void CInTree::FreeMemory()
void CMatchFinder::FreeThisClassMemory()
{
BigFree(_son);
_son = 0;
BigFree(_hash);
_hash = 0;
}
void CMatchFinder::FreeMemory()
{
FreeThisClassMemory();
CLZInWindow::Free();
}
CInTree::~CInTree()
CMatchFinder::~CMatchFinder()
{
FreeMemory();
}
HRESULT CInTree::Create(UInt32 sizeHistory, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 sizeReserv)
STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
FreeMemory();
if (!CLZInWindow::Create(sizeHistory + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter, sizeReserv))
return E_OUTOFMEMORY;
if (_blockSize + 256 > kMaxValForNormalize)
if (historySize > kMaxValForNormalize - 256)
{
FreeMemory();
return E_INVALIDARG;
_historySize = sizeHistory;
_matchMaxLen = matchMaxLen;
_cyclicBufferSize = sizeHistory + 1;
UInt32 size = kHashSize;
#ifdef HASH_ARRAY_2
size += kHash2Size;
#ifdef HASH_ARRAY_3
size += kHash3Size;
#endif
#endif
_son = (CPair *)BigAlloc((_cyclicBufferSize + 1) * sizeof(CPair));
if (_son == 0)
{
FreeMemory();
return E_OUTOFMEMORY;
}
// UInt32 numBundles = (_cyclicBufferSize + kNumPairsInBundle) >> kNumBundleBits;
// _son = (CBundle *)::VirtualAlloc(0, numBundles * sizeof(CBundle), MEM_COMMIT, PAGE_READWRITE);
_hash = (CIndex *)BigAlloc((size + 1) * sizeof(CIndex));
if (_hash == 0)
_cutValue =
#ifdef _HASH_CHAIN
8 + (matchMaxLen >> 2);
#else
16 + (matchMaxLen >> 1);
#endif
UInt32 sizeReserv = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
if (CLZInWindow::Create(historySize + keepAddBufferBefore,
matchMaxLen + keepAddBufferAfter, sizeReserv))
{
FreeMemory();
return E_OUTOFMEMORY;
_matchMaxLen = matchMaxLen;
UInt32 newCyclicBufferSize = historySize + 1;
if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
return S_OK;
FreeThisClassMemory();
_cyclicBufferSize = newCyclicBufferSize; // don't change it
UInt32 hs = kHashSize;
#ifdef HASH_ARRAY_2
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
{
#ifdef HASH_ARRAY_3
hs >>= 1;
#else
hs = (1 << 24) - 1;
#endif
}
_hashMask = hs;
hs++;
#endif
_hashSizeSum = hs + kFixHashSize;
UInt32 numItems = _hashSizeSum + _cyclicBufferSize
#ifndef _HASH_CHAIN
* 2
#endif
;
size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);
if (sizeInBytes / sizeof(CIndex) != numItems)
return E_OUTOFMEMORY;
_hash = (CIndex *)BigAlloc(sizeInBytes);
_son = _hash + _hashSizeSum;
if (_hash != 0)
return S_OK;
}
// _hash = &m_RightBase[_blockSize];
#ifdef HASH_ARRAY_2
_hash2 = &_hash[kHashSize];
#ifdef HASH_ARRAY_3
_hash3 = &_hash2[kHash2Size];
#endif
#endif
return S_OK;
FreeMemory();
return E_OUTOFMEMORY;
}
static const UInt32 kEmptyHashValue = 0;
HRESULT CInTree::Init(ISequentialInStream *stream)
STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)
{
RINOK(CLZInWindow::Init(stream));
UInt32 i;
for(i = 0; i < kHashSize; i++)
CLZInWindow::SetStream(stream);
return S_OK;
}
STDMETHODIMP CMatchFinder::Init()
{
RINOK(CLZInWindow::Init());
for(UInt32 i = 0; i < _hashSizeSum; i++)
_hash[i] = kEmptyHashValue;
#ifdef HASH_ARRAY_2
for(i = 0; i < kHash2Size; i++)
_hash2[i] = kEmptyHashValue;
#ifdef HASH_ARRAY_3
for(i = 0; i < kHash3Size; i++)
_hash3[i] = kEmptyHashValue;
#endif
#endif
_cyclicBufferPos = 0;
ReduceOffsets(-1);
return S_OK;
}
STDMETHODIMP_(void) CMatchFinder::ReleaseStream()
{
// ReleaseStream();
}
#ifdef HASH_ARRAY_2
#ifdef HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
{
UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
hash2Value = temp & (kHash2Size - 1);
hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
(kHashSize - 1);
}
#define HASH_CALC { \
UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \
hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }
#else // no HASH_ARRAY_3
inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
{
hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1);
return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2];
}
#define HASH_CALC { \
UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }
#endif // HASH_ARRAY_3
#else // no HASH_ARRAY_2
#ifdef HASH_ZIP
inline UInt32 Hash(const Byte *pointer)
{
return ((UInt32(pointer[0]) << 8) ^
CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
}
#else // no HASH_ZIP
inline UInt32 Hash(const Byte *pointer)
@ -170,7 +194,7 @@ inline UInt32 Hash(const Byte *pointer)
#endif // HASH_ZIP
#endif // HASH_ARRAY_2
UInt32 CInTree::GetLongestMatch(UInt32 *distances)
STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
@ -178,346 +202,288 @@ UInt32 CInTree::GetLongestMatch(UInt32 *distances)
else
{
lenLimit = _streamPos - _pos;
if(lenLimit < kNumHashBytes)
return 0;
if(lenLimit < kMinMatchCheck)
{
distances[0] = 0;
return MovePos();
}
}
UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1;
Byte *cur = _buffer + _pos;
int offset = 1;
/*
if ((_cyclicBufferPos & kBundleMask) == 0)
{
Byte *bytes = _son[_cyclicBufferPos >> kNumBundleBits].Bytes;
UInt32 bundleLimit = kNumBundleBytes;
if (bundleLimit > lenLimit)
bundleLimit = lenLimit;
for (UInt32 i = 0; i < bundleLimit; i++)
bytes[i] = cur[i];
}
*/
UInt32 matchHashLenMax = 0;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
const Byte *cur = _buffer + _pos;
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
#ifdef HASH_ARRAY_2
UInt32 hash2Value;
#ifdef HASH_ARRAY_3
UInt32 hash3Value;
UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
#else
UInt32 hashValue = Hash(cur, hash2Value);
#endif
UInt32 hashValue;
HASH_CALC;
#else
UInt32 hashValue = Hash(cur);
#endif
UInt32 curMatch = _hash[hashValue];
UInt32 curMatch = _hash[kFixHashSize + hashValue];
#ifdef HASH_ARRAY_2
UInt32 curMatch2 = _hash2[hash2Value];
UInt32 curMatch2 = _hash[hash2Value];
#ifdef HASH_ARRAY_3
UInt32 curMatch3 = _hash3[hash3Value];
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
#endif
_hash2[hash2Value] = _pos;
bool matchLen2Exist = false;
UInt32 len2Distance = 0;
if(curMatch2 >= matchMinPos)
{
_hash[hash2Value] = _pos;
if(curMatch2 > matchMinPos)
if (_buffer[curMatch2] == cur[0])
{
len2Distance = _pos - curMatch2 - 1;
matchHashLenMax = 2;
matchLen2Exist = true;
distances[offset++] = maxLen = 2;
distances[offset++] = _pos - curMatch2 - 1;
}
}
#ifdef HASH_ARRAY_3
_hash3[hash3Value] = _pos;
UInt32 matchLen3Exist = false;
UInt32 len3Distance = 0;
if(curMatch3 >= matchMinPos)
{
_hash[kHash3Offset + hash3Value] = _pos;
if(curMatch3 > matchMinPos)
if (_buffer[curMatch3] == cur[0])
{
len3Distance = _pos - curMatch3 - 1;
matchHashLenMax = 3;
matchLen3Exist = true;
if (matchLen2Exist)
{
if (len3Distance < len2Distance)
len2Distance = len3Distance;
}
else
{
len2Distance = len3Distance;
matchLen2Exist = true;
}
if (curMatch3 == curMatch2)
offset -= 2;
distances[offset++] = maxLen = 3;
distances[offset++] = _pos - curMatch3 - 1;
curMatch2 = curMatch3;
}
#endif
if (offset != 1 && curMatch2 == curMatch)
{
offset -= 2;
maxLen = kStartMaxLen;
}
#endif
_hash[kFixHashSize + hashValue] = _pos;
CIndex *son = _son;
#ifdef _HASH_CHAIN
son[_cyclicBufferPos] = curMatch;
#else
CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CIndex *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
#endif
#if kNumHashDirectBytes != 0
if(curMatch > matchMinPos)
{
if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])
{
distances[offset++] = maxLen = kNumHashDirectBytes;
distances[offset++] = _pos - curMatch - 1;
}
}
#endif
#endif
_hash[hashValue] = _pos;
// UInt32 bi = _cyclicBufferPos >> kNumBundleBits;
// UInt32 bo = _cyclicBufferPos & kBundleMask;
// CPair &pair = _son[bi].Pairs[bo];
CPair &pair = _son[_cyclicBufferPos];
if(curMatch < matchMinPos)
UInt32 count = _cutValue;
while(true)
{
pair.Left = kEmptyHashValue;
pair.Right = kEmptyHashValue;
#ifdef HASH_ARRAY_2
distances[2] = len2Distance;
#ifdef HASH_ARRAY_3
distances[3] = len3Distance;
#endif
#endif
return matchHashLenMax;
}
CIndex *ptrLeft = &pair.Right;
CIndex *ptrRight = &pair.Left;
UInt32 maxLen, minLeft, minRight;
maxLen = minLeft = minRight = kNumHashDirectBytes;
#ifdef HASH_ARRAY_2
#ifndef HASH_ARRAY_3
if (matchLen2Exist)
distances[2] = len2Distance;
else
if (kNumHashDirectBytes >= 2)
distances[2] = _pos - curMatch - 1;
#endif
#endif
distances[maxLen] = _pos - curMatch - 1;
for(UInt32 count = _cutValue; count > 0; count--)
{
/*
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CBundle &bundle = _son[cyclicPos >> kNumBundleBits];
UInt32 bo = cyclicPos & kBundleMask;
CPair &pair = bundle.Pairs[bo];
Byte *pby1 = bundle.Bytes + bo;
UInt32 bundleLimit = kNumBundleBytes - bo;
UInt32 currentLen = minSame;
if (bundleLimit > lenLimit)
bundleLimit = lenLimit;
for(; currentLen < bundleLimit; currentLen++)
if (pby1[currentLen] != cur[currentLen])
break;
if (currentLen >= bundleLimit)
if(curMatch <= matchMinPos || count-- == 0)
{
pby1 = _buffer + curMatch;
for(; currentLen < lenLimit; currentLen++)
if (pby1[currentLen] != cur[currentLen])
break;
}
*/
Byte *pby1 = _buffer + curMatch;
// CIndex left = pair.Left; // it's prefetch
UInt32 currentLen = MyMin(minLeft, minRight);
for(; currentLen < lenLimit; currentLen++)
if (pby1[currentLen] != cur[currentLen])
break;
UInt32 delta = _pos - curMatch;
while (currentLen > maxLen)
distances[++maxLen] = delta - 1;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CPair &pair = _son[cyclicPos];
if (currentLen != lenLimit)
{
if (pby1[currentLen] < cur[currentLen])
{
*ptrRight = curMatch;
ptrRight = &pair.Right;
curMatch = pair.Right;
if(currentLen > minLeft)
minLeft = currentLen;
}
else
{
*ptrLeft = curMatch;
ptrLeft = &pair.Left;
curMatch = pair.Left;
if(currentLen > minRight)
minRight = currentLen;
}
}
else
{
if(currentLen < _matchMaxLen)
{
*ptrLeft = curMatch;
ptrLeft = &pair.Left;
curMatch = pair.Left;
if(currentLen > minRight)
minRight = currentLen;
}
else
{
*ptrLeft = pair.Right;
*ptrRight = pair.Left;
#ifdef HASH_ARRAY_2
if (matchLen2Exist && len2Distance < distances[2])
distances[2] = len2Distance;
#ifdef HASH_ARRAY_3
if (matchLen3Exist && len3Distance < distances[3])
distances[3] = len3Distance;
#endif
#endif
return maxLen;
}
}
if(curMatch < matchMinPos)
#ifndef _HASH_CHAIN
*ptr0 = *ptr1 = kEmptyHashValue;
#endif
break;
}
*ptrLeft = kEmptyHashValue;
*ptrRight = kEmptyHashValue;
#ifdef HASH_ARRAY_2
if (matchLen2Exist)
{
if (maxLen < 2)
{
distances[2] = len2Distance;
maxLen = 2;
}
else if (len2Distance < distances[2])
distances[2] = len2Distance;
}
#ifdef HASH_ARRAY_3
if (matchLen3Exist)
{
if (maxLen < 3)
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CIndex *pair = son +
#ifdef _HASH_CHAIN
cyclicPos;
#else
(cyclicPos << 1);
#endif
// _mm_prefetch((const char *)pair, _MM_HINT_T0);
const Byte *pb = _buffer + curMatch;
UInt32 len =
#ifdef _HASH_CHAIN
kNumHashDirectBytes;
if (pb[maxLen] == cur[maxLen])
#else
MyMin(len0, len1);
#endif
if (pb[len] == cur[len])
{
distances[3] = len3Distance;
maxLen = 3;
while(++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
distances[offset++] = maxLen = len;
distances[offset++] = delta - 1;
if (len == lenLimit)
{
#ifndef _HASH_CHAIN
*ptr1 = pair[0];
*ptr0 = pair[1];
#endif
break;
}
}
}
else if (len3Distance < distances[3])
distances[3] = len3Distance;
#ifdef _HASH_CHAIN
curMatch = *pair;
#else
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
#endif
}
#endif
#endif
return maxLen;
distances[0] = offset - 1;
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
return S_OK;
}
void CInTree::DummyLongestMatch()
STDMETHODIMP CMatchFinder::Skip(UInt32 num)
{
do
{
#ifdef _HASH_CHAIN
if (_streamPos - _pos < kNumHashBytes)
{
RINOK(MovePos());
continue;
}
#else
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if(lenLimit < kNumHashBytes)
return;
if(lenLimit < kMinMatchCheck)
{
RINOK(MovePos());
continue;
}
}
UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1;
Byte *cur = _buffer + _pos;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
#endif
const Byte *cur = _buffer + _pos;
#ifdef HASH_ARRAY_2
UInt32 hash2Value;
#ifdef HASH_ARRAY_3
UInt32 hash3Value;
UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
_hash3[hash3Value] = _pos;
UInt32 hashValue;
HASH_CALC;
_hash[kHash3Offset + hash3Value] = _pos;
#else
UInt32 hashValue = Hash(cur, hash2Value);
UInt32 hashValue;
HASH_CALC;
#endif
_hash2[hash2Value] = _pos;
_hash[hash2Value] = _pos;
#else
UInt32 hashValue = Hash(cur);
#endif
UInt32 curMatch = _hash[hashValue];
_hash[hashValue] = _pos;
UInt32 curMatch = _hash[kFixHashSize + hashValue];
_hash[kFixHashSize + hashValue] = _pos;
CPair &pair = _son[_cyclicBufferPos];
#ifdef _HASH_CHAIN
_son[_cyclicBufferPos] = curMatch;
#else
CIndex *son = _son;
CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CIndex *ptr1 = son + (_cyclicBufferPos << 1);
if(curMatch < matchMinPos)
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
UInt32 count = _cutValue;
while(true)
{
pair.Left = kEmptyHashValue;
pair.Right = kEmptyHashValue;
return;
}
CIndex *ptrLeft = &pair.Right;
CIndex *ptrRight = &pair.Left;
UInt32 maxLen, minLeft, minRight;
maxLen = minLeft = minRight = kNumHashDirectBytes;
for(UInt32 count = _cutValue; count > 0; count--)
{
Byte *pby1 = _buffer + curMatch;
UInt32 currentLen = MyMin(minLeft, minRight);
for(; currentLen < lenLimit; currentLen++)
if (pby1[currentLen] != cur[currentLen])
break;
if(curMatch <= matchMinPos || count-- == 0)
{
*ptr0 = *ptr1 = kEmptyHashValue;
break;
}
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CPair &pair = _son[cyclicPos];
if (currentLen != lenLimit)
(_cyclicBufferPos - delta):
(_cyclicBufferPos - delta + _cyclicBufferSize);
CIndex *pair = son + (cyclicPos << 1);
// _mm_prefetch((const char *)pair, _MM_HINT_T0);
const Byte *pb = _buffer + curMatch;
UInt32 len = MyMin(len0, len1);
if (pb[len] == cur[len])
{
if (pby1[currentLen] < cur[currentLen])
while(++len != lenLimit)
if (pb[len] != cur[len])
break;
if (len == lenLimit)
{
*ptrRight = curMatch;
ptrRight = &pair.Right;
curMatch = pair.Right;
if(currentLen > minLeft)
minLeft = currentLen;
}
else
{
*ptrLeft = curMatch;
ptrLeft = &pair.Left;
curMatch = pair.Left;
if(currentLen > minRight)
minRight = currentLen;
*ptr1 = pair[0];
*ptr0 = pair[1];
break;
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
if(currentLen < _matchMaxLen)
{
*ptrLeft = curMatch;
ptrLeft = &pair.Left;
curMatch = pair.Left;
if(currentLen > minRight)
minRight = currentLen;
}
else
{
*ptrLeft = pair.Right;
*ptrRight = pair.Left;
return;
}
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
if(curMatch < matchMinPos)
break;
}
*ptrLeft = kEmptyHashValue;
*ptrRight = kEmptyHashValue;
#endif
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
}
while(--num != 0);
return S_OK;
}
void CInTree::NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue)
void CMatchFinder::Normalize()
{
UInt32 subValue = _pos - _cyclicBufferSize;
CIndex *items = _hash;
UInt32 numItems = (_hashSizeSum + _cyclicBufferSize
#ifndef _HASH_CHAIN
* 2
#endif
);
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 value = items[i];
@ -527,25 +493,39 @@ void CInTree::NormalizeLinks(CIndex *items, UInt32 numItems, UInt32 subValue)
value -= subValue;
items[i] = value;
}
}
void CInTree::Normalize()
{
UInt32 startItem = _pos - _historySize;
UInt32 subValue = startItem - 1;
// NormalizeLinks((CIndex *)(_son + startItem), _historySize * 2, subValue);
NormalizeLinks((CIndex *)_son, _cyclicBufferSize * 2, subValue);
NormalizeLinks(_hash, kHashSize, subValue);
#ifdef HASH_ARRAY_2
NormalizeLinks(_hash2, kHash2Size, subValue);
#ifdef HASH_ARRAY_3
NormalizeLinks(_hash3, kHash3Size, subValue);
#endif
#endif
ReduceOffsets(subValue);
}
HRESULT CMatchFinder::MovePos()
{
if (++_cyclicBufferPos == _cyclicBufferSize)
_cyclicBufferPos = 0;
RINOK(CLZInWindow::MovePos());
if (_pos == kMaxValForNormalize)
Normalize();
return S_OK;
}
STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)
{ return CLZInWindow::GetIndexByte(index); }
STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index,
UInt32 back, UInt32 limit)
{ return CLZInWindow::GetMatchLen(index, back, limit); }
STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()
{ return CLZInWindow::GetNumAvailableBytes(); }
STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()
{ return CLZInWindow::GetPointerToCurrentPos(); }
STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)
{ return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }
STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()
{ CLZInWindow::MoveBlock();}
#undef HASH_CALC
#undef kNumHashDirectBytes
}

View file

@ -3,61 +3,30 @@
#ifndef __IMATCHFINDER_H
#define __IMATCHFINDER_H
// {23170F69-40C1-278A-0000-000200010000}
DEFINE_GUID(IID_IInWindowStream,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000")
IInWindowStream: public IUnknown
struct IInWindowStream: public IUnknown
{
STDMETHOD(Init)(ISequentialInStream *inStream) PURE;
STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE;
STDMETHOD_(void, ReleaseStream)() PURE;
STDMETHOD(MovePos)() PURE;
STDMETHOD(Init)() PURE;
STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE;
STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE;
STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE;
STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE;
STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE;
STDMETHOD_(void, ChangeBufferPos)() PURE;
};
// {23170F69-40C1-278A-0000-000200020000}
DEFINE_GUID(IID_IMatchFinder,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000")
IMatchFinder: public IInWindowStream
struct IMatchFinder: public IInWindowStream
{
STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE;
STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE;
STDMETHOD_(void, DummyLongestMatch)() PURE;
STDMETHOD(GetMatches)(UInt32 *distances) PURE;
STDMETHOD(Skip)(UInt32 num) PURE;
};
// {23170F69-40C1-278A-0000-000200020100}
DEFINE_GUID(IID_IMatchFinderCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100")
IMatchFinderCallback: public IUnknown
struct IMatchFinderSetNumPasses
{
STDMETHOD(BeforeChangingBufferPos)() PURE;
STDMETHOD(AfterChangingBufferPos)() PURE;
virtual void SetNumPasses(UInt32 numPasses) PURE;
};
// {23170F69-40C1-278A-0000-000200020200}
DEFINE_GUID(IID_IMatchFinderSetCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200")
IMatchFinderSetCallback: public IUnknown
{
STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE;
};
/*
// {23170F69-40C1-278A-0000-000200030000}
DEFINE_GUID(IID_IInitMatchFinder,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000")
IMatchFinderInit: public IUnknown
{
STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE;
};
*/
#endif

View file

@ -16,22 +16,27 @@ bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 kee
{
_keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter;
_keepSizeReserv = keepSizeReserv;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == 0 || _blockSize != blockSize)
{
Free();
_blockSize = blockSize;
_bufferBase = (Byte *)::BigAlloc(_blockSize);
if (_blockSize != 0)
_bufferBase = (Byte *)::BigAlloc(_blockSize);
}
_pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter;
if (_blockSize == 0)
return true;
return (_bufferBase != 0);
}
HRESULT CLZInWindow::Init(ISequentialInStream *stream)
void CLZInWindow::SetStream(ISequentialInStream *stream)
{
_stream = stream;
}
HRESULT CLZInWindow::Init()
{
_buffer = _bufferBase;
_pos = 0;
_streamPos = 0;
@ -65,11 +70,11 @@ HRESULT CLZInWindow::ReadBlock()
return S_OK;
while(true)
{
UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos;
UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos;
if(size == 0)
return S_OK;
UInt32 numReadBytes;
RINOK(_stream->ReadPart(_buffer + _streamPos, size, &numReadBytes));
RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes));
if(numReadBytes == 0)
{
_posLimit = _streamPos;
@ -90,10 +95,11 @@ HRESULT CLZInWindow::ReadBlock()
void CLZInWindow::MoveBlock()
{
BeforeMoveBlock();
UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore;
UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset;
UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0)
offset--;
UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset;
memmove(_bufferBase, _bufferBase + offset, numBytes);
_buffer -= offset;
AfterMoveBlock();
}

View file

@ -9,7 +9,7 @@ class CLZInWindow
{
Byte *_bufferBase; // pointer to buffer with data
ISequentialInStream *_stream;
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
UInt32 _posLimit; // offset (from _buffer) when new block reading must be done
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
const Byte *_pointerToLastSafePosition;
protected:
@ -18,22 +18,20 @@ protected:
UInt32 _pos; // offset (from _buffer) of curent byte
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv
UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
virtual void BeforeMoveBlock() {};
virtual void AfterMoveBlock() {};
void MoveBlock();
virtual HRESULT ReadBlock();
HRESULT ReadBlock();
void Free();
public:
CLZInWindow(): _bufferBase(0) {}
virtual ~CLZInWindow() { Free(); }
bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter,
UInt32 keepSizeReserv = (1<<17));
// keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G)
bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17));
HRESULT Init(ISequentialInStream *stream);
void SetStream(ISequentialInStream *stream);
HRESULT Init();
// void ReleaseStream();
Byte *GetBuffer() const { return _buffer; }
@ -53,17 +51,17 @@ public:
else
return S_OK;
}
Byte GetIndexByte(Int32 index)const
{ return _buffer[(size_t)_pos + index]; }
Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; }
// index + limit have not to exceed _keepSizeAfter;
// -2G <= index < 2G
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const
{
if(_streamEndWasReached)
if ((_pos + index) + limit > _streamPos)
limit = _streamPos - (_pos + index);
distance++;
Byte *pby = _buffer + (size_t)_pos + index;
const Byte *pby = _buffer + (size_t)_pos + index;
UInt32 i;
for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);
return i;
@ -79,6 +77,11 @@ public:
_streamPos -= subValue;
}
bool NeedMove(UInt32 numCheckBytes)
{
UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos);
return (reserv <= numCheckBytes);
}
};
#endif

View file

@ -5,84 +5,13 @@
#include "../../../Common/Alloc.h"
#include "LZOutWindow.h"
bool CLZOutWindow::Create(UInt32 windowSize)
void CLZOutWindow::Init(bool solid)
{
_pos = 0;
_streamPos = 0;
const UInt32 kMinBlockSize = 1;
if (windowSize < kMinBlockSize)
windowSize = kMinBlockSize;
if (_buffer != 0 && _windowSize == windowSize)
return true;
Free();
_windowSize = windowSize;
_buffer = (Byte *)::BigAlloc(windowSize);
return (_buffer != 0);
}
void CLZOutWindow::Free()
{
::BigFree(_buffer);
_buffer = 0;
}
void CLZOutWindow::Init(ISequentialOutStream *stream, bool solid)
{
// ReleaseStream();
_stream = stream;
// _stream->AddRef();
if(!solid)
{
_streamPos = 0;
_pos = 0;
}
COutBuffer::Init();
#ifdef _NO_EXCEPTIONS
ErrorCode = S_OK;
#endif
}
/*
void CLZOutWindow::ReleaseStream()
{
if(_stream != 0)
{
// Flush(); // Test it
_stream->Release();
_stream = 0;
}
}
*/
void CLZOutWindow::FlushWithCheck()
{
HRESULT result = Flush();
#ifdef _NO_EXCEPTIONS
ErrorCode = result;
#else
if (result != S_OK)
throw CLZOutWindowException(result);
#endif
}
HRESULT CLZOutWindow::Flush()
{
UInt32 size = _pos - _streamPos;
if(size == 0)
return S_OK;
#ifdef _NO_EXCEPTIONS
if (ErrorCode != S_OK)
return ErrorCode;
#endif
UInt32 processedSize;
HRESULT result = _stream->Write(_buffer + _streamPos, size, &processedSize);
if (result != S_OK)
return result;
if (size != processedSize)
return E_FAIL;
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
return S_OK;
}

View file

@ -4,66 +4,51 @@
#define __LZ_OUT_WINDOW_H
#include "../../IStream.h"
#include "../../Common/OutBuffer.h"
#ifndef _NO_EXCEPTIONS
class CLZOutWindowException
{
public:
HRESULT ErrorCode;
CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {}
};
typedef COutBufferException CLZOutWindowException;
#endif
class CLZOutWindow
class CLZOutWindow: public COutBuffer
{
Byte *_buffer;
UInt32 _pos;
UInt32 _windowSize;
UInt32 _streamPos;
ISequentialOutStream *_stream;
void FlushWithCheck();
public:
#ifdef _NO_EXCEPTIONS
HRESULT ErrorCode;
#endif
void Free();
CLZOutWindow(): _buffer(0), _stream(0) {}
~CLZOutWindow() { Free(); /* ReleaseStream(); */ }
bool Create(UInt32 windowSize);
void Init(bool solid = false);
void Init(ISequentialOutStream *stream, bool solid = false);
HRESULT Flush();
// void ReleaseStream();
void CopyBlock(UInt32 distance, UInt32 len)
// distance >= 0, len > 0,
bool CopyBlock(UInt32 distance, UInt32 len)
{
UInt32 pos = _pos - distance - 1;
if (pos >= _windowSize)
pos += _windowSize;
for(; len > 0; len--)
if (distance >= _pos)
{
if (pos >= _windowSize)
if (!_overDict || distance >= _bufferSize)
return false;
pos += _bufferSize;
}
do
{
if (pos == _bufferSize)
pos = 0;
_buffer[_pos++] = _buffer[pos++];
if (_pos >= _windowSize)
if (_pos == _limitPos)
FlushWithCheck();
// PutOneByte(GetOneByte(distance));
}
while(--len != 0);
return true;
}
void PutByte(Byte b)
{
_buffer[_pos++] = b;
if (_pos >= _windowSize)
if (_pos == _limitPos)
FlushWithCheck();
}
Byte GetByte(UInt32 distance) const
{
UInt32 pos = _pos - distance - 1;
if (pos >= _windowSize)
pos += _windowSize;
if (pos >= _bufferSize)
pos += _bufferSize;
return _buffer[pos];
}
};

View file

@ -3,6 +3,4 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../../Platform.h"
#endif

View file

@ -24,6 +24,7 @@ public:
void UpdateMatch() { Index = kMatchNextStates[Index]; }
void UpdateRep() { Index = kRepNextStates[Index]; }
void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
bool IsCharState() const { return Index < 7; }
};
const int kNumPosSlotBits = 6;

File diff suppressed because it is too large Load diff

View file

@ -21,13 +21,11 @@ class CBaseState
protected:
CState _state;
Byte _previousByte;
bool _peviousIsMatch;
UInt32 _repDistances[kNumRepDistances];
void Init()
{
_state.Init();
_previousByte = 0;
_peviousIsMatch = false;
for(UInt32 i = 0 ; i < kNumRepDistances; i++)
_repDistances[i] = 0;
}
@ -53,23 +51,23 @@ struct COptimal
};
extern Byte g_FastPos[1024];
extern Byte g_FastPos[1 << 11];
inline UInt32 GetPosSlot(UInt32 pos)
{
if (pos < (1 << 10))
if (pos < (1 << 11))
return g_FastPos[pos];
if (pos < (1 << 19))
return g_FastPos[pos >> 9] + 18;
return g_FastPos[pos >> 18] + 36;
if (pos < (1 << 21))
return g_FastPos[pos >> 10] + 20;
return g_FastPos[pos >> 20] + 40;
}
inline UInt32 GetPosSlot2(UInt32 pos)
{
if (pos < (1 << 16))
if (pos < (1 << 17))
return g_FastPos[pos >> 6] + 12;
if (pos < (1 << 25))
return g_FastPos[pos >> 15] + 30;
return g_FastPos[pos >> 24] + 48;
if (pos < (1 << 27))
return g_FastPos[pos >> 16] + 32;
return g_FastPos[pos >> 26] + 52;
}
const UInt32 kIfinityPrice = 0xFFFFFFF;
@ -107,8 +105,7 @@ public:
}
bool Create(int numPosBits, int numPrevBits)
{
if (_coders == 0 || (numPosBits + numPrevBits) !=
(_numPrevBits + _numPosBits) )
if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))
{
Free();
UInt32 numStates = 1 << (numPosBits + numPrevBits);
@ -125,21 +122,8 @@ public:
for (UInt32 i = 0; i < numStates; i++)
_coders[i].Init();
}
UInt32 GetState(UInt32 pos, Byte prevByte) const
{ return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
{ return &_coders[GetState(pos, prevByte)]; }
/*
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
Byte symbol)
{ _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); }
void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
Byte matchByte, Byte symbol)
{ _coders[GetState(pos, prevByte)].Encode(rangeEncoder,
matchByte, symbol); }
*/
UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const
{ return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); }
{ return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }
};
namespace NLength {
@ -147,31 +131,29 @@ namespace NLength {
class CEncoder
{
CMyBitEncoder _choice;
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
CMyBitEncoder _choice2;
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
CMyBitEncoder _choice2;
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
public:
void Init(UInt32 numPosStates);
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const;
void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;
};
const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
class CPriceTableEncoder: public CEncoder
{
UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax];
UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];
UInt32 _tableSize;
UInt32 _counters[kNumPosStatesEncodingMax];
public:
void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const
{ return _prices[symbol][posState]; }
UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }
void UpdateTable(UInt32 posState)
{
for (UInt32 len = 0; len < _tableSize; len++)
_prices[len][posState] = CEncoder::GetPrice(len, posState);
SetPrices(posState, _tableSize, _prices[posState]);
_counters[posState] = _tableSize;
}
void UpdateTables(UInt32 numPosStates)
@ -179,20 +161,20 @@ public:
for (UInt32 posState = 0; posState < numPosStates; posState++)
UpdateTable(posState);
}
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)
{
CEncoder::Encode(rangeEncoder, symbol, posState);
if (--_counters[posState] == 0)
UpdateTable(posState);
if (updatePrice)
if (--_counters[posState] == 0)
UpdateTable(posState);
}
};
}
class CEncoder :
public ICompressCoder,
// public IInitMatchFinder,
public ICompressSetOutStream,
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
public CBaseState,
@ -201,8 +183,6 @@ class CEncoder :
COptimal _optimum[kNumOpts];
CMyComPtr<IMatchFinder> _matchFinder; // test it
NRangeCoder::CEncoder _rangeEncoder;
public:
private:
CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
CMyBitEncoder _isRep[kNumStates];
@ -221,12 +201,13 @@ private:
CLiteralEncoder _literalEncoder;
UInt32 _matchDistances[kMatchMaxLen + 1];
UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];
bool _fastMode;
bool _maxMode;
// bool _maxMode;
UInt32 _numFastBytes;
UInt32 _longestMatchLength;
UInt32 _numDistancePairs;
UInt32 _additionalOffset;
@ -254,11 +235,12 @@ private:
UInt32 _dictionarySizePrev;
UInt32 _numFastBytesPrev;
UInt64 lastPosSlotFillingPos;
UInt32 _matchPriceCount;
UInt64 nowPos64;
bool _finished;
ISequentialInStream *_inStream;
UInt32 _matchFinderCycles;
int _matchFinderIndex;
#ifdef COMPRESS_MF_MT
bool _multiThread;
@ -267,36 +249,50 @@ private:
bool _writeEndMark;
bool _needReleaseMFStream;
IMatchFinderSetNumPasses *setMfPasses;
void ReleaseMatchFinder()
{
setMfPasses = 0;
_matchFinder.Release();
}
HRESULT ReadMatchDistances(UInt32 &len);
HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);
HRESULT MovePos(UInt32 num);
UInt32 GetRepLen1Price(CState state, UInt32 posState) const
{
return _isRepG0[state.Index].GetPrice(0) +
_isRep0Long[state.Index][posState].GetPrice(0);
return _isRepG0[state.Index].GetPrice0() +
_isRep0Long[state.Index][posState].GetPrice0();
}
UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const
{
UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState);
UInt32 price;
if(repIndex == 0)
{
price += _isRepG0[state.Index].GetPrice(0);
price += _isRep0Long[state.Index][posState].GetPrice(1);
price = _isRepG0[state.Index].GetPrice0();
price += _isRep0Long[state.Index][posState].GetPrice1();
}
else
{
price += _isRepG0[state.Index].GetPrice(1);
price = _isRepG0[state.Index].GetPrice1();
if (repIndex == 1)
price += _isRepG1[state.Index].GetPrice(0);
price += _isRepG1[state.Index].GetPrice0();
else
{
price += _isRepG1[state.Index].GetPrice(1);
price += _isRepG1[state.Index].GetPrice1();
price += _isRepG2[state.Index].GetPrice(repIndex - 2);
}
}
return price;
}
UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
{
return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +
GetPureRepPrice(repIndex, state, posState);
}
/*
UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
{
@ -318,8 +314,6 @@ private:
*/
UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
{
if (len == 2 && pos >= 0x80)
return kIfinityPrice;
UInt32 price;
UInt32 lenToPosState = GetLenToPosState(len);
if (pos < kNumFullDistances)
@ -334,21 +328,25 @@ private:
HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
void FillPosSlotPrices();
void FillDistancesPrices();
void FillAlignPrices();
void ReleaseStreams()
void ReleaseMFStream()
{
if (_matchFinder && _needReleaseMFStream)
{
_matchFinder->ReleaseStream();
_needReleaseMFStream = false;
}
// _rangeEncoder.ReleaseStream();
}
HRESULT Flush();
void ReleaseStreams()
{
ReleaseMFStream();
ReleaseOutStream();
}
HRESULT Flush(UInt32 nowPos);
class CCoderReleaser
{
CEncoder *_coder;
@ -370,13 +368,13 @@ public:
HRESULT Create();
MY_UNKNOWN_IMP2(
MY_UNKNOWN_IMP3(
ICompressSetOutStream,
ICompressSetCoderProperties,
ICompressWriteCoderProperties
)
STDMETHOD(Init)(
ISequentialOutStream *outStream);
HRESULT Init();
// ICompressCoder interface
HRESULT SetStreams(ISequentialInStream *inStream,
@ -395,9 +393,6 @@ public:
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
// IInitMatchFinder interface
STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder);
// ICompressSetCoderProperties2
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
@ -405,6 +400,9 @@ public:
// ICompressWriteCoderProperties
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
STDMETHOD(ReleaseOutStream)();
virtual ~CEncoder() {}
};

View file

@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../../Platform.h"
#include "../../../Common/MyWindows.h"
#endif
#endif

View file

@ -14,20 +14,21 @@ const UInt32 kTopValue = (1 << kNumTopBits);
class CEncoder
{
UInt64 Low;
UInt32 Range;
UInt32 _ffNum;
UInt32 _cacheSize;
Byte _cache;
public:
UInt64 Low;
UInt32 Range;
COutBuffer Stream;
bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
void Init(ISequentialOutStream *stream)
void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
void Init()
{
Stream.Init(stream);
Stream.Init();
Low = 0;
Range = 0xFFFFFFFF;
_ffNum = 0;
_cacheSize = 1;
_cache = 0;
}
@ -40,10 +41,7 @@ public:
HRESULT FlushStream() { return Stream.Flush(); }
/*
void ReleaseStream()
{ Stream.ReleaseStream(); }
*/
void ReleaseStream() { Stream.ReleaseStream(); }
void Encode(UInt32 start, UInt32 size, UInt32 total)
{
@ -56,36 +54,21 @@ public:
}
}
/*
void EncodeDirectBitsDiv(UInt32 value, UInt32 numTotalBits)
{
Low += value * (Range >>= numTotalBits);
Normalize();
}
void EncodeDirectBitsDiv2(UInt32 value, UInt32 numTotalBits)
{
if (numTotalBits <= kNumBottomBits)
EncodeDirectBitsDiv(value, numTotalBits);
else
{
EncodeDirectBitsDiv(value >> kNumBottomBits, (numTotalBits - kNumBottomBits));
EncodeDirectBitsDiv(value & ((1 << kBottomValueBits) - 1), kNumBottomBits);
}
}
*/
void ShiftLow()
{
if (Low < (UInt32)0xFF000000 || UInt32(Low >> 32) == 1)
if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
{
Stream.WriteByte(Byte(_cache + Byte(Low >> 32)));
for (;_ffNum != 0; _ffNum--)
Stream.WriteByte(Byte(0xFF + Byte(Low >> 32)));
_cache = Byte(UInt32(Low) >> 24);
Byte temp = _cache;
do
{
Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
temp = 0xFF;
}
while(--_cacheSize != 0);
_cache = (Byte)((UInt32)Low >> 24);
}
else
_ffNum++;
Low = UInt32(Low) << 8;
_cacheSize++;
Low = (UInt32)Low << 8;
}
void EncodeDirectBits(UInt32 value, int numTotalBits)
@ -120,7 +103,7 @@ public:
}
}
UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _ffNum; }
UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
};
class CDecoder
@ -140,16 +123,17 @@ public:
}
}
void Init(ISequentialInStream *stream)
void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
void Init()
{
Stream.Init(stream);
Stream.Init();
Code = 0;
Range = 0xFFFFFFFF;
for(int i = 0; i < 5; i++)
Code = (Code << 8) | Stream.ReadByte();
}
// void ReleaseStream() { Stream.ReleaseStream(); }
void ReleaseStream() { Stream.ReleaseStream(); }
UInt32 GetThreshold(UInt32 total)
{
@ -163,32 +147,12 @@ public:
Normalize();
}
/*
UInt32 DecodeDirectBitsDiv(UInt32 numTotalBits)
{
Range >>= numTotalBits;
UInt32 threshold = Code / Range;
Code -= threshold * Range;
Normalize();
return threshold;
}
UInt32 DecodeDirectBitsDiv2(UInt32 numTotalBits)
{
if (numTotalBits <= kNumBottomBits)
return DecodeDirectBitsDiv(numTotalBits);
UInt32 result = DecodeDirectBitsDiv(numTotalBits - kNumBottomBits) << kNumBottomBits;
return (result | DecodeDirectBitsDiv(kNumBottomBits));
}
*/
UInt32 DecodeDirectBits(UInt32 numTotalBits)
UInt32 DecodeDirectBits(int numTotalBits)
{
UInt32 range = Range;
UInt32 code = Code;
UInt32 result = 0;
for (UInt32 i = numTotalBits; i > 0; i--)
for (int i = numTotalBits; i != 0; i--)
{
range >>= 1;
/*
@ -201,7 +165,6 @@ public:
*/
UInt32 t = (code - range) >> 31;
code -= range & (t - 1);
// range = rangeTmp + ((range & 1) & (1 - t));
result = (result << 1) | (1 - t);
if (range < kTopValue)

View file

@ -50,9 +50,10 @@ class CBitEncoder: public CBitModel<numMoveBits>
public:
void Encode(CEncoder *encoder, UInt32 symbol)
{
/*
encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
this->UpdateModel(symbol);
/*
*/
UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
if (symbol == 0)
{
@ -65,18 +66,19 @@ public:
encoder->Range -= newBound;
this->Prob -= (this->Prob) >> numMoveBits;
}
while (encoder->Range < kTopValue)
if (encoder->Range < kTopValue)
{
encoder->Range <<= 8;
encoder->ShiftLow();
}
*/
}
UInt32 GetPrice(UInt32 symbol) const
{
return CPriceTables::ProbPrices[
(((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
}
UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }
UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }
};

View file

@ -9,7 +9,7 @@
namespace NCompress {
namespace NRangeCoder {
template <int numMoveBits, UInt32 NumBitLevels>
template <int numMoveBits, int NumBitLevels>
class CBitTreeEncoder
{
CBitEncoder<numMoveBits> Models[1 << NumBitLevels];
@ -22,7 +22,7 @@ public:
void Encode(CEncoder *rangeEncoder, UInt32 symbol)
{
UInt32 modelIndex = 1;
for (UInt32 bitIndex = NumBitLevels; bitIndex > 0 ;)
for (int bitIndex = NumBitLevels; bitIndex != 0 ;)
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
@ -33,7 +33,7 @@ public:
void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol)
{
UInt32 modelIndex = 1;
for (UInt32 i = 0; i < NumBitLevels; i++)
for (int i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[modelIndex].Encode(rangeEncoder, bit);
@ -43,14 +43,12 @@ public:
}
UInt32 GetPrice(UInt32 symbol) const
{
symbol |= (1 << NumBitLevels);
UInt32 price = 0;
UInt32 modelIndex = 1;
for (UInt32 bitIndex = NumBitLevels; bitIndex > 0 ;)
while (symbol != 1)
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
price += Models[modelIndex].GetPrice(bit);
modelIndex = (modelIndex << 1) + bit;
price += Models[symbol >> 1].GetPrice(symbol & 1);
symbol >>= 1;
}
return price;
}
@ -58,7 +56,7 @@ public:
{
UInt32 price = 0;
UInt32 modelIndex = 1;
for (UInt32 i = NumBitLevels; i > 0; i--)
for (int i = NumBitLevels; i != 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
@ -69,7 +67,7 @@ public:
}
};
template <int numMoveBits, UInt32 NumBitLevels>
template <int numMoveBits, int NumBitLevels>
class CBitTreeDecoder
{
CBitDecoder<numMoveBits> Models[1 << NumBitLevels];
@ -83,7 +81,7 @@ public:
{
UInt32 modelIndex = 1;
RC_INIT_VAR
for(UInt32 bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)
{
// modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder);
RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex)
@ -96,7 +94,7 @@ public:
UInt32 modelIndex = 1;
UInt32 symbol = 0;
RC_INIT_VAR
for(UInt32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
// UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
// modelIndex <<= 1;
@ -111,10 +109,10 @@ public:
template <int numMoveBits>
void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models,
CEncoder *rangeEncoder, UInt32 NumBitLevels, UInt32 symbol)
CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol)
{
UInt32 modelIndex = 1;
for (UInt32 i = 0; i < NumBitLevels; i++)
for (int i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[modelIndex].Encode(rangeEncoder, bit);
@ -129,7 +127,7 @@ UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models,
{
UInt32 price = 0;
UInt32 modelIndex = 1;
for (UInt32 i = NumBitLevels; i > 0; i--)
for (int i = NumBitLevels; i != 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
@ -141,12 +139,12 @@ UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models,
template <int numMoveBits>
UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models,
CDecoder *rangeDecoder, UInt32 NumBitLevels)
CDecoder *rangeDecoder, int NumBitLevels)
{
UInt32 modelIndex = 1;
UInt32 symbol = 0;
RC_INIT_VAR
for(UInt32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
// UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
// modelIndex <<= 1;

View file

@ -3,6 +3,4 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../../Platform.h"
#endif
#endif