Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
   1/**
   2 * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
   3 * All rights reserved.
   4 *
   5 * This source code is licensed under the BSD-style license found in the
   6 * LICENSE file in the root directory of https://github.com/facebook/zstd.
   7 * An additional grant of patent rights can be found in the PATENTS file in the
   8 * same directory.
   9 *
  10 * This program is free software; you can redistribute it and/or modify it under
  11 * the terms of the GNU General Public License version 2 as published by the
  12 * Free Software Foundation. This program is dual-licensed; you may select
  13 * either version 2 of the GNU General Public License ("GPL") or BSD license
  14 * ("BSD").
  15 */
  16
  17/* Note : this file is intended to be included within zstd_compress.c */
  18
  19#ifndef ZSTD_OPT_H_91842398743
  20#define ZSTD_OPT_H_91842398743
  21
  22#define ZSTD_LITFREQ_ADD 2
  23#define ZSTD_FREQ_DIV 4
  24#define ZSTD_MAX_PRICE (1 << 30)
  25
  26/*-*************************************
  27*  Price functions for optimal parser
  28***************************************/
  29FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t *ssPtr)
  30{
  31	ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum + 1);
  32	ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum + 1);
  33	ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum + 1);
  34	ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum + 1);
  35	ssPtr->factor = 1 + ((ssPtr->litSum >> 5) / ssPtr->litLengthSum) + ((ssPtr->litSum << 1) / (ssPtr->litSum + ssPtr->matchSum));
  36}
  37
  38ZSTD_STATIC void ZSTD_rescaleFreqs(seqStore_t *ssPtr, const BYTE *src, size_t srcSize)
  39{
  40	unsigned u;
  41
  42	ssPtr->cachedLiterals = NULL;
  43	ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
  44	ssPtr->staticPrices = 0;
  45
  46	if (ssPtr->litLengthSum == 0) {
  47		if (srcSize <= 1024)
  48			ssPtr->staticPrices = 1;
  49
  50		for (u = 0; u <= MaxLit; u++)
  51			ssPtr->litFreq[u] = 0;
  52		for (u = 0; u < srcSize; u++)
  53			ssPtr->litFreq[src[u]]++;
  54
  55		ssPtr->litSum = 0;
  56		ssPtr->litLengthSum = MaxLL + 1;
  57		ssPtr->matchLengthSum = MaxML + 1;
  58		ssPtr->offCodeSum = (MaxOff + 1);
  59		ssPtr->matchSum = (ZSTD_LITFREQ_ADD << Litbits);
  60
  61		for (u = 0; u <= MaxLit; u++) {
  62			ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> ZSTD_FREQ_DIV);
  63			ssPtr->litSum += ssPtr->litFreq[u];
  64		}
  65		for (u = 0; u <= MaxLL; u++)
  66			ssPtr->litLengthFreq[u] = 1;
  67		for (u = 0; u <= MaxML; u++)
  68			ssPtr->matchLengthFreq[u] = 1;
  69		for (u = 0; u <= MaxOff; u++)
  70			ssPtr->offCodeFreq[u] = 1;
  71	} else {
  72		ssPtr->matchLengthSum = 0;
  73		ssPtr->litLengthSum = 0;
  74		ssPtr->offCodeSum = 0;
  75		ssPtr->matchSum = 0;
  76		ssPtr->litSum = 0;
  77
  78		for (u = 0; u <= MaxLit; u++) {
  79			ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> (ZSTD_FREQ_DIV + 1));
  80			ssPtr->litSum += ssPtr->litFreq[u];
  81		}
  82		for (u = 0; u <= MaxLL; u++) {
  83			ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u] >> (ZSTD_FREQ_DIV + 1));
  84			ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
  85		}
  86		for (u = 0; u <= MaxML; u++) {
  87			ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u] >> ZSTD_FREQ_DIV);
  88			ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
  89			ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
  90		}
  91		ssPtr->matchSum *= ZSTD_LITFREQ_ADD;
  92		for (u = 0; u <= MaxOff; u++) {
  93			ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u] >> ZSTD_FREQ_DIV);
  94			ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
  95		}
  96	}
  97
  98	ZSTD_setLog2Prices(ssPtr);
  99}
 100
 101FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t *ssPtr, U32 litLength, const BYTE *literals)
 102{
 103	U32 price, u;
 104
 105	if (ssPtr->staticPrices)
 106		return ZSTD_highbit32((U32)litLength + 1) + (litLength * 6);
 107
 108	if (litLength == 0)
 109		return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0] + 1);
 110
 111	/* literals */
 112	if (ssPtr->cachedLiterals == literals) {
 113		U32 const additional = litLength - ssPtr->cachedLitLength;
 114		const BYTE *literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength;
 115		price = ssPtr->cachedPrice + additional * ssPtr->log2litSum;
 116		for (u = 0; u < additional; u++)
 117			price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]] + 1);
 118		ssPtr->cachedPrice = price;
 119		ssPtr->cachedLitLength = litLength;
 120	} else {
 121		price = litLength * ssPtr->log2litSum;
 122		for (u = 0; u < litLength; u++)
 123			price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]] + 1);
 124
 125		if (litLength >= 12) {
 126			ssPtr->cachedLiterals = literals;
 127			ssPtr->cachedPrice = price;
 128			ssPtr->cachedLitLength = litLength;
 129		}
 130	}
 131
 132	/* literal Length */
 133	{
 134		const BYTE LL_deltaCode = 19;
 135		const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
 136		price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode] + 1);
 137	}
 138
 139	return price;
 140}
 141
 142FORCE_INLINE U32 ZSTD_getPrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength, const int ultra)
 143{
 144	/* offset */
 145	U32 price;
 146	BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
 147
 148	if (seqStorePtr->staticPrices)
 149		return ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit32((U32)matchLength + 1) + 16 + offCode;
 150
 151	price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode] + 1);
 152	if (!ultra && offCode >= 20)
 153		price += (offCode - 19) * 2;
 154
 155	/* match Length */
 156	{
 157		const BYTE ML_deltaCode = 36;
 158		const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
 159		price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode] + 1);
 160	}
 161
 162	return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
 163}
 164
 165ZSTD_STATIC void ZSTD_updatePrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength)
 166{
 167	U32 u;
 168
 169	/* literals */
 170	seqStorePtr->litSum += litLength * ZSTD_LITFREQ_ADD;
 171	for (u = 0; u < litLength; u++)
 172		seqStorePtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
 173
 174	/* literal Length */
 175	{
 176		const BYTE LL_deltaCode = 19;
 177		const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
 178		seqStorePtr->litLengthFreq[llCode]++;
 179		seqStorePtr->litLengthSum++;
 180	}
 181
 182	/* match offset */
 183	{
 184		BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
 185		seqStorePtr->offCodeSum++;
 186		seqStorePtr->offCodeFreq[offCode]++;
 187	}
 188
 189	/* match Length */
 190	{
 191		const BYTE ML_deltaCode = 36;
 192		const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
 193		seqStorePtr->matchLengthFreq[mlCode]++;
 194		seqStorePtr->matchLengthSum++;
 195	}
 196
 197	ZSTD_setLog2Prices(seqStorePtr);
 198}
 199
 200#define SET_PRICE(pos, mlen_, offset_, litlen_, price_)           \
 201	{                                                         \
 202		while (last_pos < pos) {                          \
 203			opt[last_pos + 1].price = ZSTD_MAX_PRICE; \
 204			last_pos++;                               \
 205		}                                                 \
 206		opt[pos].mlen = mlen_;                            \
 207		opt[pos].off = offset_;                           \
 208		opt[pos].litlen = litlen_;                        \
 209		opt[pos].price = price_;                          \
 210	}
 211
 212/* Update hashTable3 up to ip (excluded)
 213   Assumption : always within prefix (i.e. not within extDict) */
 214FORCE_INLINE
 215U32 ZSTD_insertAndFindFirstIndexHash3(ZSTD_CCtx *zc, const BYTE *ip)
 216{
 217	U32 *const hashTable3 = zc->hashTable3;
 218	U32 const hashLog3 = zc->hashLog3;
 219	const BYTE *const base = zc->base;
 220	U32 idx = zc->nextToUpdate3;
 221	const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
 222	const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
 223
 224	while (idx < target) {
 225		hashTable3[ZSTD_hash3Ptr(base + idx, hashLog3)] = idx;
 226		idx++;
 227	}
 228
 229	return hashTable3[hash3];
 230}
 231
 232/*-*************************************
 233*  Binary Tree search
 234***************************************/
 235static U32 ZSTD_insertBtAndGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, U32 nbCompares, const U32 mls, U32 extDict,
 236					 ZSTD_match_t *matches, const U32 minMatchLen)
 237{
 238	const BYTE *const base = zc->base;
 239	const U32 curr = (U32)(ip - base);
 240	const U32 hashLog = zc->params.cParams.hashLog;
 241	const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
 242	U32 *const hashTable = zc->hashTable;
 243	U32 matchIndex = hashTable[h];
 244	U32 *const bt = zc->chainTable;
 245	const U32 btLog = zc->params.cParams.chainLog - 1;
 246	const U32 btMask = (1U << btLog) - 1;
 247	size_t commonLengthSmaller = 0, commonLengthLarger = 0;
 248	const BYTE *const dictBase = zc->dictBase;
 249	const U32 dictLimit = zc->dictLimit;
 250	const BYTE *const dictEnd = dictBase + dictLimit;
 251	const BYTE *const prefixStart = base + dictLimit;
 252	const U32 btLow = btMask >= curr ? 0 : curr - btMask;
 253	const U32 windowLow = zc->lowLimit;
 254	U32 *smallerPtr = bt + 2 * (curr & btMask);
 255	U32 *largerPtr = bt + 2 * (curr & btMask) + 1;
 256	U32 matchEndIdx = curr + 8;
 257	U32 dummy32; /* to be nullified at the end */
 258	U32 mnum = 0;
 259
 260	const U32 minMatch = (mls == 3) ? 3 : 4;
 261	size_t bestLength = minMatchLen - 1;
 262
 263	if (minMatch == 3) { /* HC3 match finder */
 264		U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(zc, ip);
 265		if (matchIndex3 > windowLow && (curr - matchIndex3 < (1 << 18))) {
 266			const BYTE *match;
 267			size_t currMl = 0;
 268			if ((!extDict) || matchIndex3 >= dictLimit) {
 269				match = base + matchIndex3;
 270				if (match[bestLength] == ip[bestLength])
 271					currMl = ZSTD_count(ip, match, iLimit);
 272			} else {
 273				match = dictBase + matchIndex3;
 274				if (ZSTD_readMINMATCH(match, MINMATCH) ==
 275				    ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
 276					currMl = ZSTD_count_2segments(ip + MINMATCH, match + MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
 277			}
 278
 279			/* save best solution */
 280			if (currMl > bestLength) {
 281				bestLength = currMl;
 282				matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex3;
 283				matches[mnum].len = (U32)currMl;
 284				mnum++;
 285				if (currMl > ZSTD_OPT_NUM)
 286					goto update;
 287				if (ip + currMl == iLimit)
 288					goto update; /* best possible, and avoid read overflow*/
 289			}
 290		}
 291	}
 292
 293	hashTable[h] = curr; /* Update Hash Table */
 294
 295	while (nbCompares-- && (matchIndex > windowLow)) {
 296		U32 *nextPtr = bt + 2 * (matchIndex & btMask);
 297		size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
 298		const BYTE *match;
 299
 300		if ((!extDict) || (matchIndex + matchLength >= dictLimit)) {
 301			match = base + matchIndex;
 302			if (match[matchLength] == ip[matchLength]) {
 303				matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iLimit) + 1;
 304			}
 305		} else {
 306			match = dictBase + matchIndex;
 307			matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iLimit, dictEnd, prefixStart);
 308			if (matchIndex + matchLength >= dictLimit)
 309				match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
 310		}
 311
 312		if (matchLength > bestLength) {
 313			if (matchLength > matchEndIdx - matchIndex)
 314				matchEndIdx = matchIndex + (U32)matchLength;
 315			bestLength = matchLength;
 316			matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex;
 317			matches[mnum].len = (U32)matchLength;
 318			mnum++;
 319			if (matchLength > ZSTD_OPT_NUM)
 320				break;
 321			if (ip + matchLength == iLimit) /* equal : no way to know if inf or sup */
 322				break;			/* drop, to guarantee consistency (miss a little bit of compression) */
 323		}
 324
 325		if (match[matchLength] < ip[matchLength]) {
 326			/* match is smaller than curr */
 327			*smallerPtr = matchIndex;	  /* update smaller idx */
 328			commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
 329			if (matchIndex <= btLow) {
 330				smallerPtr = &dummy32;
 331				break;
 332			}			  /* beyond tree size, stop the search */
 333			smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */
 334			matchIndex = nextPtr[1];  /* new matchIndex larger than previous (closer to curr) */
 335		} else {
 336			/* match is larger than curr */
 337			*largerPtr = matchIndex;
 338			commonLengthLarger = matchLength;
 339			if (matchIndex <= btLow) {
 340				largerPtr = &dummy32;
 341				break;
 342			} /* beyond tree size, stop the search */
 343			largerPtr = nextPtr;
 344			matchIndex = nextPtr[0];
 345		}
 346	}
 347
 348	*smallerPtr = *largerPtr = 0;
 349
 350update:
 351	zc->nextToUpdate = (matchEndIdx > curr + 8) ? matchEndIdx - 8 : curr + 1;
 352	return mnum;
 353}
 354
 355/** Tree updater, providing best match */
 356static U32 ZSTD_BtGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches,
 357				const U32 minMatchLen)
 358{
 359	if (ip < zc->base + zc->nextToUpdate)
 360		return 0; /* skipped area */
 361	ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
 362	return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
 363}
 364
 365static U32 ZSTD_BtGetAllMatches_selectMLS(ZSTD_CCtx *zc, /* Index table will be updated */
 366					  const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
 367					  ZSTD_match_t *matches, const U32 minMatchLen)
 368{
 369	switch (matchLengthSearch) {
 370	case 3: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
 371	default:
 372	case 4: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
 373	case 5: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
 374	case 7:
 375	case 6: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
 376	}
 377}
 378
 379/** Tree updater, providing best match */
 380static U32 ZSTD_BtGetAllMatches_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls,
 381					ZSTD_match_t *matches, const U32 minMatchLen)
 382{
 383	if (ip < zc->base + zc->nextToUpdate)
 384		return 0; /* skipped area */
 385	ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
 386	return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
 387}
 388
 389static U32 ZSTD_BtGetAllMatches_selectMLS_extDict(ZSTD_CCtx *zc, /* Index table will be updated */
 390						  const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
 391						  ZSTD_match_t *matches, const U32 minMatchLen)
 392{
 393	switch (matchLengthSearch) {
 394	case 3: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
 395	default:
 396	case 4: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
 397	case 5: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
 398	case 7:
 399	case 6: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
 400	}
 401}
 402
 403/*-*******************************
 404*  Optimal parser
 405*********************************/
 406FORCE_INLINE
 407void ZSTD_compressBlock_opt_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
 408{
 409	seqStore_t *seqStorePtr = &(ctx->seqStore);
 410	const BYTE *const istart = (const BYTE *)src;
 411	const BYTE *ip = istart;
 412	const BYTE *anchor = istart;
 413	const BYTE *const iend = istart + srcSize;
 414	const BYTE *const ilimit = iend - 8;
 415	const BYTE *const base = ctx->base;
 416	const BYTE *const prefixStart = base + ctx->dictLimit;
 417
 418	const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
 419	const U32 sufficient_len = ctx->params.cParams.targetLength;
 420	const U32 mls = ctx->params.cParams.searchLength;
 421	const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
 422
 423	ZSTD_optimal_t *opt = seqStorePtr->priceTable;
 424	ZSTD_match_t *matches = seqStorePtr->matchTable;
 425	const BYTE *inr;
 426	U32 offset, rep[ZSTD_REP_NUM];
 427
 428	/* init */
 429	ctx->nextToUpdate3 = ctx->nextToUpdate;
 430	ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
 431	ip += (ip == prefixStart);
 432	{
 433		U32 i;
 434		for (i = 0; i < ZSTD_REP_NUM; i++)
 435			rep[i] = ctx->rep[i];
 436	}
 437
 438	/* Match Loop */
 439	while (ip < ilimit) {
 440		U32 cur, match_num, last_pos, litlen, price;
 441		U32 u, mlen, best_mlen, best_off, litLength;
 442		memset(opt, 0, sizeof(ZSTD_optimal_t));
 443		last_pos = 0;
 444		litlen = (U32)(ip - anchor);
 445
 446		/* check repCode */
 447		{
 448			U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
 449			for (i = (ip == anchor); i < last_i; i++) {
 450				const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
 451				if ((repCur > 0) && (repCur < (S32)(ip - prefixStart)) &&
 452				    (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
 453					mlen = (U32)ZSTD_count(ip + minMatch, ip + minMatch - repCur, iend) + minMatch;
 454					if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
 455						best_mlen = mlen;
 456						best_off = i;
 457						cur = 0;
 458						last_pos = 1;
 459						goto _storeSequence;
 460					}
 461					best_off = i - (ip == anchor);
 462					do {
 463						price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
 464						if (mlen > last_pos || price < opt[mlen].price)
 465							SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
 466						mlen--;
 467					} while (mlen >= minMatch);
 468				}
 469			}
 470		}
 471
 472		match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
 473
 474		if (!last_pos && !match_num) {
 475			ip++;
 476			continue;
 477		}
 478
 479		if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
 480			best_mlen = matches[match_num - 1].len;
 481			best_off = matches[match_num - 1].off;
 482			cur = 0;
 483			last_pos = 1;
 484			goto _storeSequence;
 485		}
 486
 487		/* set prices using matches at position = 0 */
 488		best_mlen = (last_pos) ? last_pos : minMatch;
 489		for (u = 0; u < match_num; u++) {
 490			mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
 491			best_mlen = matches[u].len;
 492			while (mlen <= best_mlen) {
 493				price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
 494				if (mlen > last_pos || price < opt[mlen].price)
 495					SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
 496				mlen++;
 497			}
 498		}
 499
 500		if (last_pos < minMatch) {
 501			ip++;
 502			continue;
 503		}
 504
 505		/* initialize opt[0] */
 506		{
 507			U32 i;
 508			for (i = 0; i < ZSTD_REP_NUM; i++)
 509				opt[0].rep[i] = rep[i];
 510		}
 511		opt[0].mlen = 1;
 512		opt[0].litlen = litlen;
 513
 514		/* check further positions */
 515		for (cur = 1; cur <= last_pos; cur++) {
 516			inr = ip + cur;
 517
 518			if (opt[cur - 1].mlen == 1) {
 519				litlen = opt[cur - 1].litlen + 1;
 520				if (cur > litlen) {
 521					price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
 522				} else
 523					price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
 524			} else {
 525				litlen = 1;
 526				price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
 527			}
 528
 529			if (cur > last_pos || price <= opt[cur].price)
 530				SET_PRICE(cur, 1, 0, litlen, price);
 531
 532			if (cur == last_pos)
 533				break;
 534
 535			if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
 536				continue;
 537
 538			mlen = opt[cur].mlen;
 539			if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
 540				opt[cur].rep[2] = opt[cur - mlen].rep[1];
 541				opt[cur].rep[1] = opt[cur - mlen].rep[0];
 542				opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
 543			} else {
 544				opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
 545				opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
 546				opt[cur].rep[0] =
 547				    ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
 548			}
 549
 550			best_mlen = minMatch;
 551			{
 552				U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
 553				for (i = (opt[cur].mlen != 1); i < last_i; i++) { /* check rep */
 554					const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
 555					if ((repCur > 0) && (repCur < (S32)(inr - prefixStart)) &&
 556					    (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
 557						mlen = (U32)ZSTD_count(inr + minMatch, inr + minMatch - repCur, iend) + minMatch;
 558
 559						if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
 560							best_mlen = mlen;
 561							best_off = i;
 562							last_pos = cur + 1;
 563							goto _storeSequence;
 564						}
 565
 566						best_off = i - (opt[cur].mlen != 1);
 567						if (mlen > best_mlen)
 568							best_mlen = mlen;
 569
 570						do {
 571							if (opt[cur].mlen == 1) {
 572								litlen = opt[cur].litlen;
 573								if (cur > litlen) {
 574									price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
 575															best_off, mlen - MINMATCH, ultra);
 576								} else
 577									price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
 578							} else {
 579								litlen = 0;
 580								price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
 581							}
 582
 583							if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
 584								SET_PRICE(cur + mlen, mlen, i, litlen, price);
 585							mlen--;
 586						} while (mlen >= minMatch);
 587					}
 588				}
 589			}
 590
 591			match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
 592
 593			if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
 594				best_mlen = matches[match_num - 1].len;
 595				best_off = matches[match_num - 1].off;
 596				last_pos = cur + 1;
 597				goto _storeSequence;
 598			}
 599
 600			/* set prices using matches at position = cur */
 601			for (u = 0; u < match_num; u++) {
 602				mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
 603				best_mlen = matches[u].len;
 604
 605				while (mlen <= best_mlen) {
 606					if (opt[cur].mlen == 1) {
 607						litlen = opt[cur].litlen;
 608						if (cur > litlen)
 609							price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
 610													matches[u].off - 1, mlen - MINMATCH, ultra);
 611						else
 612							price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
 613					} else {
 614						litlen = 0;
 615						price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
 616					}
 617
 618					if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
 619						SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
 620
 621					mlen++;
 622				}
 623			}
 624		}
 625
 626		best_mlen = opt[last_pos].mlen;
 627		best_off = opt[last_pos].off;
 628		cur = last_pos - best_mlen;
 629
 630	/* store sequence */
 631_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
 632		opt[0].mlen = 1;
 633
 634		while (1) {
 635			mlen = opt[cur].mlen;
 636			offset = opt[cur].off;
 637			opt[cur].mlen = best_mlen;
 638			opt[cur].off = best_off;
 639			best_mlen = mlen;
 640			best_off = offset;
 641			if (mlen > cur)
 642				break;
 643			cur -= mlen;
 644		}
 645
 646		for (u = 0; u <= last_pos;) {
 647			u += opt[u].mlen;
 648		}
 649
 650		for (cur = 0; cur < last_pos;) {
 651			mlen = opt[cur].mlen;
 652			if (mlen == 1) {
 653				ip++;
 654				cur++;
 655				continue;
 656			}
 657			offset = opt[cur].off;
 658			cur += mlen;
 659			litLength = (U32)(ip - anchor);
 660
 661			if (offset > ZSTD_REP_MOVE_OPT) {
 662				rep[2] = rep[1];
 663				rep[1] = rep[0];
 664				rep[0] = offset - ZSTD_REP_MOVE_OPT;
 665				offset--;
 666			} else {
 667				if (offset != 0) {
 668					best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
 669					if (offset != 1)
 670						rep[2] = rep[1];
 671					rep[1] = rep[0];
 672					rep[0] = best_off;
 673				}
 674				if (litLength == 0)
 675					offset--;
 676			}
 677
 678			ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
 679			ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
 680			anchor = ip = ip + mlen;
 681		}
 682	} /* for (cur=0; cur < last_pos; ) */
 683
 684	/* Save reps for next block */
 685	{
 686		int i;
 687		for (i = 0; i < ZSTD_REP_NUM; i++)
 688			ctx->repToConfirm[i] = rep[i];
 689	}
 690
 691	/* Last Literals */
 692	{
 693		size_t const lastLLSize = iend - anchor;
 694		memcpy(seqStorePtr->lit, anchor, lastLLSize);
 695		seqStorePtr->lit += lastLLSize;
 696	}
 697}
 698
 699FORCE_INLINE
 700void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
 701{
 702	seqStore_t *seqStorePtr = &(ctx->seqStore);
 703	const BYTE *const istart = (const BYTE *)src;
 704	const BYTE *ip = istart;
 705	const BYTE *anchor = istart;
 706	const BYTE *const iend = istart + srcSize;
 707	const BYTE *const ilimit = iend - 8;
 708	const BYTE *const base = ctx->base;
 709	const U32 lowestIndex = ctx->lowLimit;
 710	const U32 dictLimit = ctx->dictLimit;
 711	const BYTE *const prefixStart = base + dictLimit;
 712	const BYTE *const dictBase = ctx->dictBase;
 713	const BYTE *const dictEnd = dictBase + dictLimit;
 714
 715	const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
 716	const U32 sufficient_len = ctx->params.cParams.targetLength;
 717	const U32 mls = ctx->params.cParams.searchLength;
 718	const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
 719
 720	ZSTD_optimal_t *opt = seqStorePtr->priceTable;
 721	ZSTD_match_t *matches = seqStorePtr->matchTable;
 722	const BYTE *inr;
 723
 724	/* init */
 725	U32 offset, rep[ZSTD_REP_NUM];
 726	{
 727		U32 i;
 728		for (i = 0; i < ZSTD_REP_NUM; i++)
 729			rep[i] = ctx->rep[i];
 730	}
 731
 732	ctx->nextToUpdate3 = ctx->nextToUpdate;
 733	ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
 734	ip += (ip == prefixStart);
 735
 736	/* Match Loop */
 737	while (ip < ilimit) {
 738		U32 cur, match_num, last_pos, litlen, price;
 739		U32 u, mlen, best_mlen, best_off, litLength;
 740		U32 curr = (U32)(ip - base);
 741		memset(opt, 0, sizeof(ZSTD_optimal_t));
 742		last_pos = 0;
 743		opt[0].litlen = (U32)(ip - anchor);
 744
 745		/* check repCode */
 746		{
 747			U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
 748			for (i = (ip == anchor); i < last_i; i++) {
 749				const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
 750				const U32 repIndex = (U32)(curr - repCur);
 751				const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
 752				const BYTE *const repMatch = repBase + repIndex;
 753				if ((repCur > 0 && repCur <= (S32)curr) &&
 754				    (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
 755				    && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
 756					/* repcode detected we should take it */
 757					const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
 758					mlen = (U32)ZSTD_count_2segments(ip + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
 759
 760					if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
 761						best_mlen = mlen;
 762						best_off = i;
 763						cur = 0;
 764						last_pos = 1;
 765						goto _storeSequence;
 766					}
 767
 768					best_off = i - (ip == anchor);
 769					litlen = opt[0].litlen;
 770					do {
 771						price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
 772						if (mlen > last_pos || price < opt[mlen].price)
 773							SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
 774						mlen--;
 775					} while (mlen >= minMatch);
 776				}
 777			}
 778		}
 779
 780		match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
 781
 782		if (!last_pos && !match_num) {
 783			ip++;
 784			continue;
 785		}
 786
 787		{
 788			U32 i;
 789			for (i = 0; i < ZSTD_REP_NUM; i++)
 790				opt[0].rep[i] = rep[i];
 791		}
 792		opt[0].mlen = 1;
 793
 794		if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
 795			best_mlen = matches[match_num - 1].len;
 796			best_off = matches[match_num - 1].off;
 797			cur = 0;
 798			last_pos = 1;
 799			goto _storeSequence;
 800		}
 801
 802		best_mlen = (last_pos) ? last_pos : minMatch;
 803
 804		/* set prices using matches at position = 0 */
 805		for (u = 0; u < match_num; u++) {
 806			mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
 807			best_mlen = matches[u].len;
 808			litlen = opt[0].litlen;
 809			while (mlen <= best_mlen) {
 810				price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
 811				if (mlen > last_pos || price < opt[mlen].price)
 812					SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
 813				mlen++;
 814			}
 815		}
 816
 817		if (last_pos < minMatch) {
 818			ip++;
 819			continue;
 820		}
 821
 822		/* check further positions */
 823		for (cur = 1; cur <= last_pos; cur++) {
 824			inr = ip + cur;
 825
 826			if (opt[cur - 1].mlen == 1) {
 827				litlen = opt[cur - 1].litlen + 1;
 828				if (cur > litlen) {
 829					price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
 830				} else
 831					price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
 832			} else {
 833				litlen = 1;
 834				price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
 835			}
 836
 837			if (cur > last_pos || price <= opt[cur].price)
 838				SET_PRICE(cur, 1, 0, litlen, price);
 839
 840			if (cur == last_pos)
 841				break;
 842
 843			if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
 844				continue;
 845
 846			mlen = opt[cur].mlen;
 847			if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
 848				opt[cur].rep[2] = opt[cur - mlen].rep[1];
 849				opt[cur].rep[1] = opt[cur - mlen].rep[0];
 850				opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
 851			} else {
 852				opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
 853				opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
 854				opt[cur].rep[0] =
 855				    ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
 856			}
 857
 858			best_mlen = minMatch;
 859			{
 860				U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
 861				for (i = (mlen != 1); i < last_i; i++) {
 862					const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
 863					const U32 repIndex = (U32)(curr + cur - repCur);
 864					const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
 865					const BYTE *const repMatch = repBase + repIndex;
 866					if ((repCur > 0 && repCur <= (S32)(curr + cur)) &&
 867					    (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
 868					    && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
 869						/* repcode detected */
 870						const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
 871						mlen = (U32)ZSTD_count_2segments(inr + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
 872
 873						if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
 874							best_mlen = mlen;
 875							best_off = i;
 876							last_pos = cur + 1;
 877							goto _storeSequence;
 878						}
 879
 880						best_off = i - (opt[cur].mlen != 1);
 881						if (mlen > best_mlen)
 882							best_mlen = mlen;
 883
 884						do {
 885							if (opt[cur].mlen == 1) {
 886								litlen = opt[cur].litlen;
 887								if (cur > litlen) {
 888									price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
 889															best_off, mlen - MINMATCH, ultra);
 890								} else
 891									price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
 892							} else {
 893								litlen = 0;
 894								price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
 895							}
 896
 897							if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
 898								SET_PRICE(cur + mlen, mlen, i, litlen, price);
 899							mlen--;
 900						} while (mlen >= minMatch);
 901					}
 902				}
 903			}
 904
 905			match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
 906
 907			if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
 908				best_mlen = matches[match_num - 1].len;
 909				best_off = matches[match_num - 1].off;
 910				last_pos = cur + 1;
 911				goto _storeSequence;
 912			}
 913
 914			/* set prices using matches at position = cur */
 915			for (u = 0; u < match_num; u++) {
 916				mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
 917				best_mlen = matches[u].len;
 918
 919				while (mlen <= best_mlen) {
 920					if (opt[cur].mlen == 1) {
 921						litlen = opt[cur].litlen;
 922						if (cur > litlen)
 923							price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
 924													matches[u].off - 1, mlen - MINMATCH, ultra);
 925						else
 926							price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
 927					} else {
 928						litlen = 0;
 929						price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
 930					}
 931
 932					if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
 933						SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
 934
 935					mlen++;
 936				}
 937			}
 938		} /* for (cur = 1; cur <= last_pos; cur++) */
 939
 940		best_mlen = opt[last_pos].mlen;
 941		best_off = opt[last_pos].off;
 942		cur = last_pos - best_mlen;
 943
 944	/* store sequence */
 945_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
 946		opt[0].mlen = 1;
 947
 948		while (1) {
 949			mlen = opt[cur].mlen;
 950			offset = opt[cur].off;
 951			opt[cur].mlen = best_mlen;
 952			opt[cur].off = best_off;
 953			best_mlen = mlen;
 954			best_off = offset;
 955			if (mlen > cur)
 956				break;
 957			cur -= mlen;
 958		}
 959
 960		for (u = 0; u <= last_pos;) {
 961			u += opt[u].mlen;
 962		}
 963
 964		for (cur = 0; cur < last_pos;) {
 965			mlen = opt[cur].mlen;
 966			if (mlen == 1) {
 967				ip++;
 968				cur++;
 969				continue;
 970			}
 971			offset = opt[cur].off;
 972			cur += mlen;
 973			litLength = (U32)(ip - anchor);
 974
 975			if (offset > ZSTD_REP_MOVE_OPT) {
 976				rep[2] = rep[1];
 977				rep[1] = rep[0];
 978				rep[0] = offset - ZSTD_REP_MOVE_OPT;
 979				offset--;
 980			} else {
 981				if (offset != 0) {
 982					best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
 983					if (offset != 1)
 984						rep[2] = rep[1];
 985					rep[1] = rep[0];
 986					rep[0] = best_off;
 987				}
 988
 989				if (litLength == 0)
 990					offset--;
 991			}
 992
 993			ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
 994			ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
 995			anchor = ip = ip + mlen;
 996		}
 997	} /* for (cur=0; cur < last_pos; ) */
 998
 999	/* Save reps for next block */
1000	{
1001		int i;
1002		for (i = 0; i < ZSTD_REP_NUM; i++)
1003			ctx->repToConfirm[i] = rep[i];
1004	}
1005
1006	/* Last Literals */
1007	{
1008		size_t lastLLSize = iend - anchor;
1009		memcpy(seqStorePtr->lit, anchor, lastLLSize);
1010		seqStorePtr->lit += lastLLSize;
1011	}
1012}
1013
1014#endif /* ZSTD_OPT_H_91842398743 */