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