You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

zstd_opt.c 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*
  2. * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. * You may select, at your option, one of the above-listed licenses.
  9. */
  10. #include "zstd_opt.h"
  11. #include "zstd_lazy.h"
  12. #define ZSTD_LITFREQ_ADD 2
  13. #define ZSTD_FREQ_DIV 4
  14. #define ZSTD_MAX_PRICE (1<<30)
  15. /*-*************************************
  16. * Price functions for optimal parser
  17. ***************************************/
  18. static void ZSTD_setLog2Prices(optState_t* optPtr)
  19. {
  20. optPtr->log2matchLengthSum = ZSTD_highbit32(optPtr->matchLengthSum+1);
  21. optPtr->log2litLengthSum = ZSTD_highbit32(optPtr->litLengthSum+1);
  22. optPtr->log2litSum = ZSTD_highbit32(optPtr->litSum+1);
  23. optPtr->log2offCodeSum = ZSTD_highbit32(optPtr->offCodeSum+1);
  24. optPtr->factor = 1 + ((optPtr->litSum>>5) / optPtr->litLengthSum) + ((optPtr->litSum<<1) / (optPtr->litSum + optPtr->matchSum));
  25. }
  26. static void ZSTD_rescaleFreqs(optState_t* optPtr, const BYTE* src, size_t srcSize)
  27. {
  28. unsigned u;
  29. optPtr->cachedLiterals = NULL;
  30. optPtr->cachedPrice = optPtr->cachedLitLength = 0;
  31. optPtr->staticPrices = 0;
  32. if (optPtr->litLengthSum == 0) {
  33. if (srcSize <= 1024) optPtr->staticPrices = 1;
  34. assert(optPtr->litFreq!=NULL);
  35. for (u=0; u<=MaxLit; u++)
  36. optPtr->litFreq[u] = 0;
  37. for (u=0; u<srcSize; u++)
  38. optPtr->litFreq[src[u]]++;
  39. optPtr->litSum = 0;
  40. optPtr->litLengthSum = MaxLL+1;
  41. optPtr->matchLengthSum = MaxML+1;
  42. optPtr->offCodeSum = (MaxOff+1);
  43. optPtr->matchSum = (ZSTD_LITFREQ_ADD<<Litbits);
  44. for (u=0; u<=MaxLit; u++) {
  45. optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>ZSTD_FREQ_DIV);
  46. optPtr->litSum += optPtr->litFreq[u];
  47. }
  48. for (u=0; u<=MaxLL; u++)
  49. optPtr->litLengthFreq[u] = 1;
  50. for (u=0; u<=MaxML; u++)
  51. optPtr->matchLengthFreq[u] = 1;
  52. for (u=0; u<=MaxOff; u++)
  53. optPtr->offCodeFreq[u] = 1;
  54. } else {
  55. optPtr->matchLengthSum = 0;
  56. optPtr->litLengthSum = 0;
  57. optPtr->offCodeSum = 0;
  58. optPtr->matchSum = 0;
  59. optPtr->litSum = 0;
  60. for (u=0; u<=MaxLit; u++) {
  61. optPtr->litFreq[u] = 1 + (optPtr->litFreq[u]>>(ZSTD_FREQ_DIV+1));
  62. optPtr->litSum += optPtr->litFreq[u];
  63. }
  64. for (u=0; u<=MaxLL; u++) {
  65. optPtr->litLengthFreq[u] = 1 + (optPtr->litLengthFreq[u]>>(ZSTD_FREQ_DIV+1));
  66. optPtr->litLengthSum += optPtr->litLengthFreq[u];
  67. }
  68. for (u=0; u<=MaxML; u++) {
  69. optPtr->matchLengthFreq[u] = 1 + (optPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
  70. optPtr->matchLengthSum += optPtr->matchLengthFreq[u];
  71. optPtr->matchSum += optPtr->matchLengthFreq[u] * (u + 3);
  72. }
  73. optPtr->matchSum *= ZSTD_LITFREQ_ADD;
  74. for (u=0; u<=MaxOff; u++) {
  75. optPtr->offCodeFreq[u] = 1 + (optPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
  76. optPtr->offCodeSum += optPtr->offCodeFreq[u];
  77. }
  78. }
  79. ZSTD_setLog2Prices(optPtr);
  80. }
  81. static U32 ZSTD_getLiteralPrice(optState_t* optPtr, U32 litLength, const BYTE* literals)
  82. {
  83. U32 price, u;
  84. if (optPtr->staticPrices)
  85. return ZSTD_highbit32((U32)litLength+1) + (litLength*6);
  86. if (litLength == 0)
  87. return optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[0]+1);
  88. /* literals */
  89. if (optPtr->cachedLiterals == literals) {
  90. U32 const additional = litLength - optPtr->cachedLitLength;
  91. const BYTE* literals2 = optPtr->cachedLiterals + optPtr->cachedLitLength;
  92. price = optPtr->cachedPrice + additional * optPtr->log2litSum;
  93. for (u=0; u < additional; u++)
  94. price -= ZSTD_highbit32(optPtr->litFreq[literals2[u]]+1);
  95. optPtr->cachedPrice = price;
  96. optPtr->cachedLitLength = litLength;
  97. } else {
  98. price = litLength * optPtr->log2litSum;
  99. for (u=0; u < litLength; u++)
  100. price -= ZSTD_highbit32(optPtr->litFreq[literals[u]]+1);
  101. if (litLength >= 12) {
  102. optPtr->cachedLiterals = literals;
  103. optPtr->cachedPrice = price;
  104. optPtr->cachedLitLength = litLength;
  105. }
  106. }
  107. /* literal Length */
  108. { const BYTE LL_deltaCode = 19;
  109. const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
  110. price += LL_bits[llCode] + optPtr->log2litLengthSum - ZSTD_highbit32(optPtr->litLengthFreq[llCode]+1);
  111. }
  112. return price;
  113. }
  114. FORCE_INLINE_TEMPLATE U32 ZSTD_getPrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength, const int ultra)
  115. {
  116. /* offset */
  117. U32 price;
  118. BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
  119. if (optPtr->staticPrices)
  120. return ZSTD_getLiteralPrice(optPtr, litLength, literals) + ZSTD_highbit32((U32)matchLength+1) + 16 + offCode;
  121. price = offCode + optPtr->log2offCodeSum - ZSTD_highbit32(optPtr->offCodeFreq[offCode]+1);
  122. if (!ultra && offCode >= 20) price += (offCode-19)*2;
  123. /* match Length */
  124. { const BYTE ML_deltaCode = 36;
  125. const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
  126. price += ML_bits[mlCode] + optPtr->log2matchLengthSum - ZSTD_highbit32(optPtr->matchLengthFreq[mlCode]+1);
  127. }
  128. return price + ZSTD_getLiteralPrice(optPtr, litLength, literals) + optPtr->factor;
  129. }
  130. static void ZSTD_updatePrice(optState_t* optPtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
  131. {
  132. U32 u;
  133. /* literals */
  134. optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;
  135. for (u=0; u < litLength; u++)
  136. optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
  137. /* literal Length */
  138. { const BYTE LL_deltaCode = 19;
  139. const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
  140. optPtr->litLengthFreq[llCode]++;
  141. optPtr->litLengthSum++;
  142. }
  143. /* match offset */
  144. { BYTE const offCode = (BYTE)ZSTD_highbit32(offset+1);
  145. optPtr->offCodeSum++;
  146. optPtr->offCodeFreq[offCode]++;
  147. }
  148. /* match Length */
  149. { const BYTE ML_deltaCode = 36;
  150. const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
  151. optPtr->matchLengthFreq[mlCode]++;
  152. optPtr->matchLengthSum++;
  153. }
  154. ZSTD_setLog2Prices(optPtr);
  155. }
  156. #define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
  157. { \
  158. while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } \
  159. opt[pos].mlen = mlen_; \
  160. opt[pos].off = offset_; \
  161. opt[pos].litlen = litlen_; \
  162. opt[pos].price = price_; \
  163. }
  164. /* function safe only for comparisons */
  165. static U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
  166. {
  167. switch (length)
  168. {
  169. default :
  170. case 4 : return MEM_read32(memPtr);
  171. case 3 : if (MEM_isLittleEndian())
  172. return MEM_read32(memPtr)<<8;
  173. else
  174. return MEM_read32(memPtr)>>8;
  175. }
  176. }
  177. /* Update hashTable3 up to ip (excluded)
  178. Assumption : always within prefix (i.e. not within extDict) */
  179. static
  180. U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
  181. {
  182. U32* const hashTable3 = zc->hashTable3;
  183. U32 const hashLog3 = zc->hashLog3;
  184. const BYTE* const base = zc->base;
  185. U32 idx = zc->nextToUpdate3;
  186. const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
  187. const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
  188. while(idx < target) {
  189. hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
  190. idx++;
  191. }
  192. return hashTable3[hash3];
  193. }
  194. /*-*************************************
  195. * Binary Tree search
  196. ***************************************/
  197. static U32 ZSTD_insertBtAndGetAllMatches (
  198. ZSTD_CCtx* zc,
  199. const BYTE* const ip, const BYTE* const iLimit,
  200. U32 nbCompares, const U32 mls,
  201. U32 extDict, ZSTD_match_t* matches, const U32 minMatchLen)
  202. {
  203. const BYTE* const base = zc->base;
  204. const U32 current = (U32)(ip-base);
  205. const U32 hashLog = zc->appliedParams.cParams.hashLog;
  206. const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
  207. U32* const hashTable = zc->hashTable;
  208. U32 matchIndex = hashTable[h];
  209. U32* const bt = zc->chainTable;
  210. const U32 btLog = zc->appliedParams.cParams.chainLog - 1;
  211. const U32 btMask= (1U << btLog) - 1;
  212. size_t commonLengthSmaller=0, commonLengthLarger=0;
  213. const BYTE* const dictBase = zc->dictBase;
  214. const U32 dictLimit = zc->dictLimit;
  215. const BYTE* const dictEnd = dictBase + dictLimit;
  216. const BYTE* const prefixStart = base + dictLimit;
  217. const U32 btLow = btMask >= current ? 0 : current - btMask;
  218. const U32 windowLow = zc->lowLimit;
  219. U32* smallerPtr = bt + 2*(current&btMask);
  220. U32* largerPtr = bt + 2*(current&btMask) + 1;
  221. U32 matchEndIdx = current+8;
  222. U32 dummy32; /* to be nullified at the end */
  223. U32 mnum = 0;
  224. const U32 minMatch = (mls == 3) ? 3 : 4;
  225. size_t bestLength = minMatchLen-1;
  226. if (minMatch == 3) { /* HC3 match finder */
  227. U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
  228. if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
  229. const BYTE* match;
  230. size_t currentMl=0;
  231. if ((!extDict) || matchIndex3 >= dictLimit) {
  232. match = base + matchIndex3;
  233. if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
  234. } else {
  235. match = dictBase + matchIndex3;
  236. if (ZSTD_readMINMATCH(match, MINMATCH) == ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
  237. currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
  238. }
  239. /* save best solution */
  240. if (currentMl > bestLength) {
  241. bestLength = currentMl;
  242. matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3;
  243. matches[mnum].len = (U32)currentMl;
  244. mnum++;
  245. if (currentMl > ZSTD_OPT_NUM) goto update;
  246. if (ip+currentMl == iLimit) goto update; /* best possible, and avoid read overflow*/
  247. }
  248. }
  249. }
  250. hashTable[h] = current; /* Update Hash Table */
  251. while (nbCompares-- && (matchIndex > windowLow)) {
  252. U32* nextPtr = bt + 2*(matchIndex & btMask);
  253. size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
  254. const BYTE* match;
  255. if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
  256. match = base + matchIndex;
  257. if (match[matchLength] == ip[matchLength]) {
  258. matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
  259. }
  260. } else {
  261. match = dictBase + matchIndex;
  262. matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
  263. if (matchIndex+matchLength >= dictLimit)
  264. match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
  265. }
  266. if (matchLength > bestLength) {
  267. if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength;
  268. bestLength = matchLength;
  269. matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex;
  270. matches[mnum].len = (U32)matchLength;
  271. mnum++;
  272. if (matchLength > ZSTD_OPT_NUM) break;
  273. if (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */
  274. break; /* drop, to guarantee consistency (miss a little bit of compression) */
  275. }
  276. if (match[matchLength] < ip[matchLength]) {
  277. /* match is smaller than current */
  278. *smallerPtr = matchIndex; /* update smaller idx */
  279. commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
  280. if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
  281. smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
  282. matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
  283. } else {
  284. /* match is larger than current */
  285. *largerPtr = matchIndex;
  286. commonLengthLarger = matchLength;
  287. if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
  288. largerPtr = nextPtr;
  289. matchIndex = nextPtr[0];
  290. } }
  291. *smallerPtr = *largerPtr = 0;
  292. update:
  293. zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
  294. return mnum;
  295. }
  296. /** Tree updater, providing best match */
  297. static U32 ZSTD_BtGetAllMatches (
  298. ZSTD_CCtx* zc,
  299. const BYTE* const ip, const BYTE* const iLimit,
  300. const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
  301. {
  302. if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
  303. ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
  304. return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
  305. }
  306. static U32 ZSTD_BtGetAllMatches_selectMLS (
  307. ZSTD_CCtx* zc, /* Index table will be updated */
  308. const BYTE* ip, const BYTE* const iHighLimit,
  309. const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
  310. {
  311. switch(matchLengthSearch)
  312. {
  313. case 3 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
  314. default :
  315. case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
  316. case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
  317. case 7 :
  318. case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
  319. }
  320. }
  321. /** Tree updater, providing best match */
  322. static U32 ZSTD_BtGetAllMatches_extDict (
  323. ZSTD_CCtx* zc,
  324. const BYTE* const ip, const BYTE* const iLimit,
  325. const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, const U32 minMatchLen)
  326. {
  327. if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
  328. ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
  329. return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
  330. }
  331. static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
  332. ZSTD_CCtx* zc, /* Index table will be updated */
  333. const BYTE* ip, const BYTE* const iHighLimit,
  334. const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, const U32 minMatchLen)
  335. {
  336. switch(matchLengthSearch)
  337. {
  338. case 3 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
  339. default :
  340. case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
  341. case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
  342. case 7 :
  343. case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
  344. }
  345. }
  346. /*-*******************************
  347. * Optimal parser
  348. *********************************/
  349. FORCE_INLINE_TEMPLATE
  350. size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
  351. const void* src, size_t srcSize, const int ultra)
  352. {
  353. seqStore_t* seqStorePtr = &(ctx->seqStore);
  354. optState_t* optStatePtr = &(ctx->optState);
  355. const BYTE* const istart = (const BYTE*)src;
  356. const BYTE* ip = istart;
  357. const BYTE* anchor = istart;
  358. const BYTE* const iend = istart + srcSize;
  359. const BYTE* const ilimit = iend - 8;
  360. const BYTE* const base = ctx->base;
  361. const BYTE* const prefixStart = base + ctx->dictLimit;
  362. const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
  363. const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
  364. const U32 mls = ctx->appliedParams.cParams.searchLength;
  365. const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
  366. ZSTD_optimal_t* opt = optStatePtr->priceTable;
  367. ZSTD_match_t* matches = optStatePtr->matchTable;
  368. const BYTE* inr;
  369. U32 offset, rep[ZSTD_REP_NUM];
  370. /* init */
  371. ctx->nextToUpdate3 = ctx->nextToUpdate;
  372. ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
  373. ip += (ip==prefixStart);
  374. { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
  375. /* Match Loop */
  376. while (ip < ilimit) {
  377. U32 cur, match_num, last_pos, litlen, price;
  378. U32 u, mlen, best_mlen, best_off, litLength;
  379. memset(opt, 0, sizeof(ZSTD_optimal_t));
  380. last_pos = 0;
  381. litlen = (U32)(ip - anchor);
  382. /* check repCode */
  383. { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
  384. for (i=(ip == anchor); i<last_i; i++) {
  385. const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
  386. if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
  387. && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
  388. mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
  389. if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
  390. best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
  391. goto _storeSequence;
  392. }
  393. best_off = i - (ip == anchor);
  394. do {
  395. price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
  396. if (mlen > last_pos || price < opt[mlen].price)
  397. SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
  398. mlen--;
  399. } while (mlen >= minMatch);
  400. } } }
  401. match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
  402. if (!last_pos && !match_num) { ip++; continue; }
  403. if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
  404. best_mlen = matches[match_num-1].len;
  405. best_off = matches[match_num-1].off;
  406. cur = 0;
  407. last_pos = 1;
  408. goto _storeSequence;
  409. }
  410. /* set prices using matches at position = 0 */
  411. best_mlen = (last_pos) ? last_pos : minMatch;
  412. for (u = 0; u < match_num; u++) {
  413. mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
  414. best_mlen = matches[u].len;
  415. while (mlen <= best_mlen) {
  416. price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
  417. if (mlen > last_pos || price < opt[mlen].price)
  418. SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
  419. mlen++;
  420. } }
  421. if (last_pos < minMatch) { ip++; continue; }
  422. /* initialize opt[0] */
  423. { U32 i ; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
  424. opt[0].mlen = 1;
  425. opt[0].litlen = litlen;
  426. /* check further positions */
  427. for (cur = 1; cur <= last_pos; cur++) {
  428. inr = ip + cur;
  429. if (opt[cur-1].mlen == 1) {
  430. litlen = opt[cur-1].litlen + 1;
  431. if (cur > litlen) {
  432. price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
  433. } else
  434. price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
  435. } else {
  436. litlen = 1;
  437. price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
  438. }
  439. if (cur > last_pos || price <= opt[cur].price)
  440. SET_PRICE(cur, 1, 0, litlen, price);
  441. if (cur == last_pos) break;
  442. if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
  443. continue;
  444. mlen = opt[cur].mlen;
  445. if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
  446. opt[cur].rep[2] = opt[cur-mlen].rep[1];
  447. opt[cur].rep[1] = opt[cur-mlen].rep[0];
  448. opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
  449. } else {
  450. opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
  451. opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
  452. opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
  453. }
  454. best_mlen = minMatch;
  455. { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
  456. for (i=(opt[cur].mlen != 1); i<last_i; i++) { /* check rep */
  457. const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
  458. if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
  459. && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
  460. mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
  461. if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
  462. best_mlen = mlen; best_off = i; last_pos = cur + 1;
  463. goto _storeSequence;
  464. }
  465. best_off = i - (opt[cur].mlen != 1);
  466. if (mlen > best_mlen) best_mlen = mlen;
  467. do {
  468. if (opt[cur].mlen == 1) {
  469. litlen = opt[cur].litlen;
  470. if (cur > litlen) {
  471. price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
  472. } else
  473. price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
  474. } else {
  475. litlen = 0;
  476. price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
  477. }
  478. if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
  479. SET_PRICE(cur + mlen, mlen, i, litlen, price);
  480. mlen--;
  481. } while (mlen >= minMatch);
  482. } } }
  483. match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
  484. if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
  485. best_mlen = matches[match_num-1].len;
  486. best_off = matches[match_num-1].off;
  487. last_pos = cur + 1;
  488. goto _storeSequence;
  489. }
  490. /* set prices using matches at position = cur */
  491. for (u = 0; u < match_num; u++) {
  492. mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
  493. best_mlen = matches[u].len;
  494. while (mlen <= best_mlen) {
  495. if (opt[cur].mlen == 1) {
  496. litlen = opt[cur].litlen;
  497. if (cur > litlen)
  498. price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
  499. else
  500. price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
  501. } else {
  502. litlen = 0;
  503. price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
  504. }
  505. if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
  506. SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
  507. mlen++;
  508. } } }
  509. best_mlen = opt[last_pos].mlen;
  510. best_off = opt[last_pos].off;
  511. cur = last_pos - best_mlen;
  512. /* store sequence */
  513. _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
  514. opt[0].mlen = 1;
  515. while (1) {
  516. mlen = opt[cur].mlen;
  517. offset = opt[cur].off;
  518. opt[cur].mlen = best_mlen;
  519. opt[cur].off = best_off;
  520. best_mlen = mlen;
  521. best_off = offset;
  522. if (mlen > cur) break;
  523. cur -= mlen;
  524. }
  525. for (u = 0; u <= last_pos;) {
  526. u += opt[u].mlen;
  527. }
  528. for (cur=0; cur < last_pos; ) {
  529. mlen = opt[cur].mlen;
  530. if (mlen == 1) { ip++; cur++; continue; }
  531. offset = opt[cur].off;
  532. cur += mlen;
  533. litLength = (U32)(ip - anchor);
  534. if (offset > ZSTD_REP_MOVE_OPT) {
  535. rep[2] = rep[1];
  536. rep[1] = rep[0];
  537. rep[0] = offset - ZSTD_REP_MOVE_OPT;
  538. offset--;
  539. } else {
  540. if (offset != 0) {
  541. best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
  542. if (offset != 1) rep[2] = rep[1];
  543. rep[1] = rep[0];
  544. rep[0] = best_off;
  545. }
  546. if (litLength==0) offset--;
  547. }
  548. ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
  549. ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
  550. anchor = ip = ip + mlen;
  551. } } /* for (cur=0; cur < last_pos; ) */
  552. /* Save reps for next block */
  553. { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
  554. /* Return the last literals size */
  555. return iend - anchor;
  556. }
  557. size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
  558. {
  559. return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
  560. }
  561. size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
  562. {
  563. return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1);
  564. }
  565. FORCE_INLINE_TEMPLATE
  566. size_t ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
  567. const void* src, size_t srcSize, const int ultra)
  568. {
  569. seqStore_t* seqStorePtr = &(ctx->seqStore);
  570. optState_t* optStatePtr = &(ctx->optState);
  571. const BYTE* const istart = (const BYTE*)src;
  572. const BYTE* ip = istart;
  573. const BYTE* anchor = istart;
  574. const BYTE* const iend = istart + srcSize;
  575. const BYTE* const ilimit = iend - 8;
  576. const BYTE* const base = ctx->base;
  577. const U32 lowestIndex = ctx->lowLimit;
  578. const U32 dictLimit = ctx->dictLimit;
  579. const BYTE* const prefixStart = base + dictLimit;
  580. const BYTE* const dictBase = ctx->dictBase;
  581. const BYTE* const dictEnd = dictBase + dictLimit;
  582. const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
  583. const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
  584. const U32 mls = ctx->appliedParams.cParams.searchLength;
  585. const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
  586. ZSTD_optimal_t* opt = optStatePtr->priceTable;
  587. ZSTD_match_t* matches = optStatePtr->matchTable;
  588. const BYTE* inr;
  589. /* init */
  590. U32 offset, rep[ZSTD_REP_NUM];
  591. { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
  592. ctx->nextToUpdate3 = ctx->nextToUpdate;
  593. ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
  594. ip += (ip==prefixStart);
  595. /* Match Loop */
  596. while (ip < ilimit) {
  597. U32 cur, match_num, last_pos, litlen, price;
  598. U32 u, mlen, best_mlen, best_off, litLength;
  599. U32 current = (U32)(ip-base);
  600. memset(opt, 0, sizeof(ZSTD_optimal_t));
  601. last_pos = 0;
  602. opt[0].litlen = (U32)(ip - anchor);
  603. /* check repCode */
  604. { U32 i, last_i = ZSTD_REP_CHECK + (ip==anchor);
  605. for (i = (ip==anchor); i<last_i; i++) {
  606. const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
  607. const U32 repIndex = (U32)(current - repCur);
  608. const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
  609. const BYTE* const repMatch = repBase + repIndex;
  610. if ( (repCur > 0 && repCur <= (S32)current)
  611. && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
  612. && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
  613. /* repcode detected we should take it */
  614. const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
  615. mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
  616. if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
  617. best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
  618. goto _storeSequence;
  619. }
  620. best_off = i - (ip==anchor);
  621. litlen = opt[0].litlen;
  622. do {
  623. price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
  624. if (mlen > last_pos || price < opt[mlen].price)
  625. SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
  626. mlen--;
  627. } while (mlen >= minMatch);
  628. } } }
  629. match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
  630. if (!last_pos && !match_num) { ip++; continue; }
  631. { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) opt[0].rep[i] = rep[i]; }
  632. opt[0].mlen = 1;
  633. if (match_num && (matches[match_num-1].len > sufficient_len || matches[match_num-1].len >= ZSTD_OPT_NUM)) {
  634. best_mlen = matches[match_num-1].len;
  635. best_off = matches[match_num-1].off;
  636. cur = 0;
  637. last_pos = 1;
  638. goto _storeSequence;
  639. }
  640. best_mlen = (last_pos) ? last_pos : minMatch;
  641. /* set prices using matches at position = 0 */
  642. for (u = 0; u < match_num; u++) {
  643. mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
  644. best_mlen = matches[u].len;
  645. litlen = opt[0].litlen;
  646. while (mlen <= best_mlen) {
  647. price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
  648. if (mlen > last_pos || price < opt[mlen].price)
  649. SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
  650. mlen++;
  651. } }
  652. if (last_pos < minMatch) {
  653. ip++; continue;
  654. }
  655. /* check further positions */
  656. for (cur = 1; cur <= last_pos; cur++) {
  657. inr = ip + cur;
  658. if (opt[cur-1].mlen == 1) {
  659. litlen = opt[cur-1].litlen + 1;
  660. if (cur > litlen) {
  661. price = opt[cur - litlen].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-litlen);
  662. } else
  663. price = ZSTD_getLiteralPrice(optStatePtr, litlen, anchor);
  664. } else {
  665. litlen = 1;
  666. price = opt[cur - 1].price + ZSTD_getLiteralPrice(optStatePtr, litlen, inr-1);
  667. }
  668. if (cur > last_pos || price <= opt[cur].price)
  669. SET_PRICE(cur, 1, 0, litlen, price);
  670. if (cur == last_pos) break;
  671. if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
  672. continue;
  673. mlen = opt[cur].mlen;
  674. if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
  675. opt[cur].rep[2] = opt[cur-mlen].rep[1];
  676. opt[cur].rep[1] = opt[cur-mlen].rep[0];
  677. opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
  678. } else {
  679. opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur-mlen].rep[1] : opt[cur-mlen].rep[2];
  680. opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur-mlen].rep[0] : opt[cur-mlen].rep[1];
  681. opt[cur].rep[0] = ((opt[cur].off==ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur-mlen].rep[0] - 1) : (opt[cur-mlen].rep[opt[cur].off]);
  682. }
  683. best_mlen = minMatch;
  684. { U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
  685. for (i = (mlen != 1); i<last_i; i++) {
  686. const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
  687. const U32 repIndex = (U32)(current+cur - repCur);
  688. const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
  689. const BYTE* const repMatch = repBase + repIndex;
  690. if ( (repCur > 0 && repCur <= (S32)(current+cur))
  691. && (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
  692. && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
  693. /* repcode detected */
  694. const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
  695. mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
  696. if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
  697. best_mlen = mlen; best_off = i; last_pos = cur + 1;
  698. goto _storeSequence;
  699. }
  700. best_off = i - (opt[cur].mlen != 1);
  701. if (mlen > best_mlen) best_mlen = mlen;
  702. do {
  703. if (opt[cur].mlen == 1) {
  704. litlen = opt[cur].litlen;
  705. if (cur > litlen) {
  706. price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, inr-litlen, best_off, mlen - MINMATCH, ultra);
  707. } else
  708. price = ZSTD_getPrice(optStatePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
  709. } else {
  710. litlen = 0;
  711. price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
  712. }
  713. if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
  714. SET_PRICE(cur + mlen, mlen, i, litlen, price);
  715. mlen--;
  716. } while (mlen >= minMatch);
  717. } } }
  718. match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
  719. if (match_num > 0 && (matches[match_num-1].len > sufficient_len || cur + matches[match_num-1].len >= ZSTD_OPT_NUM)) {
  720. best_mlen = matches[match_num-1].len;
  721. best_off = matches[match_num-1].off;
  722. last_pos = cur + 1;
  723. goto _storeSequence;
  724. }
  725. /* set prices using matches at position = cur */
  726. for (u = 0; u < match_num; u++) {
  727. mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
  728. best_mlen = matches[u].len;
  729. while (mlen <= best_mlen) {
  730. if (opt[cur].mlen == 1) {
  731. litlen = opt[cur].litlen;
  732. if (cur > litlen)
  733. price = opt[cur - litlen].price + ZSTD_getPrice(optStatePtr, litlen, ip+cur-litlen, matches[u].off-1, mlen - MINMATCH, ultra);
  734. else
  735. price = ZSTD_getPrice(optStatePtr, litlen, anchor, matches[u].off-1, mlen - MINMATCH, ultra);
  736. } else {
  737. litlen = 0;
  738. price = opt[cur].price + ZSTD_getPrice(optStatePtr, 0, NULL, matches[u].off-1, mlen - MINMATCH, ultra);
  739. }
  740. if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
  741. SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
  742. mlen++;
  743. } } } /* for (cur = 1; cur <= last_pos; cur++) */
  744. best_mlen = opt[last_pos].mlen;
  745. best_off = opt[last_pos].off;
  746. cur = last_pos - best_mlen;
  747. /* store sequence */
  748. _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
  749. opt[0].mlen = 1;
  750. while (1) {
  751. mlen = opt[cur].mlen;
  752. offset = opt[cur].off;
  753. opt[cur].mlen = best_mlen;
  754. opt[cur].off = best_off;
  755. best_mlen = mlen;
  756. best_off = offset;
  757. if (mlen > cur) break;
  758. cur -= mlen;
  759. }
  760. for (u = 0; u <= last_pos; ) {
  761. u += opt[u].mlen;
  762. }
  763. for (cur=0; cur < last_pos; ) {
  764. mlen = opt[cur].mlen;
  765. if (mlen == 1) { ip++; cur++; continue; }
  766. offset = opt[cur].off;
  767. cur += mlen;
  768. litLength = (U32)(ip - anchor);
  769. if (offset > ZSTD_REP_MOVE_OPT) {
  770. rep[2] = rep[1];
  771. rep[1] = rep[0];
  772. rep[0] = offset - ZSTD_REP_MOVE_OPT;
  773. offset--;
  774. } else {
  775. if (offset != 0) {
  776. best_off = (offset==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
  777. if (offset != 1) rep[2] = rep[1];
  778. rep[1] = rep[0];
  779. rep[0] = best_off;
  780. }
  781. if (litLength==0) offset--;
  782. }
  783. ZSTD_updatePrice(optStatePtr, litLength, anchor, offset, mlen-MINMATCH);
  784. ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH);
  785. anchor = ip = ip + mlen;
  786. } } /* for (cur=0; cur < last_pos; ) */
  787. /* Save reps for next block */
  788. { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
  789. /* Return the last literals size */
  790. return iend - anchor;
  791. }
  792. size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
  793. {
  794. return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
  795. }
  796. size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
  797. {
  798. return ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1);
  799. }