Run dos2unix on bayou and remove white space at the end of lines.
[coreboot.git] / payloads / bayou / util / pbuilder / lzma / C / 7zip / Compress / LZ / BinTree / BinTreeMain.h
index 61d11210432357ae71e1aa46d308a720a1a4b517..d47a03de900a99eafa9025e32ee1e31e09edddf1 100644 (file)
-// BinTreeMain.h\r
-\r
-#include "../../../../Common/Defs.h"\r
-#include "../../../../Common/CRC.h"\r
-#include "../../../../Common/Alloc.h"\r
-\r
-#include "BinTree.h"\r
-\r
-// #include <xmmintrin.h>\r
-// It's for prefetch\r
-// But prefetch doesn't give big gain in K8.\r
-\r
-namespace BT_NAMESPACE {\r
-\r
-#ifdef HASH_ARRAY_2\r
-  static const UInt32 kHash2Size = 1 << 10;\r
-  #define kNumHashDirectBytes 0\r
-  #ifdef HASH_ARRAY_3\r
-    static const UInt32 kNumHashBytes = 4;\r
-    static const UInt32 kHash3Size = 1 << 16;\r
-  #else\r
-    static const UInt32 kNumHashBytes = 3;\r
-  #endif\r
-  static const UInt32 kHashSize = 0;\r
-  static const UInt32 kMinMatchCheck = kNumHashBytes;\r
-  static const UInt32 kStartMaxLen = 1;\r
-#else\r
-  #ifdef HASH_ZIP \r
-    #define kNumHashDirectBytes 0\r
-    static const UInt32 kNumHashBytes = 3;\r
-    static const UInt32 kHashSize = 1 << 16;\r
-    static const UInt32 kMinMatchCheck = kNumHashBytes;\r
-    static const UInt32 kStartMaxLen = 1;\r
-  #else\r
-    #define kNumHashDirectBytes 2\r
-    static const UInt32 kNumHashBytes = 2;\r
-    static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);\r
-    static const UInt32 kMinMatchCheck = kNumHashBytes + 1;\r
-    static const UInt32 kStartMaxLen = 1;\r
-  #endif\r
-#endif\r
-\r
-#ifdef HASH_ARRAY_2\r
-#ifdef HASH_ARRAY_3\r
-static const UInt32 kHash3Offset = kHash2Size;\r
-#endif\r
-#endif\r
-\r
-static const UInt32 kFixHashSize = 0\r
-    #ifdef HASH_ARRAY_2\r
-    + kHash2Size\r
-    #ifdef HASH_ARRAY_3\r
-    + kHash3Size\r
-    #endif\r
-    #endif\r
-    ;\r
-\r
-CMatchFinder::CMatchFinder():\r
-  _hash(0)\r
-{\r
-}\r
-\r
-void CMatchFinder::FreeThisClassMemory()\r
-{\r
-  BigFree(_hash);\r
-  _hash = 0;\r
-}\r
-\r
-void CMatchFinder::FreeMemory()\r
-{\r
-  FreeThisClassMemory();\r
-  CLZInWindow::Free();\r
-}\r
-\r
-CMatchFinder::~CMatchFinder()\r
-{ \r
-  FreeMemory();\r
-}\r
-\r
-STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, \r
-    UInt32 matchMaxLen, UInt32 keepAddBufferAfter)\r
-{\r
-  if (historySize > kMaxValForNormalize - 256)\r
-  {\r
-    FreeMemory();\r
-    return E_INVALIDARG;\r
-  }\r
-  _cutValue = \r
-  #ifdef _HASH_CHAIN\r
-    8 + (matchMaxLen >> 2);\r
-  #else\r
-    16 + (matchMaxLen >> 1);\r
-  #endif\r
-  UInt32 sizeReserv = (historySize + keepAddBufferBefore + \r
-      matchMaxLen + keepAddBufferAfter) / 2 + 256;\r
-  if (CLZInWindow::Create(historySize + keepAddBufferBefore, \r
-      matchMaxLen + keepAddBufferAfter, sizeReserv))\r
-  {\r
-    _matchMaxLen = matchMaxLen;\r
-    UInt32 newCyclicBufferSize = historySize + 1;\r
-    if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)\r
-      return S_OK;\r
-    FreeThisClassMemory();\r
-    _cyclicBufferSize = newCyclicBufferSize; // don't change it\r
-\r
-    UInt32 hs = kHashSize;\r
-\r
-    #ifdef HASH_ARRAY_2\r
-    hs = historySize - 1;\r
-    hs |= (hs >> 1);\r
-    hs |= (hs >> 2);\r
-    hs |= (hs >> 4);\r
-    hs |= (hs >> 8);\r
-    hs >>= 1;\r
-    hs |= 0xFFFF;\r
-    if (hs > (1 << 24))\r
-    {\r
-      #ifdef HASH_ARRAY_3\r
-      hs >>= 1;\r
-      #else\r
-      hs = (1 << 24) - 1;\r
-      #endif\r
-    }\r
-    _hashMask = hs;\r
-    hs++;\r
-    #endif\r
-    _hashSizeSum = hs + kFixHashSize;\r
-    UInt32 numItems = _hashSizeSum + _cyclicBufferSize\r
-    #ifndef _HASH_CHAIN\r
-     * 2\r
-    #endif\r
-    ;\r
-    size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);\r
-    if (sizeInBytes / sizeof(CIndex) != numItems)\r
-      return E_OUTOFMEMORY;\r
-    _hash = (CIndex *)BigAlloc(sizeInBytes);\r
-    _son = _hash + _hashSizeSum;\r
-    if (_hash != 0)\r
-      return S_OK;\r
-  }\r
-  FreeMemory();\r
-  return E_OUTOFMEMORY;\r
-}\r
-\r
-static const UInt32 kEmptyHashValue = 0;\r
-\r
-STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)\r
-{\r
-  CLZInWindow::SetStream(stream);\r
-  return S_OK;\r
-}\r
-\r
-STDMETHODIMP CMatchFinder::Init()\r
-{\r
-  RINOK(CLZInWindow::Init());\r
-  for(UInt32 i = 0; i < _hashSizeSum; i++)\r
-    _hash[i] = kEmptyHashValue;\r
-  _cyclicBufferPos = 0;\r
-  ReduceOffsets(-1);\r
-  return S_OK;\r
-}\r
-\r
-STDMETHODIMP_(void) CMatchFinder::ReleaseStream()\r
-{ \r
-  // ReleaseStream(); \r
-}\r
-\r
-#ifdef HASH_ARRAY_2\r
-#ifdef HASH_ARRAY_3\r
-\r
-#define HASH_CALC { \\r
-  UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \\r
-  hash2Value = temp & (kHash2Size - 1); \\r
-  hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \\r
-  hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }\r
-  \r
-#else // no HASH_ARRAY_3\r
-#define HASH_CALC { \\r
-  UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \\r
-  hash2Value = temp & (kHash2Size - 1); \\r
-  hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }\r
-#endif // HASH_ARRAY_3\r
-#else // no HASH_ARRAY_2\r
-#ifdef HASH_ZIP \r
-inline UInt32 Hash(const Byte *pointer)\r
-{\r
-  return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);\r
-}\r
-#else // no HASH_ZIP \r
-inline UInt32 Hash(const Byte *pointer)\r
-{\r
-  return pointer[0] ^ (UInt32(pointer[1]) << 8);\r
-}\r
-#endif // HASH_ZIP\r
-#endif // HASH_ARRAY_2\r
-\r
-STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)\r
-{\r
-  UInt32 lenLimit;\r
-  if (_pos + _matchMaxLen <= _streamPos)\r
-    lenLimit = _matchMaxLen;\r
-  else\r
-  {\r
-    lenLimit = _streamPos - _pos;\r
-    if(lenLimit < kMinMatchCheck)\r
-    {\r
-      distances[0] = 0;\r
-      return MovePos(); \r
-    }\r
-  }\r
-\r
-  int offset = 1;\r
-\r
-  UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\r
-  const Byte *cur = _buffer + _pos;\r
-\r
-  UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;\r
-\r
-  #ifdef HASH_ARRAY_2\r
-  UInt32 hash2Value;\r
-  #ifdef HASH_ARRAY_3\r
-  UInt32 hash3Value;\r
-  #endif\r
-  UInt32 hashValue;\r
-  HASH_CALC;\r
-  #else\r
-  UInt32 hashValue = Hash(cur);\r
-  #endif\r
-\r
-  UInt32 curMatch = _hash[kFixHashSize + hashValue];\r
-  #ifdef HASH_ARRAY_2\r
-  UInt32 curMatch2 = _hash[hash2Value];\r
-  #ifdef HASH_ARRAY_3\r
-  UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];\r
-  #endif\r
-  _hash[hash2Value] = _pos;\r
-  if(curMatch2 > matchMinPos)\r
-    if (_buffer[curMatch2] == cur[0])\r
-    {\r
-      distances[offset++] = maxLen = 2;\r
-      distances[offset++] = _pos - curMatch2 - 1;\r
-    }\r
-\r
-  #ifdef HASH_ARRAY_3\r
-  _hash[kHash3Offset + hash3Value] = _pos;\r
-  if(curMatch3 > matchMinPos)\r
-    if (_buffer[curMatch3] == cur[0])\r
-    {\r
-      if (curMatch3 == curMatch2)\r
-        offset -= 2;\r
-      distances[offset++] = maxLen = 3;\r
-      distances[offset++] = _pos - curMatch3 - 1;\r
-      curMatch2 = curMatch3;\r
-    }\r
-  #endif\r
-  if (offset != 1 && curMatch2 == curMatch)\r
-  {\r
-    offset -= 2;\r
-    maxLen = kStartMaxLen;\r
-  }\r
-  #endif\r
-\r
-  _hash[kFixHashSize + hashValue] = _pos;\r
-\r
-  CIndex *son = _son;\r
-\r
-  #ifdef _HASH_CHAIN\r
-  son[_cyclicBufferPos] = curMatch;\r
-  #else\r
-  CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
-  CIndex *ptr1 = son + (_cyclicBufferPos << 1);\r
-\r
-  UInt32 len0, len1;\r
-  len0 = len1 = kNumHashDirectBytes;\r
-  #endif\r
-\r
-  #if kNumHashDirectBytes != 0\r
-  if(curMatch > matchMinPos)\r
-  {\r
-    if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])\r
-    {\r
-      distances[offset++] = maxLen = kNumHashDirectBytes;\r
-      distances[offset++] = _pos - curMatch - 1;\r
-    }\r
-  }\r
-  #endif\r
-  UInt32 count = _cutValue;\r
-  while(true)\r
-  {\r
-    if(curMatch <= matchMinPos || count-- == 0)\r
-    {\r
-      #ifndef _HASH_CHAIN\r
-      *ptr0 = *ptr1 = kEmptyHashValue;\r
-      #endif\r
-      break;\r
-    }\r
-    UInt32 delta = _pos - curMatch;\r
-    UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?\r
-        (_cyclicBufferPos - delta):\r
-        (_cyclicBufferPos - delta + _cyclicBufferSize);\r
-    CIndex *pair = son + \r
-    #ifdef _HASH_CHAIN\r
-      cyclicPos;\r
-    #else\r
-      (cyclicPos << 1);\r
-    #endif\r
-    \r
-    // _mm_prefetch((const char *)pair, _MM_HINT_T0);\r
-    \r
-    const Byte *pb = _buffer + curMatch;\r
-    UInt32 len = \r
-    #ifdef _HASH_CHAIN\r
-    kNumHashDirectBytes;\r
-    if (pb[maxLen] == cur[maxLen])\r
-    #else\r
-    MyMin(len0, len1);\r
-    #endif\r
-    if (pb[len] == cur[len])\r
-    {\r
-      while(++len != lenLimit)\r
-        if (pb[len] != cur[len])\r
-          break;\r
-      if (maxLen < len)\r
-      {\r
-        distances[offset++] = maxLen = len;\r
-        distances[offset++] = delta - 1;\r
-        if (len == lenLimit)\r
-        {\r
-          #ifndef _HASH_CHAIN\r
-          *ptr1 = pair[0];\r
-          *ptr0 = pair[1];\r
-          #endif\r
-          break;\r
-        }\r
-      }\r
-    }\r
-    #ifdef _HASH_CHAIN\r
-    curMatch = *pair;\r
-    #else\r
-    if (pb[len] < cur[len])\r
-    {\r
-      *ptr1 = curMatch;\r
-      ptr1 = pair + 1;\r
-      curMatch = *ptr1;\r
-      len1 = len;\r
-    }\r
-    else\r
-    {\r
-      *ptr0 = curMatch;\r
-      ptr0 = pair;\r
-      curMatch = *ptr0;\r
-      len0 = len;\r
-    }\r
-    #endif\r
-  }\r
-  distances[0] = offset - 1;\r
-  if (++_cyclicBufferPos == _cyclicBufferSize)\r
-    _cyclicBufferPos = 0;\r
-  RINOK(CLZInWindow::MovePos());\r
-  if (_pos == kMaxValForNormalize)\r
-    Normalize();\r
-  return S_OK;\r
-}\r
-\r
-STDMETHODIMP CMatchFinder::Skip(UInt32 num)\r
-{\r
-  do\r
-  {\r
-  #ifdef _HASH_CHAIN\r
-  if (_streamPos - _pos < kNumHashBytes)\r
-  {\r
-    RINOK(MovePos()); \r
-    continue;\r
-  }\r
-  #else\r
-  UInt32 lenLimit;\r
-  if (_pos + _matchMaxLen <= _streamPos)\r
-    lenLimit = _matchMaxLen;\r
-  else\r
-  {\r
-    lenLimit = _streamPos - _pos;\r
-    if(lenLimit < kMinMatchCheck)\r
-    {\r
-      RINOK(MovePos());\r
-      continue;\r
-    }\r
-  }\r
-  UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\r
-  #endif\r
-  const Byte *cur = _buffer + _pos;\r
-\r
-  #ifdef HASH_ARRAY_2\r
-  UInt32 hash2Value;\r
-  #ifdef HASH_ARRAY_3\r
-  UInt32 hash3Value;\r
-  UInt32 hashValue;\r
-  HASH_CALC;\r
-  _hash[kHash3Offset + hash3Value] = _pos;\r
-  #else\r
-  UInt32 hashValue;\r
-  HASH_CALC;\r
-  #endif\r
-  _hash[hash2Value] = _pos;\r
-  #else\r
-  UInt32 hashValue = Hash(cur);\r
-  #endif\r
-\r
-  UInt32 curMatch = _hash[kFixHashSize + hashValue];\r
-  _hash[kFixHashSize + hashValue] = _pos;\r
-\r
-  #ifdef _HASH_CHAIN\r
-  _son[_cyclicBufferPos] = curMatch;\r
-  #else\r
-  CIndex *son = _son;\r
-  CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;\r
-  CIndex *ptr1 = son + (_cyclicBufferPos << 1);\r
-\r
-  UInt32 len0, len1;\r
-  len0 = len1 = kNumHashDirectBytes;\r
-  UInt32 count = _cutValue;\r
-  while(true)\r
-  {\r
-    if(curMatch <= matchMinPos || count-- == 0)\r
-    {\r
-      *ptr0 = *ptr1 = kEmptyHashValue;\r
-      break;\r
-    }\r
-    \r
-    UInt32 delta = _pos - curMatch;\r
-    UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?\r
-      (_cyclicBufferPos - delta):\r
-      (_cyclicBufferPos - delta + _cyclicBufferSize);\r
-    CIndex *pair = son + (cyclicPos << 1);\r
-    \r
-    // _mm_prefetch((const char *)pair, _MM_HINT_T0);\r
-    \r
-    const Byte *pb = _buffer + curMatch;\r
-    UInt32 len = MyMin(len0, len1);\r
-    \r
-    if (pb[len] == cur[len])\r
-    {\r
-      while(++len != lenLimit)\r
-        if (pb[len] != cur[len])\r
-          break;\r
-      if (len == lenLimit)\r
-      {\r
-        *ptr1 = pair[0];\r
-        *ptr0 = pair[1];\r
-        break;\r
-      }\r
-    }\r
-    if (pb[len] < cur[len])\r
-    {\r
-      *ptr1 = curMatch;\r
-      ptr1 = pair + 1;\r
-      curMatch = *ptr1;\r
-      len1 = len;\r
-    }\r
-    else\r
-    {\r
-      *ptr0 = curMatch;\r
-      ptr0 = pair;\r
-      curMatch = *ptr0;\r
-      len0 = len;\r
-    }\r
-  }\r
-  #endif\r
-  if (++_cyclicBufferPos == _cyclicBufferSize)\r
-    _cyclicBufferPos = 0;\r
-  RINOK(CLZInWindow::MovePos());\r
-  if (_pos == kMaxValForNormalize)\r
-    Normalize();\r
-  }\r
-  while(--num != 0);\r
-  return S_OK;\r
-}\r
-\r
-void CMatchFinder::Normalize()\r
-{\r
-  UInt32 subValue = _pos - _cyclicBufferSize;\r
-  CIndex *items = _hash;\r
-  UInt32 numItems = (_hashSizeSum + _cyclicBufferSize \r
-    #ifndef _HASH_CHAIN\r
-     * 2\r
-    #endif\r
-    );\r
-  for (UInt32 i = 0; i < numItems; i++)\r
-  {\r
-    UInt32 value = items[i];\r
-    if (value <= subValue)\r
-      value = kEmptyHashValue;\r
-    else\r
-      value -= subValue;\r
-    items[i] = value;\r
-  }\r
-  ReduceOffsets(subValue);\r
-}\r
-\r
-HRESULT CMatchFinder::MovePos()\r
-{\r
-  if (++_cyclicBufferPos == _cyclicBufferSize)\r
-    _cyclicBufferPos = 0;\r
-  RINOK(CLZInWindow::MovePos());\r
-  if (_pos == kMaxValForNormalize)\r
-    Normalize();\r
-  return S_OK;\r
-}\r
-\r
-STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)\r
-  { return CLZInWindow::GetIndexByte(index); }\r
-\r
-STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, \r
-    UInt32 back, UInt32 limit)\r
-  { return CLZInWindow::GetMatchLen(index, back, limit); }\r
-\r
-STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()\r
-  { return CLZInWindow::GetNumAvailableBytes(); }\r
-\r
-STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()\r
-  { return CLZInWindow::GetPointerToCurrentPos(); }\r
-\r
-STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)\r
-  { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }\r
-\r
-STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()\r
-  { CLZInWindow::MoveBlock();}\r
-\r
-#undef HASH_CALC\r
-#undef kNumHashDirectBytes\r
\r
-}\r
+// BinTreeMain.h
+
+#include "../../../../Common/Defs.h"
+#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 kNumHashBytes = 4;
+    static const UInt32 kHash3Size = 1 << 16;
+  #else
+    static const UInt32 kNumHashBytes = 3;
+  #endif
+  static const UInt32 kHashSize = 0;
+  static const UInt32 kMinMatchCheck = kNumHashBytes;
+  static const UInt32 kStartMaxLen = 1;
+#else
+  #ifdef HASH_ZIP
+    #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
+    #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
+
+static const UInt32 kFixHashSize = 0
+    #ifdef HASH_ARRAY_2
+    + kHash2Size
+    #ifdef HASH_ARRAY_3
+    + kHash3Size
+    #endif
+    #endif
+    ;
+
+CMatchFinder::CMatchFinder():
+  _hash(0)
+{
+}
+
+void CMatchFinder::FreeThisClassMemory()
+{
+  BigFree(_hash);
+  _hash = 0;
+}
+
+void CMatchFinder::FreeMemory()
+{
+  FreeThisClassMemory();
+  CLZInWindow::Free();
+}
+
+CMatchFinder::~CMatchFinder()
+{
+  FreeMemory();
+}
+
+STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+    UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+{
+  if (historySize > kMaxValForNormalize - 256)
+  {
+    FreeMemory();
+    return E_INVALIDARG;
+  }
+  _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))
+  {
+    _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;
+  }
+  FreeMemory();
+  return E_OUTOFMEMORY;
+}
+
+static const UInt32 kEmptyHashValue = 0;
+
+STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)
+{
+  CLZInWindow::SetStream(stream);
+  return S_OK;
+}
+
+STDMETHODIMP CMatchFinder::Init()
+{
+  RINOK(CLZInWindow::Init());
+  for(UInt32 i = 0; i < _hashSizeSum; i++)
+    _hash[i] = kEmptyHashValue;
+  _cyclicBufferPos = 0;
+  ReduceOffsets(-1);
+  return S_OK;
+}
+
+STDMETHODIMP_(void) CMatchFinder::ReleaseStream()
+{
+  // ReleaseStream();
+}
+
+#ifdef HASH_ARRAY_2
+#ifdef HASH_ARRAY_3
+
+#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
+#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);
+}
+#else // no HASH_ZIP
+inline UInt32 Hash(const Byte *pointer)
+{
+  return pointer[0] ^ (UInt32(pointer[1]) << 8);
+}
+#endif // HASH_ZIP
+#endif // HASH_ARRAY_2
+
+STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)
+{
+  UInt32 lenLimit;
+  if (_pos + _matchMaxLen <= _streamPos)
+    lenLimit = _matchMaxLen;
+  else
+  {
+    lenLimit = _streamPos - _pos;
+    if(lenLimit < kMinMatchCheck)
+    {
+      distances[0] = 0;
+      return MovePos();
+    }
+  }
+
+  int offset = 1;
+
+  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;
+  #endif
+  UInt32 hashValue;
+  HASH_CALC;
+  #else
+  UInt32 hashValue = Hash(cur);
+  #endif
+
+  UInt32 curMatch = _hash[kFixHashSize + hashValue];
+  #ifdef HASH_ARRAY_2
+  UInt32 curMatch2 = _hash[hash2Value];
+  #ifdef HASH_ARRAY_3
+  UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+  #endif
+  _hash[hash2Value] = _pos;
+  if(curMatch2 > matchMinPos)
+    if (_buffer[curMatch2] == cur[0])
+    {
+      distances[offset++] = maxLen = 2;
+      distances[offset++] = _pos - curMatch2 - 1;
+    }
+
+  #ifdef HASH_ARRAY_3
+  _hash[kHash3Offset + hash3Value] = _pos;
+  if(curMatch3 > matchMinPos)
+    if (_buffer[curMatch3] == cur[0])
+    {
+      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
+  UInt32 count = _cutValue;
+  while(true)
+  {
+    if(curMatch <= matchMinPos || count-- == 0)
+    {
+      #ifndef _HASH_CHAIN
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      #endif
+      break;
+    }
+    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])
+    {
+      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;
+        }
+      }
+    }
+    #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
+  }
+  distances[0] = offset - 1;
+  if (++_cyclicBufferPos == _cyclicBufferSize)
+    _cyclicBufferPos = 0;
+  RINOK(CLZInWindow::MovePos());
+  if (_pos == kMaxValForNormalize)
+    Normalize();
+  return S_OK;
+}
+
+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 < kMinMatchCheck)
+    {
+      RINOK(MovePos());
+      continue;
+    }
+  }
+  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_CALC;
+  _hash[kHash3Offset + hash3Value] = _pos;
+  #else
+  UInt32 hashValue;
+  HASH_CALC;
+  #endif
+  _hash[hash2Value] = _pos;
+  #else
+  UInt32 hashValue = Hash(cur);
+  #endif
+
+  UInt32 curMatch = _hash[kFixHashSize + hashValue];
+  _hash[kFixHashSize + hashValue] = _pos;
+
+  #ifdef _HASH_CHAIN
+  _son[_cyclicBufferPos] = curMatch;
+  #else
+  CIndex *son = _son;
+  CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+  CIndex *ptr1 = son + (_cyclicBufferPos << 1);
+
+  UInt32 len0, len1;
+  len0 = len1 = kNumHashDirectBytes;
+  UInt32 count = _cutValue;
+  while(true)
+  {
+    if(curMatch <= matchMinPos || count-- == 0)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      break;
+    }
+
+    UInt32 delta = _pos - curMatch;
+    UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
+      (_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])
+    {
+      while(++len != lenLimit)
+        if (pb[len] != cur[len])
+          break;
+      if (len == lenLimit)
+      {
+        *ptr1 = pair[0];
+        *ptr0 = pair[1];
+        break;
+      }
+    }
+    if (pb[len] < cur[len])
+    {
+      *ptr1 = curMatch;
+      ptr1 = pair + 1;
+      curMatch = *ptr1;
+      len1 = len;
+    }
+    else
+    {
+      *ptr0 = curMatch;
+      ptr0 = pair;
+      curMatch = *ptr0;
+      len0 = len;
+    }
+  }
+  #endif
+  if (++_cyclicBufferPos == _cyclicBufferSize)
+    _cyclicBufferPos = 0;
+  RINOK(CLZInWindow::MovePos());
+  if (_pos == kMaxValForNormalize)
+    Normalize();
+  }
+  while(--num != 0);
+  return S_OK;
+}
+
+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];
+    if (value <= subValue)
+      value = kEmptyHashValue;
+    else
+      value -= subValue;
+    items[i] = value;
+  }
+  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
+
+}