From 3564487614491f5a1e799e64616f7c50d8ab5746 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 2 Nov 2015 16:14:46 +0100 Subject: [PATCH 01/14] lazydeep --- Makefile | 2 +- NEWS | 3 + lib/zstd.h | 2 +- lib/zstdhc.c | 150 +++++++++++++++++++++++++++++++++++++++--- lib/zstdhc_static.h | 2 +- programs/Makefile | 2 +- programs/paramgrill.c | 16 ++--- programs/zstdcli.c | 2 +- 8 files changed, 156 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 7f90fd295..34d425e09 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ # ################################################################ # Version number -export VERSION := 0.3.2 +export VERSION := 0.3.3 PRGDIR = programs ZSTDDIR = lib diff --git a/NEWS b/NEWS index 9693d7793..ee8c47bea 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +v0.3.3 +Small compression ratio improvement + v0.3.2 Fixed Visual Studio diff --git a/lib/zstd.h b/lib/zstd.h index d17bc4a33..d79410d15 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -48,7 +48,7 @@ extern "C" { ***************************************/ #define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ #define ZSTD_VERSION_MINOR 3 /* for new (non-breaking) interface capabilities */ -#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ +#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) unsigned ZSTD_versionNumber (void); diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 58615f8cc..e6de28d4d 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -289,6 +289,127 @@ FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS ( } +size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + seqStore_t* seqStorePtr = &(ctx->seqStore); + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + const BYTE* match = istart; + + size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; + const U32 maxSearches = 1 << ctx->params.searchLog; + const U32 mls = ctx->params.searchLength; + + /* init */ + ZSTD_resetSeqStore(seqStorePtr); + if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; + + /* Match Loop */ + while (ip <= ilimit) + { + size_t matchLength; + size_t offset; + const BYTE* start; + + /* try to find a first match */ + if (MEM_read32(ip) == MEM_read32(ip - offset_2)) + { + /* repcode : we take it*/ + size_t offtmp = offset_2; + size_t litLength = ip - anchor; + matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); + offset_2 = offset_1; + offset_1 = offtmp; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength); + ip += matchLength+MINMATCH; + anchor = ip; + continue; + } + + offset_2 = offset_1; + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + if (!matchLength) { ip++; continue; } + + /* let's try to find a better solution */ + offset = ip - match; + start = ip; + + while (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset2 = ip - match; + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; /* search a better one */ + } + } + + if (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset2 = ip - match; + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 8); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; + } + } + } + break; /* nothing found : store previous one */ + } + + /* store sequence */ + { + size_t litLength = start - anchor; + if (offset) offset_1 = offset; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH); + ip = start + matchLength; + anchor = ip; + } + + } + + /* Last Literals */ + { + size_t lastLLSize = iend - anchor; + memcpy(seqStorePtr->lit, anchor, lastLLSize); + seqStorePtr->lit += lastLLSize; + } + + /* Final compression stage */ + return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + seqStorePtr, srcSize); +} + + size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { seqStore_t* seqStorePtr = &(ctx->seqStore); @@ -343,19 +464,19 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz if (MEM_read32(ip) == MEM_read32(ip - offset_1)) { size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH; - int gain2 = (int)(ml2 * 4); - int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset)); + int gain2 = (int)(ml2 * 3); + int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1); if (gain2 > gain1) { matchLength = ml2, offset = 0, start = ip; - break; + } } { size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); size_t offset2 = ip - match; - int gain2 = (int)(ml2*5 - ZSTD_highbit((U32)offset2)); /* raw approx */ - int gain1 = (int)(matchLength*5 - ZSTD_highbit((U32)offset)); + int gain2 = (int)(ml2*3 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 3); if (gain2 > gain1) { matchLength = ml2, offset = offset2, start = ip; @@ -488,11 +609,20 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, BYTE* const oend = op + maxDstSize; size_t (*blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); - if (ctxPtr->params.strategy == ZSTD_HC_greedy) - blockCompressor = ZSTD_HC_compressBlock_greedy; - else - blockCompressor = ZSTD_HC_compressBlock_lazy; - + switch(ctxPtr->params.strategy) + { + case ZSTD_HC_greedy: + blockCompressor = ZSTD_HC_compressBlock_greedy; + break; + case ZSTD_HC_lazy: + blockCompressor = ZSTD_HC_compressBlock_lazy; + break; + case ZSTD_HC_lazydeep: + blockCompressor = ZSTD_HC_compressBlock_lazydeep; + break; + default : + return ERROR(GENERIC); /* unknown block compressor */ + } while (remaining > blockSize) { diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index cbc938540..40d0b60c8 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -45,7 +45,7 @@ extern "C" { /* ************************************* * Types ***************************************/ -typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy } ZSTD_HC_strategy; +typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep } ZSTD_HC_strategy; typedef struct { U32 windowLog; /* largest match distance : impact decompression buffer size */ diff --git a/programs/Makefile b/programs/Makefile index 82125c994..8c7003232 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -30,7 +30,7 @@ # fullbench32: Same as fullbench, but forced to compile in 32-bits mode # ########################################################################## -VERSION?= 0.3.2 +VERSION?= 0.3.3 DESTDIR?= PREFIX ?= /usr/local diff --git a/programs/paramgrill.c b/programs/paramgrill.c index 4e84d80ae..d27a22b5f 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -425,16 +425,16 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, return 0; } -const char* g_stratName[2] = { "ZSTD_HC_greedy", "ZSTD_HC_lazy " }; +const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep" }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) { DISPLAY("\r%79s\r", ""); - fprintf(f," {%3u,%3u,%3u,%3u,%3u, %s }, ", + fprintf(f," {%3u,%3u,%3u,%3u,%3u, %s }, ", params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength, g_stratName[params.strategy]); fprintf(f, - "/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */ \n", + "/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */\n", cLevel, (double)srcSize / result.cSize, (double)result.cSpeed / 1000., (double)result.dSpeed / 1000.); } @@ -576,7 +576,7 @@ static BYTE g_alreadyTested[ZSTD_HC_WINDOWLOG_MAX+1-ZSTD_HC_WINDOWLOG_MIN] [ZSTD_HC_HASHLOG_MAX+1-ZSTD_HC_HASHLOG_MIN] [ZSTD_HC_SEARCHLOG_MAX+1-ZSTD_HC_SEARCHLOG_MIN] [ZSTD_HC_SEARCHLENGTH_MAX+1-ZSTD_HC_SEARCHLENGTH_MIN] - [2 /* strategy */ ] = {}; /* init to zero */ + [3 /* strategy */ ] = {}; /* init to zero */ #define NB_TESTS_PLAYED(p) \ g_alreadyTested[p.windowLog-ZSTD_HC_WINDOWLOG_MIN] \ @@ -628,9 +628,9 @@ static void playAround(FILE* f, winnerInfo_t* winners, case 9: p.searchLength--; break; case 10: - p.strategy = ZSTD_HC_lazy; break; + p.strategy = (ZSTD_HC_strategy)(((U32)p.strategy)+1); break; case 11: - p.strategy = ZSTD_HC_greedy; break; + p.strategy = (ZSTD_HC_strategy)(((U32)p.strategy)-1); break; } } @@ -647,7 +647,7 @@ static void playAround(FILE* f, winnerInfo_t* winners, if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_lazy) continue; + if (p.strategy > ZSTD_HC_lazydeep) continue; /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) @@ -680,7 +680,7 @@ static void BMK_selectRandomStart( p.searchLog = FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLOG_MAX+1 - ZSTD_HC_SEARCHLOG_MIN) + ZSTD_HC_SEARCHLOG_MIN; p.windowLog = FUZ_rand(&g_rand) % (ZSTD_HC_WINDOWLOG_MAX+1 - ZSTD_HC_WINDOWLOG_MIN) + ZSTD_HC_WINDOWLOG_MIN; p.searchLength=FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLENGTH_MAX+1 - ZSTD_HC_SEARCHLENGTH_MIN) + ZSTD_HC_SEARCHLENGTH_MIN; - p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) & 1); + p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 3); playAround(f, winners, p, srcBuffer, srcSize, ctx); } else diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 5bfe25b62..b22095983 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -70,7 +70,7 @@ **************************************/ #define COMPRESSOR_NAME "zstd command line interface" #ifndef ZSTD_VERSION -# define ZSTD_VERSION "v0.3.0" +# define ZSTD_VERSION "v0.3.3" #endif #define AUTHOR "Yann Collet" #define WELCOME_MESSAGE "*** %s %i-bits %s, by %s (%s) ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), ZSTD_VERSION, AUTHOR, __DATE__ From 050efba81b862f790670f72fdd92aa6d98539b14 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 09:49:30 +0100 Subject: [PATCH 02/14] level tuning --- lib/zstdhc.c | 84 +++++++++++++++++++++++++-------------------- lib/zstdhc_static.h | 59 +++++++++++++++---------------- programs/bench.c | 4 +-- 3 files changed, 79 insertions(+), 68 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index e6de28d4d..693c713b2 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -184,7 +184,7 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) } } -#define NEXT_IN_CHAIN(d) chainTable[(d) & chainMask] /* flexible, CHAINSIZE dependent */ +#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask] /* ************************************* @@ -204,7 +204,7 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U while(idx < target) { size_t h = ZSTD_HC_hashPtr(base+idx, hashLog, mls); - NEXT_IN_CHAIN(idx) = hashTable[h]; + NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; hashTable[h] = idx; idx++; } @@ -217,8 +217,8 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ size_t ZSTD_HC_insertAndFindBestMatch ( ZSTD_HC_CCtx* zc, /* Index table will be updated */ - const BYTE* ip, const BYTE* const iLimit, - const BYTE** matchpos, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, const U32 maxNbAttempts, const U32 matchLengthSearch) { U32* const chainTable = zc->chainTable; @@ -237,17 +237,22 @@ size_t ZSTD_HC_insertAndFindBestMatch ( /* HC4 match finder */ matchIndex = ZSTD_HC_insertAndFindFirstIndex (zc, ip, matchLengthSearch); - while ((matchIndex>=lowLimit) && (nbAttempts)) + while ((matchIndex>lowLimit) && (nbAttempts)) { nbAttempts--; if (matchIndex >= dictLimit) { match = base + matchIndex; - if (*(match+ml) == *(ip+ml) - && (MEM_read32(match) == MEM_read32(ip))) + if ( (match[ml] == ip[ml]) + && (MEM_read32(match) == MEM_read32(ip)) ) /* ensures minimum match of 4 */ { const size_t mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH; - if (mlt > ml) { ml = mlt; *matchpos = match; if (ip+ml >= iLimit) break; } + if (mlt > ml) + //if (((int)(4*mlt) - (int)ZSTD_highbit((U32)(ip-match)+1)) > ((int)(4*ml) - (int)ZSTD_highbit((U32)((*offsetPtr)+1)))) + { + ml = mlt; *offsetPtr = ip-match; + if (ip+ml >= iLimit) break; + } } } else @@ -261,12 +266,12 @@ size_t ZSTD_HC_insertAndFindBestMatch ( mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH; if ((ip+mlt == vLimit) && (vLimit < iLimit)) mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit); - if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */ + if (mlt > ml) { ml = mlt; *offsetPtr = (ip-base) - matchIndex; } } } if (base + matchIndex <= ip - chainSize) break; - matchIndex = NEXT_IN_CHAIN(matchIndex); + matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); } return ml; @@ -276,15 +281,15 @@ size_t ZSTD_HC_insertAndFindBestMatch ( FORCE_INLINE size_t ZSTD_HC_insertAndFindBestMatch_selectMLS ( ZSTD_HC_CCtx* zc, /* Index table will be updated */ const BYTE* ip, const BYTE* const iLimit, - const BYTE** matchpos, + size_t* offsetPtr, const U32 maxNbAttempts, const U32 matchLengthSearch) { switch(matchLengthSearch) { default : - case 4 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 4); - case 5 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 5); - case 6 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, matchpos, maxNbAttempts, 6); + case 4 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); + case 5 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); + case 6 : return ZSTD_HC_insertAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); } } @@ -297,7 +302,6 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -311,7 +315,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs while (ip <= ilimit) { size_t matchLength; - size_t offset; + size_t offset=999999; const BYTE* start; /* try to find a first match */ @@ -330,11 +334,10 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } offset_2 = offset_1; - matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* let's try to find a better solution */ - offset = ip - match; start = ip; while (ip gain1) @@ -360,6 +363,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } } + /* let's find an even better one */ if (ip gain1) matchLength = ml2, offset = 0, start = ip; } { - size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); - size_t offset2 = ip - match; + size_t offset2=999999; + size_t ml2 = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ - int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 8); + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); if (gain2 > gain1) { matchLength = ml2, offset = offset2, start = ip; @@ -383,7 +387,7 @@ size_t ZSTD_HC_compressBlock_lazydeep(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDs } } } - break; /* nothing found : store previous one */ + break; /* nothing found : store previous solution */ } /* store sequence */ @@ -418,7 +422,6 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -432,7 +435,7 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz while (ip <= ilimit) { size_t matchLength; - size_t offset; + size_t offset=0; const BYTE* start; /* try to find a first match */ @@ -451,11 +454,10 @@ size_t ZSTD_HC_compressBlock_lazy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSiz } offset_2 = offset_1; - matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* let's try to find a better solution */ - offset = ip - match; start = ip; while (ip gain1) @@ -519,7 +521,6 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; - const BYTE* match = istart; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -562,12 +563,13 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS /* search */ { - size_t matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &match, maxSearches, mls); + size_t offset=999999; + size_t matchLength = ZSTD_HC_insertAndFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); if (!matchLength) { ip++; continue; } /* store sequence */ { size_t litLength = ip-anchor; - offset_1 = ip-match; + offset_1 = offset; ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset_1, matchLength-MINMATCH); ip += matchLength; anchor = ip; @@ -591,9 +593,17 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { - if (ctx->params.strategy == ZSTD_HC_greedy) - return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); - return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); + switch(ctx->params.strategy) + { + case ZSTD_HC_greedy: + return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_lazy: + return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_lazydeep: + return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); + default : + return ERROR(GENERIC); /* unknown block compressor */ + } } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 40d0b60c8..db185b400 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -53,7 +53,7 @@ typedef struct U32 hashLog; /* dispatch table : larger == more memory, faster*/ U32 searchLog; /* nb of searches : larger == more compression, slower*/ U32 searchLength; /* size of matches : larger == faster decompression */ - ZSTD_HC_strategy strategy; /* greedy, lazy (stronger, slower) */ + ZSTD_HC_strategy strategy; /* greedy, lazy, lazydeep */ } ZSTD_HC_parameters; /* parameters boundaries */ @@ -73,7 +73,7 @@ typedef struct * Advanced function ***************************************/ /** ZSTD_HC_compress_advanced -* Same as ZSTD_HC_compressCCtx(), but can fine-tune each compression parameter */ +* Same as ZSTD_HC_compressCCtx(), with fine-tune control of each compression parameter */ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, @@ -94,35 +94,36 @@ size_t ZSTD_HC_compressEnd(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize); #define ZSTD_HC_MAX_CLEVEL 26 static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] = { /* W, C, H, S, L, strat */ - { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ - { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ - { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ - { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ - { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ - { 20, 19, 19, 3, 5, ZSTD_HC_greedy }, /* level 5 */ - { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ - { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ - { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ - { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ - { 21, 21, 20, 5, 5, ZSTD_HC_lazy }, /* level 11 */ - { 22, 20, 22, 6, 5, ZSTD_HC_lazy }, /* level 12 */ - { 22, 21, 22, 6, 5, ZSTD_HC_lazy }, /* level 13 */ - { 23, 21, 22, 6, 5, ZSTD_HC_lazy }, /* level 14 */ - { 23, 21, 23, 7, 5, ZSTD_HC_lazy }, /* level 15 */ - { 23, 22, 22, 6, 5, ZSTD_HC_lazy }, /* level 16 */ - { 23, 22, 22, 7, 5, ZSTD_HC_lazy }, /* level 17 */ - { 23, 23, 22, 7, 5, ZSTD_HC_lazy }, /* level 18 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazy }, /* level 19 */ - { 23, 23, 23, 8, 5, ZSTD_HC_lazy }, /* level 20 */ - { 23, 23, 23, 8, 5, ZSTD_HC_lazy }, /* level 21 */ - { 24, 24, 24, 8, 5, ZSTD_HC_lazy }, /* level 22 */ - { 24, 23, 23, 9, 5, ZSTD_HC_lazy }, /* level 23 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazy }, /* level 24 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazy }, /* level 25 */ - { 24, 24, 24, 10, 5, ZSTD_HC_lazy }, /* level 26 */ /* ZSTD_HC_MAX_CLEVEL */ + { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ + { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ + { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ + { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ + { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ + { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ + { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ + { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ + { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ + { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ + { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ + { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ + { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ + { 22, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 16 */ + { 23, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 17 */ + { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 18 */ + { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 19 */ + { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 20 */ + { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 21 */ + { 23, 23, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 22 */ + { 24, 24, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 23 */ + { 23, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 24 */ + { 24, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 25 */ + { 24, 24, 24, 9, 5, ZSTD_HC_lazydeep }, /* level 26 */ }; + #if defined (__cplusplus) } #endif diff --git a/programs/bench.c b/programs/bench.c index 85c3700b4..8dab71265 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -#define MAX_MEM (2 GB - 64 MB) +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : 8ULL GB; #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; @@ -401,7 +401,7 @@ static size_t BMK_findMaxMem(U64 requiredMem) requiredMem = (((requiredMem >> 26) + 1) << 26); requiredMem += 2 * step; - if (requiredMem > MAX_MEM) requiredMem = MAX_MEM; + if (requiredMem > maxMemory) requiredMem = maxMemory; while (!testmem) { From 588d1e5fa035a5aad0f3ebf2e594ba3c6798e98e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 10:48:42 +0100 Subject: [PATCH 03/14] Fixed asan issue reported by Maciej Adamczyk --- lib/zstd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index c79994456..c7dcc262a 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -570,7 +570,7 @@ static size_t ZSTD_compressBlock(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, c ZSTD_resetSeqStore(seqStorePtr); /* Main Search Loop */ - while (ip <= ilimit) + while (ip < ilimit) /* < instead of <=, because unconditionnal ZSTD_addPtr(ip+1) */ { const BYTE* match = ZSTD_updateMatch(HashTable, ip, base); @@ -591,7 +591,8 @@ static size_t ZSTD_compressBlock(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, c ZSTD_addPtr(HashTable, ip+1, base); ip += matchLength + MINMATCH; anchor = ip; - if (ip <= ilimit) ZSTD_addPtr(HashTable, ip-2, base); + if (ip < ilimit) /* same test as loop, for speed */ + ZSTD_addPtr(HashTable, ip-2, base); } } From cdc2b2f7583c05c3c8dd2430dcba44398109df52 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 10:52:14 +0100 Subject: [PATCH 04/14] fixed clang warning --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index 8dab71265..8ab66d921 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : 8ULL GB; +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(8ULL GB); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; From 293d0cc2614f253d46cce5259638e4309290276e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Nov 2015 13:10:25 +0100 Subject: [PATCH 05/14] fixed Visual warning --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index 8ab66d921..1892ddd60 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(8ULL GB); +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << (sizeof(size_t)*8-31)); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; From 96b9f0ba4d22734c4e5b5ee40e807905ab993792 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 03:52:54 +0100 Subject: [PATCH 06/14] btlazy2 --- lib/zstdhc.c | 315 +++++++++++++++++++++++++++++++++++++++++- lib/zstdhc_static.h | 8 +- programs/bench.c | 2 +- programs/paramgrill.c | 8 +- 4 files changed, 319 insertions(+), 14 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 693c713b2..d053b2138 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -173,14 +173,14 @@ static const U64 prime6bytes = 227718039650203ULL; static size_t ZSTD_HC_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; } static size_t ZSTD_HC_hash6Ptr(const void* p, U32 h) { return ZSTD_HC_hash6(MEM_read64(p), h); } -static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) +static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls) { switch(mls) { default: - case 4: return ZSTD_HC_hash4Ptr(p,h); - case 5: return ZSTD_HC_hash5Ptr(p,h); - case 6: return ZSTD_HC_hash6Ptr(p,h); + case 4: return ZSTD_HC_hash4Ptr(p, hBits); + case 5: return ZSTD_HC_hash5Ptr(p, hBits); + case 6: return ZSTD_HC_hash6Ptr(p, hBits); } } @@ -188,8 +188,308 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 h, U32 mls) /* ************************************* -* HC Compression +* Binary Tree search ***************************************/ +#define BT_SHORTCUT 256 + +/** ZSTD_HC_insertBt1 : add one ptr to tree + @ip : assumed <= iend-8 */ +static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares) +{ + U32* const hashTable = zc->hashTable; + const U32 hashLog = zc->params.hashLog; + const size_t h = ZSTD_HC_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + const U32 btLog = zc->params.chainLog - 1; + const U32 btMask= (1 << btLog) - 1; + U32 matchIndex = hashTable[h]; + size_t commonLengthSmaller=0, commonLengthLarger=0; + const BYTE* const base = zc->base; + const U32 current = (U32)(ip-base); + const U32 btLow = btMask >= current ? 0 : current - btMask; + U32* smallerPtr = bt + 2*(current&btMask); + U32* largerPtr = bt + 2*(current&btMask) + 1; + U32 dummy32; /* to be nullified at the end */ + const U32 windowSize = 1 << zc->params.windowLog; + const U32 windowLow = windowSize >= current ? 0 : current - windowSize; + + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + + while (nbCompares-- && (matchIndex > windowLow)) + { + U32* nextPtr = bt + 2*(matchIndex & btMask); + const BYTE* match = base + matchIndex; + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ + + if (match[matchLength] < ip[matchLength]) + { + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } + else + { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } + } + + *smallerPtr = *largerPtr = 0; +} + + +FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ +size_t ZSTD_HC_insertBtAndFindBestMatch ( + ZSTD_HC_CCtx* zc, + const BYTE* const ip, const BYTE* const iend, + size_t* offsetPtr, + U32 nbCompares, const U32 mls) +{ + U32* const hashTable = zc->hashTable; + const U32 hashLog = zc->params.hashLog; + const size_t h = ZSTD_HC_hashPtr(ip, hashLog, mls); + U32* const bt = zc->chainTable; + const U32 btLog = zc->params.chainLog - 1; + const U32 btMask= (1 << btLog) - 1; + U32 matchIndex = hashTable[h]; + size_t commonLengthSmaller=0, commonLengthLarger=0; + const BYTE* const base = zc->base; + const U32 current = (U32)(ip-base); + const U32 btLow = btMask >= current ? 0 : current - btMask; + const U32 windowSize = 1 << zc->params.windowLog; + const U32 windowLow = windowSize >= current ? 0 : current - windowSize; + U32* smallerPtr = bt + 2*(current&btMask); + U32* largerPtr = bt + 2*(current&btMask) + 1; + U32 bestLength = 0; + U32 dummy32; /* to be nullified at the end */ + + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + + while (nbCompares-- && (matchIndex > windowLow)) + { + U32* nextPtr = bt + 2*(matchIndex & btMask); + const BYTE* match = base + matchIndex; + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + + if (matchLength > bestLength) + { + bestLength = (U32)matchLength; + *offsetPtr = current - matchIndex; + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ + } + + if (match[matchLength] < ip[matchLength]) + { + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } + else + { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } + } + + *smallerPtr = *largerPtr = 0; + + zc->nextToUpdate = current+1; /* current has been inserted */ + if (bestLength < MINMATCH) return 0; + return bestLength; +} + + +static void ZSTD_HC_updateTree(ZSTD_HC_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls) +{ + const BYTE* const base = zc->base; + const U32 target = (U32)(ip - base); + U32 idx = zc->nextToUpdate; + //size_t dummy; + + for( ; idx < target ; idx++) + ZSTD_HC_insertBt1(zc, base+idx, mls, iend, nbCompares); + //ZSTD_HC_insertBtAndFindBestMatch(zc, base+idx, iend, &dummy, nbCompares, mls); + + zc->nextToUpdate = target; +} + + +/** Tree updater, providing best match */ +FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ +size_t ZSTD_HC_BtFindBestMatch ( + ZSTD_HC_CCtx* zc, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 maxNbAttempts, const U32 mls) +{ + ZSTD_HC_updateTree(zc, ip, iLimit, maxNbAttempts, mls); + return ZSTD_HC_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls); +} + + +FORCE_INLINE size_t ZSTD_HC_BtFindBestMatch_selectMLS ( + ZSTD_HC_CCtx* zc, /* Index table will be updated */ + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 maxNbAttempts, const U32 matchLengthSearch) +{ + switch(matchLengthSearch) + { + default : + case 4 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); + case 5 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); + case 6 : return ZSTD_HC_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); + } +} + + +size_t ZSTD_HC_compressBlock_btLazy2(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + seqStore_t* seqStorePtr = &(ctx->seqStore); + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + + size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; + const U32 maxSearches = 1 << ctx->params.searchLog; + const U32 mls = ctx->params.searchLength; + + /* init */ + ZSTD_resetSeqStore(seqStorePtr); + if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; + + /* Match Loop */ + while (ip <= ilimit) + { + size_t matchLength; + size_t offset=999999; + const BYTE* start; + + /* try to find a first match */ + if (MEM_read32(ip) == MEM_read32(ip - offset_2)) + { + /* repcode : we take it*/ + size_t offtmp = offset_2; + size_t litLength = ip - anchor; + matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend); + offset_2 = offset_1; + offset_1 = offtmp; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength); + ip += matchLength+MINMATCH; + anchor = ip; + continue; + } + + offset_2 = offset_1; + matchLength = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset, maxSearches, mls); + if (!matchLength) { ip++; continue; } + + /* let's try to find a better solution */ + start = ip; + + while (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t offset2=999999; + size_t ml2 = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; /* search a better one */ + } + } + + /* let's find an even better one */ + if (ip gain1) + matchLength = ml2, offset = 0, start = ip; + } + { + size_t offset2=999999; + size_t ml2 = ZSTD_HC_BtFindBestMatch_selectMLS(ctx, ip, iend, &offset2, maxSearches, mls); + int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */ + int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7); + if (gain2 > gain1) + { + matchLength = ml2, offset = offset2, start = ip; + continue; + } + } + } + break; /* nothing found : store previous solution */ + } + + /* store sequence */ + { + size_t litLength = start - anchor; + if (offset) offset_1 = offset; + ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH); + ip = start + matchLength; + anchor = ip; + } + + } + + /* Last Literals */ + { + size_t lastLLSize = iend - anchor; + memcpy(seqStorePtr->lit, anchor, lastLLSize); + seqStorePtr->lit += lastLLSize; + } + + /* Final compression stage */ + return ZSTD_compressSequences((BYTE*)dst, maxDstSize, + seqStorePtr, srcSize); +} + + + +/* *********************** +* Hash Chain +*************************/ + /* Update chains up to ip (excluded) */ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U32 mls) { @@ -601,6 +901,8 @@ size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, co return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); case ZSTD_HC_lazydeep: return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); + case ZSTD_HC_btlazy2: + return ZSTD_HC_compressBlock_btLazy2(ctx, dst, maxDstSize, src, srcSize); default : return ERROR(GENERIC); /* unknown block compressor */ } @@ -630,6 +932,9 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, case ZSTD_HC_lazydeep: blockCompressor = ZSTD_HC_compressBlock_lazydeep; break; + case ZSTD_HC_btlazy2: + blockCompressor = ZSTD_HC_compressBlock_btLazy2; + break; default : return ERROR(GENERIC); /* unknown block compressor */ } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index db185b400..36e0781f5 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -45,7 +45,7 @@ extern "C" { /* ************************************* * Types ***************************************/ -typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep } ZSTD_HC_strategy; +typedef enum { ZSTD_HC_greedy, ZSTD_HC_lazy, ZSTD_HC_lazydeep, ZSTD_HC_btlazy2 } ZSTD_HC_strategy; typedef struct { U32 windowLog; /* largest match distance : impact decompression buffer size */ @@ -100,13 +100,13 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ - { 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 20, 18, 19, 2, 5, ZSTD_HC_lazydeep }, //{ 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 20, 18, 19, 2, 5, ZSTD_HC_btlazy2 }, //{ 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ - { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 21, 20, 20, 5, 5, ZSTD_HC_btlazy2 }, //{ 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ diff --git a/programs/bench.c b/programs/bench.c index 1892ddd60..c19d0fd97 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -83,7 +83,7 @@ #define MB *(1 <<20) #define GB *(1U<<30) -static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << (sizeof(size_t)*8-31)); +static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31)); #define DEFAULT_CHUNKSIZE (4 MB) static U32 g_compressibilityDefault = 50; diff --git a/programs/paramgrill.c b/programs/paramgrill.c index d27a22b5f..78f2b1959 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -425,7 +425,7 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, return 0; } -const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep" }; +const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep", "ZSTD_HC_btlazy2 " }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) { @@ -576,7 +576,7 @@ static BYTE g_alreadyTested[ZSTD_HC_WINDOWLOG_MAX+1-ZSTD_HC_WINDOWLOG_MIN] [ZSTD_HC_HASHLOG_MAX+1-ZSTD_HC_HASHLOG_MIN] [ZSTD_HC_SEARCHLOG_MAX+1-ZSTD_HC_SEARCHLOG_MIN] [ZSTD_HC_SEARCHLENGTH_MAX+1-ZSTD_HC_SEARCHLENGTH_MIN] - [3 /* strategy */ ] = {}; /* init to zero */ + [4 /* strategy */ ] = {}; /* init to zero */ #define NB_TESTS_PLAYED(p) \ g_alreadyTested[p.windowLog-ZSTD_HC_WINDOWLOG_MIN] \ @@ -647,7 +647,7 @@ static void playAround(FILE* f, winnerInfo_t* winners, if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_lazydeep) continue; + if (p.strategy > ZSTD_HC_btlazy2) continue; /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) @@ -680,7 +680,7 @@ static void BMK_selectRandomStart( p.searchLog = FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLOG_MAX+1 - ZSTD_HC_SEARCHLOG_MIN) + ZSTD_HC_SEARCHLOG_MIN; p.windowLog = FUZ_rand(&g_rand) % (ZSTD_HC_WINDOWLOG_MAX+1 - ZSTD_HC_WINDOWLOG_MIN) + ZSTD_HC_WINDOWLOG_MIN; p.searchLength=FUZ_rand(&g_rand) % (ZSTD_HC_SEARCHLENGTH_MAX+1 - ZSTD_HC_SEARCHLENGTH_MIN) + ZSTD_HC_SEARCHLENGTH_MIN; - p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 3); + p.strategy = (ZSTD_HC_strategy) (FUZ_rand(&g_rand) % 4); playAround(f, winners, p, srcBuffer, srcSize, ctx); } else From 59d7063fbc86b8d8a74aa92f9a54d70cead12685 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 12:05:27 +0100 Subject: [PATCH 07/14] fix and level tuning --- lib/zstd_internal.h | 2 +- lib/zstdhc.c | 150 +++++++++++++++++++++++------------------- lib/zstdhc_static.h | 40 ++++++----- programs/paramgrill.c | 29 ++++---- 4 files changed, 116 insertions(+), 105 deletions(-) diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index 807725923..207fd84bf 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -154,7 +154,7 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pI return (size_t)(pIn - pStart); } - if (MEM_32bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; } + if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; } if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; } if ((pIn 0 */ +void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize) +{ + const U32 chainplus = (params->strategy == ZSTD_HC_btlazy2); + + /* validate params */ + if (params->windowLog > ZSTD_HC_WINDOWLOG_MAX) params->windowLog = ZSTD_HC_WINDOWLOG_MAX; + if (params->windowLog < ZSTD_HC_WINDOWLOG_MIN) params->windowLog = ZSTD_HC_WINDOWLOG_MIN; + + /* correct params, to use less memory */ + if (srcSize > 0) + { + U32 srcLog = ZSTD_highbit((U32)srcSize-1) + 1; + if (params->windowLog > srcLog) params->windowLog = srcLog; + } + + if (params->chainLog > params->windowLog + chainplus) params->chainLog = params->windowLog+chainplus; /* <= ZSTD_HC_CHAINLOG_MAX */ + if (params->chainLog < ZSTD_HC_CHAINLOG_MIN) params->chainLog = ZSTD_HC_CHAINLOG_MIN; + if (params->hashLog > ZSTD_HC_HASHLOG_MAX) params->hashLog = ZSTD_HC_HASHLOG_MAX; + if (params->hashLog < ZSTD_HC_HASHLOG_MIN) params->hashLog = ZSTD_HC_HASHLOG_MIN; + if (params->searchLog > ZSTD_HC_SEARCHLOG_MAX) params->searchLog = ZSTD_HC_SEARCHLOG_MAX; + if (params->searchLog < ZSTD_HC_SEARCHLOG_MIN) params->searchLog = ZSTD_HC_SEARCHLOG_MIN; + if (params->searchLength> ZSTD_HC_SEARCHLENGTH_MAX) params->searchLength = ZSTD_HC_SEARCHLENGTH_MAX; + if (params->searchLength< ZSTD_HC_SEARCHLENGTH_MIN) params->searchLength = ZSTD_HC_SEARCHLENGTH_MIN; + if ((U32)params->strategy>(U32)ZSTD_HC_btlazy2) params->strategy = ZSTD_HC_btlazy2; + if ((int)params->strategy<(int)ZSTD_HC_greedy) params->strategy = ZSTD_HC_greedy; +} + + static size_t ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc, ZSTD_HC_parameters params) { - /* validate params */ - if (params.windowLog > ZSTD_HC_WINDOWLOG_MAX) params.windowLog = ZSTD_HC_WINDOWLOG_MAX; - if (params.windowLog < ZSTD_HC_WINDOWLOG_MIN) params.windowLog = ZSTD_HC_WINDOWLOG_MIN; - if (params.chainLog > params.windowLog) params.chainLog = params.windowLog; /* <= ZSTD_HC_CHAINLOG_MAX */ - if (params.chainLog < ZSTD_HC_CHAINLOG_MIN) params.chainLog = ZSTD_HC_CHAINLOG_MIN; - if (params.hashLog > ZSTD_HC_HASHLOG_MAX) params.hashLog = ZSTD_HC_HASHLOG_MAX; - if (params.hashLog < ZSTD_HC_HASHLOG_MIN) params.hashLog = ZSTD_HC_HASHLOG_MIN; - if (params.searchLog > ZSTD_HC_SEARCHLOG_MAX) params.searchLog = ZSTD_HC_SEARCHLOG_MAX; - if (params.searchLog < ZSTD_HC_SEARCHLOG_MIN) params.searchLog = ZSTD_HC_SEARCHLOG_MIN; - if (params.searchLength> ZSTD_HC_SEARCHLENGTH_MAX) params.searchLength = ZSTD_HC_SEARCHLENGTH_MAX; - if (params.searchLength< ZSTD_HC_SEARCHLENGTH_MIN) params.searchLength = ZSTD_HC_SEARCHLENGTH_MIN; + ZSTD_HC_validateParams(¶ms, 0); /* reserve table memory */ { @@ -190,8 +212,6 @@ static size_t ZSTD_HC_hashPtr(const void* p, U32 hBits, U32 mls) /* ************************************* * Binary Tree search ***************************************/ -#define BT_SHORTCUT 256 - /** ZSTD_HC_insertBt1 : add one ptr to tree @ip : assumed <= iend-8 */ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares) @@ -209,7 +229,7 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 const U32 btLow = btMask >= current ? 0 : current - btMask; U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 dummy32; /* to be nullified at the end */ + U32 dummy32; /* to be nullified at the end */ const U32 windowSize = 1 << zc->params.windowLog; const U32 windowLow = windowSize >= current ? 0 : current - windowSize; @@ -223,30 +243,30 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32 matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); - if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* just drop , to guarantee consistency (miss a bit of compression; if someone knows better, please tell) */ if (match[matchLength] < ip[matchLength]) - { + { /* match is smaller than current */ *smallerPtr = matchIndex; /* update smaller idx */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } + } else - { + { /* match is larger than current */ *largerPtr = matchIndex; commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ largerPtr = nextPtr; matchIndex = nextPtr[0]; - } + } } - *smallerPtr = *largerPtr = 0; + *smallerPtr = *largerPtr = 0; } @@ -273,9 +293,9 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; U32 bestLength = 0; - U32 dummy32; /* to be nullified at the end */ + U32 dummy32; /* to be nullified at the end */ - hashTable[h] = (U32)(ip-base); /* Update Hash Table */ + hashTable[h] = (U32)(ip-base); /* Update Hash Table */ while (nbCompares-- && (matchIndex > windowLow)) { @@ -289,34 +309,34 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( { bestLength = (U32)matchLength; *offsetPtr = current - matchIndex; - if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ + if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ + break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ } if (match[matchLength] < ip[matchLength]) - { + { /* match is smaller than current */ *smallerPtr = matchIndex; /* update smaller idx */ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ - smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } + } else - { + { /* match is larger than current */ *largerPtr = matchIndex; commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ largerPtr = nextPtr; matchIndex = nextPtr[0]; - } + } } - *smallerPtr = *largerPtr = 0; + *smallerPtr = *largerPtr = 0; zc->nextToUpdate = current+1; /* current has been inserted */ - if (bestLength < MINMATCH) return 0; + if (bestLength < MINMATCH) return 0; return bestLength; } @@ -326,7 +346,7 @@ static void ZSTD_HC_updateTree(ZSTD_HC_CCtx* zc, const BYTE* const ip, const BYT const BYTE* const base = zc->base; const U32 target = (U32)(ip - base); U32 idx = zc->nextToUpdate; - //size_t dummy; + //size_t dummy; for( ; idx < target ; idx++) ZSTD_HC_insertBt1(zc, base+idx, mls, iend, nbCompares); @@ -510,7 +530,7 @@ static U32 ZSTD_HC_insertAndFindFirstIndex (ZSTD_HC_CCtx* zc, const BYTE* ip, U } zc->nextToUpdate = target; - return hashTable[ZSTD_HC_hashPtr(ip, hashLog, mls)]; + return hashTable[ZSTD_HC_hashPtr(ip, hashLog, mls)]; } @@ -891,21 +911,30 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS } +typedef size_t (*ZSTD_HC_blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); + + +static ZSTD_HC_blockCompressor ZSTD_HC_selectBlockCompressor(ZSTD_HC_strategy strat) +{ + switch(strat) + { + default : + case ZSTD_HC_greedy: + return ZSTD_HC_compressBlock_greedy; + case ZSTD_HC_lazy: + return ZSTD_HC_compressBlock_lazy; + case ZSTD_HC_lazydeep: + return ZSTD_HC_compressBlock_lazydeep; + case ZSTD_HC_btlazy2: + return ZSTD_HC_compressBlock_btLazy2; + } +} + + size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { - switch(ctx->params.strategy) - { - case ZSTD_HC_greedy: - return ZSTD_HC_compressBlock_greedy(ctx, dst, maxDstSize, src, srcSize); - case ZSTD_HC_lazy: - return ZSTD_HC_compressBlock_lazy(ctx, dst, maxDstSize, src, srcSize); - case ZSTD_HC_lazydeep: - return ZSTD_HC_compressBlock_lazydeep(ctx, dst, maxDstSize, src, srcSize); - case ZSTD_HC_btlazy2: - return ZSTD_HC_compressBlock_btLazy2(ctx, dst, maxDstSize, src, srcSize); - default : - return ERROR(GENERIC); /* unknown block compressor */ - } + ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctx->params.strategy); + return blockCompressor(ctx, dst, maxDstSize, src, srcSize); } @@ -919,25 +948,8 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; BYTE* const oend = op + maxDstSize; - size_t (*blockCompressor) (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); + const ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctxPtr->params.strategy); - switch(ctxPtr->params.strategy) - { - case ZSTD_HC_greedy: - blockCompressor = ZSTD_HC_compressBlock_greedy; - break; - case ZSTD_HC_lazy: - blockCompressor = ZSTD_HC_compressBlock_lazy; - break; - case ZSTD_HC_lazydeep: - blockCompressor = ZSTD_HC_compressBlock_lazydeep; - break; - case ZSTD_HC_btlazy2: - blockCompressor = ZSTD_HC_compressBlock_btLazy2; - break; - default : - return ERROR(GENERIC); /* unknown block compressor */ - } while (remaining > blockSize) { diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 36e0781f5..06174fcde 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -59,7 +59,7 @@ typedef struct /* parameters boundaries */ #define ZSTD_HC_WINDOWLOG_MAX 26 #define ZSTD_HC_WINDOWLOG_MIN 18 -#define ZSTD_HC_CHAINLOG_MAX ZSTD_HC_WINDOWLOG_MAX +#define ZSTD_HC_CHAINLOG_MAX (ZSTD_HC_WINDOWLOG_MAX+1) #define ZSTD_HC_CHAINLOG_MIN 4 #define ZSTD_HC_HASHLOG_MAX 28 #define ZSTD_HC_HASHLOG_MIN 4 @@ -79,6 +79,11 @@ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, const void* src, size_t srcSize, ZSTD_HC_parameters params); +/** ZSTD_HC_validateParams + correct params value to remain within authorized range + optimize for srcSize if srcSize > 0 */ +void ZSTD_HC_validateParams(ZSTD_HC_parameters* params, size_t srcSize); + /* ************************************* * Streaming functions @@ -97,33 +102,32 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 1 - in fact redirected towards zstd fast */ { 18, 12, 15, 2, 4, ZSTD_HC_greedy }, /* level 2 */ - { 19, 13, 17, 3, 5, ZSTD_HC_greedy }, /* level 3 */ - { 20, 18, 19, 2, 5, ZSTD_HC_greedy }, /* level 4 */ + { 19, 14, 18, 2, 5, ZSTD_HC_greedy }, /* level 3 */ + { 20, 17, 19, 3, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ - { 20, 18, 19, 2, 5, ZSTD_HC_lazydeep }, //{ 20, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 20, 18, 19, 2, 5, ZSTD_HC_btlazy2 }, //{ 20, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ + { 21, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ - { 21, 20, 20, 5, 5, ZSTD_HC_btlazy2 }, //{ 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ + { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ - { 22, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 16 */ - { 23, 21, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 17 */ - { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 18 */ - { 23, 22, 23, 7, 5, ZSTD_HC_lazydeep }, /* level 19 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 20 */ - { 23, 22, 23, 8, 5, ZSTD_HC_lazydeep }, /* level 21 */ - { 23, 23, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 22 */ - { 24, 24, 24, 8, 5, ZSTD_HC_lazydeep }, /* level 23 */ - { 23, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 24 */ - { 24, 23, 23, 9, 5, ZSTD_HC_lazydeep }, /* level 25 */ - { 24, 24, 24, 9, 5, ZSTD_HC_lazydeep }, /* level 26 */ + { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ + { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ + { 24, 24, 22, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 24 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 25 */ + { 25, 25, 24, 9, 5, ZSTD_HC_btlazy2 }, /* level 26 */ }; - #if defined (__cplusplus) } #endif diff --git a/programs/paramgrill.c b/programs/paramgrill.c index 78f2b1959..f7cfef98e 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -348,7 +348,7 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, if (totalTime > g_maxParamTime) break; /* Compression */ - DISPLAY("%1u-%s : %9u ->\r", loopNb, name, (U32)srcSize); + DISPLAY("\r%1u-%s : %9u ->", loopNb, name, (U32)srcSize); memset(compressedBuffer, 0xE5, maxCompressedSize); nbLoops = 0; @@ -371,8 +371,9 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, cSize += blockTable[blockNb].cSize; if ((double)milliTime < fastestC*nbLoops) fastestC = (double)milliTime / nbLoops; ratio = (double)srcSize / (double)cSize; + DISPLAY("\r"); DISPLAY("%1u-%s : %9u ->", loopNb, name, (U32)srcSize); - DISPLAY(" %9u (%4.3f),%7.1f MB/s\r", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); + DISPLAY(" %9u (%4.3f),%7.1f MB/s", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); resultPtr->cSize = cSize; resultPtr->cSpeed = (U32)((double)srcSize / fastestC); @@ -393,9 +394,10 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, milliTime = BMK_GetMilliSpan(milliTime); if ((double)milliTime < fastestD*nbLoops) fastestD = (double)milliTime / nbLoops; + DISPLAY("\r"); DISPLAY("%1u-%s : %9u -> ", loopNb, name, (U32)srcSize); DISPLAY("%9u (%4.3f),%7.1f MB/s, ", (U32)cSize, ratio, (double)srcSize / fastestC / 1000.); - DISPLAY("%7.1f MB/s\r", (double)srcSize / fastestD / 1000.); + DISPLAY("%7.1f MB/s", (double)srcSize / fastestD / 1000.); resultPtr->dSpeed = (U32)((double)srcSize / fastestD); /* CRC Checking */ @@ -420,11 +422,13 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr, } /* End cleaning */ + DISPLAY("\r"); free(compressedBuffer); free(resultBuffer); return 0; } + const char* g_stratName[] = { "ZSTD_HC_greedy ", "ZSTD_HC_lazy ", "ZSTD_HC_lazydeep", "ZSTD_HC_btlazy2 " }; static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_HC_parameters params, size_t srcSize) @@ -592,7 +596,6 @@ static void playAround(FILE* f, winnerInfo_t* winners, const void* srcBuffer, size_t srcSize, ZSTD_HC_CCtx* ctx) { - const U32 srcLog = BMK_highbit((U32)( (g_blockSize ? g_blockSize : srcSize) -1))+1; int nbVariations = 0; const int startTime = BMK_GetMilliStart(); @@ -635,19 +638,11 @@ static void playAround(FILE* f, winnerInfo_t* winners, } /* validate new conf */ - if (p.windowLog > srcLog) continue; - if (p.windowLog > ZSTD_HC_WINDOWLOG_MAX) continue; - if (p.windowLog < MAX(ZSTD_HC_WINDOWLOG_MIN, p.chainLog)) continue; - if (p.chainLog > p.windowLog) continue; - if (p.chainLog < ZSTD_HC_CHAINLOG_MIN) continue; - if (p.hashLog > ZSTD_HC_HASHLOG_MAX) continue; - if (p.hashLog < ZSTD_HC_HASHLOG_MIN) continue; - if (p.searchLog > p.chainLog) continue; - if (p.searchLog < ZSTD_HC_SEARCHLOG_MIN) continue; - if (p.searchLength > ZSTD_HC_SEARCHLENGTH_MAX) continue; - if (p.searchLength < ZSTD_HC_SEARCHLENGTH_MIN) continue; - if (p.strategy < ZSTD_HC_greedy) continue; - if (p.strategy > ZSTD_HC_btlazy2) continue; + { + ZSTD_HC_parameters saved = p; + ZSTD_HC_validateParams(&p, g_blockSize ? g_blockSize : srcSize); + if (memcmp(&p, &saved, sizeof(p))) continue; /* p was invalid */ + } /* exclude faster if already played params */ if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1)) From b241e9deb7d207f87658f79856b2717a19c25162 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 13:57:24 +0100 Subject: [PATCH 08/14] small compression improvement --- lib/zstdhc.c | 6 +++--- lib/zstdhc_static.h | 6 +++--- programs/paramgrill.c | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index 716213fd3..e90b7f3a6 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -292,7 +292,7 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( const U32 windowLow = windowSize >= current ? 0 : current - windowSize; U32* smallerPtr = bt + 2*(current&btMask); U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 bestLength = 0; + size_t bestLength = 0; U32 dummy32; /* to be nullified at the end */ hashTable[h] = (U32)(ip-base); /* Update Hash Table */ @@ -307,8 +307,8 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( if (matchLength > bestLength) { - bestLength = (U32)matchLength; - *offsetPtr = current - matchIndex; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit(offsetPtr[0]+1)) ) + bestLength = matchLength, *offsetPtr = current - matchIndex; if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ } diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index 06174fcde..bbe157134 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -116,10 +116,10 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ - { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 22, 23, 22, 4, 5, ZSTD_HC_btlazy2 }, /* level 17 */ { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ - { 24, 24, 22, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 23, 23, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 24, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ diff --git a/programs/paramgrill.c b/programs/paramgrill.c index f7cfef98e..40033a6a3 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -696,6 +696,7 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize) if (g_singleRun) { BMK_result_t testResult; + ZSTD_HC_validateParams(&g_params, g_blockSize ? g_blockSize : srcSize); BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, g_params); DISPLAY("\n"); return; @@ -978,7 +979,8 @@ int main(int argc, char** argv) argument++; while ((*argument>= '0') && (*argument<='9')) { - if (*argument++) g_params.strategy = ZSTD_HC_lazy; + g_params.strategy = (ZSTD_HC_strategy)((U32)g_params.strategy *10); + g_params.strategy = (ZSTD_HC_strategy)((U32)g_params.strategy + *argument++ - '0'); } continue; case 'L': From e8455f51eac9ec84eeeb035dc1a92175fa3f1b2d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 17:41:20 +0100 Subject: [PATCH 09/14] fix clang warning --- lib/zstdhc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index e90b7f3a6..c061ecdbe 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -307,7 +307,7 @@ size_t ZSTD_HC_insertBtAndFindBestMatch ( if (matchLength > bestLength) { - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit(offsetPtr[0]+1)) ) + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) ) bestLength = matchLength, *offsetPtr = current - matchIndex; if (ip+matchLength == iend) /* equal : no way to know if inf or sup */ break; /* drop, next to null, to guarantee consistency (is there a way to do better ?) */ From 2c7ac7c055c8f12758cd4b72de44993915eae6cf Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 17:52:18 +0100 Subject: [PATCH 10/14] fix bench on /dev/null --- programs/bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/bench.c b/programs/bench.c index c19d0fd97..0009e4ae5 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -241,7 +241,7 @@ static size_t local_compress_fast (void* dst, size_t maxDstSize, const void* src static int BMK_benchMem(void* srcBuffer, size_t srcSize, const char* fileName, int cLevel) { - const size_t blockSize = g_blockSize ? g_blockSize : srcSize; + const size_t blockSize = (g_blockSize ? g_blockSize : srcSize) + (!srcSize); /* avoid div by 0 */ const U32 nbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize); blockParam_t* const blockTable = (blockParam_t*) malloc(nbBlocks * sizeof(blockParam_t)); const size_t maxCompressedSize = (size_t)nbBlocks * ZSTD_compressBound(blockSize); From 3e3582719c3fdc2be5792ebdf9304d7a65fcabec Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 18:19:39 +0100 Subject: [PATCH 11/14] Fixed issue #62, reported by @luben --- lib/zstdhc.c | 39 +++++++++++---------------------------- programs/fuzzer.c | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/lib/zstdhc.c b/lib/zstdhc.c index c061ecdbe..ccd252362 100644 --- a/lib/zstdhc.c +++ b/lib/zstdhc.c @@ -942,18 +942,22 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, void* dst, size_t maxDstSize, const void* src, size_t srcSize) { - static const size_t blockSize = 128 KB; + size_t blockSize = BLOCKSIZE; size_t remaining = srcSize; const BYTE* ip = (const BYTE*)src; BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; - BYTE* const oend = op + maxDstSize; const ZSTD_HC_blockCompressor blockCompressor = ZSTD_HC_selectBlockCompressor(ctxPtr->params.strategy); - - while (remaining > blockSize) + while (remaining) { - size_t cSize = blockCompressor(ctxPtr, op+3, oend-op, ip, blockSize); + size_t cSize; + + if (maxDstSize < 5) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ + + if (remaining < blockSize) blockSize = remaining; + cSize = blockCompressor(ctxPtr, op+3, maxDstSize-3, ip, blockSize); + if (ZSTD_isError(cSize)) return cSize; if (cSize == 0) { @@ -969,30 +973,9 @@ static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr, } remaining -= blockSize; + maxDstSize -= cSize; ip += blockSize; op += cSize; - if (ZSTD_isError(cSize)) return cSize; - } - - /* last block */ - { - size_t cSize = blockCompressor(ctxPtr, op+3, oend-op, ip, remaining); - - if (cSize == 0) - { - cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, remaining); /* block is not compressible */ - } - else - { - op[0] = (BYTE)(cSize>>16); - op[1] = (BYTE)(cSize>>8); - op[2] = (BYTE)cSize; - op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */ - cSize += 3; - } - - op += cSize; - if (ZSTD_isError(cSize)) return cSize; } return op-ostart; @@ -1077,7 +1060,7 @@ size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx, /* body (compression) */ ctx->base = (const BYTE*)src; - op += ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize); + oSize = ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize); if(ZSTD_isError(oSize)) return oSize; op += oSize; maxDstSize -= oSize; diff --git a/programs/fuzzer.c b/programs/fuzzer.c index a549d232f..217c82929 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -328,14 +328,15 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize); crcOrig = XXH64(srcBuffer + sampleStart, sampleSize, 0); - /* HC compression test */ - cLevel = (FUZ_rand(&lseed) & 3) + 2; - cSize = ZSTD_HC_compressCCtx(hcctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize, cLevel); - CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); - /* compression test */ + /* covered by HC cLevel 1 cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize); - CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); + CHECK(ZSTD_isError(cSize), "ZSTD_compress failed"); */ + + /* HC compression test */ + cLevel = (FUZ_rand(&lseed) & 3) +1; + cSize = ZSTD_HC_compressCCtx(hcctx, cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize, cLevel); + CHECK(ZSTD_isError(cSize), "ZSTD_HC_compressCCtx failed"); /* compression failure test : too small dest buffer */ if (cSize > 3) @@ -346,16 +347,16 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit static const U32 endMark = 0x4DC2B1A9; U32 endCheck; memcpy(dstBuffer+tooSmallSize, &endMark, 4); - errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, srcBuffer + sampleStart, sampleSize); - CHECK(!ZSTD_isError(errorCode), "ZSTD_compress should have failed ! (buffer too small)"); + errorCode = ZSTD_HC_compressCCtx(hcctx, dstBuffer, tooSmallSize, srcBuffer + sampleStart, sampleSize, cLevel); + CHECK(!ZSTD_isError(errorCode), "ZSTD_HC_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize); memcpy(&endCheck, dstBuffer+tooSmallSize, 4); - CHECK(endCheck != endMark, "ZSTD_compress : dst buffer overflow"); + CHECK(endCheck != endMark, "ZSTD_HC_compressCCtx : dst buffer overflow"); } /* successfull decompression tests*/ dSupSize = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1; dSize = ZSTD_decompress(dstBuffer, sampleSize + dSupSize, cBuffer, cSize); - CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s)", ZSTD_getErrorName(dSize)); + CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize); crcDest = XXH64(dstBuffer, sampleSize, 0); CHECK(crcOrig != crcDest, "dstBuffer corrupted (pos %u / %u)", (U32)findDiff(srcBuffer+sampleStart, dstBuffer, sampleSize), (U32)sampleSize); From 50c5cdb44ca30860ddebe64c9a3633fa7fc8f04c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 20:35:33 +0100 Subject: [PATCH 12/14] fixed issues reported by Maciej Adamczyk --- lib/zstd.c | 1 + lib/zstd_internal.h | 4 +++- programs/zstdcli.c | 17 +++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index c7dcc262a..db533f9a5 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -921,6 +921,7 @@ size_t ZSTD_decodeLiteralsBlock(void* ctx, { if (litSize > srcSize-3) return ERROR(corruption_detected); memcpy(dctx->litBuffer, istart, litSize); + dctx->litPtr = dctx->litBuffer; dctx->litBufSize = BLOCKSIZE+8; dctx->litSize = litSize; return litSize+3; diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index 207fd84bf..f63636459 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -171,7 +171,9 @@ static void ZSTD_wildcopy(void* dst, const void* src, size_t length) const BYTE* ip = (const BYTE*)src; BYTE* op = (BYTE*)dst; BYTE* const oend = op + length; - do COPY8(op, ip) while (op < oend); + do + COPY8(op, ip) + while (op < oend); } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b22095983..4c8460d8a 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -178,7 +178,7 @@ int main(int argc, char** argv) const char* inFileName = NULL; const char* outFileName = NULL; char* dynNameSpace = NULL; - char extension[] = ZSTD_EXTENSION; + const char extension[] = ZSTD_EXTENSION; displayOut = stderr; /* Pick out basename component. Don't rely on stdlib because of conflicting behavior. */ @@ -351,16 +351,17 @@ int main(int argc, char** argv) } /* decompression to file (automatic name will work only if input filename has correct format extension) */ { - size_t outl; - size_t inl = strlen(inFileName); - dynNameSpace = (char*)calloc(1,inl+1); + size_t filenameSize = strlen(inFileName); + if (strcmp(inFileName + (filenameSize-4), extension)) + { + DISPLAYLEVEL(1, "unknown suffix - cannot determine destination filename\n"); + return badusage(programName); + } + dynNameSpace = (char*)calloc(1,filenameSize+1); if (dynNameSpace==NULL) { DISPLAY("not enough memory\n"); exit(1); } outFileName = dynNameSpace; strcpy(dynNameSpace, inFileName); - outl = inl; - if (inl>4) - while ((outl >= inl-4) && (inFileName[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0; - if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); return badusage(programName); } + dynNameSpace[filenameSize-4]=0; DISPLAYLEVEL(2, "Decoding file %s \n", outFileName); } } From 3137d1a059eb78b8791c825c795d5170166aac17 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 4 Nov 2015 23:36:36 +0100 Subject: [PATCH 13/14] fix fuzzer32 litCSize limit condition --- lib/zstd.c | 2 -- lib/zstd_internal.h | 4 ++++ lib/zstdhc.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/zstd.c b/lib/zstd.c index db533f9a5..776a5bca5 100644 --- a/lib/zstd.c +++ b/lib/zstd.c @@ -120,8 +120,6 @@ #define GB *(1U<<30) #define BLOCKSIZE (128 KB) /* define, for static allocation */ -#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) -#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE) #define IS_RAW BIT0 #define IS_RLE BIT1 diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h index f63636459..ee0f67359 100644 --- a/lib/zstd_internal.h +++ b/lib/zstd_internal.h @@ -214,6 +214,10 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr); #define MaxLL ((1< Date: Thu, 5 Nov 2015 00:48:37 +0100 Subject: [PATCH 14/14] level tuning --- images/CSpeed.png | Bin 18232 -> 18534 bytes lib/zstdhc_static.h | 24 +++++++++++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/images/CSpeed.png b/images/CSpeed.png index 6e60dbc78f70e5907339a28c0399ecd63ec56895..88d302c8a1d1755b16286f6df0ec812da334175b 100644 GIT binary patch literal 18534 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

