|
|
|
@ -255,13 +255,13 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
|
|
|
|
* to provide a cost which is directly comparable to a match ending at same position */
|
|
|
|
|
static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel)
|
|
|
|
|
{
|
|
|
|
|
if (optPtr->priceType >= zop_predef) return WEIGHT(litLength, optLevel);
|
|
|
|
|
if (optPtr->priceType >= zop_predef) return (int)WEIGHT(litLength, optLevel);
|
|
|
|
|
|
|
|
|
|
/* dynamic statistics */
|
|
|
|
|
{ U32 const llCode = ZSTD_LLcode(litLength);
|
|
|
|
|
int const contribution = (LL_bits[llCode] * BITCOST_MULTIPLIER)
|
|
|
|
|
+ WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
|
|
|
|
- WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
|
|
|
|
int const contribution = (int)(LL_bits[llCode] * BITCOST_MULTIPLIER)
|
|
|
|
|
+ (int)WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */
|
|
|
|
|
- (int)WEIGHT(optPtr->litLengthFreq[llCode], optLevel);
|
|
|
|
|
#if 1
|
|
|
|
|
return contribution;
|
|
|
|
|
#else
|
|
|
|
@ -278,7 +278,7 @@ static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLe
|
|
|
|
|
const optState_t* const optPtr,
|
|
|
|
|
int optLevel)
|
|
|
|
|
{
|
|
|
|
|
int const contribution = ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
|
|
|
|
int const contribution = (int)ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel)
|
|
|
|
|
+ ZSTD_litLengthContribution(litLength, optPtr, optLevel);
|
|
|
|
|
return contribution;
|
|
|
|
|
}
|
|
|
|
@ -372,13 +372,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
|
|
|
|
|
|
|
|
|
|
/* Update hashTable3 up to ip (excluded)
|
|
|
|
|
Assumption : always within prefix (i.e. not within extDict) */
|
|
|
|
|
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip)
|
|
|
|
|
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
|
|
|
|
|
U32* nextToUpdate3,
|
|
|
|
|
const BYTE* const ip)
|
|
|
|
|
{
|
|
|
|
|
U32* const hashTable3 = ms->hashTable3;
|
|
|
|
|
U32 const hashLog3 = ms->hashLog3;
|
|
|
|
|
const BYTE* const base = ms->window.base;
|
|
|
|
|
U32 idx = ms->nextToUpdate3;
|
|
|
|
|
U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
|
|
|
|
|
U32 idx = *nextToUpdate3;
|
|
|
|
|
U32 const target = (U32)(ip - base);
|
|
|
|
|
size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
|
|
|
|
|
assert(hashLog3 > 0);
|
|
|
|
|
|
|
|
|
@ -387,6 +389,7 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE*
|
|
|
|
|
idx++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*nextToUpdate3 = target;
|
|
|
|
|
return hashTable3[hash3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -531,11 +534,12 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE_TEMPLATE
|
|
|
|
|
U32 ZSTD_insertBtAndGetAllMatches (
|
|
|
|
|
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
|
|
|
|
ZSTD_matchState_t* ms,
|
|
|
|
|
U32* nextToUpdate3,
|
|
|
|
|
const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
|
|
|
|
|
U32 rep[ZSTD_REP_NUM],
|
|
|
|
|
const U32 rep[ZSTD_REP_NUM],
|
|
|
|
|
U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
|
|
|
|
ZSTD_match_t* matches,
|
|
|
|
|
const U32 lengthToBeat,
|
|
|
|
|
U32 const mls /* template */)
|
|
|
|
|
{
|
|
|
|
@ -627,7 +631,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
|
|
|
|
|
|
|
|
/* HC3 match finder */
|
|
|
|
|
if ((mls == 3) /*static*/ && (bestLength < mls)) {
|
|
|
|
|
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
|
|
|
|
|
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
|
|
|
|
|
if ((matchIndex3 >= matchLow)
|
|
|
|
|
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
|
|
|
|
|
size_t mlen;
|
|
|
|
@ -653,9 +657,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
|
|
|
(ip+mlen == iLimit) ) { /* best possible length */
|
|
|
|
|
ms->nextToUpdate = current+1; /* skip insertion */
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} } }
|
|
|
|
|
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -760,10 +762,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
|
|
|
ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
|
|
|
|
|
ZSTD_matchState_t* ms,
|
|
|
|
|
U32* nextToUpdate3,
|
|
|
|
|
const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
|
|
|
|
|
U32 rep[ZSTD_REP_NUM], U32 const ll0,
|
|
|
|
|
ZSTD_match_t* matches, U32 const lengthToBeat)
|
|
|
|
|
const U32 rep[ZSTD_REP_NUM],
|
|
|
|
|
U32 const ll0,
|
|
|
|
|
U32 const lengthToBeat)
|
|
|
|
|
{
|
|
|
|
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
|
|
|
|
U32 const matchLengthSearch = cParams->minMatch;
|
|
|
|
@ -772,12 +777,12 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
|
|
|
|
|
ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
|
|
|
|
|
switch(matchLengthSearch)
|
|
|
|
|
{
|
|
|
|
|
case 3 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 3);
|
|
|
|
|
case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
|
|
|
|
|
default :
|
|
|
|
|
case 4 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 4);
|
|
|
|
|
case 5 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 5);
|
|
|
|
|
case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
|
|
|
|
|
case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
|
|
|
|
|
case 7 :
|
|
|
|
|
case 6 : return ZSTD_insertBtAndGetAllMatches(ms, ip, iHighLimit, dictMode, rep, ll0, matches, lengthToBeat, 6);
|
|
|
|
|
case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -853,6 +858,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
|
|
|
|
|
|
|
|
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
|
|
|
|
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
|
|
|
|
|
U32 nextToUpdate3 = ms->nextToUpdate;
|
|
|
|
|
|
|
|
|
|
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
|
|
|
|
|
ZSTD_match_t* const matches = optStatePtr->matchTable;
|
|
|
|
@ -862,7 +868,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
|
|
|
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
|
|
|
|
|
(U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);
|
|
|
|
|
assert(optLevel <= 2);
|
|
|
|
|
ms->nextToUpdate3 = ms->nextToUpdate; /* note : why a separate nextToUpdate3 stored into cctx->ms if it's synchtonized from nextToUpdate anyway ? */
|
|
|
|
|
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);
|
|
|
|
|
ip += (ip==prefixStart);
|
|
|
|
|
|
|
|
|
@ -873,7 +878,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
|
|
|
/* find first match */
|
|
|
|
|
{ U32 const litlen = (U32)(ip - anchor);
|
|
|
|
|
U32 const ll0 = !litlen;
|
|
|
|
|
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, ip, iend, dictMode, rep, ll0, matches, minMatch);
|
|
|
|
|
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
|
|
|
|
|
if (!nbMatches) { ip++; continue; }
|
|
|
|
|
|
|
|
|
|
/* initialize opt[0] */
|
|
|
|
@ -970,7 +975,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
|
|
|
|
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
|
|
|
|
|
U32 const previousPrice = opt[cur].price;
|
|
|
|
|
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
|
|
|
|
|
U32 const nbMatches = ZSTD_BtGetAllMatches(ms, inr, iend, dictMode, opt[cur].rep, ll0, matches, minMatch);
|
|
|
|
|
U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
|
|
|
|
|
U32 matchNb;
|
|
|
|
|
if (!nbMatches) {
|
|
|
|
|
DEBUGLOG(7, "rPos:%u : no match found", cur);
|
|
|
|
@ -1094,7 +1099,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
|
|
|
|
|
} /* while (ip < ilimit) */
|
|
|
|
|
|
|
|
|
|
/* Return the last literals size */
|
|
|
|
|
return iend - anchor;
|
|
|
|
|
return (size_t)(iend - anchor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1158,7 +1163,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
|
|
|
|
ms->window.dictLimit += (U32)srcSize;
|
|
|
|
|
ms->window.lowLimit = ms->window.dictLimit;
|
|
|
|
|
ms->nextToUpdate = ms->window.dictLimit;
|
|
|
|
|
ms->nextToUpdate3 = ms->window.dictLimit;
|
|
|
|
|
|
|
|
|
|
/* re-inforce weight of collected statistics */
|
|
|
|
|
ZSTD_upscaleStats(&ms->opt);
|
|
|
|
|