Merge pull request #136 from inikep/dev

merging mml3 mode
This commit is contained in:
Yann Collet
2016-03-01 17:31:03 +01:00
7 changed files with 706 additions and 599 deletions
+169 -136
View File
@@ -74,24 +74,6 @@ size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) +
/*-************************************* /*-*************************************
* Sequence storage * Sequence storage
***************************************/ ***************************************/
/** ZSTD_resetFreqs() : for opt variants */
static void ZSTD_resetFreqs(seqStore_t* ssPtr)
{
unsigned u;
ssPtr->matchLengthSum = 512; // (1<<MLbits);
ssPtr->litLengthSum = 256; // (1<<LLbits);
ssPtr->litSum = (1<<Litbits);
ssPtr->offCodeSum = (1<<Offbits);
for (u=0; u<=MaxLit; u++)
ssPtr->litFreq[u] = 1;
for (u=0; u<=MaxLL; u++)
ssPtr->litLengthFreq[u] = 1;
for (u=0; u<=MaxML; u++)
ssPtr->matchLengthFreq[u] = 1;
for (u=0; u<=MaxOff; u++)
ssPtr->offCodeFreq[u] = 1;
}
static void ZSTD_resetSeqStore(seqStore_t* ssPtr) static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
{ {
@@ -114,6 +96,7 @@ struct ZSTD_CCtx_s
U32 dictLimit; /* below that point, need extDict */ U32 dictLimit; /* below that point, need extDict */
U32 lowLimit; /* below that point, no more data */ U32 lowLimit; /* below that point, no more data */
U32 nextToUpdate; /* index from which to continue dictionary update */ U32 nextToUpdate; /* index from which to continue dictionary update */
U32 nextToUpdate3; /* index from which to continue dictionary update */
U32 loadedDictEnd; U32 loadedDictEnd;
U32 stage; U32 stage;
ZSTD_parameters params; ZSTD_parameters params;
@@ -125,6 +108,7 @@ struct ZSTD_CCtx_s
seqStore_t seqStore; /* sequences storage ptrs */ seqStore_t seqStore; /* sequences storage ptrs */
U32* hashTable; U32* hashTable;
U32* hashTable3;
U32* contentTable; U32* contentTable;
HUF_CElt* hufTable; HUF_CElt* hufTable;
U32 flagStaticTables; U32 flagStaticTables;
@@ -167,6 +151,7 @@ void ZSTD_validateParams(ZSTD_parameters* params)
CLAMP(params->windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); CLAMP(params->windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
CLAMP(params->contentLog, ZSTD_CONTENTLOG_MIN, ZSTD_CONTENTLOG_MAX); CLAMP(params->contentLog, ZSTD_CONTENTLOG_MIN, ZSTD_CONTENTLOG_MAX);
CLAMP(params->hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX); CLAMP(params->hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
CLAMP(params->hashLog3, ZSTD_HASHLOG3_MIN, ZSTD_HASHLOG3_MAX);
CLAMP(params->searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX); CLAMP(params->searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
CLAMP(params->searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX); CLAMP(params->searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
CLAMP(params->targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX); CLAMP(params->targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
@@ -188,7 +173,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
const size_t blockSize = MIN(BLOCKSIZE, (size_t)1 << params.windowLog); const size_t blockSize = MIN(BLOCKSIZE, (size_t)1 << params.windowLog);
/* reserve table memory */ /* reserve table memory */
const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog; const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog;
const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32); const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog) + (1 << params.hashLog3)) * sizeof(U32);
const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize) + ((1<<MLbits) + (1<<LLbits) + (1<<Offbits) + (1<<Litbits))*sizeof(U32); const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize) + ((1<<MLbits) + (1<<LLbits) + (1<<Offbits) + (1<<Litbits))*sizeof(U32);
if (zc->workSpaceSize < neededSpace) { if (zc->workSpaceSize < neededSpace) {
free(zc->workSpace); free(zc->workSpace);
@@ -197,7 +182,8 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
zc->workSpaceSize = neededSpace; zc->workSpaceSize = neededSpace;
} }
memset(zc->workSpace, 0, tableSpace ); /* reset only tables */ memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
zc->hashTable = (U32*)(zc->workSpace); zc->hashTable3 = (U32*)(zc->workSpace);
zc->hashTable = zc->hashTable3 + ((size_t)1 << params.hashLog3);
zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog); zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog);
zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog); zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog);
zc->hufTable = (HUF_CElt*)zc->seqStore.buffer; zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
@@ -225,6 +211,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + (blockSize>>2); zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + (blockSize>>2);
zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + (blockSize>>2); zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + (blockSize>>2);
// zc->seqStore.XXX = zc->seqStore.dumpsStart + (blockSize>>4); // zc->seqStore.XXX = zc->seqStore.dumpsStart + (blockSize>>4);
zc->seqStore.litLengthSum = 0;
zc->hbSize = 0; zc->hbSize = 0;
zc->stage = 0; zc->stage = 0;
@@ -241,14 +228,14 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx) size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
{ {
const U32 contentLog = (srcCCtx->params.strategy == ZSTD_fast) ? 1 : srcCCtx->params.contentLog; const U32 contentLog = (srcCCtx->params.strategy == ZSTD_fast) ? 1 : srcCCtx->params.contentLog;
const size_t tableSpace = ((1 << contentLog) + (1 << srcCCtx->params.hashLog)) * sizeof(U32); const size_t tableSpace = ((1 << contentLog) + (1 << srcCCtx->params.hashLog) + (1 << srcCCtx->params.hashLog3)) * sizeof(U32);
if (srcCCtx->stage!=0) return ERROR(stage_wrong); if (srcCCtx->stage!=0) return ERROR(stage_wrong);
ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params); ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params);
/* copy tables */ /* copy tables */
memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace); memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
/* copy frame header */ /* copy frame header */
dstCCtx->hbSize = srcCCtx->hbSize; dstCCtx->hbSize = srcCCtx->hbSize;
@@ -256,6 +243,7 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
/* copy dictionary pointers */ /* copy dictionary pointers */
dstCCtx->nextToUpdate= srcCCtx->nextToUpdate; dstCCtx->nextToUpdate= srcCCtx->nextToUpdate;
dstCCtx->nextToUpdate3 = srcCCtx->nextToUpdate3;
dstCCtx->nextSrc = srcCCtx->nextSrc; dstCCtx->nextSrc = srcCCtx->nextSrc;
dstCCtx->base = srcCCtx->base; dstCCtx->base = srcCCtx->base;
dstCCtx->dictBase = srcCCtx->dictBase; dstCCtx->dictBase = srcCCtx->dictBase;
@@ -555,6 +543,11 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
op += cSize; op += cSize;
} }
#if ZSTD_OPT_DEBUG >= 5
if (nbSeq >= 32768)
printf("ERROR: nbSeq=%d\n", (int)nbSeq);
#endif
/* Sequences Header */ /* Sequences Header */
if ((oend-op) < MIN_SEQUENCES_SIZE) return ERROR(dstSize_tooSmall); if ((oend-op) < MIN_SEQUENCES_SIZE) return ERROR(dstSize_tooSmall);
if (nbSeq < 128) *op++ = (BYTE)nbSeq; if (nbSeq < 128) *op++ = (BYTE)nbSeq;
@@ -732,7 +725,13 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
if (g_start==NULL) g_start = literals; if (g_start==NULL) g_start = literals;
//if (literals - g_start == 8695) //if (literals - g_start == 8695)
printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n", printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
(U32)(literals - g_start), (U32)litLength, (U32)matchCode+4, (U32)offsetCode); (U32)(literals - g_start), (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
#endif
#if ZSTD_OPT_DEBUG >= 3
if (offsetCode == 0) seqStorePtr->realRepSum++;
seqStorePtr->realSeqSum++;
seqStorePtr->realMatchSum += matchCode;
seqStorePtr->realLitSum += litLength;
#endif #endif
/* copy Literals */ /* copy Literals */
@@ -875,6 +874,10 @@ static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE
/*-************************************* /*-*************************************
* Hashes * Hashes
***************************************/ ***************************************/
static const U32 prime3bytes = 506832829U;
static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
static size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_read32(ptr), h); }
static const U32 prime4bytes = 2654435761U; static const U32 prime4bytes = 2654435761U;
static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; } static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); } static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
@@ -1373,6 +1376,7 @@ static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const B
while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1); while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
} }
#include "zstd_opt_internal.h"
/** Tree updater, providing best match */ /** Tree updater, providing best match */
static size_t ZSTD_BtFindBestMatch_extDict ( static size_t ZSTD_BtFindBestMatch_extDict (
@@ -1651,16 +1655,13 @@ _storeSequence:
} }
} }
#include "zstd_opt.h"
static void ZSTD_compressBlock_opt_bt(ZSTD_CCtx* ctx, const void* src, size_t srcSize) static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{ {
ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1, 2); if (ctx->params.searchLength == 3)
} ZSTD_compressBlock_opt_generic3(ctx, src, srcSize, 2);
else
static void ZSTD_compressBlock_opt(ZSTD_CCtx* ctx, const void* src, size_t srcSize) ZSTD_compressBlock_opt_generic4(ctx, src, srcSize, 2);
{
ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0, 2);
} }
static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize) static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
@@ -1877,14 +1878,12 @@ static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src,
ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2); ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
} }
static void ZSTD_compressBlock_opt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize) static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{ {
ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0, 2); if (ctx->params.searchLength == 3)
} ZSTD_compressBlock_opt_extDict_generic3(ctx, src, srcSize, 2);
else
static void ZSTD_compressBlock_opt_bt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize) ZSTD_compressBlock_opt_extDict_generic4(ctx, src, srcSize, 2);
{
ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1, 2);
} }
@@ -1892,9 +1891,9 @@ typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t sr
static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict) static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
{ {
static const ZSTD_blockCompressor blockCompressor[2][7] = { static const ZSTD_blockCompressor blockCompressor[2][6] = {
{ ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy,ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_opt, ZSTD_compressBlock_opt_bt }, { ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt },
{ ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_opt_extDict, ZSTD_compressBlock_opt_bt_extDict } { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict }
}; };
return blockCompressor[extDict][(U32)strat]; return blockCompressor[extDict][(U32)strat];
@@ -1920,6 +1919,11 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
BYTE* const ostart = (BYTE*)dst; BYTE* const ostart = (BYTE*)dst;
BYTE* op = ostart; BYTE* op = ostart;
const U32 maxDist = 1 << zc->params.windowLog; const U32 maxDist = 1 << zc->params.windowLog;
seqStore_t* ssPtr = &zc->seqStore;
static U32 priceFunc = 0;
ssPtr->realMatchSum = ssPtr->realLitSum = ssPtr->realSeqSum = ssPtr->realRepSum = 1;
ssPtr->priceFunc = priceFunc;
while (remaining) { while (remaining) {
size_t cSize; size_t cSize;
@@ -1953,6 +1957,13 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
op += cSize; op += cSize;
} }
#if ZSTD_OPT_DEBUG == 3
ssPtr->realMatchSum += ssPtr->realSeqSum * ((zc->params.searchLength == 3) ? 3 : 4);
printf("avgMatchL=%.2f avgLitL=%.2f match=%.1f%% lit=%.1f%% reps=%d seq=%d priceFunc=%d\n", (float)ssPtr->realMatchSum/ssPtr->realSeqSum, (float)ssPtr->realLitSum/ssPtr->realSeqSum, 100.0*ssPtr->realMatchSum/(ssPtr->realMatchSum+ssPtr->realLitSum), 100.0*ssPtr->realLitSum/(ssPtr->realMatchSum+ssPtr->realLitSum), ssPtr->realRepSum, ssPtr->realSeqSum, ssPtr->priceFunc);
priceFunc++;
#endif
return op-ostart; return op-ostart;
} }
@@ -2029,6 +2040,8 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t maxDstSize, const void* src, size_t srcSize) size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{ {
if (srcSize > BLOCKSIZE) return ERROR(srcSize_wrong); if (srcSize > BLOCKSIZE) return ERROR(srcSize_wrong);
zc->params.searchLength = MINMATCH; /* force ZSTD_btopt to MINMATCH in block mode */
ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.searchLength);
return ZSTD_compressContinue_internal(zc, dst, maxDstSize, src, srcSize, 0); return ZSTD_compressContinue_internal(zc, dst, maxDstSize, src, srcSize, 0);
} }
@@ -2058,7 +2071,6 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
case ZSTD_greedy: case ZSTD_greedy:
case ZSTD_lazy: case ZSTD_lazy:
case ZSTD_lazy2: case ZSTD_lazy2:
case ZSTD_opt:
ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength); ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength);
break; break;
@@ -2153,7 +2165,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
if (ZSTD_isError(errorCode)) return errorCode; if (ZSTD_isError(errorCode)) return errorCode;
MEM_writeLE32(zc->headerBuffer, ZSTD_MAGICNUMBER); /* Write Header */ MEM_writeLE32(zc->headerBuffer, ZSTD_MAGICNUMBER); /* Write Header */
((BYTE*)zc->headerBuffer)[4] = (BYTE)(params.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN); ((BYTE*)zc->headerBuffer)[4] = (BYTE)(params.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN + ((params.searchLength==3)<<4));
zc->hbSize = ZSTD_frameHeaderSize_min; zc->hbSize = ZSTD_frameHeaderSize_min;
zc->stage = 0; zc->stage = 0;
@@ -2163,11 +2175,13 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel) size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel)
{ {
ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_usingDict compressionLevel=%d\n", zc->base, compressionLevel);
return ZSTD_compressBegin_advanced(zc, dict, dictSize, ZSTD_getParams(compressionLevel, MAX(128 KB, dictSize))); return ZSTD_compressBegin_advanced(zc, dict, dictSize, ZSTD_getParams(compressionLevel, MAX(128 KB, dictSize)));
} }
size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel) size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
{ {
ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin compressionLevel=%d\n", zc->base, compressionLevel);
return ZSTD_compressBegin_advanced(zc, NULL, 0, ZSTD_getParams(compressionLevel, 0)); return ZSTD_compressBegin_advanced(zc, NULL, 0, ZSTD_getParams(compressionLevel, 0));
} }
@@ -2247,11 +2261,13 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel) size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
{ {
ZSTD_LOG_BLOCK("%p: ZSTD_compress_usingDict srcSize=%d dictSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, (int)dictSize, compressionLevel);
return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, dict, dictSize, ZSTD_getParams(compressionLevel, srcSize)); return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, dict, dictSize, ZSTD_getParams(compressionLevel, srcSize));
} }
size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel) size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel)
{ {
ZSTD_LOG_BLOCK("%p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, compressionLevel);
return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, NULL, 0, ZSTD_getParams(compressionLevel, srcSize)); return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, NULL, 0, ZSTD_getParams(compressionLevel, srcSize));
} }
@@ -2268,110 +2284,127 @@ size_t ZSTD_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSi
/*-===== Pre-defined compression levels =====-*/ /*-===== Pre-defined compression levels =====-*/
#define ZSTD_MAX_CLEVEL 21 #define ZSTD_MAX_CLEVEL 25
unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
static const ZSTD_parameters ZSTD_defaultParameters[4][ZSTD_MAX_CLEVEL+1] = { static const ZSTD_parameters ZSTD_defaultParameters[4][ZSTD_MAX_CLEVEL+1] = {
{ /* "default" */ { /* "default" */
/* l, W, C, H, S, L, SL, strat */ /* l, W, C, H, H3, S, L, SL, strat */
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */ { 0, 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
{ 0, 19, 13, 14, 1, 7, 4, ZSTD_fast }, /* level 1 */ { 0, 19, 13, 14, 0, 1, 7, 4, ZSTD_fast }, /* level 1 */
{ 0, 19, 15, 16, 1, 6, 4, ZSTD_fast }, /* level 2 */ { 0, 19, 15, 16, 0, 1, 6, 4, ZSTD_fast }, /* level 2 */
{ 0, 20, 18, 20, 1, 6, 4, ZSTD_fast }, /* level 3 */ { 0, 20, 18, 20, 0, 1, 6, 4, ZSTD_fast }, /* level 3 */
{ 0, 21, 19, 21, 1, 6, 4, ZSTD_fast }, /* level 4 */ { 0, 21, 19, 21, 0, 1, 6, 4, ZSTD_fast }, /* level 4 */
{ 0, 20, 14, 18, 3, 5, 4, ZSTD_greedy }, /* level 5 */ { 0, 20, 14, 18, 0, 3, 5, 4, ZSTD_greedy }, /* level 5 */
{ 0, 20, 18, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ { 0, 20, 18, 19, 0, 3, 5, 4, ZSTD_greedy }, /* level 6 */
{ 0, 21, 17, 20, 3, 5, 4, ZSTD_lazy }, /* level 7 */ { 0, 21, 17, 20, 0, 3, 5, 4, ZSTD_lazy }, /* level 7 */
{ 0, 21, 19, 20, 3, 5, 4, ZSTD_lazy }, /* level 8 */ { 0, 21, 19, 20, 0, 3, 5, 4, ZSTD_lazy }, /* level 8 */
{ 0, 21, 20, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */ { 0, 21, 20, 20, 0, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */
{ 0, 21, 19, 21, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */ { 0, 21, 19, 21, 0, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */
{ 0, 22, 20, 22, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */ { 0, 22, 20, 22, 0, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */
{ 0, 22, 20, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */ { 0, 22, 20, 22, 0, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */
{ 0, 22, 21, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */ { 0, 22, 21, 22, 0, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */
{ 0, 22, 22, 23, 5, 5, 4, ZSTD_lazy2 }, /* level 14 */ { 0, 22, 22, 23, 0, 5, 5, 4, ZSTD_lazy2 }, /* level 14 */
{ 0, 23, 23, 23, 5, 5, 4, ZSTD_lazy2 }, /* level 15 */ { 0, 23, 23, 23, 0, 5, 5, 4, ZSTD_lazy2 }, /* level 15 */
{ 0, 23, 22, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */ { 0, 23, 22, 22, 0, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */
{ 0, 24, 24, 23, 4, 5, 4, ZSTD_btlazy2 }, /* level 17 */ { 0, 24, 24, 23, 0, 4, 5, 4, ZSTD_btlazy2 }, /* level 17 */
{ 0, 24, 24, 23, 5, 5, 30, ZSTD_btopt }, /* level 18 */ { 0, 24, 24, 23, 0, 5, 5, 30, ZSTD_btopt }, /* level 18 */
{ 0, 25, 25, 24, 5, 4, 40, ZSTD_btopt }, /* level 19 */ { 0, 25, 25, 24, 0, 5, 4, 40, ZSTD_btopt }, /* level 19 */
{ 0, 26, 26, 25, 8, 4,256, ZSTD_btopt }, /* level 20 */ { 0, 26, 26, 25, 0, 8, 4,256, ZSTD_btopt }, /* level 20 */
{ 0, 26, 27, 25, 10, 4,256, ZSTD_btopt }, /* level 21 */ { 0, 26, 27, 25, 0, 10, 4,256, ZSTD_btopt }, /* level 21 */
{ 0, 24, 24, 23, 16, 5, 3, 30, ZSTD_btopt }, /* level 22 */
{ 0, 25, 25, 24, 16, 5, 3, 40, ZSTD_btopt }, /* level 23 */
{ 0, 26, 26, 25, 16, 8, 3,256, ZSTD_btopt }, /* level 24 */
{ 0, 26, 27, 25, 24, 10, 3,256, ZSTD_btopt }, /* level 25 */
}, },
{ /* for srcSize <= 256 KB */ { /* for srcSize <= 256 KB */
/* l, W, C, H, S, L, T, strat */ /* l, W, C, H, H3, S, L, T, strat */
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */
{ 0, 18, 14, 15, 1, 6, 4, ZSTD_fast }, /* level 1 */ { 0, 18, 14, 15, 0, 1, 6, 4, ZSTD_fast }, /* level 1 */
{ 0, 18, 14, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */ { 0, 18, 14, 16, 0, 1, 5, 4, ZSTD_fast }, /* level 2 */
{ 0, 18, 14, 17, 1, 5, 4, ZSTD_fast }, /* level 3.*/ { 0, 18, 14, 17, 0, 1, 5, 4, ZSTD_fast }, /* level 3.*/
{ 0, 18, 14, 15, 4, 4, 4, ZSTD_greedy }, /* level 4 */ { 0, 18, 14, 15, 0, 4, 4, 4, ZSTD_greedy }, /* level 4 */
{ 0, 18, 16, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */ { 0, 18, 16, 17, 0, 4, 4, 4, ZSTD_greedy }, /* level 5 */
{ 0, 18, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ { 0, 18, 17, 17, 0, 3, 4, 4, ZSTD_lazy }, /* level 6 */
{ 0, 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */ { 0, 18, 17, 17, 0, 4, 4, 4, ZSTD_lazy }, /* level 7 */
{ 0, 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */ { 0, 18, 17, 17, 0, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
{ 0, 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */ { 0, 18, 17, 17, 0, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
{ 0, 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */ { 0, 18, 17, 17, 0, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
{ 0, 18, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */ { 0, 18, 17, 17, 0, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
{ 0, 18, 18, 17, 4, 4, 4, ZSTD_btlazy2 }, /* level 12 */ { 0, 18, 18, 17, 0, 4, 4, 4, ZSTD_btlazy2 }, /* level 12 */
{ 0, 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13.*/ { 0, 18, 19, 17, 0, 7, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
{ 0, 18, 17, 19, 8, 4, 24, ZSTD_btopt }, /* level 14.*/ { 0, 18, 17, 19, 0, 8, 4, 24, ZSTD_btopt }, /* level 14.*/
{ 0, 18, 19, 19, 8, 4, 48, ZSTD_btopt }, /* level 15.*/ { 0, 18, 19, 19, 0, 8, 4, 48, ZSTD_btopt }, /* level 15.*/
{ 0, 18, 19, 18, 9, 4,128, ZSTD_btopt }, /* level 16.*/ { 0, 18, 19, 18, 0, 9, 4,128, ZSTD_btopt }, /* level 16.*/
{ 0, 18, 19, 18, 9, 4,192, ZSTD_btopt }, /* level 17.*/ { 0, 18, 19, 18, 0, 9, 4,192, ZSTD_btopt }, /* level 17.*/
{ 0, 18, 19, 18, 9, 4,256, ZSTD_btopt }, /* level 18.*/ { 0, 18, 19, 18, 0, 9, 4,256, ZSTD_btopt }, /* level 18.*/
{ 0, 18, 19, 18, 10, 4,256, ZSTD_btopt }, /* level 19.*/ { 0, 18, 19, 18, 0, 10, 4,256, ZSTD_btopt }, /* level 19.*/
{ 0, 18, 19, 18, 11, 4,256, ZSTD_btopt }, /* level 20.*/ { 0, 18, 19, 18, 0, 11, 4,256, ZSTD_btopt }, /* level 20.*/
{ 0, 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 21.*/ { 0, 18, 19, 18, 0, 12, 4,256, ZSTD_btopt }, /* level 21.*/
{ 0, 18, 19, 18, 0, 12, 4,256, ZSTD_btopt }, /* level 21-2*/
{ 0, 18, 19, 18, 0, 12, 4,256, ZSTD_btopt }, /* level 21-3*/
{ 0, 18, 19, 18, 0, 12, 4,256, ZSTD_btopt }, /* level 21-4*/
{ 0, 18, 19, 18, 0, 12, 4,256, ZSTD_btopt }, /* level 21-5*/
}, },
{ /* for srcSize <= 128 KB */ { /* for srcSize <= 128 KB */
/* l, W, C, H, S, L, T, strat */ /* l, W, C, H, H3, S, L, T, strat */
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */ { 0, 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
{ 0, 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */ { 0, 17, 12, 13, 0, 1, 6, 4, ZSTD_fast }, /* level 1 */
{ 0, 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */ { 0, 17, 13, 16, 0, 1, 5, 4, ZSTD_fast }, /* level 2 */
{ 0, 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */ { 0, 17, 13, 14, 0, 2, 5, 4, ZSTD_greedy }, /* level 3 */
{ 0, 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */ { 0, 17, 13, 15, 0, 3, 4, 4, ZSTD_greedy }, /* level 4 */
{ 0, 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */ { 0, 17, 15, 17, 0, 4, 4, 4, ZSTD_greedy }, /* level 5 */
{ 0, 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ { 0, 17, 16, 17, 0, 3, 4, 4, ZSTD_lazy }, /* level 6 */
{ 0, 17, 16, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */ { 0, 17, 16, 17, 0, 4, 4, 4, ZSTD_lazy }, /* level 7 */
{ 0, 17, 17, 16, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */ { 0, 17, 17, 16, 0, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
{ 0, 17, 17, 16, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */ { 0, 17, 17, 16, 0, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
{ 0, 17, 17, 16, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */ { 0, 17, 17, 16, 0, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
{ 0, 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */ { 0, 17, 17, 17, 0, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
{ 0, 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */ { 0, 17, 17, 17, 0, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
{ 0, 17, 17, 17, 9, 4, 4, ZSTD_lazy2 }, /* level 13 */ { 0, 17, 17, 17, 0, 9, 4, 4, ZSTD_lazy2 }, /* level 13 */
{ 0, 17, 18, 16, 5, 4, 20, ZSTD_btopt }, /* level 14 */ { 0, 17, 18, 16, 0, 5, 4, 20, ZSTD_btopt }, /* level 14 */
{ 0, 17, 18, 16, 9, 4, 48, ZSTD_btopt }, /* level 15 */ { 0, 17, 18, 16, 0, 9, 4, 48, ZSTD_btopt }, /* level 15 */
{ 0, 17, 18, 17, 7, 4,128, ZSTD_btopt }, /* level 16 */ { 0, 17, 18, 17, 0, 7, 4,128, ZSTD_btopt }, /* level 16 */
{ 0, 17, 18, 17, 8, 4,128, ZSTD_btopt }, /* level 17 */ { 0, 17, 18, 17, 0, 8, 4,128, ZSTD_btopt }, /* level 17 */
{ 0, 17, 18, 17, 8, 4,256, ZSTD_btopt }, /* level 18 */ { 0, 17, 18, 17, 0, 8, 4,256, ZSTD_btopt }, /* level 18 */
{ 0, 17, 18, 17, 9, 4,256, ZSTD_btopt }, /* level 19 */ { 0, 17, 18, 17, 0, 9, 4,256, ZSTD_btopt }, /* level 19 */
{ 0, 17, 18, 17, 10, 4,512, ZSTD_btopt }, /* level 20 */ { 0, 17, 18, 17, 0, 10, 4,512, ZSTD_btopt }, /* level 20 */
{ 0, 17, 18, 17, 11, 4,512, ZSTD_btopt }, /* level 21 */ { 0, 17, 18, 17, 0, 11, 4,512, ZSTD_btopt }, /* level 21 */
{ 0, 17, 18, 17, 0, 11, 4,512, ZSTD_btopt }, /* level 21-2 */
{ 0, 17, 18, 17, 0, 11, 4,512, ZSTD_btopt }, /* level 21-3 */
{ 0, 17, 18, 17, 0, 11, 4,512, ZSTD_btopt }, /* level 21-4 */
{ 0, 17, 18, 17, 0, 11, 4,512, ZSTD_btopt }, /* level 21-5 */
}, },
{ /* for srcSize <= 16 KB */ { /* for srcSize <= 16 KB */
/* l, W, C, H, S, L, T, strat */ /* l, W, C, H, H3, S, L, T, strat */
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */ { 0, 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */
{ 0, 14, 14, 14, 1, 4, 4, ZSTD_fast }, /* level 1 */ { 0, 14, 14, 14, 0, 1, 4, 4, ZSTD_fast }, /* level 1 */
{ 0, 14, 14, 15, 1, 4, 4, ZSTD_fast }, /* level 2 */ { 0, 14, 14, 15, 0, 1, 4, 4, ZSTD_fast }, /* level 2 */
{ 0, 14, 13, 15, 4, 4, 4, ZSTD_greedy }, /* level 3 */ { 0, 14, 13, 15, 0, 4, 4, 4, ZSTD_greedy }, /* level 3 */
{ 0, 14, 14, 15, 3, 4, 4, ZSTD_lazy }, /* level 4 */ { 0, 14, 14, 15, 0, 3, 4, 4, ZSTD_lazy }, /* level 4 */
{ 0, 14, 14, 14, 6, 4, 4, ZSTD_lazy }, /* level 5 */ { 0, 14, 14, 14, 0, 6, 4, 4, ZSTD_lazy }, /* level 5 */
{ 0, 14, 14, 14, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */ { 0, 14, 14, 14, 0, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */
{ 0, 14, 14, 14, 7, 4, 4, ZSTD_lazy2 }, /* level 7 */ { 0, 14, 14, 14, 0, 7, 4, 4, ZSTD_lazy2 }, /* level 7 */
{ 0, 14, 14, 14, 8, 4, 4, ZSTD_lazy2 }, /* level 8 */ { 0, 14, 14, 14, 0, 8, 4, 4, ZSTD_lazy2 }, /* level 8 */
{ 0, 14, 14, 14, 9, 4, 4, ZSTD_lazy2 }, /* level 9 */ { 0, 14, 14, 14, 0, 9, 4, 4, ZSTD_lazy2 }, /* level 9 */
{ 0, 14, 14, 14, 10, 4, 4, ZSTD_lazy2 }, /* level 10 */ { 0, 14, 14, 14, 0, 10, 4, 4, ZSTD_lazy2 }, /* level 10 */
{ 0, 14, 14, 14, 11, 4, 4, ZSTD_lazy2 }, /* level 11 */ { 0, 14, 14, 14, 0, 11, 4, 4, ZSTD_lazy2 }, /* level 11 */
{ 0, 14, 15, 15, 12, 4, 32, ZSTD_btopt }, /* level 12 */ { 0, 14, 15, 15, 0, 12, 4, 32, ZSTD_btopt }, /* level 12 */
{ 0, 14, 15, 15, 12, 4, 64, ZSTD_btopt }, /* level 13 */ { 0, 14, 15, 15, 0, 12, 4, 64, ZSTD_btopt }, /* level 13 */
{ 0, 14, 15, 15, 12, 4, 96, ZSTD_btopt }, /* level 14 */ { 0, 14, 15, 15, 0, 12, 4, 96, ZSTD_btopt }, /* level 14 */
{ 0, 14, 15, 15, 12, 4,128, ZSTD_btopt }, /* level 15 */ { 0, 14, 15, 15, 0, 12, 4,128, ZSTD_btopt }, /* level 15 */
{ 0, 14, 15, 15, 12, 4,256, ZSTD_btopt }, /* level 16 */ { 0, 14, 15, 15, 0, 12, 4,256, ZSTD_btopt }, /* level 16 */
{ 0, 14, 15, 15, 13, 4,256, ZSTD_btopt }, /* level 17 */ { 0, 14, 15, 15, 0, 13, 4,256, ZSTD_btopt }, /* level 17 */
{ 0, 14, 15, 15, 14, 4,256, ZSTD_btopt }, /* level 18 */ { 0, 14, 15, 15, 0, 14, 4,256, ZSTD_btopt }, /* level 18 */
{ 0, 14, 15, 15, 15, 4,256, ZSTD_btopt }, /* level 19 */ { 0, 14, 15, 15, 0, 15, 4,256, ZSTD_btopt }, /* level 19 */
{ 0, 14, 15, 15, 16, 4,256, ZSTD_btopt }, /* level 20 */ { 0, 14, 15, 15, 0, 16, 4,256, ZSTD_btopt }, /* level 20 */
{ 0, 14, 15, 15, 17, 4,256, ZSTD_btopt }, /* level 21 */ { 0, 14, 15, 15, 0, 17, 4,256, ZSTD_btopt }, /* level 21 */
{ 0, 14, 15, 15, 0, 17, 4,256, ZSTD_btopt }, /* level 21-2 */
{ 0, 14, 15, 15, 0, 17, 4,256, ZSTD_btopt }, /* level 21-3 */
{ 0, 14, 15, 15, 0, 17, 4,256, ZSTD_btopt }, /* level 21-4 */
{ 0, 14, 15, 15, 0, 17, 4,256, ZSTD_btopt }, /* level 21-5 */
}, },
}; };
+12 -5
View File
@@ -159,6 +159,8 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
dctx->dictEnd = NULL; dctx->dictEnd = NULL;
dctx->hufTableX4[0] = HufLog; dctx->hufTableX4[0] = HufLog;
dctx->flagStaticTables = 0; dctx->flagStaticTables = 0;
dctx->params.searchLength = MINMATCH; /* overwritten by frame but forces ZSTD_btopt to MINMATCH in block mode */
ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin searchLength=%d\n", dctx->base, dctx->params.searchLength);
return 0; return 0;
} }
@@ -292,7 +294,8 @@ size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcS
if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
memset(params, 0, sizeof(*params)); memset(params, 0, sizeof(*params));
params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN; params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported); /* reserved bits */ params->searchLength = (((const BYTE*)src)[4] & 16) ? MINMATCH-1 : MINMATCH;
if ((((const BYTE*)src)[4] >> 5) != 0) return ERROR(frameParameter_unsupported); /* reserved 3 bits */
return 0; return 0;
} }
@@ -614,7 +617,7 @@ typedef struct {
static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
{ {
size_t litLength; size_t litLength;
size_t prevOffset; size_t prevOffset;
@@ -669,7 +672,7 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
} }
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */ if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
} }
matchLength += MINMATCH; matchLength += mls;
/* save result */ /* save result */
seq->litLength = litLength; seq->litLength = litLength;
@@ -747,7 +750,7 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
} }
op += 8; match += 8; op += 8; match += 8;
if (oMatchEnd > oend-12) { if (oMatchEnd > oend-(16-3)) { // 3 = MINMATCH
if (op < oend_8) { if (op < oend_8) {
ZSTD_wildcopy(op, match, oend_8 - op); ZSTD_wildcopy(op, match, oend_8 - op);
match += oend_8 - op; match += oend_8 - op;
@@ -784,6 +787,7 @@ static size_t ZSTD_decompressSequences(
const BYTE* const base = (const BYTE*) (dctx->base); const BYTE* const base = (const BYTE*) (dctx->base);
const BYTE* const vBase = (const BYTE*) (dctx->vBase); const BYTE* const vBase = (const BYTE*) (dctx->vBase);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
const U32 mls = dctx->params.searchLength;
/* Build Decoding Tables */ /* Build Decoding Tables */
errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
@@ -811,7 +815,7 @@ static size_t ZSTD_decompressSequences(
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) { for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
size_t oneSeqSize; size_t oneSeqSize;
nbSeq--; nbSeq--;
ZSTD_decodeSequence(&sequence, &seqState); ZSTD_decodeSequence(&sequence, &seqState, mls);
oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd); oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
if (ZSTD_isError(oneSeqSize)) return oneSeqSize; if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
op += oneSeqSize; op += oneSeqSize;
@@ -854,6 +858,8 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong); if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);
ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->params.searchLength);
/* Decode literals sub-block */ /* Decode literals sub-block */
litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
if (ZSTD_isError(litCSize)) return litCSize; if (ZSTD_isError(litCSize)) return litCSize;
@@ -963,6 +969,7 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
const void* dict, size_t dictSize) const void* dict, size_t dictSize)
{ {
ZSTD_decompressBegin_usingDict(dctx, dict, dictSize); ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->params.searchLength);
ZSTD_checkContinuity(dctx, dst); ZSTD_checkContinuity(dctx, dst);
return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize); return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
} }
+22
View File
@@ -50,6 +50,20 @@
/*-************************************* /*-*************************************
* Common constants * Common constants
***************************************/ ***************************************/
#define ZSTD_OPT_DEBUG 0 // 1 = tableID=0; 3 = price func tests; 5 = check encoded sequences; 9 = full logs
#if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>0
#include <stdio.h>
#endif
#if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>=9
#define ZSTD_LOG_PARSER(...) printf(__VA_ARGS__)
#define ZSTD_LOG_ENCODE(...) printf(__VA_ARGS__)
#define ZSTD_LOG_BLOCK(...) printf(__VA_ARGS__)
#else
#define ZSTD_LOG_PARSER(...)
#define ZSTD_LOG_ENCODE(...)
#define ZSTD_LOG_BLOCK(...)
#endif
#define ZSTD_DICT_MAGIC 0xEC30A435 #define ZSTD_DICT_MAGIC 0xEC30A435
#define KB *(1 <<10) #define KB *(1 <<10)
@@ -171,9 +185,17 @@ typedef struct {
U32* litFreq; U32* litFreq;
U32* offCodeFreq; U32* offCodeFreq;
U32 matchLengthSum; U32 matchLengthSum;
U32 matchSum;
U32 litLengthSum; U32 litLengthSum;
U32 litSum; U32 litSum;
U32 offCodeSum; U32 offCodeSum;
U32 realMatchSum;
U32 realLitSum;
U32 realSeqSum;
U32 realRepSum;
U32 factor;
U32 factor2;
U32 priceFunc;
} seqStore_t; } seqStore_t;
seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx); seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx);
+263 -444
View File
@@ -31,153 +31,47 @@
- Zstd source repository : https://www.zstd.net - Zstd source repository : https://www.zstd.net
*/ */
/* Note : this file is intended to be included within zstd_compress.c */ /* Note : this file is intended to be included within zstd_opt_internal.h */
/*- Dependencies -*/
#include <stdio.h> /* for debug */
/*- Local types -*/ FORCE_INLINE U32 ZSTD_GETPRICE(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
typedef struct {
U32 off;
U32 len;
U32 back;
} ZSTD_match_t;
typedef struct {
U32 price;
U32 off;
U32 mlen;
U32 litlen;
U32 rep;
U32 rep2;
} ZSTD_optimal_t;
/*- Constants -*/
#define ZSTD_OPT_NUM (1<<12)
#define ZSTD_FREQ_THRESHOLD (256)
/*- Debug -*/
#define ZSTD_OPT_DEBUG 0 // 1 = tableID=0; 5 = check encoded sequences
#if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>=1
#define ZSTD_LOG_PARSER(...) printf(__VA_ARGS__)
#define ZSTD_LOG_ENCODE(...) printf(__VA_ARGS__)
#define ZSTD_LOG_TRY_PRICE(...) printf(__VA_ARGS__)
#else
#define ZSTD_LOG_PARSER(...)
#define ZSTD_LOG_ENCODE(...)
#define ZSTD_LOG_TRY_PRICE(...)
#endif
FORCE_INLINE U32 ZSTD_getLiteralPriceReal(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals)
{
U32 price, freq, u;
if (!litLength) return 1; /* special case */
/* literals */
price = litLength * ZSTD_highbit(seqStorePtr->litSum);
for (u=0; u < litLength; u++)
price -= ZSTD_highbit(seqStorePtr->litFreq[literals[u]]);
/* literal Length */
price += ((litLength >= MaxLL)*8) + ((litLength >= 255+MaxLL)*16) + ((litLength>=(1<<15))*8);
if (litLength >= MaxLL) litLength = MaxLL;
freq = seqStorePtr->litLengthFreq[litLength];
price += ZSTD_highbit(seqStorePtr->litLengthSum) - ZSTD_highbit(freq);
return price;
}
FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals)
{
if (seqStorePtr->litSum > ZSTD_FREQ_THRESHOLD)
return ZSTD_getLiteralPriceReal(seqStorePtr, litLength, literals);
/* backup eval */
return 1 + (litLength<<3);
}
FORCE_INLINE U32 ZSTD_getMatchPriceReal(seqStore_t* seqStorePtr, U32 offset, U32 matchLength)
{ {
/* offset */ /* offset */
BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset) + 1 : 0; BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset+1) + 1 : 0;
U32 price = ZSTD_highbit(seqStorePtr->offCodeSum) - ZSTD_highbit(seqStorePtr->offCodeFreq[offCode]); U32 price = (offCode-1) + (!offCode) + ZSTD_highbit(seqStorePtr->offCodeSum+1) - ZSTD_highbit(seqStorePtr->offCodeFreq[offCode]+1);
price += offCode;
/* match Length */ /* match Length */
price += ((matchLength >= MaxML)*8) + ((matchLength >= 255+MaxML)*16) + ((matchLength>=(1<<15))*8); matchLength -= MINMATCHOPT;
price += ((matchLength >= MaxML)<<3) + ((matchLength >= 255+MaxML)<<4) + ((matchLength>=(1<<15))<<3);
if (matchLength >= MaxML) matchLength = MaxML; if (matchLength >= MaxML) matchLength = MaxML;
price += ZSTD_highbit(seqStorePtr->matchLengthSum) - ZSTD_highbit(seqStorePtr->matchLengthFreq[matchLength]); price += ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit(seqStorePtr->matchLengthSum+1) - ZSTD_highbit(seqStorePtr->matchLengthFreq[matchLength]+1);
return price; #if ZSTD_OPT_DEBUG >= 3
} switch (seqStorePtr->priceFunc) {
default:
case 0:
FORCE_INLINE U32 ZSTD_getPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength) return 1 + price + seqStorePtr->factor + ((seqStorePtr->litSum>>5) / seqStorePtr->litLengthSum) + ((seqStorePtr->litSum<<1) / (seqStorePtr->litSum + seqStorePtr->matchSum));
{ case 1:
if (seqStorePtr->litSum > ZSTD_FREQ_THRESHOLD) return 1 + price + seqStorePtr->factor + ((seqStorePtr->factor2) ? ((seqStorePtr->litSum>>5) / seqStorePtr->litLengthSum) + ((seqStorePtr->litSum<<1) / (seqStorePtr->litSum + seqStorePtr->matchSum)) : 0);
return ZSTD_getLiteralPriceReal(seqStorePtr, litLength, literals) + ZSTD_getMatchPriceReal(seqStorePtr, offset, matchLength); case 2:
/* backup eval */ return 1 + price + seqStorePtr->factor + ((seqStorePtr->factor2) ? ((seqStorePtr->litSum>>4) / seqStorePtr->litLengthSum) + ((seqStorePtr->litSum<<1) / (seqStorePtr->litSum + seqStorePtr->matchSum)) : 0);
return (litLength<<3) + ZSTD_highbit((U32)matchLength+1) + Offbits + ZSTD_highbit((U32)offset+1); case 3:
} return 1 + price;
MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
{
U32 u;
/* literals */
seqStorePtr->litSum += litLength;
for (u=0; u < litLength; u++)
seqStorePtr->litFreq[literals[u]]++;
/* literal Length */
seqStorePtr->litLengthSum++;
if (litLength >= MaxLL)
seqStorePtr->litLengthFreq[MaxLL]++;
else
seqStorePtr->litLengthFreq[litLength]++;
/* match offset */
seqStorePtr->offCodeSum++;
BYTE offCode = (BYTE)ZSTD_highbit(offset) + 1;
if (offset==0) offCode=0;
seqStorePtr->offCodeFreq[offCode]++;
/* match Length */
seqStorePtr->matchLengthSum++;
if (matchLength >= MaxML)
seqStorePtr->matchLengthFreq[MaxML]++;
else
seqStorePtr->matchLengthFreq[matchLength]++;
}
#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
{ \
while (last_pos < pos) { opt[last_pos+1].price = 1<<30; last_pos++; } \
opt[pos].mlen = mlen_; \
opt[pos].off = offset_; \
opt[pos].litlen = litlen_; \
opt[pos].price = price_; \
ZSTD_LOG_PARSER("%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\n", (int)(inr-base), (int)pos, (int)last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \
} }
#else
return 1 + price + ((seqStorePtr->litSum>>5) / seqStorePtr->litLengthSum) + ((seqStorePtr->litSum<<1) / (seqStorePtr->litSum + seqStorePtr->matchSum));
#endif
}
/*-************************************* /*-*************************************
* Binary Tree search * Binary Tree search
***************************************/ ***************************************/
static U32 ZSTD_insertBtAndGetAllMatches ( static U32 ZSTD_INSERTBTANDGETALLMATCHES (
ZSTD_CCtx* zc, ZSTD_CCtx* zc,
const BYTE* const ip, const BYTE* const iend, const BYTE* const ip, const BYTE* const iLimit,
U32 nbCompares, const U32 mls, U32 nbCompares, const U32 mls,
U32 extDict, ZSTD_match_t* matches, size_t bestLength) U32 extDict, ZSTD_match_t* matches)
{ {
const BYTE* const base = zc->base; const BYTE* const base = zc->base;
const U32 current = (U32)(ip-base); const U32 current = (U32)(ip-base);
@@ -201,9 +95,37 @@ static U32 ZSTD_insertBtAndGetAllMatches (
U32 dummy32; /* to be nullified at the end */ U32 dummy32; /* to be nullified at the end */
U32 mnum = 0; U32 mnum = 0;
bestLength = MINMATCH-1; size_t bestLength = MINMATCHOPT-1;
hashTable[h] = current; /* Update Hash Table */ hashTable[h] = current; /* Update Hash Table */
#if MINMATCHOPT == 3
/* HC3 match finder */
U32 matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
if (matchIndex3>windowLow) {
const BYTE* match;
size_t currentMl=0;
if ((!extDict) || matchIndex3 >= dictLimit) {
match = base + matchIndex3;
if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
} else {
match = dictBase + matchIndex3;
if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
currentMl = ZSTD_count_2segments(ip+MINMATCHOPT, match+MINMATCHOPT, iLimit, dictEnd, prefixStart) + MINMATCHOPT;
}
/* save best solution */
if (currentMl > bestLength) {
bestLength = currentMl;
matches[mnum].off = current - matchIndex3;
matches[mnum].len = (U32)currentMl;
mnum++;
if (currentMl > ZSTD_OPT_NUM) return mnum;
if (ip+currentMl == iLimit) return mnum; /* best possible, and avoid read overflow*/
}
}
#endif
while (nbCompares-- && (matchIndex > windowLow)) { while (nbCompares-- && (matchIndex > windowLow)) {
U32* nextPtr = bt + 2*(matchIndex & btMask); U32* nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
@@ -211,11 +133,26 @@ static U32 ZSTD_insertBtAndGetAllMatches (
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) { if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
match = base + matchIndex; match = base + matchIndex;
if (match[matchLength] == ip[matchLength]) if (match[matchLength] == ip[matchLength]) {
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1; #if ZSTD_OPT_DEBUG >= 5
size_t ml;
if (matchIndex < dictLimit)
ml = ZSTD_count_2segments(ip, dictBase + matchIndex, iLimit, dictEnd, prefixStart);
else
ml = ZSTD_count(ip, match, ip+matchLength);
if (ml < matchLength)
printf("%d: ERROR_NOEXT: offset=%d matchLength=%d matchIndex=%d dictLimit=%d ml=%d\n", current, (int)(current - matchIndex), (int)matchLength, (int)matchIndex, (int)dictLimit, (int)ml), exit(0);
#endif
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iLimit) +1;
}
} else { } else {
match = dictBase + matchIndex; match = dictBase + matchIndex;
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); #if ZSTD_OPT_DEBUG >= 5
if (memcmp(match, ip, matchLength) != 0)
printf("%d: ERROR_EXT: matchLength=%d ZSTD_count=%d\n", current, (int)matchLength, (int)ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart)), exit(0);
#endif
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);
ZSTD_LOG_PARSER("%d: ZSTD_INSERTBTANDGETALLMATCHES=%d offset=%d dictBase=%p dictEnd=%p prefixStart=%p ip=%p match=%p\n", (int)current, (int)matchLength, (int)(current - matchIndex), dictBase, dictEnd, prefixStart, ip, match);
if (matchIndex+matchLength >= dictLimit) if (matchIndex+matchLength >= dictLimit)
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
} }
@@ -225,10 +162,9 @@ static U32 ZSTD_insertBtAndGetAllMatches (
bestLength = matchLength; bestLength = matchLength;
matches[mnum].off = current - matchIndex; matches[mnum].off = current - matchIndex;
matches[mnum].len = (U32)matchLength; matches[mnum].len = (U32)matchLength;
matches[mnum].back = 0;
mnum++; mnum++;
if (matchLength > ZSTD_OPT_NUM) break; if (matchLength > ZSTD_OPT_NUM) break;
if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ if (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */
break; /* drop, to guarantee consistency (miss a little bit of compression) */ break; /* drop, to guarantee consistency (miss a little bit of compression) */
} }
@@ -256,153 +192,56 @@ static U32 ZSTD_insertBtAndGetAllMatches (
/** Tree updater, providing best match */ /** Tree updater, providing best match */
static U32 ZSTD_BtGetAllMatches ( static U32 ZSTD_BTGETALLMATCHES (
ZSTD_CCtx* zc, ZSTD_CCtx* zc,
const BYTE* const ip, const BYTE* const iLimit, const BYTE* const ip, const BYTE* const iLimit,
const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, U32 minml) const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches)
{ {
if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls); ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minml); return ZSTD_INSERTBTANDGETALLMATCHES(zc, ip, iLimit, maxNbAttempts, mls, 0, matches);
} }
static U32 ZSTD_BtGetAllMatches_selectMLS ( static U32 ZSTD_BTGETALLMATCHES_SELECTMLS (
ZSTD_CCtx* zc, /* Index table will be updated */ ZSTD_CCtx* zc, /* Index table will be updated */
const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit, const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml) const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches)
{ {
(void)iLowLimit; /* unused */ (void)iLowLimit; /* unused */
switch(matchLengthSearch) switch(matchLengthSearch)
{ {
default : default :
case 4 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minml); case 4 : return ZSTD_BTGETALLMATCHES(zc, ip, iHighLimit, maxNbAttempts, 4, matches);
case 5 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minml); case 5 : return ZSTD_BTGETALLMATCHES(zc, ip, iHighLimit, maxNbAttempts, 5, matches);
case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minml); case 6 : return ZSTD_BTGETALLMATCHES(zc, ip, iHighLimit, maxNbAttempts, 6, matches);
} }
} }
/** Tree updater, providing best match */ /** Tree updater, providing best match */
static U32 ZSTD_BtGetAllMatches_extDict ( static U32 ZSTD_BTGETALLMATCHES_EXTDICT (
ZSTD_CCtx* zc, ZSTD_CCtx* zc,
const BYTE* const ip, const BYTE* const iLimit, const BYTE* const ip, const BYTE* const iLimit,
const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches, U32 minml) const U32 maxNbAttempts, const U32 mls, ZSTD_match_t* matches)
{ {
if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */ if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls); ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minml); return ZSTD_INSERTBTANDGETALLMATCHES(zc, ip, iLimit, maxNbAttempts, mls, 1, matches);
} }
static U32 ZSTD_BtGetAllMatches_selectMLS_extDict ( static U32 ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT (
ZSTD_CCtx* zc, /* Index table will be updated */ ZSTD_CCtx* zc, /* Index table will be updated */
const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit, const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml) const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches)
{ {
(void)iLowLimit; (void)iLowLimit;
switch(matchLengthSearch) switch(matchLengthSearch)
{ {
default : default :
case 4 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minml); case 4 : return ZSTD_BTGETALLMATCHES_EXTDICT(zc, ip, iHighLimit, maxNbAttempts, 4, matches);
case 5 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minml); case 5 : return ZSTD_BTGETALLMATCHES_EXTDICT(zc, ip, iHighLimit, maxNbAttempts, 5, matches);
case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minml); case 6 : return ZSTD_BTGETALLMATCHES_EXTDICT(zc, ip, iHighLimit, maxNbAttempts, 6, matches);
}
}
/* ***********************
* Hash Chain
*************************/
FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
U32 ZSTD_HcGetAllMatches_generic (
ZSTD_CCtx* zc, /* Index table will be updated */
const BYTE* const ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const U32 maxNbAttempts, const U32 mls, const U32 extDict, ZSTD_match_t* matches, size_t minml)
{
U32* const chainTable = zc->contentTable;
const U32 chainSize = (1U << zc->params.contentLog);
const U32 chainMask = chainSize-1;
const BYTE* const base = zc->base;
const BYTE* const dictBase = zc->dictBase;
const U32 dictLimit = zc->dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const dictStart = dictBase + zc->lowLimit;
const U32 lowLimit = zc->lowLimit;
const U32 current = (U32)(ip-base);
const U32 minChain = current > chainSize ? current - chainSize : 0;
U32 matchIndex;
U32 mnum = 0;
const BYTE* match;
U32 nbAttempts=maxNbAttempts;
minml=MINMATCH-1;
/* HC4 match finder */
matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
while ((matchIndex>lowLimit) && (nbAttempts)) {
size_t currentMl=0;
int back = 0;
nbAttempts--;
if ((!extDict) || matchIndex >= dictLimit) {
match = base + matchIndex;
if (match[minml] == ip[minml]) currentMl = ZSTD_count(ip, match, iHighLimit); if (currentMl>0) { // faster
//if (MEM_read32(match) == MEM_read32(ip)) { currentMl = ZSTD_count(ip+MINMATCH, match+MINMATCH, iHighLimit)+MINMATCH; // stronger
while ((match-back > prefixStart) && (ip-back > iLowLimit) && (ip[-back-1] == match[-back-1])) back++;
currentMl += back;
}
} else {
match = dictBase + matchIndex;
if (MEM_read32(match) == MEM_read32(ip)) { /* assumption : matchIndex <= dictLimit-4 (by table construction) */
currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, prefixStart) + MINMATCH;
while ((match-back > dictStart) && (ip-back > iLowLimit) && (ip[-back-1] == match[-back-1])) back++; /* backward match extension */
currentMl += back;
} }
/* save best solution */
if (currentMl > minml) {
minml = currentMl;
matches[mnum].off = current - matchIndex;
matches[mnum].len = (U32)currentMl;
matches[mnum].back = back;
mnum++;
if (currentMl > ZSTD_OPT_NUM) break;
if (ip+currentMl == iHighLimit) break; /* best possible, and avoid read overflow*/
}
if (matchIndex <= minChain) break;
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
}
return mnum;
}
static U32 ZSTD_HcGetAllMatches_selectMLS (
ZSTD_CCtx* zc,
const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
{
switch(matchLengthSearch)
{
default :
case 4 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 4, 0, matches, minml);
case 5 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 5, 0, matches, minml);
case 6 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 6, 0, matches, minml);
}
}
static U32 ZSTD_HcGetAllMatches_selectMLS_extDict (
ZSTD_CCtx* zc,
const BYTE* ip, const BYTE* const iLowLimit, const BYTE* const iHighLimit,
const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml)
{
switch(matchLengthSearch)
{
default :
case 4 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 4, 1, matches, minml);
case 5 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 5, 1, matches, minml);
case 6 : return ZSTD_HcGetAllMatches_generic(zc, ip, iLowLimit, iHighLimit, maxNbAttempts, 6, 1, matches, minml);
} }
} }
@@ -411,39 +250,63 @@ static U32 ZSTD_HcGetAllMatches_selectMLS_extDict (
* Optimal parser * Optimal parser
*********************************/ *********************************/
FORCE_INLINE FORCE_INLINE
void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx, void ZSTD_COMPRESSBLOCK_OPT_GENERIC(ZSTD_CCtx* ctx,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const U32 searchMethod, const U32 depth) const U32 depth)
{ {
seqStore_t* seqStorePtr = &(ctx->seqStore); seqStore_t* seqStorePtr = &(ctx->seqStore);
const BYTE* const istart = (const BYTE*)src; const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart; const BYTE* ip = istart;
const BYTE* anchor = istart; const BYTE* anchor = istart;
const BYTE* litstart;
const BYTE* const iend = istart + srcSize; const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8; const BYTE* const ilimit = iend - 8;
const BYTE* const base = ctx->base + ctx->dictLimit; const BYTE* const base = ctx->base;
const BYTE* const prefixStart = base + ctx->dictLimit;
U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE; U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE;
const U32 maxSearches = 1U << ctx->params.searchLog; const U32 maxSearches = 1U << ctx->params.searchLog;
const U32 mls = ctx->params.searchLength; const U32 mls = ctx->params.searchLength;
const U32 sufficient_len = ctx->params.targetLength;
typedef U32 (*getAllMatches_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLowLimit, const BYTE* iHighLimit, ZSTD_optimal_t opt[ZSTD_OPT_NUM+1];
U32 maxNbAttempts, U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml);
getAllMatches_f getAllMatches = searchMethod ? ZSTD_BtGetAllMatches_selectMLS : ZSTD_HcGetAllMatches_selectMLS;
ZSTD_optimal_t opt[ZSTD_OPT_NUM+4];
ZSTD_match_t matches[ZSTD_OPT_NUM+1]; ZSTD_match_t matches[ZSTD_OPT_NUM+1];
const BYTE* inr; const BYTE* inr;
U32 skip_num, cur, cur2, match_num, last_pos, litlen, price; U32 cur, match_num, last_pos, litlen, price;
const U32 sufficient_len = ctx->params.targetLength;
const U32 faster_get_matches = (ctx->params.strategy == ZSTD_opt);
/* init */ /* init */
ctx->nextToUpdate3 = ctx->nextToUpdate;
ZSTD_resetSeqStore(seqStorePtr); ZSTD_resetSeqStore(seqStorePtr);
ZSTD_resetFreqs(seqStorePtr); ZSTD_rescaleFreqs(seqStorePtr);
if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE; if ((ip-prefixStart) < REPCODE_STARTVALUE) ip = prefixStart + REPCODE_STARTVALUE;
#if ZSTD_OPT_DEBUG >= 3
size_t mostFrequent;
unsigned count[256], maxSymbolValue, usedSymbols = 0;
maxSymbolValue = 255;
mostFrequent = FSE_count(count, &maxSymbolValue, src, srcSize);
for (unsigned i=0; i<=maxSymbolValue; i++)
if (count[i]) usedSymbols++;
seqStorePtr->factor = ((usedSymbols <= 18) && (mostFrequent < (1<<14))) ? mostFrequent>>10 : 0; // helps RTF files
seqStorePtr->factor2 = (usedSymbols==256) && (mostFrequent > (1<<14));
#endif
#if 0
if (seqStorePtr->factor2)
printf("FACTOR2 usedSymbols==256;mostFrequent>(1<<14) maxSymbolValue=%d mostFrequent=%d usedSymbols=%d\n", maxSymbolValue, (int)mostFrequent, usedSymbols);
if (seqStorePtr->factor) {
printf("FACTOR1 usedSymbols<56;mostFrequent<(1<<14) maxSymbolValue=%d mostFrequent=%d usedSymbols=%d\n", maxSymbolValue, (int)mostFrequent, usedSymbols);
#if 0
for (int i=0; i<256; i++)
if (count[i]) printf("%d=%d ", i, count[i]);
printf("\n");
#endif
}
#endif
ZSTD_LOG_BLOCK("%d: COMPBLOCK_OPT_GENERIC srcSz=%d maxSrch=%d mls=%d sufLen=%d\n", (int)(ip-base), (int)srcSize, maxSearches, mls, sufficient_len);
/* Match Loop */ /* Match Loop */
while (ip < ilimit) { while (ip < ilimit) {
@@ -454,12 +317,13 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
memset(opt, 0, sizeof(ZSTD_optimal_t)); memset(opt, 0, sizeof(ZSTD_optimal_t));
last_pos = 0; last_pos = 0;
inr = ip; inr = ip;
opt[0].litlen = (U32)(ip - anchor); litstart = ((U32)(ip - anchor) > 128) ? ip - 128 : anchor;
opt[0].litlen = (U32)(ip - litstart);
/* check repCode */ /* check repCode */
if (MEM_read32(ip+1) == MEM_read32(ip+1 - rep_1)) { if (MEM_readMINMATCH(ip+1) == MEM_readMINMATCH(ip+1 - rep_1)) {
/* repcode : we take it */ /* repcode : we take it */
mlen = (U32)ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-rep_1, iend) + MINMATCH; mlen = (U32)ZSTD_count(ip+1+MINMATCHOPT, ip+1+MINMATCHOPT-rep_1, iend) + MINMATCHOPT;
ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen); ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen);
if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) { if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
@@ -469,19 +333,14 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
litlen = opt[0].litlen + 1; litlen = opt[0].litlen + 1;
do { do {
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, 0, mlen);
if (mlen + 1 > last_pos || price < opt[mlen + 1].price) if (mlen + 1 > last_pos || price < opt[mlen + 1].price)
SET_PRICE(mlen + 1, mlen, 0, litlen, price); /* note : macro modifies last_pos */ SET_PRICE(mlen + 1, mlen, 0, litlen, price); /* note : macro modifies last_pos */
mlen--; mlen--;
} while (mlen >= MINMATCH); } while (mlen >= MINMATCHOPT);
} }
best_mlen = (last_pos) ? last_pos : MINMATCH; match_num = ZSTD_BTGETALLMATCHES_SELECTMLS(ctx, ip, ip, iend, maxSearches, mls, matches); /* first search (depth 0) */
if (faster_get_matches && last_pos)
match_num = 0;
else
match_num = getAllMatches(ctx, ip, ip, iend, maxSearches, mls, matches, best_mlen); /* first search (depth 0) */
ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos); ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos);
if (!last_pos && !match_num) { ip++; continue; } if (!last_pos && !match_num) { ip++; continue; }
@@ -498,6 +357,8 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
goto _storeSequence; goto _storeSequence;
} }
best_mlen = (last_pos) ? last_pos : MINMATCHOPT;
// set prices using matches at position = 0 // set prices using matches at position = 0
for (u = 0; u < match_num; u++) { for (u = 0; u < match_num; u++) {
mlen = (u>0) ? matches[u-1].len+1 : best_mlen; mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
@@ -505,16 +366,16 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos); ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos);
litlen = opt[0].litlen; litlen = opt[0].litlen;
while (mlen <= best_mlen) { while (mlen <= best_mlen) {
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, matches[u].off, mlen);
if (mlen > last_pos || price < opt[mlen].price) if (mlen > last_pos || price < opt[mlen].price)
SET_PRICE(mlen, mlen, matches[u].off, litlen, price); SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
mlen++; mlen++;
} } } }
if (last_pos < MINMATCH) { ip++; continue; } if (last_pos < MINMATCHOPT) { ip++; continue; }
/* check further positions */ /* check further positions */
for (skip_num = 0, cur = 1; cur <= last_pos; cur++) { for (cur = 1; cur <= last_pos; cur++) {
size_t cur_rep; size_t cur_rep;
inr = ip + cur; inr = ip + cur;
@@ -522,17 +383,13 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
litlen = opt[cur-1].litlen + 1; litlen = opt[cur-1].litlen + 1;
if (cur > litlen) { if (cur > litlen) {
price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen); price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
ZSTD_LOG_TRY_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
} else } else
price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor); price = ZSTD_getLiteralPrice(seqStorePtr, litlen, litstart);
} else { } else {
litlen = 1; litlen = 1;
price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1); price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
ZSTD_LOG_TRY_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-base), price, cur, litlen, (int)ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1));
} }
ZSTD_LOG_TRY_PRICE("%d: TRY4 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur, opt[cur].price);
if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen))) if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
SET_PRICE(cur, 1, 0, litlen, price); SET_PRICE(cur, 1, 0, litlen, price);
@@ -543,35 +400,35 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
mlen = opt[cur].mlen; mlen = opt[cur].mlen;
if (opt[cur-mlen].off) { if (opt[cur].off) {
opt[cur].rep2 = opt[cur-mlen].rep; opt[cur].rep2 = opt[cur-mlen].rep;
opt[cur].rep = opt[cur-mlen].off; opt[cur].rep = opt[cur].off;
ZSTD_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_OFF cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} else { } else {
if (cur!=mlen && opt[cur-mlen].litlen == 0) { if (cur!=mlen && opt[cur].litlen == 0) {
opt[cur].rep2 = opt[cur-mlen].rep; opt[cur].rep2 = opt[cur-mlen].rep;
opt[cur].rep = opt[cur-mlen].rep2; opt[cur].rep = opt[cur-mlen].rep2;
ZSTD_LOG_PARSER("%d: COPYREP2 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_SWI cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} else { } else {
opt[cur].rep2 = opt[cur-mlen].rep2; opt[cur].rep2 = opt[cur-mlen].rep2;
opt[cur].rep = opt[cur-mlen].rep; opt[cur].rep = opt[cur-mlen].rep;
ZSTD_LOG_PARSER("%d: COPYREP3 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_NOR cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} } } }
ZSTD_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_PARSER("%d: CURRENT_NoExt price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
best_mlen = 0; best_mlen = 0;
if (!opt[cur].off && opt[cur].mlen != 1) { if (opt[cur].mlen != 1) {
cur_rep = opt[cur].rep2; cur_rep = opt[cur].rep2;
ZSTD_LOG_PARSER("%d: try REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen); ZSTD_LOG_PARSER("%d: tryNoExt REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
} else { } else {
cur_rep = opt[cur].rep; cur_rep = opt[cur].rep;
ZSTD_LOG_PARSER("%d: try REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen); ZSTD_LOG_PARSER("%d: tryNoExt REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
} }
if (MEM_read32(inr) == MEM_read32(inr - cur_rep)) { // check rep if (MEM_readMINMATCH(inr) == MEM_readMINMATCH(inr - cur_rep)) { // check rep
mlen = (U32)ZSTD_count(inr+MINMATCH, inr+MINMATCH - cur_rep, iend) + MINMATCH; mlen = (U32)ZSTD_count(inr+MINMATCHOPT, inr+MINMATCHOPT - cur_rep, iend) + MINMATCHOPT;
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off); ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off);
if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) { if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
@@ -585,77 +442,66 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
if (opt[cur].mlen == 1) { if (opt[cur].mlen == 1) {
litlen = opt[cur].litlen; litlen = opt[cur].litlen;
if (cur > litlen) { if (cur > litlen) {
price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, 0, mlen - MINMATCH); price = opt[cur - litlen].price + ZSTD_GETPRICE(seqStorePtr, litlen, inr-litlen, 0, mlen);
ZSTD_LOG_TRY_PRICE("%d: TRY5 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
} else } else
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, 0, mlen);
} else { } else {
litlen = 0; litlen = 0;
price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH); price = opt[cur].price + ZSTD_GETPRICE(seqStorePtr, 0, NULL, 0, mlen);
ZSTD_LOG_TRY_PRICE("%d: TRY7 price=%d cur=%d litlen=0 getprice=%d\n", (int)(inr-base), price, cur, (int)ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH));
} }
best_mlen = mlen; best_mlen = mlen;
if (faster_get_matches) skip_num = best_mlen; ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, 0, price, litlen);
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);
do { do {
if (cur + mlen > last_pos || price <= opt[cur + mlen].price) if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
SET_PRICE(cur + mlen, mlen, 0, litlen, price); SET_PRICE(cur + mlen, mlen, 0, litlen, price);
mlen--; mlen--;
} while (mlen >= MINMATCH); } while (mlen >= MINMATCHOPT);
} }
if (faster_get_matches && skip_num > 0) { skip_num--; continue; } match_num = ZSTD_BTGETALLMATCHES_SELECTMLS(ctx, inr, ip, iend, maxSearches, mls, matches);
best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH;
match_num = getAllMatches(ctx, inr, ip, iend, maxSearches, mls, matches, best_mlen);
ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num); ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num);
if (match_num > 0 && matches[match_num-1].len > sufficient_len) { if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
cur -= matches[match_num-1].back;
best_mlen = matches[match_num-1].len; best_mlen = matches[match_num-1].len;
best_off = matches[match_num-1].off; best_off = matches[match_num-1].off;
last_pos = cur + 1; last_pos = cur + 1;
goto _storeSequence; goto _storeSequence;
} }
best_mlen = (best_mlen > MINMATCHOPT) ? best_mlen : MINMATCHOPT;
/* set prices using matches at position = cur */ /* set prices using matches at position = cur */
for (u = 0; u < match_num; u++) { for (u = 0; u < match_num; u++) {
mlen = (u>0) ? matches[u-1].len+1 : best_mlen; mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
cur2 = cur - matches[u].back; best_mlen = (cur + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur;
best_mlen = (cur2 + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur2;
ZSTD_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, cur2, matches[u].len, matches[u].off, best_mlen, last_pos); // ZSTD_LOG_PARSER("%d: Found1 cur=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, matches[u].len, matches[u].off, best_mlen, last_pos);
if (mlen < matches[u].back + 1)
mlen = matches[u].back + 1;
while (mlen <= best_mlen) { while (mlen <= best_mlen) {
if (opt[cur2].mlen == 1) { if (opt[cur].mlen == 1) {
litlen = opt[cur2].litlen; litlen = opt[cur].litlen;
if (cur2 > litlen) if (cur > litlen)
price = opt[cur2 - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur2-litlen, matches[u].off, mlen - MINMATCH); price = opt[cur - litlen].price + ZSTD_GETPRICE(seqStorePtr, litlen, ip+cur-litlen, matches[u].off, mlen);
else else
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, matches[u].off, mlen);
} else { } else {
litlen = 0; litlen = 0;
price = opt[cur2].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off, mlen - MINMATCH); price = opt[cur].price + ZSTD_GETPRICE(seqStorePtr, 0, NULL, matches[u].off, mlen);
} }
ZSTD_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), matches[u].back, mlen, best_mlen, matches[u].off, price, litlen, cur - litlen, opt[cur - litlen].price); // ZSTD_LOG_PARSER("%d: Found2 mlen=%d best_mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, best_mlen, matches[u].off, price, litlen);
ZSTD_LOG_TRY_PRICE("%d: TRY8 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur2 + mlen, opt[cur2 + mlen].price);
if (cur2 + mlen > last_pos || (price < opt[cur2 + mlen].price)) if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
SET_PRICE(cur2 + mlen, mlen, matches[u].off, litlen, price); SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
mlen++; mlen++;
} } } // for (skip_num = 0, cur = 1; cur <= last_pos; cur++) } } } // for (cur = 1; cur <= last_pos; cur++)
best_mlen = opt[last_pos].mlen; best_mlen = opt[last_pos].mlen;
best_off = opt[last_pos].off; best_off = opt[last_pos].off;
cur = last_pos - best_mlen; cur = last_pos - best_mlen;
// printf("%d: start=%d best_mlen=%d best_off=%d cur=%d\n", (int)(ip - base), (int)(start - ip), (int)best_mlen, (int)best_off, cur);
/* store sequence */ /* store sequence */
_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
@@ -668,7 +514,6 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
while (1) { while (1) {
mlen = opt[cur].mlen; mlen = opt[cur].mlen;
ZSTD_LOG_PARSER("%d: cur=%d mlen=%d\n", (int)(ip-base), cur, mlen);
offset = opt[cur].off; offset = opt[cur].off;
opt[cur].mlen = best_mlen; opt[cur].mlen = best_mlen;
opt[cur].off = best_off; opt[cur].off = best_off;
@@ -691,7 +536,7 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
cur += mlen; cur += mlen;
U32 litLength = (U32)(ip - anchor); U32 litLength = (U32)(ip - anchor);
ZSTD_LOG_ENCODE("%d/%d: ENCODE1 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2); ZSTD_LOG_ENCODE("%d/%d: ENCODE literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
if (offset) { if (offset) {
rep_2 = rep_1; rep_2 = rep_1;
@@ -703,45 +548,39 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
rep_1 = best_off; rep_1 = best_off;
} } } }
ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2); // ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
#if ZSTD_OPT_DEBUG >= 5 #if ZSTD_OPT_DEBUG >= 5
int ml2; U32 ml2;
if (offset) if (offset)
ml2 = ZSTD_count(ip, ip-offset, iend); ml2 = (U32)ZSTD_count(ip, ip-offset, iend);
else else
ml2 = ZSTD_count(ip, ip-rep_1, iend); ml2 = (U32)ZSTD_count(ip, ip-rep_1, iend);
if (ml2 < mlen && ml2 < MINMATCH) { if ((offset >= 8) && (ml2 < mlen || ml2 < MINMATCHOPT)) {
printf("%d: ERROR iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); } printf("%d: ERROR_NoExt iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); }
if (ip < anchor) { if (ip < anchor) {
printf("%d: ERROR ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); } printf("%d: ERROR_NoExt ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (ip - offset < ctx->base) {
printf("%d: ERROR ip - offset < base iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if ((int)offset >= (1 << ctx->params.windowLog)) {
printf("%d: offset >= (1 << params.windowLog) iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (mlen < MINMATCH) {
printf("%d: ERROR mlen < MINMATCH iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (ip + mlen > iend) { if (ip + mlen > iend) {
printf("%d: ERROR ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); } printf("%d: ERROR_NoExt ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
#endif #endif
ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH); ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCHOPT);
ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH); ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCHOPT);
anchor = ip = ip + mlen; anchor = ip = ip + mlen;
} /* for (cur=0; cur < last_pos; ) */ } /* for (cur=0; cur < last_pos; ) */
/* check immediate repcode */ /* check immediate repcode */
while ( (anchor <= ilimit) while ((anchor >= prefixStart + rep_2) && (anchor <= ilimit)
&& (MEM_read32(anchor) == MEM_read32(anchor - rep_2)) ) { && (MEM_readMINMATCH(anchor) == MEM_readMINMATCH(anchor - rep_2)) ) {
/* store sequence */ /* store sequence */
best_mlen = (U32)ZSTD_count(anchor+MINMATCH, anchor+MINMATCH-rep_2, iend); best_mlen = (U32)ZSTD_count(anchor+MINMATCHOPT, anchor+MINMATCHOPT-rep_2, iend);
best_off = rep_2; best_off = rep_2;
rep_2 = rep_1; rep_2 = rep_1;
rep_1 = best_off; rep_1 = best_off;
ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2); ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, best_mlen); ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, best_mlen);
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, best_mlen); ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, best_mlen);
anchor += best_mlen+MINMATCH; anchor += best_mlen+MINMATCHOPT;
continue; /* faster when present ... (?) */ continue; /* faster when present ... (?) */
} }
if (anchor > ip) ip = anchor; if (anchor > ip) ip = anchor;
@@ -757,14 +596,15 @@ _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
FORCE_INLINE FORCE_INLINE
void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx, void ZSTD_COMPRESSBLOCK_OPT_EXTDICT_GENERIC(ZSTD_CCtx* ctx,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const U32 searchMethod, const U32 depth) const U32 depth)
{ {
seqStore_t* seqStorePtr = &(ctx->seqStore); seqStore_t* seqStorePtr = &(ctx->seqStore);
const BYTE* const istart = (const BYTE*)src; const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart; const BYTE* ip = istart;
const BYTE* anchor = istart; const BYTE* anchor = istart;
const BYTE* litstart;
const BYTE* const iend = istart + srcSize; const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8; const BYTE* const ilimit = iend - 8;
const BYTE* const base = ctx->base; const BYTE* const base = ctx->base;
@@ -772,28 +612,26 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* const prefixStart = base + dictLimit; const BYTE* const prefixStart = base + dictLimit;
const BYTE* const dictBase = ctx->dictBase; const BYTE* const dictBase = ctx->dictBase;
const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit;
const U32 lowLimit = ctx->lowLimit;
U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE; U32 rep_2=REPCODE_STARTVALUE, rep_1=REPCODE_STARTVALUE;
const U32 maxSearches = 1U << ctx->params.searchLog; const U32 maxSearches = 1U << ctx->params.searchLog;
const U32 mls = ctx->params.searchLength; const U32 mls = ctx->params.searchLength;
const U32 sufficient_len = ctx->params.targetLength;
typedef U32 (*getAllMatches_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLowLimit, const BYTE* iHighLimit, ZSTD_optimal_t opt[ZSTD_OPT_NUM+1];
U32 maxNbAttempts, U32 matchLengthSearch, ZSTD_match_t* matches, U32 minml);
getAllMatches_f getAllMatches = searchMethod ? ZSTD_BtGetAllMatches_selectMLS_extDict : ZSTD_HcGetAllMatches_selectMLS_extDict;
ZSTD_optimal_t opt[ZSTD_OPT_NUM+4];
ZSTD_match_t matches[ZSTD_OPT_NUM+1]; ZSTD_match_t matches[ZSTD_OPT_NUM+1];
const BYTE* inr; const BYTE* inr;
U32 skip_num, cur, cur2, match_num, last_pos, litlen, price; U32 cur, match_num, last_pos, litlen, price;
const U32 sufficient_len = ctx->params.targetLength;
const U32 faster_get_matches = (ctx->params.strategy == ZSTD_opt);
/* init */ /* init */
ctx->nextToUpdate3 = ctx->nextToUpdate;
ZSTD_resetSeqStore(seqStorePtr); ZSTD_resetSeqStore(seqStorePtr);
ZSTD_resetFreqs(seqStorePtr); ZSTD_rescaleFreqs(seqStorePtr);
if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
ZSTD_LOG_BLOCK("%d: COMPBLOCK_OPT_EXTDICT srcSz=%d maxSrch=%d mls=%d sufLen=%d\n", (int)(ip-base), (int)srcSize, maxSearches, mls, sufficient_len);
/* Match Loop */ /* Match Loop */
while (ip < ilimit) { while (ip < ilimit) {
U32 u, offset, best_off=0; U32 u, offset, best_off=0;
@@ -802,7 +640,8 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
memset(opt, 0, sizeof(ZSTD_optimal_t)); memset(opt, 0, sizeof(ZSTD_optimal_t));
last_pos = 0; last_pos = 0;
inr = ip; inr = ip;
opt[0].litlen = (U32)(ip - anchor); litstart = ((U32)(ip - anchor) > 128) ? ip - 128 : anchor;
opt[0].litlen = (U32)(ip - litstart);
/* check repCode */ /* check repCode */
{ {
@@ -810,10 +649,10 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
&& (MEM_read32(ip+1) == MEM_read32(repMatch)) ) { && (MEM_readMINMATCH(ip+1) == MEM_readMINMATCH(repMatch)) ) {
/* repcode detected we should take it */ /* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
mlen = (U32)ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; mlen = (U32)ZSTD_count_2segments(ip+1+MINMATCHOPT, repMatch+MINMATCHOPT, iend, repEnd, prefixStart) + MINMATCHOPT;
ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen); ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen);
if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) { if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
@@ -823,19 +662,16 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
litlen = opt[0].litlen + 1; litlen = opt[0].litlen + 1;
do { do {
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, 0, mlen);
if (mlen + 1 > last_pos || price < opt[mlen + 1].price) if (mlen + 1 > last_pos || price < opt[mlen + 1].price)
SET_PRICE(mlen + 1, mlen, 0, litlen, price); SET_PRICE(mlen + 1, mlen, 0, litlen, price);
mlen--; mlen--;
} while (mlen >= MINMATCH); } while (mlen >= MINMATCHOPT);
} } } }
best_mlen = (last_pos) ? last_pos : MINMATCH; best_mlen = (last_pos) ? last_pos : MINMATCHOPT;
if (faster_get_matches && last_pos) match_num = ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT(ctx, ip, ip, iend, maxSearches, mls, matches); /* first search (depth 0) */
match_num = 0;
else
match_num = getAllMatches(ctx, ip, ip, iend, maxSearches, mls, matches, best_mlen); /* first search (depth 0) */
ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos); ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos);
if (!last_pos && !match_num) { ip++; continue; } if (!last_pos && !match_num) { ip++; continue; }
@@ -859,19 +695,19 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos); ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos);
litlen = opt[0].litlen; litlen = opt[0].litlen;
while (mlen <= best_mlen) { while (mlen <= best_mlen) {
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, matches[u].off, mlen);
if (mlen > last_pos || price < opt[mlen].price) if (mlen > last_pos || price < opt[mlen].price)
SET_PRICE(mlen, mlen, matches[u].off, litlen, price); SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
mlen++; mlen++;
} } } }
if (last_pos < MINMATCH) { if (last_pos < MINMATCHOPT) {
// ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ // ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
ip++; continue; ip++; continue;
} }
/* check further positions */ /* check further positions */
for (skip_num = 0, cur = 1; cur <= last_pos; cur++) { for (cur = 1; cur <= last_pos; cur++) {
size_t cur_rep; size_t cur_rep;
inr = ip + cur; inr = ip + cur;
@@ -879,17 +715,13 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
litlen = opt[cur-1].litlen + 1; litlen = opt[cur-1].litlen + 1;
if (cur > litlen) { if (cur > litlen) {
price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen); price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
ZSTD_LOG_TRY_PRICE("%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
} else } else
price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor); price = ZSTD_getLiteralPrice(seqStorePtr, litlen, litstart);
} else { } else {
litlen = 1; litlen = 1;
price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1); price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
ZSTD_LOG_TRY_PRICE("%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\n", (int)(inr-base), price, cur, litlen, (int)ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1));
} }
ZSTD_LOG_TRY_PRICE("%d: TRY4 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur, opt[cur].price);
if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen))) if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
SET_PRICE(cur, 1, 0, litlen, price); SET_PRICE(cur, 1, 0, litlen, price);
@@ -900,41 +732,41 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
mlen = opt[cur].mlen; mlen = opt[cur].mlen;
if (opt[cur-mlen].off) { if (opt[cur].off) {
opt[cur].rep2 = opt[cur-mlen].rep; opt[cur].rep2 = opt[cur-mlen].rep;
opt[cur].rep = opt[cur-mlen].off; opt[cur].rep = opt[cur].off;
ZSTD_LOG_PARSER("%d: COPYREP1 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_OFF cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} else { } else {
if (cur!=mlen && opt[cur-mlen].litlen == 0) { if (cur!=mlen && opt[cur].litlen == 0) {
opt[cur].rep2 = opt[cur-mlen].rep; opt[cur].rep2 = opt[cur-mlen].rep;
opt[cur].rep = opt[cur-mlen].rep2; opt[cur].rep = opt[cur-mlen].rep2;
ZSTD_LOG_PARSER("%d: COPYREP2 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_SWI cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} else { } else {
opt[cur].rep2 = opt[cur-mlen].rep2; opt[cur].rep2 = opt[cur-mlen].rep2;
opt[cur].rep = opt[cur-mlen].rep; opt[cur].rep = opt[cur-mlen].rep;
ZSTD_LOG_PARSER("%d: COPYREP3 cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_ENCODE("%d: COPYREP_NOR cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
} } } }
ZSTD_LOG_PARSER("%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2); ZSTD_LOG_PARSER("%d: CURRENT_Ext price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
best_mlen = 0; best_mlen = 0;
if (!opt[cur].off && opt[cur].mlen != 1) { if (opt[cur].mlen != 1) {
cur_rep = opt[cur].rep2; cur_rep = opt[cur].rep2;
ZSTD_LOG_PARSER("%d: try REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen); ZSTD_LOG_PARSER("%d: tryExt REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
} else { } else {
cur_rep = opt[cur].rep; cur_rep = opt[cur].rep;
ZSTD_LOG_PARSER("%d: try REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen); ZSTD_LOG_PARSER("%d: tryExt REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
} }
const U32 repIndex = (U32)(current+cur - cur_rep); const U32 repIndex = (U32)(current+cur - cur_rep);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
&&(MEM_read32(inr) == MEM_read32(repMatch)) ) { &&(MEM_readMINMATCH(inr) == MEM_readMINMATCH(repMatch)) ) {
/* repcode detected */ /* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
mlen = (U32)ZSTD_count_2segments(inr+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; mlen = (U32)ZSTD_count_2segments(inr+MINMATCHOPT, repMatch+MINMATCHOPT, iend, repEnd, prefixStart) + MINMATCHOPT;
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off); ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off);
if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) { if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
@@ -948,37 +780,31 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
if (opt[cur].mlen == 1) { if (opt[cur].mlen == 1) {
litlen = opt[cur].litlen; litlen = opt[cur].litlen;
if (cur > litlen) { if (cur > litlen) {
price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, 0, mlen - MINMATCH); price = opt[cur - litlen].price + ZSTD_GETPRICE(seqStorePtr, litlen, inr-litlen, 0, mlen);
ZSTD_LOG_TRY_PRICE("%d: TRY5 opt[%d].price=%d price=%d cur=%d litlen=%d\n", (int)(inr-base), cur - litlen, opt[cur - litlen].price, price, cur, litlen);
} else } else
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, 0, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, 0, mlen);
} else { } else {
litlen = 0; litlen = 0;
price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH); price = opt[cur].price + ZSTD_GETPRICE(seqStorePtr, 0, NULL, 0, mlen);
ZSTD_LOG_TRY_PRICE("%d: TRY7 price=%d cur=%d litlen=0 getprice=%d\n", (int)(inr-base), price, cur, (int)ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - MINMATCH));
} }
best_mlen = mlen; best_mlen = mlen;
if (faster_get_matches) skip_num = best_mlen;
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price); ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, 0, price, litlen);
do { do {
if (cur + mlen > last_pos || price <= opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH if (cur + mlen > last_pos || price <= opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH
SET_PRICE(cur + mlen, mlen, 0, litlen, price); SET_PRICE(cur + mlen, mlen, 0, litlen, price);
mlen--; mlen--;
} while (mlen >= MINMATCH); } while (mlen >= MINMATCHOPT);
} }
if (faster_get_matches && skip_num > 0) { skip_num--; continue; } best_mlen = (best_mlen > MINMATCHOPT) ? best_mlen : MINMATCHOPT;
best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH; match_num = ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT(ctx, inr, ip, iend, maxSearches, mls, matches);
match_num = getAllMatches(ctx, inr, ip, iend, maxSearches, mls, matches, best_mlen);
ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num); ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num);
if (match_num > 0 && matches[match_num-1].len > sufficient_len) { if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
cur -= matches[match_num-1].back;
best_mlen = matches[match_num-1].len; best_mlen = matches[match_num-1].len;
best_off = matches[match_num-1].off; best_off = matches[match_num-1].off;
last_pos = cur + 1; last_pos = cur + 1;
@@ -988,38 +814,33 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
// set prices using matches at position = cur // set prices using matches at position = cur
for (u = 0; u < match_num; u++) { for (u = 0; u < match_num; u++) {
mlen = (u>0) ? matches[u-1].len+1 : best_mlen; mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
cur2 = cur - matches[u].back; best_mlen = (cur + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur;
best_mlen = (cur2 + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur2;
ZSTD_LOG_PARSER("%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, cur2, matches[u].len, matches[u].off, best_mlen, last_pos); // ZSTD_LOG_PARSER("%d: Found1 cur=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, matches[u].len, matches[u].off, best_mlen, last_pos);
if (mlen < matches[u].back + 1)
mlen = matches[u].back + 1;
while (mlen <= best_mlen) { while (mlen <= best_mlen) {
if (opt[cur2].mlen == 1) { if (opt[cur].mlen == 1) {
litlen = opt[cur2].litlen; litlen = opt[cur].litlen;
if (cur2 > litlen) if (cur > litlen)
price = opt[cur2 - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur2-litlen, matches[u].off, mlen - MINMATCH); price = opt[cur - litlen].price + ZSTD_GETPRICE(seqStorePtr, litlen, ip+cur-litlen, matches[u].off, mlen);
else else
price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off, mlen - MINMATCH); price = ZSTD_GETPRICE(seqStorePtr, litlen, litstart, matches[u].off, mlen);
} else { } else {
litlen = 0; litlen = 0;
price = opt[cur2].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off, mlen - MINMATCH); price = opt[cur].price + ZSTD_GETPRICE(seqStorePtr, 0, NULL, matches[u].off, mlen);
} }
ZSTD_LOG_PARSER("%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\n", (int)(inr-base), matches[u].back, mlen, best_mlen, matches[u].off, price, litlen, cur - litlen, opt[cur - litlen].price); // ZSTD_LOG_PARSER("%d: Found2 mlen=%d best_mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, best_mlen, matches[u].off, price, litlen);
ZSTD_LOG_TRY_PRICE("%d: TRY8 price=%d opt[%d].price=%d\n", (int)(inr-base), price, cur2 + mlen, opt[cur2 + mlen].price);
if (cur2 + mlen > last_pos || (price < opt[cur2 + mlen].price)) if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
SET_PRICE(cur2 + mlen, mlen, matches[u].off, litlen, price); SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
mlen++; mlen++;
} } } // for (skip_num = 0, cur = 1; cur <= last_pos; cur++) } } } // for (cur = 1; cur <= last_pos; cur++)
best_mlen = opt[last_pos].mlen; best_mlen = opt[last_pos].mlen;
best_off = opt[last_pos].off; best_off = opt[last_pos].off;
cur = last_pos - best_mlen; cur = last_pos - best_mlen;
// printf("%d: start=%d best_mlen=%d best_off=%d cur=%d\n", (int)(ip - base), (int)(start - ip), (int)best_mlen, (int)best_off, cur);
/* store sequence */ /* store sequence */
_storeSequence: // cur, last_pos, best_mlen, best_off have to be set _storeSequence: // cur, last_pos, best_mlen, best_off have to be set
@@ -1031,7 +852,6 @@ _storeSequence: // cur, last_pos, best_mlen, best_off have to be set
while (1) { while (1) {
mlen = opt[cur].mlen; mlen = opt[cur].mlen;
ZSTD_LOG_PARSER("%d: cur=%d mlen=%d\n", (int)(ip-base), cur, mlen);
offset = opt[cur].off; offset = opt[cur].off;
opt[cur].mlen = best_mlen; opt[cur].mlen = best_mlen;
opt[cur].off = best_off; opt[cur].off = best_off;
@@ -1070,44 +890,43 @@ _storeSequence: // cur, last_pos, best_mlen, best_off have to be set
ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2); ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
#if ZSTD_OPT_DEBUG >= 5 #if ZSTD_OPT_DEBUG >= 5
int ml2; U32 ml2;
if (offset) if (offset) {
ml2 = ZSTD_count(ip, ip-offset, iend); if (offset > (size_t)(ip - prefixStart)) {
else const BYTE* match = dictEnd - (offset - (ip - prefixStart));
ml2 = ZSTD_count(ip, ip-rep_1, iend); ml2 = ZSTD_count_2segments(ip, match, iend, dictEnd, prefixStart);
if (ml2 < mlen && ml2 < MINMATCH) { ZSTD_LOG_PARSER("%d: ZSTD_count_2segments=%d offset=%d dictBase=%p dictEnd=%p prefixStart=%p ip=%p match=%p\n", (int)current, (int)ml2, (int)offset, dictBase, dictEnd, prefixStart, ip, match);
printf("%d: ERROR iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); } }
else ml2 = (U32)ZSTD_count(ip, ip-offset, iend);
}
else ml2 = (U32)ZSTD_count(ip, ip-rep_1, iend);
if ((offset >= 8) && (ml2 < mlen || ml2 < MINMATCHOPT)) {
printf("%d: ERROR_Ext iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); }
if (ip < anchor) { if (ip < anchor) {
printf("%d: ERROR ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); } printf("%d: ERROR_Ext ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (ip - offset < ctx->base) {
printf("%d: ERROR ip - offset < base iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if ((int)offset >= (1 << ctx->params.windowLog)) {
printf("%d: offset >= (1 << params.windowLog) iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (mlen < MINMATCH) {
printf("%d: ERROR mlen < MINMATCH iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
if (ip + mlen > iend) { if (ip + mlen > iend) {
printf("%d: ERROR ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); } printf("%d: ERROR_Ext ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
#endif #endif
ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH); ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-MINMATCHOPT);
ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCH); ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-MINMATCHOPT);
anchor = ip = ip + mlen; anchor = ip = ip + mlen;
} }
/* check immediate repcode */ /* check immediate repcode */
while (anchor <= ilimit) { while ((anchor >= base + lowLimit + rep_2) && (anchor <= ilimit)) {
const U32 repIndex = (U32)((anchor-base) - rep_2); const U32 repIndex = (U32)((anchor-base) - rep_2);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex; const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
&& (MEM_read32(anchor) == MEM_read32(repMatch)) ) { && (MEM_readMINMATCH(anchor) == MEM_readMINMATCH(repMatch)) ) {
/* repcode detected, let's take it */ /* repcode detected, let's take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
mlen = (U32)ZSTD_count_2segments(anchor+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH; mlen = (U32)ZSTD_count_2segments(anchor+MINMATCHOPT, repMatch+MINMATCHOPT, iend, repEnd, prefixStart) + MINMATCHOPT;
offset = rep_2; rep_2 = rep_1; rep_1 = offset; /* swap offset history */ offset = rep_2; rep_2 = rep_1; rep_1 = offset; /* swap offset history */
ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2); ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, mlen-MINMATCH); ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, mlen-MINMATCHOPT);
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, mlen-MINMATCH); ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, mlen-MINMATCHOPT);
anchor += mlen; anchor += mlen;
continue; /* faster when present ... (?) */ continue; /* faster when present ... (?) */
} }
+224
View File
@@ -0,0 +1,224 @@
/*
zstd_opt_internal - common optimal parser functions to include
Header File for include
Copyright (C) 2016, Przemyslaw Skibinski, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- zstd source repository : https://github.com/Cyan4973/zstd
*/
/* Note : this file is intended to be included within zstd_compress.c */
#ifndef ZSTD_OPT_INTERNAL_H_MODULE
#define ZSTD_OPT_INTERNAL_H_MODULE
/*-*******************************************
* The optimal parser
*********************************************/
/*- Constants -*/
#define ZSTD_OPT_NUM (1<<12)
#define ZSTD_FREQ_START 1
#define ZSTD_FREQ_STEP 1
#define ZSTD_FREQ_DIV 5
typedef struct {
U32 off;
U32 len;
} ZSTD_match_t;
typedef struct {
U32 price;
U32 off;
U32 mlen;
U32 litlen;
U32 rep;
U32 rep2;
} ZSTD_optimal_t;
MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr)
{
unsigned u;
if (ssPtr->litLengthSum == 0) {
ssPtr->matchLengthSum = ZSTD_FREQ_START*(1<<MLbits);
ssPtr->litLengthSum = ZSTD_FREQ_START*(1<<LLbits);
ssPtr->litSum = ZSTD_FREQ_START*(1<<Litbits);
ssPtr->offCodeSum = ZSTD_FREQ_START*(1<<Offbits);
ssPtr->matchSum = ssPtr->litSum;
for (u=0; u<=MaxLit; u++)
ssPtr->litFreq[u] = ZSTD_FREQ_START;
for (u=0; u<=MaxLL; u++)
ssPtr->litLengthFreq[u] = ZSTD_FREQ_START;
for (u=0; u<=MaxML; u++)
ssPtr->matchLengthFreq[u] = ZSTD_FREQ_START;
for (u=0; u<=MaxOff; u++)
ssPtr->offCodeFreq[u] = ZSTD_FREQ_START;
} else {
ssPtr->matchLengthSum = 0;
ssPtr->litLengthSum = 0;
ssPtr->litSum = 0;
ssPtr->offCodeSum = 0;
ssPtr->matchSum = 0;
for (u=0; u<=MaxLit; u++) {
ssPtr->litFreq[u] = ZSTD_FREQ_START + (ssPtr->litFreq[u]>>ZSTD_FREQ_DIV);
ssPtr->litSum += ssPtr->litFreq[u];
}
for (u=0; u<=MaxLL; u++) {
ssPtr->litLengthFreq[u] = ZSTD_FREQ_START + (ssPtr->litLengthFreq[u]>>ZSTD_FREQ_DIV);
ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
}
for (u=0; u<=MaxML; u++) {
ssPtr->matchLengthFreq[u] = ZSTD_FREQ_START + (ssPtr->matchLengthFreq[u]>>ZSTD_FREQ_DIV);
ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
}
for (u=0; u<=MaxOff; u++) {
ssPtr->offCodeFreq[u] = ZSTD_FREQ_START + (ssPtr->offCodeFreq[u]>>ZSTD_FREQ_DIV);
ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
}
}
}
MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
{
U32 u;
/* literals */
seqStorePtr->litSum += litLength * ZSTD_FREQ_STEP;
for (u=0; u < litLength; u++)
seqStorePtr->litFreq[literals[u]] += ZSTD_FREQ_STEP;
/* literal Length */
seqStorePtr->litLengthSum += ZSTD_FREQ_STEP;
if (litLength >= MaxLL)
seqStorePtr->litLengthFreq[MaxLL] += ZSTD_FREQ_STEP;
else
seqStorePtr->litLengthFreq[litLength] += ZSTD_FREQ_STEP;
/* match offset */
seqStorePtr->offCodeSum += ZSTD_FREQ_STEP;
BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset+1) + 1 : 0;
seqStorePtr->offCodeFreq[offCode] += ZSTD_FREQ_STEP;
/* match Length */
seqStorePtr->matchLengthSum += ZSTD_FREQ_STEP;
if (matchLength >= MaxML)
seqStorePtr->matchLengthFreq[MaxML] += ZSTD_FREQ_STEP;
else
seqStorePtr->matchLengthFreq[matchLength] += ZSTD_FREQ_STEP;
}
FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals)
{
U32 price, u;
if (litLength == 0)
return ZSTD_highbit(seqStorePtr->litLengthSum+1) - ZSTD_highbit(seqStorePtr->litLengthFreq[0]+1);
/* literals */
price = litLength * ZSTD_highbit(seqStorePtr->litSum+1);
for (u=0; u < litLength; u++)
price -= ZSTD_highbit(seqStorePtr->litFreq[literals[u]]+1);
/* literal Length */
price += ((litLength >= MaxLL)<<3) + ((litLength >= 255+MaxLL)<<4) + ((litLength>=(1<<15))<<3);
if (litLength >= MaxLL) litLength = MaxLL;
price += ZSTD_highbit(seqStorePtr->litLengthSum+1) - ZSTD_highbit(seqStorePtr->litLengthFreq[litLength]+1);
return price;
}
#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
{ \
while (last_pos < pos) { opt[last_pos+1].price = 1<<30; last_pos++; } \
opt[pos].mlen = mlen_; \
opt[pos].off = offset_; \
opt[pos].litlen = litlen_; \
opt[pos].price = price_; \
ZSTD_LOG_PARSER("%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\n", (int)(inr-base), (int)pos, (int)last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \
}
/* Update hashTable3 up to ip (excluded)
Assumption : always within prefix (ie. not within extDict) */
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
{
U32* const hashTable3 = zc->hashTable3;
const U32 hashLog3 = zc->params.hashLog3;
const BYTE* const base = zc->base;
const U32 target = (U32)(ip - base);
U32 idx = zc->nextToUpdate3;
while(idx < target) {
hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
idx++;
}
zc->nextToUpdate3 = target;
return hashTable3[ZSTD_hash3Ptr(ip, hashLog3)];
}
#define MINMATCHOPT 4
#define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr))
#define ZSTD_GETPRICE ZSTD_getPrice4
#define ZSTD_INSERTBTANDGETALLMATCHES ZSTD_insertBtAndGetAllMatches4
#define ZSTD_BTGETALLMATCHES ZSTD_BtGetAllMatches4
#define ZSTD_BTGETALLMATCHES_SELECTMLS ZSTD_BtGetAllMatches_selectMLS4
#define ZSTD_BTGETALLMATCHES_EXTDICT ZSTD_BtGetAllMatches_extDict4
#define ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT ZSTD_BtGetAllMatches_selectMLS_extDict4
#define ZSTD_COMPRESSBLOCK_OPT_GENERIC ZSTD_compressBlock_opt_generic4
#define ZSTD_COMPRESSBLOCK_OPT_EXTDICT_GENERIC ZSTD_compressBlock_opt_extDict_generic4
#include "zstd_opt.h"
#undef MINMATCHOPT
#undef MEM_readMINMATCH
#undef ZSTD_GETPRICE
#undef ZSTD_INSERTBTANDGETALLMATCHES
#undef ZSTD_BTGETALLMATCHES
#undef ZSTD_BTGETALLMATCHES_SELECTMLS
#undef ZSTD_BTGETALLMATCHES_EXTDICT
#undef ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT
#undef ZSTD_COMPRESSBLOCK_OPT_GENERIC
#undef ZSTD_COMPRESSBLOCK_OPT_EXTDICT_GENERIC
#define MINMATCHOPT 3
#define MEM_readMINMATCH(ptr) ((U32)(MEM_read32(ptr)<<8))
#define ZSTD_GETPRICE ZSTD_getPrice3
#define ZSTD_INSERTBTANDGETALLMATCHES ZSTD_insertBtAndGetAllMatches3
#define ZSTD_BTGETALLMATCHES ZSTD_BtGetAllMatches3
#define ZSTD_BTGETALLMATCHES_SELECTMLS ZSTD_BtGetAllMatches_selectMLS3
#define ZSTD_BTGETALLMATCHES_EXTDICT ZSTD_BtGetAllMatches_extDict3
#define ZSTD_BTGETALLMATCHES_SELECTMLS_EXTDICT ZSTD_BtGetAllMatches_selectMLS_extDict3
#define ZSTD_COMPRESSBLOCK_OPT_GENERIC ZSTD_compressBlock_opt_generic3
#define ZSTD_COMPRESSBLOCK_OPT_EXTDICT_GENERIC ZSTD_compressBlock_opt_extDict_generic3
#include "zstd_opt.h"
#endif /* ZSTD_OPT_INTERNAL_H_MODULE */
+5 -2
View File
@@ -64,15 +64,17 @@ extern "C" {
#define ZSTD_CONTENTLOG_MIN 4 #define ZSTD_CONTENTLOG_MIN 4
#define ZSTD_HASHLOG_MAX 28 #define ZSTD_HASHLOG_MAX 28
#define ZSTD_HASHLOG_MIN 12 #define ZSTD_HASHLOG_MIN 12
#define ZSTD_HASHLOG3_MAX 24
#define ZSTD_HASHLOG3_MIN 12
#define ZSTD_SEARCHLOG_MAX (ZSTD_CONTENTLOG_MAX-1) #define ZSTD_SEARCHLOG_MAX (ZSTD_CONTENTLOG_MAX-1)
#define ZSTD_SEARCHLOG_MIN 1 #define ZSTD_SEARCHLOG_MIN 1
#define ZSTD_SEARCHLENGTH_MAX 7 #define ZSTD_SEARCHLENGTH_MAX 7
#define ZSTD_SEARCHLENGTH_MIN 4 #define ZSTD_SEARCHLENGTH_MIN 3
#define ZSTD_TARGETLENGTH_MIN 4 #define ZSTD_TARGETLENGTH_MIN 4
#define ZSTD_TARGETLENGTH_MAX 999 #define ZSTD_TARGETLENGTH_MAX 999
/* from faster to stronger */ /* from faster to stronger */
typedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2, ZSTD_opt, ZSTD_btopt } ZSTD_strategy; typedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2, ZSTD_btopt } ZSTD_strategy;
typedef struct typedef struct
{ {
@@ -80,6 +82,7 @@ typedef struct
U32 windowLog; /* largest match distance : larger == more compression, more memory needed during decompression */ U32 windowLog; /* largest match distance : larger == more compression, more memory needed during decompression */
U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */ U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */
U32 hashLog; /* dispatch table : larger == faster, more memory */ U32 hashLog; /* dispatch table : larger == faster, more memory */
U32 hashLog3; /* dispatch table : larger == faster, more memory */
U32 searchLog; /* nb of searches : larger == more compression, slower */ U32 searchLog; /* nb of searches : larger == more compression, slower */
U32 searchLength; /* match length searched : larger == faster decompression, sometimes less compression */ U32 searchLength; /* match length searched : larger == faster decompression, sometimes less compression */
U32 targetLength; /* acceptable match size for optimal parser (only) : larger == more compression, slower */ U32 targetLength; /* acceptable match size for optimal parser (only) : larger == more compression, slower */
+2 -3
View File
@@ -127,7 +127,7 @@ static U32 g_rand = 1;
static U32 g_singleRun = 0; static U32 g_singleRun = 0;
static U32 g_target = 0; static U32 g_target = 0;
static U32 g_noSeed = 0; static U32 g_noSeed = 0;
static ZSTD_parameters g_params = { 0, 0, 0, 0, 0, 0, 0, ZSTD_greedy }; static ZSTD_parameters g_params = { 0, 0, 0, 0, 0, 0, 0, 0, ZSTD_greedy };
void BMK_SetNbIterations(int nbLoops) void BMK_SetNbIterations(int nbLoops)
{ {
@@ -406,7 +406,6 @@ const char* g_stratName[] = { "ZSTD_fast ",
"ZSTD_lazy ", "ZSTD_lazy ",
"ZSTD_lazy2 ", "ZSTD_lazy2 ",
"ZSTD_btlazy2", "ZSTD_btlazy2",
"ZSTD_opt ",
"ZSTD_btopt " }; "ZSTD_btopt " };
static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_parameters params, size_t srcSize) static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_parameters params, size_t srcSize)
@@ -549,7 +548,7 @@ static ZSTD_parameters* sanitizeParams(ZSTD_parameters params)
g_params = params; g_params = params;
if (params.strategy == ZSTD_fast) if (params.strategy == ZSTD_fast)
g_params.contentLog = 0, g_params.searchLog = 0; g_params.contentLog = 0, g_params.searchLog = 0;
if ((params.strategy != ZSTD_opt) && (params.strategy != ZSTD_btopt )) if (params.strategy != ZSTD_btopt )
g_params.targetLength = 0; g_params.targetLength = 0;
return &g_params; return &g_params;
} }