LzFindMt.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
  2. 2008-10-04 : Igor Pavlov : Public domain */
  3. #include "LzHash.h"
  4. #include "LzFindMt.h"
  5. void MtSync_Construct(CMtSync *p)
  6. {
  7. p->wasCreated = False;
  8. p->csWasInitialized = False;
  9. p->csWasEntered = False;
  10. Thread_Construct(&p->thread);
  11. Event_Construct(&p->canStart);
  12. Event_Construct(&p->wasStarted);
  13. Event_Construct(&p->wasStopped);
  14. Semaphore_Construct(&p->freeSemaphore);
  15. Semaphore_Construct(&p->filledSemaphore);
  16. }
  17. void MtSync_GetNextBlock(CMtSync *p)
  18. {
  19. if (p->needStart)
  20. {
  21. p->numProcessedBlocks = 1;
  22. p->needStart = False;
  23. p->stopWriting = False;
  24. p->exit = False;
  25. Event_Reset(&p->wasStarted);
  26. Event_Reset(&p->wasStopped);
  27. Event_Set(&p->canStart);
  28. Event_Wait(&p->wasStarted);
  29. }
  30. else
  31. {
  32. CriticalSection_Leave(&p->cs);
  33. p->csWasEntered = False;
  34. p->numProcessedBlocks++;
  35. Semaphore_Release1(&p->freeSemaphore);
  36. }
  37. Semaphore_Wait(&p->filledSemaphore);
  38. CriticalSection_Enter(&p->cs);
  39. p->csWasEntered = True;
  40. }
  41. /* MtSync_StopWriting must be called if Writing was started */
  42. void MtSync_StopWriting(CMtSync *p)
  43. {
  44. UInt32 myNumBlocks = p->numProcessedBlocks;
  45. if (!Thread_WasCreated(&p->thread) || p->needStart)
  46. return;
  47. p->stopWriting = True;
  48. if (p->csWasEntered)
  49. {
  50. CriticalSection_Leave(&p->cs);
  51. p->csWasEntered = False;
  52. }
  53. Semaphore_Release1(&p->freeSemaphore);
  54. Event_Wait(&p->wasStopped);
  55. while (myNumBlocks++ != p->numProcessedBlocks)
  56. {
  57. Semaphore_Wait(&p->filledSemaphore);
  58. Semaphore_Release1(&p->freeSemaphore);
  59. }
  60. p->needStart = True;
  61. }
  62. void MtSync_Destruct(CMtSync *p)
  63. {
  64. if (Thread_WasCreated(&p->thread))
  65. {
  66. MtSync_StopWriting(p);
  67. p->exit = True;
  68. if (p->needStart)
  69. Event_Set(&p->canStart);
  70. Thread_Wait(&p->thread);
  71. Thread_Close(&p->thread);
  72. }
  73. if (p->csWasInitialized)
  74. {
  75. CriticalSection_Delete(&p->cs);
  76. p->csWasInitialized = False;
  77. }
  78. Event_Close(&p->canStart);
  79. Event_Close(&p->wasStarted);
  80. Event_Close(&p->wasStopped);
  81. Semaphore_Close(&p->freeSemaphore);
  82. Semaphore_Close(&p->filledSemaphore);
  83. p->wasCreated = False;
  84. }
  85. #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
  86. static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
  87. {
  88. if (p->wasCreated)
  89. return SZ_OK;
  90. RINOK_THREAD(CriticalSection_Init(&p->cs));
  91. p->csWasInitialized = True;
  92. RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
  93. RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
  94. RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
  95. RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
  96. RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
  97. p->needStart = True;
  98. RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
  99. p->wasCreated = True;
  100. return SZ_OK;
  101. }
  102. static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
  103. {
  104. SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
  105. if (res != SZ_OK)
  106. MtSync_Destruct(p);
  107. return res;
  108. }
  109. void MtSync_Init(CMtSync *p) { p->needStart = True; }
  110. #define kMtMaxValForNormalize 0xFFFFFFFF
  111. #define DEF_GetHeads2(name, v, action) \
  112. static void GetHeads ## name(const Byte *p, UInt32 pos, \
  113. UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
  114. { action; for (; numHeads != 0; numHeads--) { \
  115. const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
  116. #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
  117. DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
  118. DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
  119. DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
  120. DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
  121. DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask)
  122. void HashThreadFunc(CMatchFinderMt *mt)
  123. {
  124. CMtSync *p = &mt->hashSync;
  125. for (;;)
  126. {
  127. UInt32 numProcessedBlocks = 0;
  128. Event_Wait(&p->canStart);
  129. Event_Set(&p->wasStarted);
  130. for (;;)
  131. {
  132. if (p->exit)
  133. return;
  134. if (p->stopWriting)
  135. {
  136. p->numProcessedBlocks = numProcessedBlocks;
  137. Event_Set(&p->wasStopped);
  138. break;
  139. }
  140. {
  141. CMatchFinder *mf = mt->MatchFinder;
  142. if (MatchFinder_NeedMove(mf))
  143. {
  144. CriticalSection_Enter(&mt->btSync.cs);
  145. CriticalSection_Enter(&mt->hashSync.cs);
  146. {
  147. const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
  148. const Byte *afterPtr;
  149. MatchFinder_MoveBlock(mf);
  150. afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
  151. mt->pointerToCurPos -= beforePtr - afterPtr;
  152. mt->buffer -= beforePtr - afterPtr;
  153. }
  154. CriticalSection_Leave(&mt->btSync.cs);
  155. CriticalSection_Leave(&mt->hashSync.cs);
  156. continue;
  157. }
  158. Semaphore_Wait(&p->freeSemaphore);
  159. MatchFinder_ReadIfRequired(mf);
  160. if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
  161. {
  162. UInt32 subValue = (mf->pos - mf->historySize - 1);
  163. MatchFinder_ReduceOffsets(mf, subValue);
  164. MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
  165. }
  166. {
  167. UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
  168. UInt32 num = mf->streamPos - mf->pos;
  169. heads[0] = 2;
  170. heads[1] = num;
  171. if (num >= mf->numHashBytes)
  172. {
  173. num = num - mf->numHashBytes + 1;
  174. if (num > kMtHashBlockSize - 2)
  175. num = kMtHashBlockSize - 2;
  176. mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
  177. heads[0] += num;
  178. }
  179. mf->pos += num;
  180. mf->buffer += num;
  181. }
  182. }
  183. Semaphore_Release1(&p->filledSemaphore);
  184. }
  185. }
  186. }
  187. void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
  188. {
  189. MtSync_GetNextBlock(&p->hashSync);
  190. p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
  191. p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
  192. p->hashNumAvail = p->hashBuf[p->hashBufPos++];
  193. }
  194. #define kEmptyHashValue 0
  195. /* #define MFMT_GM_INLINE */
  196. #ifdef MFMT_GM_INLINE
  197. #define NO_INLINE MY_FAST_CALL
  198. Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
  199. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
  200. UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
  201. {
  202. do
  203. {
  204. UInt32 *distances = _distances + 1;
  205. UInt32 curMatch = pos - *hash++;
  206. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  207. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  208. UInt32 len0 = 0, len1 = 0;
  209. UInt32 cutValue = _cutValue;
  210. UInt32 maxLen = _maxLen;
  211. for (;;)
  212. {
  213. UInt32 delta = pos - curMatch;
  214. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  215. {
  216. *ptr0 = *ptr1 = kEmptyHashValue;
  217. break;
  218. }
  219. {
  220. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  221. const Byte *pb = cur - delta;
  222. UInt32 len = (len0 < len1 ? len0 : len1);
  223. if (pb[len] == cur[len])
  224. {
  225. if (++len != lenLimit && pb[len] == cur[len])
  226. while (++len != lenLimit)
  227. if (pb[len] != cur[len])
  228. break;
  229. if (maxLen < len)
  230. {
  231. *distances++ = maxLen = len;
  232. *distances++ = delta - 1;
  233. if (len == lenLimit)
  234. {
  235. *ptr1 = pair[0];
  236. *ptr0 = pair[1];
  237. break;
  238. }
  239. }
  240. }
  241. if (pb[len] < cur[len])
  242. {
  243. *ptr1 = curMatch;
  244. ptr1 = pair + 1;
  245. curMatch = *ptr1;
  246. len1 = len;
  247. }
  248. else
  249. {
  250. *ptr0 = curMatch;
  251. ptr0 = pair;
  252. curMatch = *ptr0;
  253. len0 = len;
  254. }
  255. }
  256. }
  257. pos++;
  258. _cyclicBufferPos++;
  259. cur++;
  260. {
  261. UInt32 num = (UInt32)(distances - _distances);
  262. *_distances = num - 1;
  263. _distances += num;
  264. limit -= num;
  265. }
  266. }
  267. while (limit > 0 && --size != 0);
  268. *posRes = pos;
  269. return limit;
  270. }
  271. #endif
  272. void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
  273. {
  274. UInt32 numProcessed = 0;
  275. UInt32 curPos = 2;
  276. UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
  277. distances[1] = p->hashNumAvail;
  278. while (curPos < limit)
  279. {
  280. if (p->hashBufPos == p->hashBufPosLimit)
  281. {
  282. MatchFinderMt_GetNextBlock_Hash(p);
  283. distances[1] = numProcessed + p->hashNumAvail;
  284. if (p->hashNumAvail >= p->numHashBytes)
  285. continue;
  286. for (; p->hashNumAvail != 0; p->hashNumAvail--)
  287. distances[curPos++] = 0;
  288. break;
  289. }
  290. {
  291. UInt32 size = p->hashBufPosLimit - p->hashBufPos;
  292. UInt32 lenLimit = p->matchMaxLen;
  293. UInt32 pos = p->pos;
  294. UInt32 cyclicBufferPos = p->cyclicBufferPos;
  295. if (lenLimit >= p->hashNumAvail)
  296. lenLimit = p->hashNumAvail;
  297. {
  298. UInt32 size2 = p->hashNumAvail - lenLimit + 1;
  299. if (size2 < size)
  300. size = size2;
  301. size2 = p->cyclicBufferSize - cyclicBufferPos;
  302. if (size2 < size)
  303. size = size2;
  304. }
  305. #ifndef MFMT_GM_INLINE
  306. while (curPos < limit && size-- != 0)
  307. {
  308. UInt32 *startDistances = distances + curPos;
  309. UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
  310. pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
  311. startDistances + 1, p->numHashBytes - 1) - startDistances);
  312. *startDistances = num - 1;
  313. curPos += num;
  314. cyclicBufferPos++;
  315. pos++;
  316. p->buffer++;
  317. }
  318. #else
  319. {
  320. UInt32 posRes;
  321. curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
  322. distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
  323. p->hashBufPos += posRes - pos;
  324. cyclicBufferPos += posRes - pos;
  325. p->buffer += posRes - pos;
  326. pos = posRes;
  327. }
  328. #endif
  329. numProcessed += pos - p->pos;
  330. p->hashNumAvail -= pos - p->pos;
  331. p->pos = pos;
  332. if (cyclicBufferPos == p->cyclicBufferSize)
  333. cyclicBufferPos = 0;
  334. p->cyclicBufferPos = cyclicBufferPos;
  335. }
  336. }
  337. distances[0] = curPos;
  338. }
  339. void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
  340. {
  341. CMtSync *sync = &p->hashSync;
  342. if (!sync->needStart)
  343. {
  344. CriticalSection_Enter(&sync->cs);
  345. sync->csWasEntered = True;
  346. }
  347. BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
  348. if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
  349. {
  350. UInt32 subValue = p->pos - p->cyclicBufferSize;
  351. MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
  352. p->pos -= subValue;
  353. }
  354. if (!sync->needStart)
  355. {
  356. CriticalSection_Leave(&sync->cs);
  357. sync->csWasEntered = False;
  358. }
  359. }
  360. void BtThreadFunc(CMatchFinderMt *mt)
  361. {
  362. CMtSync *p = &mt->btSync;
  363. for (;;)
  364. {
  365. UInt32 blockIndex = 0;
  366. Event_Wait(&p->canStart);
  367. Event_Set(&p->wasStarted);
  368. for (;;)
  369. {
  370. if (p->exit)
  371. return;
  372. if (p->stopWriting)
  373. {
  374. p->numProcessedBlocks = blockIndex;
  375. MtSync_StopWriting(&mt->hashSync);
  376. Event_Set(&p->wasStopped);
  377. break;
  378. }
  379. Semaphore_Wait(&p->freeSemaphore);
  380. BtFillBlock(mt, blockIndex++);
  381. Semaphore_Release1(&p->filledSemaphore);
  382. }
  383. }
  384. }
  385. void MatchFinderMt_Construct(CMatchFinderMt *p)
  386. {
  387. p->hashBuf = 0;
  388. MtSync_Construct(&p->hashSync);
  389. MtSync_Construct(&p->btSync);
  390. }
  391. void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
  392. {
  393. alloc->Free(alloc, p->hashBuf);
  394. p->hashBuf = 0;
  395. }
  396. void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
  397. {
  398. MtSync_Destruct(&p->hashSync);
  399. MtSync_Destruct(&p->btSync);
  400. MatchFinderMt_FreeMem(p, alloc);
  401. }
  402. #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
  403. #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
  404. static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
  405. static unsigned MY_STD_CALL BtThreadFunc2(void *p)
  406. {
  407. Byte allocaDummy[0x180];
  408. int i = 0;
  409. for (i = 0; i < 16; i++)
  410. allocaDummy[i] = (Byte)i;
  411. BtThreadFunc((CMatchFinderMt *)p);
  412. return 0;
  413. }
  414. SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
  415. UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
  416. {
  417. CMatchFinder *mf = p->MatchFinder;
  418. p->historySize = historySize;
  419. if (kMtBtBlockSize <= matchMaxLen * 4)
  420. return SZ_ERROR_PARAM;
  421. if (p->hashBuf == 0)
  422. {
  423. p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
  424. if (p->hashBuf == 0)
  425. return SZ_ERROR_MEM;
  426. p->btBuf = p->hashBuf + kHashBufferSize;
  427. }
  428. keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
  429. keepAddBufferAfter += kMtHashBlockSize;
  430. if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
  431. return SZ_ERROR_MEM;
  432. RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
  433. RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
  434. return SZ_OK;
  435. }
  436. /* Call it after ReleaseStream / SetStream */
  437. void MatchFinderMt_Init(CMatchFinderMt *p)
  438. {
  439. CMatchFinder *mf = p->MatchFinder;
  440. p->btBufPos = p->btBufPosLimit = 0;
  441. p->hashBufPos = p->hashBufPosLimit = 0;
  442. MatchFinder_Init(mf);
  443. p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
  444. p->btNumAvailBytes = 0;
  445. p->lzPos = p->historySize + 1;
  446. p->hash = mf->hash;
  447. p->fixedHashSize = mf->fixedHashSize;
  448. p->crc = mf->crc;
  449. p->son = mf->son;
  450. p->matchMaxLen = mf->matchMaxLen;
  451. p->numHashBytes = mf->numHashBytes;
  452. p->pos = mf->pos;
  453. p->buffer = mf->buffer;
  454. p->cyclicBufferPos = mf->cyclicBufferPos;
  455. p->cyclicBufferSize = mf->cyclicBufferSize;
  456. p->cutValue = mf->cutValue;
  457. }
  458. /* ReleaseStream is required to finish multithreading */
  459. void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
  460. {
  461. MtSync_StopWriting(&p->btSync);
  462. /* p->MatchFinder->ReleaseStream(); */
  463. }
  464. void MatchFinderMt_Normalize(CMatchFinderMt *p)
  465. {
  466. MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
  467. p->lzPos = p->historySize + 1;
  468. }
  469. void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
  470. {
  471. UInt32 blockIndex;
  472. MtSync_GetNextBlock(&p->btSync);
  473. blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
  474. p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
  475. p->btBufPosLimit += p->btBuf[p->btBufPos++];
  476. p->btNumAvailBytes = p->btBuf[p->btBufPos++];
  477. if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
  478. MatchFinderMt_Normalize(p);
  479. }
  480. const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
  481. {
  482. return p->pointerToCurPos;
  483. }
  484. #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
  485. UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
  486. {
  487. GET_NEXT_BLOCK_IF_REQUIRED;
  488. return p->btNumAvailBytes;
  489. }
  490. Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
  491. {
  492. return p->pointerToCurPos[index];
  493. }
  494. UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  495. {
  496. UInt32 hash2Value, curMatch2;
  497. UInt32 *hash = p->hash;
  498. const Byte *cur = p->pointerToCurPos;
  499. UInt32 lzPos = p->lzPos;
  500. MT_HASH2_CALC
  501. curMatch2 = hash[hash2Value];
  502. hash[hash2Value] = lzPos;
  503. if (curMatch2 >= matchMinPos)
  504. if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  505. {
  506. *distances++ = 2;
  507. *distances++ = lzPos - curMatch2 - 1;
  508. }
  509. return distances;
  510. }
  511. UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  512. {
  513. UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
  514. UInt32 *hash = p->hash;
  515. const Byte *cur = p->pointerToCurPos;
  516. UInt32 lzPos = p->lzPos;
  517. MT_HASH3_CALC
  518. curMatch2 = hash[ hash2Value];
  519. curMatch3 = hash[kFix3HashSize + hash3Value];
  520. hash[ hash2Value] =
  521. hash[kFix3HashSize + hash3Value] =
  522. lzPos;
  523. if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  524. {
  525. distances[1] = lzPos - curMatch2 - 1;
  526. if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
  527. {
  528. distances[0] = 3;
  529. return distances + 2;
  530. }
  531. distances[0] = 2;
  532. distances += 2;
  533. }
  534. if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
  535. {
  536. *distances++ = 3;
  537. *distances++ = lzPos - curMatch3 - 1;
  538. }
  539. return distances;
  540. }
  541. /*
  542. UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  543. {
  544. UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
  545. UInt32 *hash = p->hash;
  546. const Byte *cur = p->pointerToCurPos;
  547. UInt32 lzPos = p->lzPos;
  548. MT_HASH4_CALC
  549. curMatch2 = hash[ hash2Value];
  550. curMatch3 = hash[kFix3HashSize + hash3Value];
  551. curMatch4 = hash[kFix4HashSize + hash4Value];
  552. hash[ hash2Value] =
  553. hash[kFix3HashSize + hash3Value] =
  554. hash[kFix4HashSize + hash4Value] =
  555. lzPos;
  556. if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  557. {
  558. distances[1] = lzPos - curMatch2 - 1;
  559. if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
  560. {
  561. distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
  562. return distances + 2;
  563. }
  564. distances[0] = 2;
  565. distances += 2;
  566. }
  567. if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
  568. {
  569. distances[1] = lzPos - curMatch3 - 1;
  570. if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
  571. {
  572. distances[0] = 4;
  573. return distances + 2;
  574. }
  575. distances[0] = 3;
  576. distances += 2;
  577. }
  578. if (curMatch4 >= matchMinPos)
  579. if (
  580. cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
  581. cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
  582. )
  583. {
  584. *distances++ = 4;
  585. *distances++ = lzPos - curMatch4 - 1;
  586. }
  587. return distances;
  588. }
  589. */
  590. #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
  591. UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
  592. {
  593. const UInt32 *btBuf = p->btBuf + p->btBufPos;
  594. UInt32 len = *btBuf++;
  595. p->btBufPos += 1 + len;
  596. p->btNumAvailBytes--;
  597. {
  598. UInt32 i;
  599. for (i = 0; i < len; i += 2)
  600. {
  601. *distances++ = *btBuf++;
  602. *distances++ = *btBuf++;
  603. }
  604. }
  605. INCREASE_LZ_POS
  606. return len;
  607. }
  608. UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
  609. {
  610. const UInt32 *btBuf = p->btBuf + p->btBufPos;
  611. UInt32 len = *btBuf++;
  612. p->btBufPos += 1 + len;
  613. if (len == 0)
  614. {
  615. if (p->btNumAvailBytes-- >= 4)
  616. len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
  617. }
  618. else
  619. {
  620. /* Condition: there are matches in btBuf with length < p->numHashBytes */
  621. UInt32 *distances2;
  622. p->btNumAvailBytes--;
  623. distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
  624. do
  625. {
  626. *distances2++ = *btBuf++;
  627. *distances2++ = *btBuf++;
  628. }
  629. while ((len -= 2) != 0);
  630. len = (UInt32)(distances2 - (distances));
  631. }
  632. INCREASE_LZ_POS
  633. return len;
  634. }
  635. #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
  636. #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
  637. #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
  638. void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
  639. {
  640. SKIP_HEADER2 { p->btNumAvailBytes--;
  641. SKIP_FOOTER
  642. }
  643. void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
  644. {
  645. SKIP_HEADER(2)
  646. UInt32 hash2Value;
  647. MT_HASH2_CALC
  648. hash[hash2Value] = p->lzPos;
  649. SKIP_FOOTER
  650. }
  651. void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
  652. {
  653. SKIP_HEADER(3)
  654. UInt32 hash2Value, hash3Value;
  655. MT_HASH3_CALC
  656. hash[kFix3HashSize + hash3Value] =
  657. hash[ hash2Value] =
  658. p->lzPos;
  659. SKIP_FOOTER
  660. }
  661. /*
  662. void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
  663. {
  664. SKIP_HEADER(4)
  665. UInt32 hash2Value, hash3Value, hash4Value;
  666. MT_HASH4_CALC
  667. hash[kFix4HashSize + hash4Value] =
  668. hash[kFix3HashSize + hash3Value] =
  669. hash[ hash2Value] =
  670. p->lzPos;
  671. SKIP_FOOTER
  672. }
  673. */
  674. void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
  675. {
  676. vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
  677. vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
  678. vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
  679. vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
  680. vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
  681. switch(p->MatchFinder->numHashBytes)
  682. {
  683. case 2:
  684. p->GetHeadsFunc = GetHeads2;
  685. p->MixMatchesFunc = (Mf_Mix_Matches)0;
  686. vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
  687. vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
  688. break;
  689. case 3:
  690. p->GetHeadsFunc = GetHeads3;
  691. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
  692. vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
  693. break;
  694. default:
  695. /* case 4: */
  696. p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
  697. /* p->GetHeadsFunc = GetHeads4; */
  698. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
  699. vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
  700. break;
  701. /*
  702. default:
  703. p->GetHeadsFunc = GetHeads5;
  704. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
  705. vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
  706. break;
  707. */
  708. }
  709. }