2ZoLxMXH^BB34A>%N=vRdzB9ZxcklMStK)4h zysz8%{H`y%dHI*zyI(GDJ*gRgmk;c%*k#rZtW5CGmoe;Ozjf>9#nb+Kzkiw>I9*|; zRrucfZv5cr)tkG(6f!WHFf-}SH+%l0@0Q!-zKx6iRI1Aka^IalJORHvC2AX@*k^(x zB(@Bz1pgbkYqr<;*r&?}IMcP>sZvX`F! z_AAV|Ilmb~=lD0u2(Wpu!&J%aEjU^$ZfGg1Irrn$wczw|=MT?>>Ss^?pU(cE+v>A~ zZON5`pN>`(rW~^6h~B>`{d_d@>##2;{_LL1{{GIakGfH;;8d~mE90t&d7YPLtzZu* zyvKQ%;pG7jH776GEjq_Oo(?x(drwu)<6rK_<%=$YqW|oA;gZ0Ea5YB9Uaq{Icc)@z zRlL1Y_r9c=j_ydMQxN;w{*O-<7O$(G@Ta=!!zBG!KX725J;?C0J#MP_eeLy!FSD;G z1s70O8QwjYgSX$kz9_Y7`{xHm^~!?auvC>^aN?iH<)0PMx-p17x98)R2ddY#Gj`^) zLb6ah<0=cenYs@uB;eWd+c8k_^Ul0~ceG>mb{@UU+)3aBqIZ))HLk+HVj)u_EGuX@ z^(<%C-x=q4H{1L1^!2|k{c!;K!knKuWd5QGMR+=LOxj~+`Sn}d-$#wt*1oW;d@)D= zEGM`yDt^HdTL5=oYuCp5^BbyVKm&~B>FUV_^efN9ZKvr$% zWz(q3nD*9i?%J;V8~wkTcuh57hb6{<0}}Z))_1o)WB%wc+xl10M+dM+w%uXyow950 z&dwg6wXG+^LT`7NuIkw~OKT=K+`)#)BKIF3n|%Mrn{(!MKi@~2*KU~t3$po)UfRf?1W9Bj|%^kNlib)THa8Spy@!R*vVVuL}KCrvAy~+^LjRLarNco}7jh@J}T4 z`+Rn=C%z8DLl0WB#GQte&=p;;ht{uzKna2EWVg= z)xG_hKmM$iO=u`dP!U#K%E#38@!0mu?-t&0V&`@S#k{#bbI9A-!isSj^Y~XxlZOXN zgyB4SIbr54d9LT5+$fDV;fG|L^};2+j|J^Rrp$JL+x;NP=7P0~Tt>0`{Xf>s;0$pZ zUdVFj9ou1iVd5ppcoT7O*j{3XGmj|2_fKe1J{)6<1^1e{kfQN|NV1K`t1nk_<3k`V zkv~?BpT#16Ls~!!bdKG--rvD~Yj^4e{ppVG9*=hYJGFKH8&BO=@@xzm0t5sKiXX1<<6a746f}8I~K3_>%B!BmRcM4No-z!WbtCDee>t;G%N~R zw%a`a*P@*t!vA!v;+?qj)KPmQhoxS#m&kfpERI@i(4MO?dr3;^*1s~@W==16-E+lBjWl`cQ1uZ&Lnz%@E6qjg(X6QVLe>kW zS7g$6w`+9hTAyIu|Z%W8A{YGl35>1sZbfMO^3oI~SjeUEKJiW^eB6 zi@*Qt9e;T!JGSn!py|3Jx*=UjvxNgU2Sj>B&-zj{=~w9{#hXE2@(+v7R($j{`ittgF{o=X%;qs8*Ge?LPmZTYrhn8KLFD{`N1;=k7eW z`>0o9@AH+BAG#%{U$|lB@jJ(NQ|04Okb&1ZckQXSa@@`eY2HL7_qcb88@Kdv&9J#+ z|KWqZn(n!c?C<}do)^1s7bh=|&r*wBs*heTU2*Kcg}d^VHTMo2bdyks@{KF;m^9bflq@45N!e_fCNdmGfuStasy|J9k& z_vco8S-6Bzs^-zgpC!y)f81H0JKss&U-YqmkHblOaj%>5ii!P7i;m7%QMjdazhr!r znpW59N$nGET>B$fSp0^0ip?cg*>j&7pdH~Wjn^cWFVD-bS@->^`u*yk^A~|?iCwl6 zTJOJ_y11QPzW&P2`NIA7HXGmD*R+^NvCE8e<}?1m1GYqUzzP)#ty4@m>giUt9M^ zJASz!c=9=~ue>2hLcU!kyezOxBe})I@EUwPo47AQ;FV_ki|R?_2XumQwnb#oVVbHQ4n2SR$P zxASDxa-~5R2V@=y*>;sT=+%Lc9&vZIEq1KN5I3ebT;f0Yg5|E2PipjCg{6ExME*3q3=FT|jMc$G`lrcJ+ZM zP#dq4v1%f9btGWE$*|ouRQ&I z=WoHck1{WxFZcDo`|WD6(EXL3H)cjz3vBQ3%AS{Vbaluq_3+bHT$%53LQ1(sXN8zL z9yxoNVW;zo4I7*z?F<~OHV7os;|Fqx+{@QGFkZuR3ZSlfLhFnziU| z*Sy`Ezt;r*SaH3u>eaVn>E&v==kn{!_UAeD%683YeDynGqVlI}3bTA~vSiLO@a{Yo z=z8{A`!4Nly(OzOmB2an%CVb}V0(Ns+$w4Rqh*cq{|?XGs(*FvzI)qBOP=?=`EvHa zMrq~r)L(zZ^_Oh>_R?7U&%9e)_TjQA$tB;V_4>~I77D4*c~SA~@#+0_|M<`S-SaEv z{c?A`A6?6)-0gAK`*zYb@>_SRxIp+?P2N;C&fYoBmo^{qJ0$L=z5C{>;~!>c1ew}H z3K~#y)j4AE;RXNXx>QTG^m*t0ZZkIX5oZ5pd06H0ncnw*7V4<~i7B1Xd(oD4^;#}0z%ng-ZyOt-+4txLU^uuIF_stzU zETtAa3EseZw<9Xf0Gz%gx*zw4#h&gwF2B#p;=yaNz8v3e6YktPvTxswgFbTa`fV@o zykB;#?D-F8{$s1p6n9bP><3Jvo{NV(+1W4z7l zy5HOqyO)=&^DQTryn3lVd6~L3@BSZ6CX++e_`jbP`y+Pv_#4fa^P2Ylido-Reh^Xw z-eJ7da5HB$|Jua5O^=RizAk>#xZi*3j+d9y!)mtv?9FHEySumY^7=V1>_b-YOPL=0 zq`C5CcL$_&H2cEXb^GdPkBJk#!lq0=9bz_9Hike_0uvh$tq<@orr{u_FG zu9^OM#9hd2-ud`v)$MEV_gTos{8v1^e95vxs6#BJ7W}-J^WfU2-o*=V^*jDDn_BI4 zbJ9*oYcxnE?T+Hh8}@b=mN;L!zi-cn>9)Jit*JeEbMC2-BM@g*mVdjqOVsvJ<2qlz zpNkRR%_;W% zPnH>H$4mX+Q1X0se$8&B#F*n3xxATuR zE$dI-nw!%(JHJUnp;M57DK+K)z9-Ko_St?p@Zi+)$F4Kk!v8(l{OEuh#PIJ9No`v5ejqZ z@%(GP=hPX?g6va|EBZq+!AnFSqew9t>sDWAy}k>SYBvf``nle0zv8x&=2@06G;-d( z5auuWbis1Ji~`g^o(TbFwuZj*>s-rDKAi3P+Dbcktx(eJ#~o+=wk@%Q_S|-gh8#rxm(A(E>xwPioQQP+sXWUlDwGJ z=5MMW-S%18Uod?3=tPUef>P}&r#}W;;A7#N)=Ev-WV*vWSzYe);mLEWet8*v=V|Jpz8=l(Z0zy5vGlW)R*VWS{;to7EGs_VV^%WDH0Az2n?l^B)l~p{r>K`=0}ZYF>8c^6S3!+B~RfBw)tBUqyc`bgbvuSe-lhqE&mn-Sycf4*6?;_b=Kj4sV8n ztK?=NaUlk@)7{^D%L`_WN(sHx_l;lIR_wtUu` zzo~9?StlSXe(K4M(sJjFV)yvMeG@ZKVw-2;{@TieylVe%u6iCjU7;j~1vIw*z41x> zN9TQ8)t>3|J_3_4G<=@|b2JO|E3~FJ%y=xTlPT~q^sZRVYHMsL5EWCSDl$P+!dY_*D zZ%5(YiUrC4e>i;BSJg_0ECsECkn>n}?|T21jnRmV%ALM)qEE{dt{+*Sr5`n>Nd4bX zFyHLl#HZH`>-_ii#x|iFe&yiv{r|(CH|p*EJWW5yox5bu$G2Nv3xP(dE?hMGlY^nY z@rXpd?yp1HvHL>A*IxYi?#Gx&it z{#dRZG$-OcT@qe=iJc1qPpM4k*;pl?aoRdP{^gIHtDn>V{ahMdFZ=!K!An)L@9)fd zS^Kx6T4r1M=>+b3eDIeK>*t^EvFG zto`HZ>U|}Z@bnGWdQ-x_wk-8c-JLHljkRlHXKV>{|7iQJaE8y{>bB|Y(=npM>clZ{ z3-aA@-+g*Mw^lEnA-B=)9CPlw7tzb+U4$nSojFUvlK~3Si={PnEP3rd&REYqS?NVZ zVM@~FSFzwhYRMbskGwy_`=kx6o3DTe_fwMh7#4jy@|gelyXQZg?RS8hfrpkTSb^3E z9OIjuSsnf#G}<%~GQ|%nc3`$G$m_Y@Zol4+a6ZiT{q)02GOYak@7}w2^?e@e)31~Ez)KovVzkPT zd;EQ~vHbrRoF5&o`_290${6G$>(3uobib$W>&|;i>-8_f${VAd@}i>YrXafO!pZddng_+!2jj! z0mJ<=B8)F*{0X~oTl(Ai|C=!*G-00Mztr=3h7RI!uRoo36r9ty^1R#mbQVKQSDcqv zzJH$%+lwog{eL}Oz!3=Y{JX77E!ihyW|q(WACDwo{2}qEcpX5E&pPzkfmz(05RuibO;-cZt zlSi&pf5MCzN5grMzb{>6h;O^T-Q=Zo-{)cz>mFT>PTDzm@F^qtJz-@hg2LmhvEM}n>^?E)H8V=RsyniAnaRU$t(4WE zg+GDc0~UkUBts`UHgrhb6&Lik`}!n(^*sB}=k@RYdc9-4hE`e0nX%SGB@=M;xT2&qk*O~V5&eis%{Bw(mv z2MYTMKc=xvZ0(c{GyyHy{f-|{@jmCS(#;%_4<5D z)_?UsQsHkW;&SI(X;Ypke6&}`*6pK1UQN%TDuoiCNir@zXD+;G)!xU{)dgEf=CQIl z2As;zG5;-m{EMkdq2!EF-OpFg`s~u1zvW5pDPFyx{Jnz!Vgt~G@SctAR=-!ri>%;SXTYMKhZt}Rxwae&R?D_0=#5#cc98n!eA(q&yy#3PF~shs@5jpHBwk?xMSG&?vA3I$Fh@$|L$Ay zbiw0CGv@8O`}6a6_+)5ShA5J|q68lQXjgsSsK)o^v+G(`S@E-=!LK|0^J`?caDj(_ zATtDOI}1M*?Embr*t-13BC)2vZnb|=B{tvzZoa5iBo|LRTJiSE$;bS*8gef#S?B*; z6xP_+o%ZFB=yl-}zDEC-FSP${h3W#y$6p_wpUb}ML)3KrEY24@M4(ON@NYFA3xC^Z zB?ut7L$|N+*Xz^ja@7$w7p~vl_G{5o@Ja_z%K)<0V~gD}P;2-uyVU;;uJ47x(~zLv z7I^ZkdE1eS+8@P+4o0=c1!u%{)xlF-pzaT7+25-Lv4(y!H^eI!u>bpaIX!IN&*#&p zm0mGGog%xiP9i<8#{5G+zs%nMcIDa`A3BduKM$GjL|9aIwBp;;z8inRqdGr!?LnKG zeA`v{;G(?R-Tv7%v5;9>WUW7Lu6iE)F8xF2acr^`$xq&N9$(DQ^z$Wq{r9Wy?|&$* zM4Q;ZB>@W4yUiPt|9@y+Y`^3EV|m+;f8X@1KP`&tnScorcZD~m{?ZWuPZEOqtl-^v z8Xi4)J1RCh)>(#wCmD~zR{S_Rg46tCd0R!f7spOS#!rz)3quRTy1lupB^InVdwyS3 z3N*ouh#V1hP~gabtUZR`^B|MC zh=kT)`0O5J_8%#5436E|&4}jpq+>Jk%@xqxaYo|q42kLYDo^X{qb))UI3tnYGe?ve z)WZMs=@NKS8sU_qJs;0q&F{1Q!TizTu>QV+*XtkeE7^!Psm*lEqWJOdgU979tNzy} zHKa(@Jo>0wh32#)Jkfbf&cenpcysXTJ(rzZS^kaPN_2K!u*%Ob;SA95j@i2z#LHj1)O-M+| zh1k;xs}D%pj(R(xp>3CZ;TlcfAB&8HmzwTd)U$f6SQ-D)*`Z#u;Opt&yH}x$nX&C^ z1FxtB?*IX}pYx>U8%@g$IR6W8FZhhI5(U0R^R^xHl^gpzjEl@G4IDnVfNOb#q#pB? zBYThhV`nyrhZKGAO|@?g9ejViH`!#-ZRT*iPga);l-J+i&tl*uBi51sq#O#%B`!(&a5`d%Puxp%8M_1x!$oiGgo}L zvqrviny~R_?X}A@Z>VR^y`QoqZf#Lw8yjyx9s3HWpKsRwRb1`#X!2yE>TRnQs%_8e zF_N5iNkI8k%d)3;)~uejNqF-={mqLKwwis3FZeV2jD~nsNy_V`T}i53sb-S(D?*f4bv4~f|M!3|>rW|6wh!XmG$|@IEOf_3Q6tF-i;9gG&pIT$xi7}l z_2Ns(Kb}$F%_A)ZjkR`Ha)|t8^Z0!}#4r5+e|HQ~SDADrByH8JHY>ue6c z>pN$L<$65qocYsIP1Gl>?f357FSEaVS{BM@^Y+=_nv&O%;He>ZcVS^~kfMO}l>x%1+q$v#uAJu&&_==&sb zCt9~TEwwUoSB=+6-RF8W!RAuzsyo*_Vs0zT3ru&ZF8AD@wnm^ zuGm`Hi=o?sqUQFm`+wEaJbJHOc($;#Zv3Iguea)`M!6jQXV1Aw_2k!8?33s8m(8{4 zn)UT`=|?N4kO>xDpK`t(*rZyRy#4u`z+=41cYXyr$4}AI$Y1P~8ZLNst;+WBrFEJN z8LZ4K8*D=KUvp;ZZHHz=e2KiHpb~*v?@$|IzgNFZ~f|AEncN1MsdbFpRTZZyk*ITDj9|aay$YD zJ_QutTsL74SNQZ*OFO4N;;uYvHMR9g>b`&LPI-L3GIigwCA+51ntR0i%x>Uv8(^C>_PULO%3N77zbwwi1y0$^b$ZS23GQ2G&O1@KR(<306*fDQxBG27A{w^+(w75S&s%d| z?>auyZo@Oxr{~U`+*={^+fSxwOH|Q4Q_mc`oy}g(3zxa>*&b5EumE)Q%R$bkr}oS_ zzH>|N^0#LT=B zy}Z;C1rt33J=4@yqf`b4x0RkQjv*CsZ}0X`7fzk`{^M`Ubv5?X=Q_wT2~3!HsyIw% zhx+D&6%!d)p7b%W=v;Yo zzUbM~2Ceeo-$$P3BwP#oCRsRNbn)6nuRor;61B6mG<<95*0aL=mun;5b+tX7dhp8M zqm#Dh|Fc-Fl`XwiVDtNhnSr_MCjE5{7uvmc&HDYmcLNUB&zyB-e_&Dl*5B)M!~eh6 zSoAiyde!|^2Wy#UC^HFcaNwP1@;c<&^?9dXnXk7~zSa1H^U_|q{FqvyHSgBcojw^sA>tzZdS1HkI!G9$SCC^m|aX$~)cc?BuD^rcr^noxjRO-HHACc-CdD!07B9 zw?izLr`|sDI;C}Ytm|UyHM?*9IN0%G)$fQ`->2LQ{M*c8z|W$P&^YOQ?AKTGO||bx ztIR(wd`0n17t8Z33T~_8=v|Z_|$DLY}+v%yTf%|uD zYEPT0_WtfpyY|pDg|91wX7B9ZlPS9KRIlvXZR@7U-486f|E}5F_EVW0SHn$#h6dKG zpD9;fL|&6!T`%QhfAearzrFCT-9`G*FQu=@<)p^G+IZIJ-5rySjn-j1-`va1THu$O z>$>Os7v8Mj{_DHDvo@}BoP9}o;;vek@JGH{*;02^!fqZ~XC7^?yX#+FQ2)`JlXqWU z<(ACwtc`(1C*aGSt6w_T{mVR8H1F*sbHBX!a@)Pe-#aht%?WJ_%DNr$?(T})xr+ANYw3Fm2k)eBwzVja-#O*dHLcy{rz?->J>R#u`{nHj-d8L43xCcC`p>tn zBK6Zoi|SP|KKCLgALm<83kt(m^S=s7tt~mO<-g+G=IBp1*S)JMO8wihJ6gN8xlL=f z>5UC}cW%};SFe&@9aHvwnpDP#pW8j|FEG25l)m zmKS*a?vYccu2!(0JpL$W&YjF97bO~YDl#x~hkdu19`N5L{Gr`V)%;m^_Pne5m3jVd z=wkJwPd;Y_pEX<4yL-34o!7)Fm3Ob$ZZBW@Zo#{c7QgcYL%KtIdg!|2{pvf-%U}P})sDKtxxkl2L4kRy`mSB-nv#a+1Ewxte{0o| z(C3nylzyg!m*2g!?c0^``p2hkJ=vV}=v@}S_CA5ayjwYY>b`g0HQN=n`#c-7Qq_lZ z0e|(*Y@IgM%Dhajc=zf_iwCK~5Yj1Y#O`6A`eJB0kse-%bbid!5e12o-=Kken z_xG$gwQObkGd_v4|Bt@mozp&PPwC`EN@v5bzSrM1ZAa$Ry9OJt?X1j-bxm#lB|4Qo zxqZ&<(;i!ntz5OuNXqB!%6IoyU4-Pm2fe2@Ct10(tgx8M^g@hD-~lg_07FVE14~6S z0}Df>A_F5s!y)>Rnl21hrLU&!6=~@f*T3cMxIpHthP&~pi#i*MnnF4lw&dTptJdUb z{Mub)vKS<_`M@d8Nnbh`o=7g^gsAK(nqd4=knx1EkMOL(zO*TeC7&v!Us7h8kUm2V zqR04@f)()gKEawzx4|0*CEc4R=V)YJ6ufiF{?gQ=QA`tWwXK)lcT%GMhAOR?nHVb&MIm zPVqCJe}DIa`If@Fzo+ZPY+Rg$8l}6wi$$0|F?sN0euZ$crEQYlc7x>%DleaJ-(T^0 zW&6E~SN9jCzP+@4OR54&>IoFT&y@X(Z(2^mwWsn8Z1e6*FQ0#E)5dz&lj|-wq9lMT zSHl~m_P2{ZpMQpF!j&7#(*M^U@U$=cx!(Mn?5)oyJ$|;_%`ltaTl4SItMBuo_x(NZ z|3Ccai9%~G1_xzfVc~C*+?5mSzrABsFn?(=%XLmGi$e8EUg=+LLNA}MY&YK-9v`{2 z_(N;$Z?EI-_EPflyEF2i&G*reA%u_I<96QsMKjTX+8spYo`%eB#^Gx4YN#&JOu< z>Xq#03gNYXZyZ5M@u&WaDsbwBz3p9RacW7B@19bdIdYk~evBS-BZ6_ zgU$TsZ(dx*{apVv+oV#Jj~?$LZ(e?&yZMV!^e*p5rD{80Et`L8)5re(xAaz?xVO3) zH3ZLYKk&)$I)h2LdHx+K`P~-3F78;eD7N`&=zqD^<-3;t^WCyjZ~dBEKfigir#>&z z7wSaI#tV8>@3}<(y>adD((@@7V%5&oCU0N&>+=6P^L?F>^D0XcYTsLTI!1=+-uv|H z*4<}sw{bt$zkU09_U95M-WgvZB?2U^budiXdo6#FsmjU|y}m_1yFcAOtL16A-0htA zqltGm=iS^^F}tEN_3F8WzV7`s1wmy+e{cExUM{@!>HIn91}$-&y)pC4W_^_x9&%N` zmo|46cb>WQ{lu~(FI`^O|Lxmb=*{iv_xaeG<&e^aHOy}UxI|j=+qCfA>`(tLS8wY# zsqWN>OId5l9X&0!In^^T%`pGW+4rBbxsPCIJ9BIOm(xz?ZLA*b+i$kq_0h$Z6F)yY zYg)}dGwIr8NQPq4R`&pxf@yE3w@gi2F5KxYzHY|#>XgoS##^Qlb+vEbMcVJ*wkh4g z%vj#jc;$(ATPB+Mt7GcF_42ySxkF-|Pqt)zytY5@pU0-YpT`!b<*%E${c4+;>{Q)U z{%6d2Z|D1AIj=*Vgn3x>&MUp5Y_wTQ3%eOy~FJ$J+6oykJi!66AL_IvdIW_@uP&sEUV{@r!^Z?=0@MoVgJ*slhzGT@%mJYkY(x32z4 z^W;gTDql?goXg(4CVJc3ne)ze7O$KC^Jc@{Kri?DcZ(J7eiQ*^aY)57Q^{XA_`aXF zmezZF-IXi8a$euGXH!=CpQ6A&v3+y@?d(@7cee*w1h4-%g|g>Wnw07VPA*1Ns7m2{|T7&yXfMxuhnspTaE9jZQK$6Tw~>l zJz-Z~V%5=j>rc(T2@%4}7hQWEWB>d8+kao$<1KE0ax*-k&rsWS`mfdTYwJZlFKybs z^2Lke@2y+V?RHuy{{Qh_mtThR&adMGwcgv$J&ax1k(I8i#q;m}yR`6!_S*1oJbxaB z=l}j8C&@lLZOY=vgr_W?(AIz-ufML;-;6y+XF3bb&bzlGb=#Fr3|lw1J&oB_kos0X zINtF|O<~~wu1QZ+BEL=TI~{aS{;yq>_55A$zeu{uwh>1`FFoh>k!|OxC+fAKSCLNn9VBoU)c%1d=EPYS zbmkXbvVSqrVzI`=mS?qxuqqHr7diR#ar^ncI+K6jyxGIQU8$3Z7dk(Y-_Nfve%5zR zXK>;IHS?gU!fErJQ<-IM7tcy>pX8}gdMMy`yrWAwS`3?94)&YVa;E=@`n2n>?ThqJ zf0-)(MprhduYdo8i#(vXLA30A5-r#IOL*yIPve=zzu@gnyP_w}ldJz1m7IP2@Xsk* z48<>n+wA`BPd3u{d2A2Imdd|!o;JPpS4$c5=W8B0xD2^fc{$Rrd%c3!Y>V%`M;3qj zcX>D4XK5+ScGN!x0*?Hzt`;f|K$Pq?>pyjpZ>9XJ#T-1>=yIOU7$3Dq&Ut}_nzJ4(A{jO z|7v>`3Ps)jeQw@c<>32%vw64FHua#Y4m(q%^6`zf?DQ|f>I=ie-rD>+=$SiT;c>!c zq})AAbkCfR8@u1{Gt0Sedigu25ue#v4dixl$87UFS!ui9U(QR_G@Z%2s0xZggp=GX zH+~T}_-4B)^Lm1%owG(ghV&6}1G~SQ&whMb9xwgQi)WGbtUyE{8J{XtwR1Epd^h{W z_LHj&Gcqn;oU`9|;ycuac6wOweZS*|8L8(F%zLYRef`-RrLu0IR01ic!L9Sl%ebHG z^Y7bm{>TDTZ?^AK`<@Flg9<=I(&#CAmh$M1`TF&D=SE{VV`lrujot57JAN$pO#kP4 z3EdZ;%O3to{VwvdH~W74){5+H@hZM(_HT9wzVFAMYb8}%w~rZ9dUEG%^SrfxD&Jmz z_IT-@|6iQq*wI7cq}Q+RCG)Fp{M&YHSL*G1wYfho^j-Y8v0G^B8{S(EXx2@hdPLlF zeO=D$c=LLdoyY&4t=xR#!~^c%-=_A>mzA|E@;CX4qzDNvyEFfU%hp^K>CkIS z-P4@GT?g(3GAEsvyPbP4rSsi3>HNa7>2vCPO`~OUW8k^Wx3r4kx&d*cxt~zkFeDbqyxxa5!XwdzDd-lf}bz z?+GoRpZ>r0bp5)UlJQe3N^*XzxqC$zp|O^A#mnl5Z*O&(0;Isb#GC(O<<;%N%KqLu zvru;N>uI^hh8}t{KOa1qvoCr@H#}T-i8p8&F27lMCM`6K(IbncA+0RW{?DCHZ`Ih= zM(ug}_WvF0UpK|eWG_@Ax)67m19tA0s(N$UhSy_@;p#=)Uzgh~cTYR4?EtDlT(#3{ z-aLApT|Qf4OWMf?7nUs!zVDa*Z}FGNhY6PJH(*+gC|V%8EXosBR05 zm^Cw=dhkfqB+l=2++_3lMcUl^az_p>gH(H0KrMJjaOi6nSqhc3naTFr*{uJ1yBY2y zc-MNiyX9(ecXeO&X`lXGmfGjg@h(Fw!qRaPqOWb%Uo@+>dV^>yRdFdtOKT>x z-7QzjFO{#!e?0MrOXlVhZO)6bXOZfBPzCWU-0!gb(&;;t7cSrJiD|{P&LSzbg$KpI z$x7SZeyJa_#2T77;6nnXTjrDqMcp+1@GkrCa<_B0bvLRh$csAF+xl-@Eq284VQ^62@3URE83Yn_XKiDhCsf?V|H`3+j?XJsBi+}m!*S&Hdo=K@6T5A`}_uk)Ac>3OfbeWtJGrwpYW(aw= z-~3wqw&uI;;LNyKX0D3F-oKX)rpw*UNxCpgwb^-gpWmF{$JTulW|uBfvpuE7;5)5q z?iJ<8728cR*Oy3w%ix|O6Y0Nixa8>I_oR{oE5vTxI_SK-y>1jkQ;0K zxfkw_*RQ`T+d8lPe#T!}C$7Q`is_e>&oM#=)FK^ENy_j3@#Vak<;&xGWn04_)*fb9 zA_8+|cA(!c>z2CT-P_+-twjsAqnhd;Wt}#ixN5xE>zr3cPctv_cwX3wqOALhSByVA zSHEv;_~P#MwySlS5I05@Fl>5my<43@vW9DoGGwTsE9TtBhnt_7F66Cs4!-YqJJ1(m z+j`h=;F<@Z*8I|XSI@V%6Cn;=%`oMM+=3$e^$ewK;Id!xY0Q2z;~$6YK9}9tcd5{N z74u!>rqZmyKE;d2Qx zA6f1iZ&81(W&VZI^=DS)O-231nptINFDqHY=&WIfp<`<4yts7+iB zlb7CmVQcVP`$Jb9&pd`DQcpnxq^Y5xEOW2!<$@H2$hewUdwFY}rLXUu|9}1Q%d$^= zs-}Fjbh!Ftu?C}H1E`4BaNnGB`sT)`$=}VNT-U4Be$L|pa%Er{e?uYin{zcby}y7{S#H)ttVarYJ;Yh@dcQE@|jk(*tp?Kjam=P>#5OwKOb&5l63uP z(>sOqON-z5HC^jMNSDv5&ZV%JiFcR4|gW=`_0Plma9pO=erLH z@{3K(0V4G!YVzGM2RscpcVuV&HQn24k{Pw{t&48bm7#zMrHXqTNcYYfCA}a6Z3@6jpgdxnoh8s_em%H{5Qdq4zjh@Jz#(9 zFa;z>Z4!XxmD4-t7%!guOy}j-z3)pNwI6-~YGTl=L_>K{iSPlG?Z(PHtY9UR~?9$Y(P{aO~5(B)#SCXP%0|oqheZrD@T{J99Mb~nS7 zynibv{kf!L92&m#v0v4Zn7l?_JL{njawz%W1ikB*HD`o z8p*1#Qjp;S=kM~`oOA5IlHYH8J}v+M=ga>??TYTKbFNlXQ+s19_DSjg8_9jF(=Mpo zp7MLO_7kqswvAn%H00mU4%` z+4T*Q4DWhgc)Q9~Rl0nUPx2z4tf|H#?Q_3)WWxf_C)ASp{QKU^{;4-_>|c~}eQP^7 zA^c$uxCaZYnX8Jz?6+O@v@hHE`j#`;J8g_BzWwsO{C)o}xSv;Qr90mbQ2P5P?`3pZ zY&AHdPiZk+J$JU#LoDkv@2Ydk;1+XWU)m~AA)R5zFR#zu?suc~?LtV1PG0a@sQ-zg zu09hivm56=og+EdB)`S>?`Gdm`~PZtndjfx^!gS!JqyAM(w?GEiaXse^`|Vb{ObkD z8FQH7Q#&Wmwtk+j%CPp00OqFPuq6Bl!sna)2Bc_2X_iw*)zz#>6viVf< z`Pkah)7w1RwBF~xF1!TF+eo?p$(t)DDmfjpr}6m3|2)WN3NBYcSGg9T2fkS9D zgGl}7#4oK5PG_$(2sVU(r?QOWPtDx->F}v}j3*t^-J)$Z!A4IBWmr`wT(Wb2(Wm~u z{cNz{~BNLQDC}uE*QXdofIsxblYm5IDRZsbs*W#r(>1Ur0~lflDC;<*wIfUMyi* zFx8fscfa^Vu;pu*1m-iH=7g4wC9&P_U6+9Ux_k11pCS=@kg8N;`RhmTU48a*xRlqV z`~98z{GXTDjBK_QdrB_7XcfLWable0`dRn2^)4-b12&HpYF@^LH?9i19$O1HyqUU_ zRpI82?IC$zZmv8Tv|qBDDd;a>_V?*=*Tr52rafnH<#(Ln9{6AXVk|tYE*H)EYr%H+ zI+=*GG&vc)=o7P-tg?>r~V0YsWJ^}r=KokE#ZU}%%8W*d{&yE^RC;WWV!IZ zJ6j6>zx_Yuq0zTLRl8q%#A+FauW~Lt(|IL!Wt_L$tS6=6k4rZx-wgh;-#7n8*B6b= z3?jB29#0#$tWwE``}TEFo0+Wd9uAjstHdYQ{Z)j{Fil_FZHs+yO1t!+LXoaf4EnE1UXDw@6Fxf7xU)t z5PW_hcKiS2-)6gawW={Lvy$1Xl63uaK4&iLmKLJf*s&=eqp^uJXJFj?PdQn7s` zqj27!GusU`747%(JqwpZ0(&%MJ_sfpRlTj>gCT1Bo3)T;RsG9DqPq`8H_GNXPLfL% zZ5!p}z`iuasm7(5yWUUq^|uxI>o7wnd-}eo)ofgE61XRQ(OAtOa&&&w zE6ww-yH{Gn+Z(MR=MH?Xe*7gk((K!Mjhm%)P}RGkrMX|zI}Wu%a77)M{WUpy?w4fo z-RJzFPWUDk5&Pugmzfpt01mQ*%wv{&-{185j|e0%%GNX7+*~iTYko64#5|t%^vA|* zt?-^x7p8mfm+Q~>Wpn340_M~^m5jA;g$YmJ-2b| z?yh`1P4eT!_`4J9Uwz!zy(wnDS#rCW%Oj7&HU`lQT}eGR6{c#adH;P@l{-5k^>NYU z-#LCDrv%Na=WtjBUX>7e;OU-CS<6!v1S>y(TgqQ~WiIz~{r?}sZ(rA`44$^t`+nAE zcF!#Rt09xU{&4yF%A~!yT4&B+nR$Xu&D?zF^w%cQ7r(IidiEPtbLYJKK2I1P?gf_M zGX2(`y8gZI6ytXle?F$`Y5!@xtp4k|owW{2FTX$Q3FOrQ6^bIMUb#H;@%fPnh44IxboM6K? z2hXo7dNgyN|1`V0Kjx>`*P14}KhH~hwcF?0W(S#^S*oWbZudJi>|!bWeBZ?7w@XiNyZL(G z$EDVn!|Oc$@SS{Lcky1P!&&C`md0D^n^HDsnRMu>B{k)|YEeypoZ))+-s!(rqnCwA z#_~E$o%A{bnz`2spZ{`n7-e8)M{tmSlZt(V746Rp*g9 zySO{a@0H_aa%L?({W3mq((}j0i;Js*E+1O_PUioIJNfeUmzT^p^=7lbXPy?mCB)Ns zn$6AK;ZJw%jq+stxaySpR-uCmUVM3Zos(N+d-8Jht{Ju6bzK~~=c&6GzqeVOI&%8H z*`ACzd8?B1i;mRYiaB#OwKG1kD?W7BzpvN71#VNcV}5x!b^nV;k{&a;|K+FuI>j&4 z5cZ8H<;zo(om^|ILB*Ct!=331Z`F&gdJJ*$BxAmN;ivW5<##-v{m{AWZp?|gC)?iD z9b;$r>HGQXLZgMj+=^eG!sT{_OT^OHtD?=#gb@-$d=Ff{J zF46Xn7uGs-uf*9JDTPYEWOjUx7gF9N zv+uv$N$1JC%Z{XrA5G^g{l2?9O5?=AXD{;?vt663;Mu>cfG=QA?BX5~R?TwPr&X?{ z(_c=!25|}F6yvE@%qQoZ{POqZMsN52p8UH?JJml%T|C}heQw{kR}WvC!JJavan}W%8TP_|&GGUs`B!*YeXrPfmws{U0Wi*}*;(lWS0EUvj_OYmRX2 z@?T;RzrsZQ)_ESE`=w*&9VT#lYR!hHOZGFL)HxomGyl$3XHOw5zw&kQvp>Gu9?1L} zw8Da$-(ga^6zhVtpK5A9mp**$0ym(E1=NwdWwNWd{kN9buKc>{?xM+E*XDlucUh=Gh3)3+U98}E zFyeCPg7)i{`(BQpXZ`!t=}C1yJXSkitlRkf`tkkl*A!h}gGPhE105&2&mV?FAcw;| z&0A}pi=Vov(_W<4U-RqdtMtd>Ep~BtjCW=q?>D#ll>ChKP2W$OJ>vRI5W7HH9;|sT zcVMlF9{u5NwkhbqyNWML0SR{@>i}mmovV^tD08+* z@A+|QWAShAB!7Mt{>bel)NJ&JZ(&l|@#*4?OyI=8qHtcM_}XXIry1AQ7A@OvWB%<= z)#OG#yB&R60b zx?hfmb>EpA9_AX)vp0LgRq=Ht;c!1Fov->8*q2sy%Ch47{#`GR>y*Xb?z$uU`RIjB zCs?hQ_+TpZ{D0%s!fNrGrMcP_|SfSTh4l^nV$9K$V2vb zD_Iv)uvNJi)h85T>OKyq?FW*z)?mSsnWgU!3-p zzWwu4#xCVEH!sY-{(j^2s~q6;2^w7jFJ@Y{M~2f@sMd$=SIW!Bo9hhbz3W(+zZ^Wy zsrCN)*Y#*7pXn~zXK$NU=luA?-|t)Mtb5)`fEzups#AjhcU?MG`aXVF!O?XuR>2#H zXR1IA#C=nWKfk*ALt9wA{OyLtnkC0)?E7@s*mm~(Dve(udqAz^rHah(l$QuzJN0?> zoXzX^hVYB-9W%5h^ z6PIO^VJ+o#)$mkj0A9ZIGs5pnuj6<3`x0MHUOK+M{_j@VwF|6|fd?ofKmVAG#qce2 zvg3VaYM&^cbePlv3IO+)epi3oaQ)od@$pl;`n`9*-Y+c zMxa@Y*q?Dn4*V-?QUUeV)Hc+Co72-yI=r*IxbL+~Id}+q!PmX-eQK?9+dm22xDP7% zSrpE*T+;_P|9>y}@2{A;z^~-_v)<_0*WVjTYCPvZ#$L986}*H8<^W?&^(EIEt**$P zba*yf=xP1uGY*ixj$nh0aKwJ_s^l|Mgwq$i)IUG7(7$w@^`vUhswc@8U$^d7<-d86 zj~m?G>R@;>^T01xQ0FeK(DGS&F#rAf^IO-eo$2Vex;1xY{&HV7P+ML0)rJFn+aQbI zIM>93mMv#In^yekd$uaG?9c7<>%Lv7ui5nFS_kG18=v#?Vt97{Ykrg&4KkiQ=H2m>3f_}WX904*~Rks|76!Wb!R?( zd?dH~9Q)6b=VxA|*hy+^Xx4?S9b|ef4j$}RJ!M&P|8Cwd!|vGU&3ASQr!RE$ZSo(z*x<6rKOJrxD-=E9=Jdy27X)uRv0-;ca} z{=om;kF*~XVxKq9*stNZ%HSX-+6X@yYjR9bNkX3UG9{Q=Wo4!Rl3o7?g`9AhAYi(Yg1C_be_cP~09rntJLF@bd>@U;Q-UftLT}@eeo$u@P*}aG* z^Up%gU2o^}V6gfy+1mc+(MgZ@N7lVv&AHo&cmFQqY-n&o*V8{#<1+dx==P|e*Y2wK z*4$Z$w&kp|E9cBy`JV62PyOHd`+bup=p5#^TcFEad3~-0^VjtnCsVDXM8VMvS|#tT zCUMg2V`-$i;c;2R>6ewC6>)>RR>r3;=J-9GQ?X3n&pz#EMPYyJ^5*`#6YnU$bT^uy zvd{(UnibWI8dKv_6zV)rv@C|Un<4!I4foBKQ;T2h+kN*-ve<4vcK_YQe{Y>>+qbX; zrZt*zMPk)N$Lgy76CXrDjd!l>AJ6;ME}cL4`~Ak(8w?iDul;!E)7wdn*Yv83m((2U zJ9qI&%dX9vn$-Wlxy$LWdEWlucm3DWMH}8MRVY~+Ki3&tLKka6nn#P?H*Y&V_y3>! zyUTBuT2t4ke#C9gDc#zJ@5I zf3|qD#61c==JZ)FJ?+(QP-9DF;pF}C+3g}63#`ra?{pboxah20CK7d0@%rA$3qHdq z0>y&PeP4c@Pj8pE5vUcv+4-)RTlpiNEmnouLOVrOfXjikH>)H0zjCGe2pC!|T^chD?L30!859M!fe|gfOvGjTG^Rh{eQzkq2 zF+7ok4hMQl-{0lx$;P$b`u#pLAGS;2eK9^2ms|FVuz+e@sV?ISPbd1n4KQc9DQh$# z?UFLng!HC4YE6!ovjY8$)8lI+nLv$`QbXp}Te3zIqQDBA=BgcX04d;3KEM8b9vjyV z>lB5#;8pT0HohzkMJ9{qT-!Cf@zA@zvkv`vbw6+J&wC+#Ysb64-s0`}g#Va4GzA6Jt?Bh_ zT>GpaCyQU#k?gtLAMp;!Lw=+z(HA^$Be;yS9%Qp|_@u_Z^$~iKFCHJYErL%sgPM7ey-(+C?(C`h`a+rC zlkHc{*Ue=sjKR}DNOL{Up5F==Zhybu9h#sZbI_nN9y*C+oIl;&ZYqPyX?OejFF*39 zd8=&F-UOaqL{S8)52H$+|GS-UY?$%mAiL3d2k;CYs1E?0t@>Q{Xy!hPzcZdbK5APQ z>xSWyw-;*5cY}LFSmY)z?N`5a{zLQk+oh7=c}T=Mr&BYxue>PSF5h9tkv84>-^=~w z?>D_Raso|&A~|uhz;t&z)BG0M9k1iR-7ma-GdzBqHioLnov-8Tbq!xUShRc7-@FX) zEH$XL4cR$1XU&ZJ9J4Fdr>swJ1WgZsQaW_zOI>?+x+&_PB<=kgo44O|v^3}-;t$V9g7(jz!)wKuFL(8b-^Q%x!2gy3I z9(0#PEAOv!GP|HO^4gDUxAwmo#Mu1!QYb(87er>T~ELLszG;UiBp(87kB{xQi8e62};wu-shcknE&U~$Lx6D8y9zC zMA95kw@yFpy^M|yFr|IH*J+e>-KVBE!_*?@g<`Czq{A+H@s5JY>e!tq1=V6>WZnSjEs&1YPh6 zSuHZTdXd6qokJ&fdHq|NtGsgMN!S=9s33$c9WDK+yWtt6#hw+RtlkKOt|bio z&J^(ZkJ8B#drmkrcqK!!stjZ?d#N_VRuBEce~JvI2cX3eWEJ`=KZdNre}0=gjNdbq zJUGC3(t&~DMai2RhQE7S_mrqIc;;mmek-aq>Dm_i!t(+H1H-yJ7KM|#eHw>$bZSh^ zdUW>j!!H~R3=Y3{ec}>eU~n)OY+zt;cql*w$s*sd=zRpwGj3t#KWrx&eg*$-^56g3 zbNi9UkM(w}56u1Y;qPx{FS|!#xtHQ2ULCwHxBK%0X;Z$tVr2}IlGkky$$QU!_{(ga zud}Td-8}p+V$J(gfA=n(^k@G6zY~|;Fxr#n|I7c_^P)@jMs@!MP3tb~`zyG#Z=+l8 zr)TR|9uyQcU9wN|)oP7Z58@e%{!eQPoaxA<;rVJpq@r!?j}>{RzU@)i-emBvMk?gt zL;1kNaTUMZul(4t%53SjYl|Q2+bs$@`(Z^#lOjW<#)PgVJ*WN$i?}hYx{@6C_}jn# zSBv=#W?s$yvwF?155fI+j@vI{+xy{L|B8qE_Zw@7-?g$0sQ$3kZYf(!eZ32#GDD^M zgsM9)m3scUY>uh7{1t!ybs@ju%H>wcr(NTfv{7hm*^8JYD%e+sp39tP0wf>1J}U72oEHC1o!uSg-aQtks&Xk`7|!-) z@h|+Bxb(dg)UtWCy)PoSSw-!ZvHgEtZ)W$_=Z|kir7xel{KJo*QR^(DT@HV<@B7kG zz57;kp}u?hTbr(3x5KX;-7a{s;j@O8_+@?_TcP}%cb0!O9`h68=m$dv?|8tlw*|s$~7n+mI|- z^uJIlhfyJcMPY&SqUTR;1+R*keEMR<*OxoXc7D4e-FsEbKbLy{7lXyw&}>w~oa1y<7iI?ksP% z^bB9E#apj_o%1nmHUozUBgcz5FFd!d`t>Ah-gfOd3%_jM5M$#1Gf#YsI=ypw z#+|*%#k0S3NUnLi^eOY|{W_PT&1>eIWWQFmq{wJNG{(ix( zg)43=?c45B%i!eBz%=Fa)0sOb_ZKJrUU%NUcVd0RB1HzqQ-TdgoXY(EF|kj-~Q{Mg|6r4&(H5f9gH1Z*hN7B)W-#fq}u()z4*}Q$iB}S?jd% diff --git a/lib/zstdhc_static.h b/lib/zstdhc_static.h index bbe157134..0cf7476b7 100644 --- a/lib/zstdhc_static.h +++ b/lib/zstdhc_static.h @@ -96,7 +96,7 @@ size_t ZSTD_HC_compressEnd(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize); /* ************************************* * Pre-defined compression levels ***************************************/ -#define ZSTD_HC_MAX_CLEVEL 26 +#define ZSTD_HC_MAX_CLEVEL 22 static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] = { /* W, C, H, S, L, strat */ { 18, 12, 14, 1, 4, ZSTD_HC_greedy }, /* level 0 - never used */ @@ -106,28 +106,26 @@ static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[ZSTD_HC_MAX_CLEVEL+1] { 20, 17, 19, 3, 5, ZSTD_HC_greedy }, /* level 4 */ { 20, 18, 19, 2, 5, ZSTD_HC_lazy }, /* level 5 */ { 21, 18, 20, 3, 5, ZSTD_HC_lazy }, /* level 6 */ - { 21, 18, 20, 4, 5, ZSTD_HC_lazy }, /* level 7 */ + { 21, 20, 20, 3, 5, ZSTD_HC_lazy }, /* level 7 */ { 21, 19, 20, 4, 5, ZSTD_HC_lazy }, /* level 8 */ { 21, 19, 20, 5, 5, ZSTD_HC_lazy }, /* level 9 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazy }, /* level 10 */ { 21, 20, 20, 5, 5, ZSTD_HC_lazydeep }, /* level 11 */ { 22, 20, 22, 5, 5, ZSTD_HC_lazydeep }, /* level 12 */ { 22, 20, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 13 */ - { 21, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ + { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 14 */ { 22, 21, 22, 6, 5, ZSTD_HC_lazydeep }, /* level 15 */ { 22, 21, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 16 */ - { 22, 23, 22, 4, 5, ZSTD_HC_btlazy2 }, /* level 17 */ - { 22, 22, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 18 */ - { 23, 23, 23, 7, 5, ZSTD_HC_btlazy2 }, /* level 19 */ - { 24, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 21 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 22 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 23 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 24 */ - { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 25 */ - { 25, 25, 24, 9, 5, ZSTD_HC_btlazy2 }, /* level 26 */ + { 22, 22, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 17 */ + { 23, 23, 23, 5, 5, ZSTD_HC_btlazy2 }, /* level 18 */ + { 25, 25, 22, 5, 5, ZSTD_HC_btlazy2 }, /* level 19 */ + { 25, 25, 23, 8, 5, ZSTD_HC_btlazy2 }, /* level 20 */ + { 25, 26, 23, 9, 5, ZSTD_HC_btlazy2 }, /* level 21 */ + { 25, 26, 23, 9, 5, ZSTD_HC_btlazy2 }, /* level 22 */ }; + + #if defined (__cplusplus) } #endif