LzFindMt.c 22 KB

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