| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- #define LIZARD_LOWESTPRICE_MIN_OFFSET 8
- FORCE_INLINE size_t Lizard_more_profitable(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, size_t literals, int last_off)
- {
- size_t sum;
- if (literals > 0)
- sum = MAX(common + literals, best_common);
- else
- sum = MAX(common, best_common - literals);
- if ((int)off == last_off) off = 0; // rep code
- if ((int)best_off == last_off) best_off = 0;
- return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, sum - common, (U32)off, common) <= Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, sum - best_common, (U32)best_off, best_common);
- }
- FORCE_INLINE size_t Lizard_better_price(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, int last_off)
- {
- if ((int)off == last_off) off = 0; // rep code
- if ((int)best_off == last_off) best_off = 0;
- return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, 0, (U32)off, common) < Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, common - best_common, (U32)best_off, best_common);
- }
- FORCE_INLINE int Lizard_FindMatchLowestPrice (Lizard_stream_t* ctx, /* Index table will be updated */
- const BYTE* ip, const BYTE* const iLimit,
- const BYTE** matchpos)
- {
- U32* const chainTable = ctx->chainTable;
- U32* const HashTable = ctx->hashTable;
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
- const intptr_t dictLimit = ctx->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;
- const intptr_t current = (ip - base);
- const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const U32 contentMask = (1 << ctx->params.contentLog) - 1;
- const size_t minMatchLongOff = ctx->params.minMatchLongOff;
- intptr_t matchIndex;
- const BYTE* match, *matchDict;
- int nbAttempts=ctx->params.searchNum;
- size_t ml=0, mlt;
- matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
- if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
- intptr_t matchIndexLO = (ip - ctx->last_off) - base;
- if (matchIndexLO >= lowLimit) {
- if (matchIndexLO >= dictLimit) {
- match = base + matchIndexLO;
- mlt = Lizard_count(ip, match, iLimit);// + MINMATCH;
- // if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
- if (mlt > REPMINMATCH) {
- *matchpos = match;
- return (int)mlt;
- }
- } else {
- match = dictBase + matchIndexLO;
- if ((U32)((dictLimit-1) - matchIndexLO) >= 3) { /* intentional overflow */
- mlt = Lizard_count_2segments(ip, match, iLimit, dictEnd, lowPrefixPtr);
- // if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))
- if (mlt > REPMINMATCH) {
- *matchpos = base + matchIndexLO; /* virtual matchpos */
- return (int)mlt;
- }
- }
- }
- }
- }
- #if MINMATCH == 3
- {
- U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
- if (matchIndex3 < current && matchIndex3 >= lowLimit)
- {
- size_t offset = (size_t)current - matchIndex3;
- if (offset < LIZARD_MAX_8BIT_OFFSET)
- {
- match = ip - offset;
- if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match))
- {
- ml = 3;//Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
- *matchpos = match;
- }
- }
- }
- }
- #endif
- while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
- nbAttempts--;
- match = base + matchIndex;
- if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
- if (matchIndex >= dictLimit) {
- if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip))) {
- mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
- if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
- if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (ip - match), mlt, ctx->last_off)))
- { ml = mlt; *matchpos = match; }
- }
- } else {
- matchDict = dictBase + matchIndex;
- if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
- if (MEM_read32(matchDict) == MEM_read32(ip)) {
- mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;
- if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
- if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (U32)(ip - match), mlt, ctx->last_off)))
- { ml = mlt; *matchpos = match; } /* virtual matchpos */
- }
- }
- }
- matchIndex -= chainTable[matchIndex & contentMask];
- }
- return (int)ml;
- }
- FORCE_INLINE size_t Lizard_GetWiderMatch (
- Lizard_stream_t* ctx,
- const BYTE* const ip,
- const BYTE* const iLowLimit,
- const BYTE* const iHighLimit,
- size_t longest,
- const BYTE** matchpos,
- const BYTE** startpos)
- {
- U32* const chainTable = ctx->chainTable;
- U32* const HashTable = ctx->hashTable;
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
- const intptr_t dictLimit = ctx->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;
- const intptr_t current = (ip - base);
- const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const U32 contentMask = (1 << ctx->params.contentLog) - 1;
- const BYTE* match, *matchDict;
- const size_t minMatchLongOff = ctx->params.minMatchLongOff;
- intptr_t matchIndex;
- int nbAttempts = ctx->params.searchNum;
- size_t mlt;
- /* First Match */
- matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];
- if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
- intptr_t matchIndexLO = (ip - ctx->last_off) - base;
- if (matchIndexLO >= lowLimit) {
- if (matchIndexLO >= dictLimit) {
- match = base + matchIndexLO;
- if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
- int back = 0;
- mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
- while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
- mlt -= back;
- if (mlt > longest)
- if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {
- *matchpos = match+back;
- *startpos = ip+back;
- longest = mlt;
- }
- }
- } else {
- match = dictBase + matchIndexLO;
- if ((U32)((dictLimit-1) - matchIndexLO) >= 3) /* intentional overflow */
- if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {
- int back=0;
- mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
- while ((ip+back > iLowLimit) && (matchIndexLO+back > lowLimit) && (ip[back-1] == match[back-1])) back--;
- mlt -= back;
- if (mlt > longest)
- if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {
- *matchpos = base + matchIndexLO + back; /* virtual matchpos */
- *startpos = ip+back;
- longest = mlt;
- }
- }
- }
- }
- }
- #if MINMATCH == 3
- {
- U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];
- if (matchIndex3 < current && matchIndex3 >= lowLimit) {
- size_t offset = (size_t)current - matchIndex3;
- if (offset < LIZARD_MAX_8BIT_OFFSET) {
- match = ip - offset;
- if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {
- mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;
- int back = 0;
- while ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;
- mlt -= back;
- if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off))) {
- *matchpos = match + back;
- *startpos = ip + back;
- longest = mlt;
- }
- }
- }
- }
- }
- #endif
- while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {
- nbAttempts--;
- match = base + matchIndex;
- if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {
- if (matchIndex >= dictLimit) {
- if (MEM_read32(match) == MEM_read32(ip)) {
- int back = 0;
- mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;
- while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
- mlt -= back;
- if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
- if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off)))
- { longest = mlt; *startpos = ip+back; *matchpos = match+back; }
- }
- } else {
- matchDict = dictBase + matchIndex;
- if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
- if (MEM_read32(matchDict) == MEM_read32(ip)) {
- int back=0;
- mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;
- while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchDict[back-1])) back--;
- mlt -= back;
- if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
- if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (U32)(ip - match), mlt, ctx->last_off)))
- { longest = mlt; *startpos = ip+back; *matchpos = match+back; } /* virtual matchpos */
- }
- }
- }
- matchIndex -= chainTable[matchIndex & contentMask];
- }
- return longest;
- }
- FORCE_INLINE int Lizard_compress_lowestPrice(
- Lizard_stream_t* const ctx,
- const BYTE* ip,
- const BYTE* const iend)
- {
- const BYTE* anchor = ip;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = (iend - LASTLITERALS);
- size_t ml, ml2, ml0;
- const BYTE* ref=NULL;
- const BYTE* start2=NULL;
- const BYTE* ref2=NULL;
- const BYTE* start0;
- const BYTE* ref0;
- const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;
- const size_t minMatchLongOff = ctx->params.minMatchLongOff;
- const size_t sufficient_len = ctx->params.sufficientLength;
- /* Main Loop */
- while (ip < mflimit)
- {
- Lizard_Insert(ctx, ip);
- ml = Lizard_FindMatchLowestPrice (ctx, ip, matchlimit, (&ref));
- if (!ml) { ip++; continue; }
- {
- int back = 0;
- while ((ip + back > anchor) && (ref + back > lowPrefixPtr) && (ip[back - 1] == ref[back - 1])) back--;
- ml -= back;
- ip += back;
- ref += back;
- }
- /* saved, in case we would skip too much */
- start0 = ip;
- ref0 = ref;
- ml0 = ml;
- // goto _Encode;
- _Search:
- if (ip+ml >= mflimit) { goto _Encode; }
- if (ml >= sufficient_len) { goto _Encode; }
- Lizard_Insert(ctx, ip);
- ml2 = (int)Lizard_GetWiderMatch(ctx, ip + ml - 2, anchor, matchlimit, 0, &ref2, &start2);
- if (!ml2) goto _Encode;
- {
- U64 price, best_price;
- int off0=0, off1=0;
- const BYTE *pos, *best_pos;
- // find the lowest price for encoding ml bytes
- best_pos = ip;
- best_price = LIZARD_MAX_PRICE;
- off0 = (int)(ip - ref);
- off1 = (int)(start2 - ref2);
- for (pos = ip + ml; pos >= start2; pos--)
- {
- int common0 = (int)(pos - ip);
- if (common0 >= MINMATCH) {
- price = (int)Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, ip - anchor, (off0 == ctx->last_off) ? 0 : off0, common0);
-
- {
- int common1 = (int)(start2 + ml2 - pos);
- if (common1 >= MINMATCH)
- price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, 0, (off1 == off0) ? 0 : (off1), common1);
- else
- price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, common1, 0, 0);
- }
- if (price < best_price) {
- best_price = price;
- best_pos = pos;
- }
- } else {
- price = Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, start2 - anchor, (off1 == ctx->last_off) ? 0 : off1, ml2);
- if (price < best_price)
- best_pos = pos;
- break;
- }
- }
- ml = (int)(best_pos - ip);
- }
- if ((ml < MINMATCH) || ((ml < minMatchLongOff) && ((U32)(ip-ref) >= LIZARD_MAX_16BIT_OFFSET)))
- {
- ip = start2;
- ref = ref2;
- ml = ml2;
- goto _Search;
- }
- _Encode:
- if (start0 < ip)
- {
- if (Lizard_more_profitable(ctx, ip, (ip - ref), ml, start0, (start0 - ref0), ml0, (ref0 - ref), ctx->last_off))
- {
- ip = start0;
- ref = ref0;
- ml = ml0;
- }
- }
- if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, ml, ((ip - ref == ctx->last_off) ? ip : ref))) return 0;
- }
- /* Encode Last Literals */
- ip = iend;
- if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;
- /* End */
- return 1;
- _output_error:
- return 0;
- }
|