tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LzmaEnc.c (75082B)


      1 /* LzmaEnc.c -- LZMA Encoder
      2 2018-04-29 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 #include <string.h>
      7 
      8 /* #define SHOW_STAT */
      9 /* #define SHOW_STAT2 */
     10 
     11 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
     12 #include <stdio.h>
     13 #endif
     14 
     15 #include "LzmaEnc.h"
     16 
     17 #include "LzFind.h"
     18 #ifndef _7ZIP_ST
     19 #include "LzFindMt.h"
     20 #endif
     21 
     22 #ifdef SHOW_STAT
     23 static unsigned g_STAT_OFFSET = 0;
     24 #endif
     25 
     26 #define kLzmaMaxHistorySize ((UInt32)3 << 29)
     27 /* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
     28 
     29 #define kNumTopBits 24
     30 #define kTopValue ((UInt32)1 << kNumTopBits)
     31 
     32 #define kNumBitModelTotalBits 11
     33 #define kBitModelTotal (1 << kNumBitModelTotalBits)
     34 #define kNumMoveBits 5
     35 #define kProbInitValue (kBitModelTotal >> 1)
     36 
     37 #define kNumMoveReducingBits 4
     38 #define kNumBitPriceShiftBits 4
     39 #define kBitPrice (1 << kNumBitPriceShiftBits)
     40 
     41 void LzmaEncProps_Init(CLzmaEncProps *p)
     42 {
     43  p->level = 5;
     44  p->dictSize = p->mc = 0;
     45  p->reduceSize = (UInt64)(Int64)-1;
     46  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
     47  p->writeEndMark = 0;
     48 }
     49 
     50 void LzmaEncProps_Normalize(CLzmaEncProps *p)
     51 {
     52  int level = p->level;
     53  if (level < 0) level = 5;
     54  p->level = level;
     55  
     56  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
     57  if (p->dictSize > p->reduceSize)
     58  {
     59    unsigned i;
     60    UInt32 reduceSize = (UInt32)p->reduceSize;
     61    for (i = 11; i <= 30; i++)
     62    {
     63      if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
     64      if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
     65    }
     66  }
     67 
     68  if (p->lc < 0) p->lc = 3;
     69  if (p->lp < 0) p->lp = 0;
     70  if (p->pb < 0) p->pb = 2;
     71 
     72  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
     73  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
     74  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
     75  if (p->numHashBytes < 0) p->numHashBytes = 4;
     76  if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
     77  
     78  if (p->numThreads < 0)
     79    p->numThreads =
     80      #ifndef _7ZIP_ST
     81      ((p->btMode && p->algo) ? 2 : 1);
     82      #else
     83      1;
     84      #endif
     85 }
     86 
     87 UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
     88 {
     89  CLzmaEncProps props = *props2;
     90  LzmaEncProps_Normalize(&props);
     91  return props.dictSize;
     92 }
     93 
     94 #if (_MSC_VER >= 1400)
     95 /* BSR code is fast for some new CPUs */
     96 /* #define LZMA_LOG_BSR */
     97 #endif
     98 
     99 #ifdef LZMA_LOG_BSR
    100 
    101 #define kDicLogSizeMaxCompress 32
    102 
    103 #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
    104 
    105 static unsigned GetPosSlot1(UInt32 pos)
    106 {
    107  unsigned res;
    108  BSR2_RET(pos, res);
    109  return res;
    110 }
    111 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
    112 #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
    113 
    114 #else
    115 
    116 #define kNumLogBits (9 + sizeof(size_t) / 2)
    117 /* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
    118 
    119 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
    120 
    121 static void LzmaEnc_FastPosInit(Byte *g_FastPos)
    122 {
    123  unsigned slot;
    124  g_FastPos[0] = 0;
    125  g_FastPos[1] = 1;
    126  g_FastPos += 2;
    127  
    128  for (slot = 2; slot < kNumLogBits * 2; slot++)
    129  {
    130    size_t k = ((size_t)1 << ((slot >> 1) - 1));
    131    size_t j;
    132    for (j = 0; j < k; j++)
    133      g_FastPos[j] = (Byte)slot;
    134    g_FastPos += k;
    135  }
    136 }
    137 
    138 /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
    139 /*
    140 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
    141  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
    142  res = p->g_FastPos[pos >> zz] + (zz * 2); }
    143 */
    144 
    145 /*
    146 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
    147  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
    148  res = p->g_FastPos[pos >> zz] + (zz * 2); }
    149 */
    150 
    151 #define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
    152  res = p->g_FastPos[pos >> zz] + (zz * 2); }
    153 
    154 /*
    155 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
    156  p->g_FastPos[pos >> 6] + 12 : \
    157  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
    158 */
    159 
    160 #define GetPosSlot1(pos) p->g_FastPos[pos]
    161 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
    162 #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
    163 
    164 #endif
    165 
    166 
    167 #define LZMA_NUM_REPS 4
    168 
    169 typedef UInt16 CState;
    170 typedef UInt16 CExtra;
    171 
    172 typedef struct
    173 {
    174  UInt32 price;
    175  CState state;
    176  CExtra extra;
    177      // 0   : normal
    178      // 1   : LIT : MATCH
    179      // > 1 : MATCH (extra-1) : LIT : REP0 (len)
    180  UInt32 len;
    181  UInt32 dist;
    182  UInt32 reps[LZMA_NUM_REPS];
    183 } COptimal;
    184 
    185 
    186 #define kNumOpts (1 << 12)
    187 #define kPackReserve (1 + kNumOpts * 2)
    188 
    189 #define kNumLenToPosStates 4
    190 #define kNumPosSlotBits 6
    191 #define kDicLogSizeMin 0
    192 #define kDicLogSizeMax 32
    193 #define kDistTableSizeMax (kDicLogSizeMax * 2)
    194 
    195 #define kNumAlignBits 4
    196 #define kAlignTableSize (1 << kNumAlignBits)
    197 #define kAlignMask (kAlignTableSize - 1)
    198 
    199 #define kStartPosModelIndex 4
    200 #define kEndPosModelIndex 14
    201 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
    202 
    203 typedef
    204 #ifdef _LZMA_PROB32
    205  UInt32
    206 #else
    207  UInt16
    208 #endif
    209  CLzmaProb;
    210 
    211 #define LZMA_PB_MAX 4
    212 #define LZMA_LC_MAX 8
    213 #define LZMA_LP_MAX 4
    214 
    215 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
    216 
    217 #define kLenNumLowBits 3
    218 #define kLenNumLowSymbols (1 << kLenNumLowBits)
    219 #define kLenNumHighBits 8
    220 #define kLenNumHighSymbols (1 << kLenNumHighBits)
    221 #define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
    222 
    223 #define LZMA_MATCH_LEN_MIN 2
    224 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
    225 
    226 #define kNumStates 12
    227 
    228 
    229 typedef struct
    230 {
    231  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
    232  CLzmaProb high[kLenNumHighSymbols];
    233 } CLenEnc;
    234 
    235 
    236 typedef struct
    237 {
    238  unsigned tableSize;
    239  unsigned counters[LZMA_NUM_PB_STATES_MAX];
    240  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
    241 } CLenPriceEnc;
    242 
    243 
    244 typedef struct
    245 {
    246  UInt32 range;
    247  unsigned cache;
    248  UInt64 low;
    249  UInt64 cacheSize;
    250  Byte *buf;
    251  Byte *bufLim;
    252  Byte *bufBase;
    253  ISeqOutStream *outStream;
    254  UInt64 processed;
    255  SRes res;
    256 } CRangeEnc;
    257 
    258 
    259 typedef struct
    260 {
    261  CLzmaProb *litProbs;
    262 
    263  unsigned state;
    264  UInt32 reps[LZMA_NUM_REPS];
    265 
    266  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
    267  CLzmaProb isRep[kNumStates];
    268  CLzmaProb isRepG0[kNumStates];
    269  CLzmaProb isRepG1[kNumStates];
    270  CLzmaProb isRepG2[kNumStates];
    271  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
    272  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
    273 
    274  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
    275  CLzmaProb posEncoders[kNumFullDistances];
    276  
    277  CLenEnc lenProbs;
    278  CLenEnc repLenProbs;
    279 
    280 } CSaveState;
    281 
    282 
    283 typedef UInt32 CProbPrice;
    284 
    285 
    286 typedef struct
    287 {
    288  void *matchFinderObj;
    289  IMatchFinder matchFinder;
    290 
    291  unsigned optCur;
    292  unsigned optEnd;
    293 
    294  unsigned longestMatchLen;
    295  unsigned numPairs;
    296  UInt32 numAvail;
    297 
    298  unsigned state;
    299  unsigned numFastBytes;
    300  unsigned additionalOffset;
    301  UInt32 reps[LZMA_NUM_REPS];
    302  unsigned lpMask, pbMask;
    303  CLzmaProb *litProbs;
    304  CRangeEnc rc;
    305 
    306  UInt32 backRes;
    307 
    308  unsigned lc, lp, pb;
    309  unsigned lclp;
    310 
    311  Bool fastMode;
    312  Bool writeEndMark;
    313  Bool finished;
    314  Bool multiThread;
    315  Bool needInit;
    316 
    317  UInt64 nowPos64;
    318  
    319  unsigned matchPriceCount;
    320  unsigned alignPriceCount;
    321 
    322  unsigned distTableSize;
    323 
    324  UInt32 dictSize;
    325  SRes result;
    326 
    327  #ifndef _7ZIP_ST
    328  Bool mtMode;
    329  // begin of CMatchFinderMt is used in LZ thread
    330  CMatchFinderMt matchFinderMt;
    331  // end of CMatchFinderMt is used in BT and HASH threads
    332  #endif
    333 
    334  CMatchFinder matchFinderBase;
    335 
    336  #ifndef _7ZIP_ST
    337  Byte pad[128];
    338  #endif
    339  
    340  // LZ thread
    341  CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
    342 
    343  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
    344 
    345  UInt32 alignPrices[kAlignTableSize];
    346  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
    347  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
    348 
    349  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
    350  CLzmaProb isRep[kNumStates];
    351  CLzmaProb isRepG0[kNumStates];
    352  CLzmaProb isRepG1[kNumStates];
    353  CLzmaProb isRepG2[kNumStates];
    354  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
    355  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
    356  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
    357  CLzmaProb posEncoders[kNumFullDistances];
    358  
    359  CLenEnc lenProbs;
    360  CLenEnc repLenProbs;
    361 
    362  #ifndef LZMA_LOG_BSR
    363  Byte g_FastPos[1 << kNumLogBits];
    364  #endif
    365 
    366  CLenPriceEnc lenEnc;
    367  CLenPriceEnc repLenEnc;
    368 
    369  COptimal opt[kNumOpts];
    370 
    371  CSaveState saveState;
    372 
    373  #ifndef _7ZIP_ST
    374  Byte pad2[128];
    375  #endif
    376 } CLzmaEnc;
    377 
    378 
    379 
    380 #define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
    381 
    382 void LzmaEnc_SaveState(CLzmaEncHandle pp)
    383 {
    384  CLzmaEnc *p = (CLzmaEnc *)pp;
    385  CSaveState *dest = &p->saveState;
    386  
    387  dest->state = p->state;
    388  
    389  dest->lenProbs = p->lenProbs;
    390  dest->repLenProbs = p->repLenProbs;
    391 
    392  COPY_ARR(dest, p, reps);
    393 
    394  COPY_ARR(dest, p, posAlignEncoder);
    395  COPY_ARR(dest, p, isRep);
    396  COPY_ARR(dest, p, isRepG0);
    397  COPY_ARR(dest, p, isRepG1);
    398  COPY_ARR(dest, p, isRepG2);
    399  COPY_ARR(dest, p, isMatch);
    400  COPY_ARR(dest, p, isRep0Long);
    401  COPY_ARR(dest, p, posSlotEncoder);
    402  COPY_ARR(dest, p, posEncoders);
    403 
    404  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
    405 }
    406 
    407 
    408 void LzmaEnc_RestoreState(CLzmaEncHandle pp)
    409 {
    410  CLzmaEnc *dest = (CLzmaEnc *)pp;
    411  const CSaveState *p = &dest->saveState;
    412 
    413  dest->state = p->state;
    414 
    415  dest->lenProbs = p->lenProbs;
    416  dest->repLenProbs = p->repLenProbs;
    417  
    418  COPY_ARR(dest, p, reps);
    419  
    420  COPY_ARR(dest, p, posAlignEncoder);
    421  COPY_ARR(dest, p, isRep);
    422  COPY_ARR(dest, p, isRepG0);
    423  COPY_ARR(dest, p, isRepG1);
    424  COPY_ARR(dest, p, isRepG2);
    425  COPY_ARR(dest, p, isMatch);
    426  COPY_ARR(dest, p, isRep0Long);
    427  COPY_ARR(dest, p, posSlotEncoder);
    428  COPY_ARR(dest, p, posEncoders);
    429 
    430  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
    431 }
    432 
    433 
    434 
    435 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
    436 {
    437  CLzmaEnc *p = (CLzmaEnc *)pp;
    438  CLzmaEncProps props = *props2;
    439  LzmaEncProps_Normalize(&props);
    440 
    441  if (props.lc > LZMA_LC_MAX
    442      || props.lp > LZMA_LP_MAX
    443      || props.pb > LZMA_PB_MAX
    444      || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
    445      || props.dictSize > kLzmaMaxHistorySize)
    446    return SZ_ERROR_PARAM;
    447 
    448  p->dictSize = props.dictSize;
    449  {
    450    unsigned fb = props.fb;
    451    if (fb < 5)
    452      fb = 5;
    453    if (fb > LZMA_MATCH_LEN_MAX)
    454      fb = LZMA_MATCH_LEN_MAX;
    455    p->numFastBytes = fb;
    456  }
    457  p->lc = props.lc;
    458  p->lp = props.lp;
    459  p->pb = props.pb;
    460  p->fastMode = (props.algo == 0);
    461  p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
    462  {
    463    unsigned numHashBytes = 4;
    464    if (props.btMode)
    465    {
    466      if (props.numHashBytes < 2)
    467        numHashBytes = 2;
    468      else if (props.numHashBytes < 4)
    469        numHashBytes = props.numHashBytes;
    470    }
    471    p->matchFinderBase.numHashBytes = numHashBytes;
    472  }
    473 
    474  p->matchFinderBase.cutValue = props.mc;
    475 
    476  p->writeEndMark = props.writeEndMark;
    477 
    478  #ifndef _7ZIP_ST
    479  /*
    480  if (newMultiThread != _multiThread)
    481  {
    482    ReleaseMatchFinder();
    483    _multiThread = newMultiThread;
    484  }
    485  */
    486  p->multiThread = (props.numThreads > 1);
    487  #endif
    488 
    489  return SZ_OK;
    490 }
    491 
    492 
    493 void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
    494 {
    495  CLzmaEnc *p = (CLzmaEnc *)pp;
    496  p->matchFinderBase.expectedDataSize = expectedDataSiize;
    497 }
    498 
    499 
    500 #define kState_Start 0
    501 #define kState_LitAfterMatch 4
    502 #define kState_LitAfterRep   5
    503 #define kState_MatchAfterLit 7
    504 #define kState_RepAfterLit   8
    505 
    506 static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
    507 static const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
    508 static const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
    509 static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
    510 
    511 #define IsLitState(s) ((s) < 7)
    512 #define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
    513 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
    514 
    515 #define kInfinityPrice (1 << 30)
    516 
    517 static void RangeEnc_Construct(CRangeEnc *p)
    518 {
    519  p->outStream = NULL;
    520  p->bufBase = NULL;
    521 }
    522 
    523 #define RangeEnc_GetProcessed(p)       ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
    524 #define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
    525 
    526 #define RC_BUF_SIZE (1 << 16)
    527 
    528 static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
    529 {
    530  if (!p->bufBase)
    531  {
    532    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
    533    if (!p->bufBase)
    534      return 0;
    535    p->bufLim = p->bufBase + RC_BUF_SIZE;
    536  }
    537  return 1;
    538 }
    539 
    540 static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
    541 {
    542  ISzAlloc_Free(alloc, p->bufBase);
    543  p->bufBase = 0;
    544 }
    545 
    546 static void RangeEnc_Init(CRangeEnc *p)
    547 {
    548  /* Stream.Init(); */
    549  p->range = 0xFFFFFFFF;
    550  p->cache = 0;
    551  p->low = 0;
    552  p->cacheSize = 0;
    553 
    554  p->buf = p->bufBase;
    555 
    556  p->processed = 0;
    557  p->res = SZ_OK;
    558 }
    559 
    560 MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
    561 {
    562  size_t num;
    563  if (p->res != SZ_OK)
    564    return;
    565  num = p->buf - p->bufBase;
    566  if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
    567    p->res = SZ_ERROR_WRITE;
    568  p->processed += num;
    569  p->buf = p->bufBase;
    570 }
    571 
    572 MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
    573 {
    574  UInt32 low = (UInt32)p->low;
    575  unsigned high = (unsigned)(p->low >> 32);
    576  p->low = (UInt32)(low << 8);
    577  if (low < (UInt32)0xFF000000 || high != 0)
    578  {
    579    {
    580      Byte *buf = p->buf;
    581      *buf++ = (Byte)(p->cache + high);
    582      p->cache = (unsigned)(low >> 24);
    583      p->buf = buf;
    584      if (buf == p->bufLim)
    585        RangeEnc_FlushStream(p);
    586      if (p->cacheSize == 0)
    587        return;
    588    }
    589    high += 0xFF;
    590    for (;;)
    591    {
    592      Byte *buf = p->buf;
    593      *buf++ = (Byte)(high);
    594      p->buf = buf;
    595      if (buf == p->bufLim)
    596        RangeEnc_FlushStream(p);
    597      if (--p->cacheSize == 0)
    598        return;
    599    }
    600  }
    601  p->cacheSize++;
    602 }
    603 
    604 static void RangeEnc_FlushData(CRangeEnc *p)
    605 {
    606  int i;
    607  for (i = 0; i < 5; i++)
    608    RangeEnc_ShiftLow(p);
    609 }
    610 
    611 #define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
    612 
    613 #define RC_BIT_PRE(p, prob) \
    614  ttt = *(prob); \
    615  newBound = (range >> kNumBitModelTotalBits) * ttt;
    616 
    617 // #define _LZMA_ENC_USE_BRANCH
    618 
    619 #ifdef _LZMA_ENC_USE_BRANCH
    620 
    621 #define RC_BIT(p, prob, symbol) { \
    622  RC_BIT_PRE(p, prob) \
    623  if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
    624  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
    625  *(prob) = (CLzmaProb)ttt; \
    626  RC_NORM(p) \
    627  }
    628 
    629 #else
    630 
    631 #define RC_BIT(p, prob, symbol) { \
    632  UInt32 mask; \
    633  RC_BIT_PRE(p, prob) \
    634  mask = 0 - (UInt32)symbol; \
    635  range &= mask; \
    636  mask &= newBound; \
    637  range -= mask; \
    638  (p)->low += mask; \
    639  mask = (UInt32)symbol - 1; \
    640  range += newBound & mask; \
    641  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
    642  mask += ((1 << kNumMoveBits) - 1); \
    643  ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
    644  *(prob) = (CLzmaProb)ttt; \
    645  RC_NORM(p) \
    646  }
    647 
    648 #endif
    649 
    650 
    651 
    652 
    653 #define RC_BIT_0_BASE(p, prob) \
    654  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
    655 
    656 #define RC_BIT_1_BASE(p, prob) \
    657  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
    658 
    659 #define RC_BIT_0(p, prob) \
    660  RC_BIT_0_BASE(p, prob) \
    661  RC_NORM(p)
    662 
    663 #define RC_BIT_1(p, prob) \
    664  RC_BIT_1_BASE(p, prob) \
    665  RC_NORM(p)
    666 
    667 static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
    668 {
    669  UInt32 range, ttt, newBound;
    670  range = p->range;
    671  RC_BIT_PRE(p, prob)
    672  RC_BIT_0(p, prob)
    673  p->range = range;
    674 }
    675 
    676 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
    677 {
    678  UInt32 range = p->range;
    679  symbol |= 0x100;
    680  do
    681  {
    682    UInt32 ttt, newBound;
    683    // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
    684    CLzmaProb *prob = probs + (symbol >> 8);
    685    UInt32 bit = (symbol >> 7) & 1;
    686    symbol <<= 1;
    687    RC_BIT(p, prob, bit);
    688  }
    689  while (symbol < 0x10000);
    690  p->range = range;
    691 }
    692 
    693 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
    694 {
    695  UInt32 range = p->range;
    696  UInt32 offs = 0x100;
    697  symbol |= 0x100;
    698  do
    699  {
    700    UInt32 ttt, newBound;
    701    CLzmaProb *prob;
    702    UInt32 bit;
    703    matchByte <<= 1;
    704    // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
    705    prob = probs + (offs + (matchByte & offs) + (symbol >> 8));
    706    bit = (symbol >> 7) & 1;
    707    symbol <<= 1;
    708    offs &= ~(matchByte ^ symbol);
    709    RC_BIT(p, prob, bit);
    710  }
    711  while (symbol < 0x10000);
    712  p->range = range;
    713 }
    714 
    715 
    716 
    717 static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
    718 {
    719  UInt32 i;
    720  for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
    721  {
    722    const unsigned kCyclesBits = kNumBitPriceShiftBits;
    723    UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
    724    unsigned bitCount = 0;
    725    unsigned j;
    726    for (j = 0; j < kCyclesBits; j++)
    727    {
    728      w = w * w;
    729      bitCount <<= 1;
    730      while (w >= ((UInt32)1 << 16))
    731      {
    732        w >>= 1;
    733        bitCount++;
    734      }
    735    }
    736    ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
    737    // printf("\n%3d: %5d", i, ProbPrices[i]);
    738  }
    739 }
    740 
    741 
    742 #define GET_PRICE(prob, symbol) \
    743  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
    744 
    745 #define GET_PRICEa(prob, symbol) \
    746     ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
    747 
    748 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
    749 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
    750 
    751 #define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
    752 #define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
    753 
    754 
    755 static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices)
    756 {
    757  UInt32 price = 0;
    758  symbol |= 0x100;
    759  do
    760  {
    761    unsigned bit = symbol & 1;
    762    symbol >>= 1;
    763    price += GET_PRICEa(probs[symbol], bit);
    764  }
    765  while (symbol >= 2);
    766  return price;
    767 }
    768 
    769 
    770 static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices)
    771 {
    772  UInt32 price = 0;
    773  UInt32 offs = 0x100;
    774  symbol |= 0x100;
    775  do
    776  {
    777    matchByte <<= 1;
    778    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
    779    symbol <<= 1;
    780    offs &= ~(matchByte ^ symbol);
    781  }
    782  while (symbol < 0x10000);
    783  return price;
    784 }
    785 
    786 
    787 static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol)
    788 {
    789  UInt32 range = rc->range;
    790  unsigned m = 1;
    791  do
    792  {
    793    UInt32 ttt, newBound;
    794    unsigned bit = symbol & 1;
    795    // RangeEnc_EncodeBit(rc, probs + m, bit);
    796    symbol >>= 1;
    797    RC_BIT(rc, probs + m, bit);
    798    m = (m << 1) | bit;
    799  }
    800  while (--numBits);
    801  rc->range = range;
    802 }
    803 
    804 
    805 
    806 static void LenEnc_Init(CLenEnc *p)
    807 {
    808  unsigned i;
    809  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
    810    p->low[i] = kProbInitValue;
    811  for (i = 0; i < kLenNumHighSymbols; i++)
    812    p->high[i] = kProbInitValue;
    813 }
    814 
    815 static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState)
    816 {
    817  UInt32 range, ttt, newBound;
    818  CLzmaProb *probs = p->low;
    819  range = rc->range;
    820  RC_BIT_PRE(rc, probs);
    821  if (symbol >= kLenNumLowSymbols)
    822  {
    823    RC_BIT_1(rc, probs);
    824    probs += kLenNumLowSymbols;
    825    RC_BIT_PRE(rc, probs);
    826    if (symbol >= kLenNumLowSymbols * 2)
    827    {
    828      RC_BIT_1(rc, probs);
    829      rc->range = range;
    830      // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2);
    831      LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2);
    832      return;
    833    }
    834    symbol -= kLenNumLowSymbols;
    835  }
    836 
    837  // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
    838  {
    839    unsigned m;
    840    unsigned bit;
    841    RC_BIT_0(rc, probs);
    842    probs += (posState << (1 + kLenNumLowBits));
    843    bit = (symbol >> 2)    ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
    844    bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
    845    bit =  symbol       & 1; RC_BIT(rc, probs + m, bit);
    846    rc->range = range;
    847  }
    848 }
    849 
    850 static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
    851 {
    852  unsigned i;
    853  for (i = 0; i < 8; i += 2)
    854  {
    855    UInt32 price = startPrice;
    856    UInt32 prob;
    857    price += GET_PRICEa(probs[1           ], (i >> 2));
    858    price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
    859    prob = probs[4 + (i >> 1)];
    860    prices[i    ] = price + GET_PRICEa_0(prob);
    861    prices[i + 1] = price + GET_PRICEa_1(prob);
    862  }
    863 }
    864 
    865 
    866 MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable(
    867    CLenPriceEnc *p, unsigned posState,
    868    const CLenEnc *enc,
    869    const CProbPrice *ProbPrices)
    870 {
    871  // int y; for (y = 0; y < 100; y++) {
    872  UInt32 a;
    873  unsigned i, numSymbols;
    874 
    875  UInt32 *prices = p->prices[posState];
    876  {
    877    const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
    878    SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices);
    879    a = GET_PRICEa_1(enc->low[0]);
    880    SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices);
    881    a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
    882  }
    883  numSymbols = p->tableSize;
    884  p->counters[posState] = numSymbols;
    885  for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1)
    886  {
    887    prices[i] = a +
    888       // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
    889       LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices);
    890    /*
    891    unsigned sym = (i - kLenNumLowSymbols * 2) >> 1;
    892    UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices);
    893    UInt32 prob = enc->high[(1 << 7) + sym];
    894    prices[i    ] = price + GET_PRICEa_0(prob);
    895    prices[i + 1] = price + GET_PRICEa_1(prob);
    896    */
    897  }
    898  // }
    899 }
    900 
    901 static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,
    902    const CLenEnc *enc,
    903    const CProbPrice *ProbPrices)
    904 {
    905  unsigned posState;
    906  for (posState = 0; posState < numPosStates; posState++)
    907    LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices);
    908 }
    909 
    910 
    911 /*
    912  #ifdef SHOW_STAT
    913  g_STAT_OFFSET += num;
    914  printf("\n MovePos %u", num);
    915  #endif
    916 */
    917  
    918 #define MOVE_POS(p, num) { \
    919    p->additionalOffset += (num); \
    920    p->matchFinder.Skip(p->matchFinderObj, (num)); }
    921 
    922 
    923 static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
    924 {
    925  unsigned numPairs;
    926  
    927  p->additionalOffset++;
    928  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
    929  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
    930  *numPairsRes = numPairs;
    931  
    932  #ifdef SHOW_STAT
    933  printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);
    934  g_STAT_OFFSET++;
    935  {
    936    unsigned i;
    937    for (i = 0; i < numPairs; i += 2)
    938      printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);
    939  }
    940  #endif
    941  
    942  if (numPairs == 0)
    943    return 0;
    944  {
    945    unsigned len = p->matches[(size_t)numPairs - 2];
    946    if (len != p->numFastBytes)
    947      return len;
    948    {
    949      UInt32 numAvail = p->numAvail;
    950      if (numAvail > LZMA_MATCH_LEN_MAX)
    951        numAvail = LZMA_MATCH_LEN_MAX;
    952      {
    953        const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
    954        const Byte *p2 = p1 + len;
    955        ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];
    956        const Byte *lim = p1 + numAvail;
    957        for (; p2 != lim && *p2 == p2[dif]; p2++);
    958        return (unsigned)(p2 - p1);
    959      }
    960    }
    961  }
    962 }
    963 
    964 #define MARK_LIT ((UInt32)(Int32)-1)
    965 
    966 #define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }
    967 #define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }
    968 #define IsShortRep(p)       ((p)->dist == 0)
    969 
    970 
    971 #define GetPrice_ShortRep(p, state, posState) \
    972  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
    973 
    974 #define GetPrice_Rep_0(p, state, posState) ( \
    975    GET_PRICE_1(p->isMatch[state][posState]) \
    976  + GET_PRICE_1(p->isRep0Long[state][posState])) \
    977  + GET_PRICE_1(p->isRep[state]) \
    978  + GET_PRICE_0(p->isRepG0[state])
    979  
    980 
    981 static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
    982 {
    983  UInt32 price;
    984  UInt32 prob = p->isRepG0[state];
    985  if (repIndex == 0)
    986  {
    987    price = GET_PRICE_0(prob);
    988    price += GET_PRICE_1(p->isRep0Long[state][posState]);
    989  }
    990  else
    991  {
    992    price = GET_PRICE_1(prob);
    993    prob = p->isRepG1[state];
    994    if (repIndex == 1)
    995      price += GET_PRICE_0(prob);
    996    else
    997    {
    998      price += GET_PRICE_1(prob);
    999      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
   1000    }
   1001  }
   1002  return price;
   1003 }
   1004 
   1005 
   1006 static unsigned Backward(CLzmaEnc *p, unsigned cur)
   1007 {
   1008  unsigned wr = cur + 1;
   1009  p->optEnd = wr;
   1010 
   1011  for (;;)
   1012  {
   1013    UInt32 dist = p->opt[cur].dist;
   1014    UInt32 len = p->opt[cur].len;
   1015    UInt32 extra = p->opt[cur].extra;
   1016    cur -= len;
   1017 
   1018    if (extra)
   1019    {
   1020      wr--;
   1021      p->opt[wr].len = len;
   1022      cur -= extra;
   1023      len = extra;
   1024      if (extra == 1)
   1025      {
   1026        p->opt[wr].dist = dist;
   1027        dist = MARK_LIT;
   1028      }
   1029      else
   1030      {
   1031        p->opt[wr].dist = 0;
   1032        len--;
   1033        wr--;
   1034        p->opt[wr].dist = MARK_LIT;
   1035        p->opt[wr].len = 1;
   1036      }
   1037    }
   1038 
   1039    if (cur == 0)
   1040    {
   1041      p->backRes = dist;
   1042      p->optCur = wr;
   1043      return len;
   1044    }
   1045    
   1046    wr--;
   1047    p->opt[wr].dist = dist;
   1048    p->opt[wr].len = len;
   1049  }
   1050 }
   1051 
   1052 
   1053 
   1054 #define LIT_PROBS(pos, prevByte) \
   1055  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
   1056 
   1057 
   1058 static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
   1059 {
   1060  unsigned last, cur;
   1061  UInt32 reps[LZMA_NUM_REPS];
   1062  unsigned repLens[LZMA_NUM_REPS];
   1063  UInt32 *matches;
   1064 
   1065  {
   1066    UInt32 numAvail;
   1067    unsigned numPairs, mainLen, repMaxIndex, i, posState;
   1068    UInt32 matchPrice, repMatchPrice;
   1069    const Byte *data;
   1070    Byte curByte, matchByte;
   1071    
   1072    p->optCur = p->optEnd = 0;
   1073    
   1074    if (p->additionalOffset == 0)
   1075      mainLen = ReadMatchDistances(p, &numPairs);
   1076    else
   1077    {
   1078      mainLen = p->longestMatchLen;
   1079      numPairs = p->numPairs;
   1080    }
   1081    
   1082    numAvail = p->numAvail;
   1083    if (numAvail < 2)
   1084    {
   1085      p->backRes = MARK_LIT;
   1086      return 1;
   1087    }
   1088    if (numAvail > LZMA_MATCH_LEN_MAX)
   1089      numAvail = LZMA_MATCH_LEN_MAX;
   1090    
   1091    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1092    repMaxIndex = 0;
   1093    
   1094    for (i = 0; i < LZMA_NUM_REPS; i++)
   1095    {
   1096      unsigned len;
   1097      const Byte *data2;
   1098      reps[i] = p->reps[i];
   1099      data2 = data - reps[i];
   1100      if (data[0] != data2[0] || data[1] != data2[1])
   1101      {
   1102        repLens[i] = 0;
   1103        continue;
   1104      }
   1105      for (len = 2; len < numAvail && data[len] == data2[len]; len++);
   1106      repLens[i] = len;
   1107      if (len > repLens[repMaxIndex])
   1108        repMaxIndex = i;
   1109    }
   1110    
   1111    if (repLens[repMaxIndex] >= p->numFastBytes)
   1112    {
   1113      unsigned len;
   1114      p->backRes = repMaxIndex;
   1115      len = repLens[repMaxIndex];
   1116      MOVE_POS(p, len - 1)
   1117      return len;
   1118    }
   1119    
   1120    matches = p->matches;
   1121    
   1122    if (mainLen >= p->numFastBytes)
   1123    {
   1124      p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
   1125      MOVE_POS(p, mainLen - 1)
   1126      return mainLen;
   1127    }
   1128    
   1129    curByte = *data;
   1130    matchByte = *(data - reps[0]);
   1131    
   1132    if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
   1133    {
   1134      p->backRes = MARK_LIT;
   1135      return 1;
   1136    }
   1137    
   1138    p->opt[0].state = (CState)p->state;
   1139    
   1140    posState = (position & p->pbMask);
   1141    
   1142    {
   1143      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
   1144      p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
   1145        (!IsLitState(p->state) ?
   1146          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
   1147          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
   1148    }
   1149    
   1150    MakeAs_Lit(&p->opt[1]);
   1151    
   1152    matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
   1153    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
   1154    
   1155    if (matchByte == curByte)
   1156    {
   1157      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
   1158      if (shortRepPrice < p->opt[1].price)
   1159      {
   1160        p->opt[1].price = shortRepPrice;
   1161        MakeAs_ShortRep(&p->opt[1]);
   1162      }
   1163    }
   1164    
   1165    last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]);
   1166    
   1167    if (last < 2)
   1168    {
   1169      p->backRes = p->opt[1].dist;
   1170      return 1;
   1171    }
   1172    
   1173    p->opt[1].len = 1;
   1174    
   1175    p->opt[0].reps[0] = reps[0];
   1176    p->opt[0].reps[1] = reps[1];
   1177    p->opt[0].reps[2] = reps[2];
   1178    p->opt[0].reps[3] = reps[3];
   1179    
   1180    {
   1181      unsigned len = last;
   1182      do
   1183        p->opt[len--].price = kInfinityPrice;
   1184      while (len >= 2);
   1185    }
   1186 
   1187    // ---------- REP ----------
   1188    
   1189    for (i = 0; i < LZMA_NUM_REPS; i++)
   1190    {
   1191      unsigned repLen = repLens[i];
   1192      UInt32 price;
   1193      if (repLen < 2)
   1194        continue;
   1195      price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
   1196      do
   1197      {
   1198        UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2];
   1199        COptimal *opt = &p->opt[repLen];
   1200        if (price2 < opt->price)
   1201        {
   1202          opt->price = price2;
   1203          opt->len = repLen;
   1204          opt->dist = i;
   1205          opt->extra = 0;
   1206        }
   1207      }
   1208      while (--repLen >= 2);
   1209    }
   1210    
   1211    
   1212    // ---------- MATCH ----------
   1213    {
   1214      unsigned len  = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
   1215      if (len <= mainLen)
   1216      {
   1217        unsigned offs = 0;
   1218        UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
   1219 
   1220        while (len > matches[offs])
   1221          offs += 2;
   1222    
   1223        for (; ; len++)
   1224        {
   1225          COptimal *opt;
   1226          UInt32 dist = matches[(size_t)offs + 1];
   1227          UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
   1228          unsigned lenToPosState = GetLenToPosState(len);
   1229       
   1230          if (dist < kNumFullDistances)
   1231            price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
   1232          else
   1233          {
   1234            unsigned slot;
   1235            GetPosSlot2(dist, slot);
   1236            price2 += p->alignPrices[dist & kAlignMask];
   1237            price2 += p->posSlotPrices[lenToPosState][slot];
   1238          }
   1239          
   1240          opt = &p->opt[len];
   1241          
   1242          if (price2 < opt->price)
   1243          {
   1244            opt->price = price2;
   1245            opt->len = len;
   1246            opt->dist = dist + LZMA_NUM_REPS;
   1247            opt->extra = 0;
   1248          }
   1249          
   1250          if (len == matches[offs])
   1251          {
   1252            offs += 2;
   1253            if (offs == numPairs)
   1254              break;
   1255          }
   1256        }
   1257      }
   1258    }
   1259    
   1260 
   1261    cur = 0;
   1262 
   1263    #ifdef SHOW_STAT2
   1264    /* if (position >= 0) */
   1265    {
   1266      unsigned i;
   1267      printf("\n pos = %4X", position);
   1268      for (i = cur; i <= last; i++)
   1269      printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
   1270    }
   1271    #endif
   1272  }
   1273 
   1274 
   1275  
   1276  // ---------- Optimal Parsing ----------
   1277 
   1278  for (;;)
   1279  {
   1280    UInt32 numAvail, numAvailFull;
   1281    unsigned newLen, numPairs, prev, state, posState, startLen;
   1282    UInt32 curPrice, litPrice, matchPrice, repMatchPrice;
   1283    Bool nextIsLit;
   1284    Byte curByte, matchByte;
   1285    const Byte *data;
   1286    COptimal *curOpt, *nextOpt;
   1287 
   1288    if (++cur == last)
   1289      return Backward(p, cur);
   1290 
   1291    newLen = ReadMatchDistances(p, &numPairs);
   1292    
   1293    if (newLen >= p->numFastBytes)
   1294    {
   1295      p->numPairs = numPairs;
   1296      p->longestMatchLen = newLen;
   1297      return Backward(p, cur);
   1298    }
   1299    
   1300    curOpt = &p->opt[cur];
   1301    prev = cur - curOpt->len;
   1302    
   1303    if (curOpt->len == 1)
   1304    {
   1305      state = p->opt[prev].state;
   1306      if (IsShortRep(curOpt))
   1307        state = kShortRepNextStates[state];
   1308      else
   1309        state = kLiteralNextStates[state];
   1310    }
   1311    else
   1312    {
   1313      const COptimal *prevOpt;
   1314      UInt32 b0;
   1315      UInt32 dist = curOpt->dist;
   1316 
   1317      if (curOpt->extra)
   1318      {
   1319        prev -= curOpt->extra;
   1320        state = kState_RepAfterLit;
   1321        if (curOpt->extra == 1)
   1322          state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit;
   1323      }
   1324      else
   1325      {
   1326        state = p->opt[prev].state;
   1327        if (dist < LZMA_NUM_REPS)
   1328          state = kRepNextStates[state];
   1329        else
   1330          state = kMatchNextStates[state];
   1331      }
   1332 
   1333      prevOpt = &p->opt[prev];
   1334      b0 = prevOpt->reps[0];
   1335 
   1336      if (dist < LZMA_NUM_REPS)
   1337      {
   1338        if (dist == 0)
   1339        {
   1340          reps[0] = b0;
   1341          reps[1] = prevOpt->reps[1];
   1342          reps[2] = prevOpt->reps[2];
   1343          reps[3] = prevOpt->reps[3];
   1344        }
   1345        else
   1346        {
   1347          reps[1] = b0;
   1348          b0 = prevOpt->reps[1];
   1349          if (dist == 1)
   1350          {
   1351            reps[0] = b0;
   1352            reps[2] = prevOpt->reps[2];
   1353            reps[3] = prevOpt->reps[3];
   1354          }
   1355          else
   1356          {
   1357            reps[2] = b0;
   1358            reps[0] = prevOpt->reps[dist];
   1359            reps[3] = prevOpt->reps[dist ^ 1];
   1360          }
   1361        }
   1362      }
   1363      else
   1364      {
   1365        reps[0] = (dist - LZMA_NUM_REPS + 1);
   1366        reps[1] = b0;
   1367        reps[2] = prevOpt->reps[1];
   1368        reps[3] = prevOpt->reps[2];
   1369      }
   1370    }
   1371    
   1372    curOpt->state = (CState)state;
   1373    curOpt->reps[0] = reps[0];
   1374    curOpt->reps[1] = reps[1];
   1375    curOpt->reps[2] = reps[2];
   1376    curOpt->reps[3] = reps[3];
   1377 
   1378    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1379    curByte = *data;
   1380    matchByte = *(data - reps[0]);
   1381 
   1382    position++;
   1383    posState = (position & p->pbMask);
   1384 
   1385    /*
   1386    The order of Price checks:
   1387       <  LIT
   1388       <= SHORT_REP
   1389       <  LIT : REP_0
   1390       <  REP    [ : LIT : REP_0 ]
   1391       <  MATCH  [ : LIT : REP_0 ]
   1392    */
   1393 
   1394    curPrice = curOpt->price;
   1395    litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
   1396 
   1397    nextOpt = &p->opt[(size_t)cur + 1];
   1398    nextIsLit = False;
   1399 
   1400    // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new
   1401    {
   1402      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
   1403      litPrice += (!IsLitState(state) ?
   1404          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
   1405          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
   1406      
   1407      if (litPrice < nextOpt->price)
   1408      {
   1409        nextOpt->price = litPrice;
   1410        nextOpt->len = 1;
   1411        MakeAs_Lit(nextOpt);
   1412        nextIsLit = True;
   1413      }
   1414    }
   1415 
   1416    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
   1417    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
   1418    
   1419    // ---------- SHORT_REP ----------
   1420    // if (IsLitState(state)) // 18.new
   1421    if (matchByte == curByte)
   1422    // if (repMatchPrice < nextOpt->price) // 18.new
   1423    if (nextOpt->len < 2
   1424        || (nextOpt->dist != 0
   1425            && nextOpt->extra <= 1 // 17.old
   1426        ))
   1427    {
   1428      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
   1429      if (shortRepPrice <= nextOpt->price) // 17.old
   1430      // if (shortRepPrice < nextOpt->price)  // 18.new
   1431      {
   1432        nextOpt->price = shortRepPrice;
   1433        nextOpt->len = 1;
   1434        MakeAs_ShortRep(nextOpt);
   1435        nextIsLit = False;
   1436      }
   1437    }
   1438    
   1439    numAvailFull = p->numAvail;
   1440    {
   1441      UInt32 temp = kNumOpts - 1 - cur;
   1442      if (numAvailFull > temp)
   1443        numAvailFull = temp;
   1444    }
   1445 
   1446    if (numAvailFull < 2)
   1447      continue;
   1448    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
   1449 
   1450    // numAvail <= p->numFastBytes
   1451 
   1452    // ---------- LIT : REP_0 ----------
   1453 
   1454    if (
   1455        // litPrice != 0 && // 18.new
   1456        !nextIsLit
   1457        && matchByte != curByte
   1458        && numAvailFull > 2)
   1459    {
   1460      const Byte *data2 = data - reps[0];
   1461      if (data[1] == data2[1] && data[2] == data2[2])
   1462      {
   1463        unsigned len;
   1464        unsigned limit = p->numFastBytes + 1;
   1465        if (limit > numAvailFull)
   1466          limit = numAvailFull;
   1467        for (len = 3; len < limit && data[len] == data2[len]; len++);
   1468        
   1469        {
   1470          unsigned state2 = kLiteralNextStates[state];
   1471          unsigned posState2 = (position + 1) & p->pbMask;
   1472          UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
   1473          {
   1474            unsigned offset = cur + len;
   1475            while (last < offset)
   1476              p->opt[++last].price = kInfinityPrice;
   1477          
   1478            // do
   1479            {
   1480              UInt32 price2;
   1481              COptimal *opt;
   1482              len--;
   1483              // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
   1484              price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];
   1485 
   1486              opt = &p->opt[offset];
   1487              // offset--;
   1488              if (price2 < opt->price)
   1489              {
   1490                opt->price = price2;
   1491                opt->len = len;
   1492                opt->dist = 0;
   1493                opt->extra = 1;
   1494              }
   1495            }
   1496            // while (len >= 3);
   1497          }
   1498        }
   1499      }
   1500    }
   1501    
   1502    startLen = 2; /* speed optimization */
   1503    {
   1504      // ---------- REP ----------
   1505      unsigned repIndex = 0; // 17.old
   1506      // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
   1507      for (; repIndex < LZMA_NUM_REPS; repIndex++)
   1508      {
   1509        unsigned len;
   1510        UInt32 price;
   1511        const Byte *data2 = data - reps[repIndex];
   1512        if (data[0] != data2[0] || data[1] != data2[1])
   1513          continue;
   1514        
   1515        for (len = 2; len < numAvail && data[len] == data2[len]; len++);
   1516        
   1517        // if (len < startLen) continue; // 18.new: speed optimization
   1518 
   1519        while (last < cur + len)
   1520          p->opt[++last].price = kInfinityPrice;
   1521        {
   1522          unsigned len2 = len;
   1523          price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
   1524          do
   1525          {
   1526            UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];
   1527            COptimal *opt = &p->opt[cur + len2];
   1528            if (price2 < opt->price)
   1529            {
   1530              opt->price = price2;
   1531              opt->len = len2;
   1532              opt->dist = repIndex;
   1533              opt->extra = 0;
   1534            }
   1535          }
   1536          while (--len2 >= 2);
   1537        }
   1538        
   1539        if (repIndex == 0) startLen = len + 1;  // 17.old
   1540        // startLen = len + 1; // 18.new
   1541 
   1542        /* if (_maxMode) */
   1543        {
   1544          // ---------- REP : LIT : REP_0 ----------
   1545          // numFastBytes + 1 + numFastBytes
   1546 
   1547          unsigned len2 = len + 1;
   1548          unsigned limit = len2 + p->numFastBytes;
   1549          if (limit > numAvailFull)
   1550            limit = numAvailFull;
   1551          
   1552          for (; len2 < limit && data[len2] == data2[len2]; len2++);
   1553          
   1554          len2 -= len;
   1555          if (len2 >= 3)
   1556          {
   1557            unsigned state2 = kRepNextStates[state];
   1558            unsigned posState2 = (position + len) & p->pbMask;
   1559            price +=
   1560                  p->repLenEnc.prices[posState][(size_t)len - 2]
   1561                + GET_PRICE_0(p->isMatch[state2][posState2])
   1562                + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
   1563                    data[len], data2[len], p->ProbPrices);
   1564            
   1565            // state2 = kLiteralNextStates[state2];
   1566            state2 = kState_LitAfterRep;
   1567            posState2 = (posState2 + 1) & p->pbMask;
   1568 
   1569 
   1570            price += GetPrice_Rep_0(p, state2, posState2);
   1571            {
   1572              unsigned offset = cur + len + len2;
   1573              while (last < offset)
   1574                p->opt[++last].price = kInfinityPrice;
   1575              // do
   1576              {
   1577                unsigned price2;
   1578                COptimal *opt;
   1579                len2--;
   1580                // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
   1581                price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
   1582 
   1583                opt = &p->opt[offset];
   1584                // offset--;
   1585                if (price2 < opt->price)
   1586                {
   1587                  opt->price = price2;
   1588                  opt->len = len2;
   1589                  opt->extra = (CExtra)(len + 1);
   1590                  opt->dist = repIndex;
   1591                }
   1592              }
   1593              // while (len2 >= 3);
   1594            }
   1595          }
   1596        }
   1597      }
   1598    }
   1599 
   1600 
   1601    // ---------- MATCH ----------
   1602    /* for (unsigned len = 2; len <= newLen; len++) */
   1603    if (newLen > numAvail)
   1604    {
   1605      newLen = numAvail;
   1606      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
   1607      matches[numPairs] = newLen;
   1608      numPairs += 2;
   1609    }
   1610    
   1611    if (newLen >= startLen)
   1612    {
   1613      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
   1614      UInt32 dist;
   1615      unsigned offs, posSlot, len;
   1616      while (last < cur + newLen)
   1617        p->opt[++last].price = kInfinityPrice;
   1618 
   1619      offs = 0;
   1620      while (startLen > matches[offs])
   1621        offs += 2;
   1622      dist = matches[(size_t)offs + 1];
   1623      
   1624      // if (dist >= kNumFullDistances)
   1625      GetPosSlot2(dist, posSlot);
   1626      
   1627      for (len = /*2*/ startLen; ; len++)
   1628      {
   1629        UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
   1630        {
   1631          COptimal *opt;
   1632          unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);
   1633          if (dist < kNumFullDistances)
   1634            price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
   1635          else
   1636            price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];
   1637          
   1638          opt = &p->opt[cur + len];
   1639          if (price < opt->price)
   1640          {
   1641            opt->price = price;
   1642            opt->len = len;
   1643            opt->dist = dist + LZMA_NUM_REPS;
   1644            opt->extra = 0;
   1645          }
   1646        }
   1647 
   1648        if (/*_maxMode && */ len == matches[offs])
   1649        {
   1650          // MATCH : LIT : REP_0
   1651 
   1652          const Byte *data2 = data - dist - 1;
   1653          unsigned len2 = len + 1;
   1654          unsigned limit = len2 + p->numFastBytes;
   1655          if (limit > numAvailFull)
   1656            limit = numAvailFull;
   1657          
   1658          for (; len2 < limit && data[len2] == data2[len2]; len2++);
   1659          
   1660          len2 -= len;
   1661          
   1662          if (len2 >= 3)
   1663          {
   1664            unsigned state2 = kMatchNextStates[state];
   1665            unsigned posState2 = (position + len) & p->pbMask;
   1666            unsigned offset;
   1667            price += GET_PRICE_0(p->isMatch[state2][posState2]);
   1668            price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
   1669                    data[len], data2[len], p->ProbPrices);
   1670 
   1671            // state2 = kLiteralNextStates[state2];
   1672            state2 = kState_LitAfterMatch;
   1673 
   1674            posState2 = (posState2 + 1) & p->pbMask;
   1675            price += GetPrice_Rep_0(p, state2, posState2);
   1676 
   1677            offset = cur + len + len2;
   1678            while (last < offset)
   1679              p->opt[++last].price = kInfinityPrice;
   1680            // do
   1681            {
   1682              UInt32 price2;
   1683              COptimal *opt;
   1684              len2--;
   1685              // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
   1686              price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
   1687              opt = &p->opt[offset];
   1688              // offset--;
   1689              if (price2 < opt->price)
   1690              {
   1691                opt->price = price2;
   1692                opt->len = len2;
   1693                opt->extra = (CExtra)(len + 1);
   1694                opt->dist = dist + LZMA_NUM_REPS;
   1695              }
   1696            }
   1697            // while (len2 >= 3);
   1698          }
   1699        
   1700          offs += 2;
   1701          if (offs == numPairs)
   1702            break;
   1703          dist = matches[(size_t)offs + 1];
   1704          // if (dist >= kNumFullDistances)
   1705            GetPosSlot2(dist, posSlot);
   1706        }
   1707      }
   1708    }
   1709  }
   1710 }
   1711 
   1712 
   1713 
   1714 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
   1715 
   1716 
   1717 
   1718 static unsigned GetOptimumFast(CLzmaEnc *p)
   1719 {
   1720  UInt32 numAvail, mainDist;
   1721  unsigned mainLen, numPairs, repIndex, repLen, i;
   1722  const Byte *data;
   1723 
   1724  if (p->additionalOffset == 0)
   1725    mainLen = ReadMatchDistances(p, &numPairs);
   1726  else
   1727  {
   1728    mainLen = p->longestMatchLen;
   1729    numPairs = p->numPairs;
   1730  }
   1731 
   1732  numAvail = p->numAvail;
   1733  p->backRes = MARK_LIT;
   1734  if (numAvail < 2)
   1735    return 1;
   1736  if (numAvail > LZMA_MATCH_LEN_MAX)
   1737    numAvail = LZMA_MATCH_LEN_MAX;
   1738  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1739  repLen = repIndex = 0;
   1740  
   1741  for (i = 0; i < LZMA_NUM_REPS; i++)
   1742  {
   1743    unsigned len;
   1744    const Byte *data2 = data - p->reps[i];
   1745    if (data[0] != data2[0] || data[1] != data2[1])
   1746      continue;
   1747    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
   1748    if (len >= p->numFastBytes)
   1749    {
   1750      p->backRes = i;
   1751      MOVE_POS(p, len - 1)
   1752      return len;
   1753    }
   1754    if (len > repLen)
   1755    {
   1756      repIndex = i;
   1757      repLen = len;
   1758    }
   1759  }
   1760 
   1761  if (mainLen >= p->numFastBytes)
   1762  {
   1763    p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
   1764    MOVE_POS(p, mainLen - 1)
   1765    return mainLen;
   1766  }
   1767 
   1768  mainDist = 0; /* for GCC */
   1769  
   1770  if (mainLen >= 2)
   1771  {
   1772    mainDist = p->matches[(size_t)numPairs - 1];
   1773    while (numPairs > 2)
   1774    {
   1775      UInt32 dist2;
   1776      if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
   1777        break;
   1778      dist2 = p->matches[(size_t)numPairs - 3];
   1779      if (!ChangePair(dist2, mainDist))
   1780        break;
   1781      numPairs -= 2;
   1782      mainLen--;
   1783      mainDist = dist2;
   1784    }
   1785    if (mainLen == 2 && mainDist >= 0x80)
   1786      mainLen = 1;
   1787  }
   1788 
   1789  if (repLen >= 2)
   1790    if (    repLen + 1 >= mainLen
   1791        || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
   1792        || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
   1793  {
   1794    p->backRes = repIndex;
   1795    MOVE_POS(p, repLen - 1)
   1796    return repLen;
   1797  }
   1798  
   1799  if (mainLen < 2 || numAvail <= 2)
   1800    return 1;
   1801 
   1802  {
   1803    unsigned len1 = ReadMatchDistances(p, &p->numPairs);
   1804    p->longestMatchLen = len1;
   1805  
   1806    if (len1 >= 2)
   1807    {
   1808      UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
   1809      if (   (len1 >= mainLen && newDist < mainDist)
   1810          || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
   1811          || (len1 >  mainLen + 1)
   1812          || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
   1813        return 1;
   1814    }
   1815  }
   1816  
   1817  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1818  
   1819  for (i = 0; i < LZMA_NUM_REPS; i++)
   1820  {
   1821    unsigned len, limit;
   1822    const Byte *data2 = data - p->reps[i];
   1823    if (data[0] != data2[0] || data[1] != data2[1])
   1824      continue;
   1825    limit = mainLen - 1;
   1826    for (len = 2;; len++)
   1827    {
   1828      if (len >= limit)
   1829        return 1;
   1830      if (data[len] != data2[len])
   1831        break;
   1832    }
   1833  }
   1834  
   1835  p->backRes = mainDist + LZMA_NUM_REPS;
   1836  if (mainLen != 2)
   1837  {
   1838    MOVE_POS(p, mainLen - 2)
   1839  }
   1840  return mainLen;
   1841 }
   1842 
   1843 
   1844 
   1845 
   1846 static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
   1847 {
   1848  UInt32 range;
   1849  range = p->rc.range;
   1850  {
   1851    UInt32 ttt, newBound;
   1852    CLzmaProb *prob = &p->isMatch[p->state][posState];
   1853    RC_BIT_PRE(&p->rc, prob)
   1854    RC_BIT_1(&p->rc, prob)
   1855    prob = &p->isRep[p->state];
   1856    RC_BIT_PRE(&p->rc, prob)
   1857    RC_BIT_0(&p->rc, prob)
   1858  }
   1859  p->state = kMatchNextStates[p->state];
   1860  
   1861  p->rc.range = range;
   1862  LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
   1863  range = p->rc.range;
   1864 
   1865  {
   1866    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
   1867    CLzmaProb *probs = p->posSlotEncoder[0];
   1868    unsigned m = 1;
   1869    do
   1870    {
   1871      UInt32 ttt, newBound;
   1872      RC_BIT_PRE(p, probs + m)
   1873      RC_BIT_1(&p->rc, probs + m);
   1874      m = (m << 1) + 1;
   1875    }
   1876    while (m < (1 << kNumPosSlotBits));
   1877  }
   1878  {
   1879    // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;
   1880    unsigned numBits = 30 - kNumAlignBits;
   1881    do
   1882    {
   1883      range >>= 1;
   1884      p->rc.low += range;
   1885      RC_NORM(&p->rc)
   1886    }
   1887    while (--numBits);
   1888  }
   1889   
   1890  {
   1891    // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
   1892    CLzmaProb *probs = p->posAlignEncoder;
   1893    unsigned m = 1;
   1894    do
   1895    {
   1896      UInt32 ttt, newBound;
   1897      RC_BIT_PRE(p, probs + m)
   1898      RC_BIT_1(&p->rc, probs + m);
   1899      m = (m << 1) + 1;
   1900    }
   1901    while (m < kAlignTableSize);
   1902  }
   1903  p->rc.range = range;
   1904 }
   1905 
   1906 
   1907 static SRes CheckErrors(CLzmaEnc *p)
   1908 {
   1909  if (p->result != SZ_OK)
   1910    return p->result;
   1911  if (p->rc.res != SZ_OK)
   1912    p->result = SZ_ERROR_WRITE;
   1913  if (p->matchFinderBase.result != SZ_OK)
   1914    p->result = SZ_ERROR_READ;
   1915  if (p->result != SZ_OK)
   1916    p->finished = True;
   1917  return p->result;
   1918 }
   1919 
   1920 
   1921 MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
   1922 {
   1923  /* ReleaseMFStream(); */
   1924  p->finished = True;
   1925  if (p->writeEndMark)
   1926    WriteEndMarker(p, nowPos & p->pbMask);
   1927  RangeEnc_FlushData(&p->rc);
   1928  RangeEnc_FlushStream(&p->rc);
   1929  return CheckErrors(p);
   1930 }
   1931 
   1932 
   1933 
   1934 static void FillAlignPrices(CLzmaEnc *p)
   1935 {
   1936  unsigned i;
   1937  const CProbPrice *ProbPrices = p->ProbPrices;
   1938  const CLzmaProb *probs = p->posAlignEncoder;
   1939  p->alignPriceCount = 0;
   1940  for (i = 0; i < kAlignTableSize / 2; i++)
   1941  {
   1942    UInt32 price = 0;
   1943    unsigned symbol = i;
   1944    unsigned m = 1;
   1945    unsigned bit;
   1946    UInt32 prob;
   1947    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
   1948    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
   1949    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
   1950    prob = probs[m];
   1951    p->alignPrices[i    ] = price + GET_PRICEa_0(prob);
   1952    p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
   1953    // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
   1954  }
   1955 }
   1956 
   1957 
   1958 static void FillDistancesPrices(CLzmaEnc *p)
   1959 {
   1960  UInt32 tempPrices[kNumFullDistances];
   1961  unsigned i, lenToPosState;
   1962 
   1963  const CProbPrice *ProbPrices = p->ProbPrices;
   1964  p->matchPriceCount = 0;
   1965 
   1966  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
   1967  {
   1968    unsigned posSlot = GetPosSlot1(i);
   1969    unsigned footerBits = ((posSlot >> 1) - 1);
   1970    unsigned base = ((2 | (posSlot & 1)) << footerBits);
   1971    // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
   1972 
   1973    const CLzmaProb *probs = p->posEncoders + base;
   1974    UInt32 price = 0;
   1975    unsigned m = 1;
   1976    unsigned symbol = i - base;
   1977    do
   1978    {
   1979      unsigned bit = symbol & 1;
   1980      symbol >>= 1;
   1981      price += GET_PRICEa(probs[m], bit);
   1982      m = (m << 1) + bit;
   1983    }
   1984    while (--footerBits);
   1985    tempPrices[i] = price;
   1986  }
   1987 
   1988  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
   1989  {
   1990    unsigned posSlot;
   1991    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
   1992    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
   1993    unsigned distTableSize = p->distTableSize;
   1994    const CLzmaProb *probs = encoder;
   1995    for (posSlot = 0; posSlot < distTableSize; posSlot += 2)
   1996    {
   1997      // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
   1998      UInt32 price = 0;
   1999      unsigned bit;
   2000      unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));
   2001      UInt32 prob;
   2002      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
   2003      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
   2004      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
   2005      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
   2006      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
   2007      prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];
   2008      posSlotPrices[posSlot    ] = price + GET_PRICEa_0(prob);
   2009      posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);
   2010    }
   2011    for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)
   2012      posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
   2013 
   2014    {
   2015      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
   2016      {
   2017        distancesPrices[0] = posSlotPrices[0];
   2018        distancesPrices[1] = posSlotPrices[1];
   2019        distancesPrices[2] = posSlotPrices[2];
   2020        distancesPrices[3] = posSlotPrices[3];
   2021      }
   2022      for (i = 4; i < kNumFullDistances; i += 2)
   2023      {
   2024        UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
   2025        distancesPrices[i    ] = slotPrice + tempPrices[i];
   2026        distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];
   2027      }
   2028    }
   2029  }
   2030 }
   2031 
   2032 
   2033 
   2034 void LzmaEnc_Construct(CLzmaEnc *p)
   2035 {
   2036  RangeEnc_Construct(&p->rc);
   2037  MatchFinder_Construct(&p->matchFinderBase);
   2038  
   2039  #ifndef _7ZIP_ST
   2040  MatchFinderMt_Construct(&p->matchFinderMt);
   2041  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
   2042  #endif
   2043 
   2044  {
   2045    CLzmaEncProps props;
   2046    LzmaEncProps_Init(&props);
   2047    LzmaEnc_SetProps(p, &props);
   2048  }
   2049 
   2050  #ifndef LZMA_LOG_BSR
   2051  LzmaEnc_FastPosInit(p->g_FastPos);
   2052  #endif
   2053 
   2054  LzmaEnc_InitPriceTables(p->ProbPrices);
   2055  p->litProbs = NULL;
   2056  p->saveState.litProbs = NULL;
   2057 
   2058 }
   2059 
   2060 CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
   2061 {
   2062  void *p;
   2063  p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
   2064  if (p)
   2065    LzmaEnc_Construct((CLzmaEnc *)p);
   2066  return p;
   2067 }
   2068 
   2069 void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
   2070 {
   2071  ISzAlloc_Free(alloc, p->litProbs);
   2072  ISzAlloc_Free(alloc, p->saveState.litProbs);
   2073  p->litProbs = NULL;
   2074  p->saveState.litProbs = NULL;
   2075 }
   2076 
   2077 void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2078 {
   2079  #ifndef _7ZIP_ST
   2080  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
   2081  #endif
   2082  
   2083  MatchFinder_Free(&p->matchFinderBase, allocBig);
   2084  LzmaEnc_FreeLits(p, alloc);
   2085  RangeEnc_Free(&p->rc, alloc);
   2086 }
   2087 
   2088 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2089 {
   2090  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
   2091  ISzAlloc_Free(alloc, p);
   2092 }
   2093 
   2094 
   2095 static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
   2096 {
   2097  UInt32 nowPos32, startPos32;
   2098  if (p->needInit)
   2099  {
   2100    p->matchFinder.Init(p->matchFinderObj);
   2101    p->needInit = 0;
   2102  }
   2103 
   2104  if (p->finished)
   2105    return p->result;
   2106  RINOK(CheckErrors(p));
   2107 
   2108  nowPos32 = (UInt32)p->nowPos64;
   2109  startPos32 = nowPos32;
   2110 
   2111  if (p->nowPos64 == 0)
   2112  {
   2113    unsigned numPairs;
   2114    Byte curByte;
   2115    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
   2116      return Flush(p, nowPos32);
   2117    ReadMatchDistances(p, &numPairs);
   2118    RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
   2119    // p->state = kLiteralNextStates[p->state];
   2120    curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
   2121    LitEnc_Encode(&p->rc, p->litProbs, curByte);
   2122    p->additionalOffset--;
   2123    nowPos32++;
   2124  }
   2125 
   2126  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
   2127  
   2128  for (;;)
   2129  {
   2130    UInt32 dist;
   2131    unsigned len, posState;
   2132    UInt32 range, ttt, newBound;
   2133    CLzmaProb *probs;
   2134  
   2135    if (p->fastMode)
   2136      len = GetOptimumFast(p);
   2137    else
   2138    {
   2139      unsigned oci = p->optCur;
   2140      if (p->optEnd == oci)
   2141        len = GetOptimum(p, nowPos32);
   2142      else
   2143      {
   2144        const COptimal *opt = &p->opt[oci];
   2145        len = opt->len;
   2146        p->backRes = opt->dist;
   2147        p->optCur = oci + 1;
   2148      }
   2149    }
   2150 
   2151    posState = (unsigned)nowPos32 & p->pbMask;
   2152    range = p->rc.range;
   2153    probs = &p->isMatch[p->state][posState];
   2154    
   2155    RC_BIT_PRE(&p->rc, probs)
   2156    
   2157    dist = p->backRes;
   2158 
   2159    #ifdef SHOW_STAT2
   2160    printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);
   2161    #endif
   2162 
   2163    if (dist == MARK_LIT)
   2164    {
   2165      Byte curByte;
   2166      const Byte *data;
   2167      unsigned state;
   2168 
   2169      RC_BIT_0(&p->rc, probs);
   2170      p->rc.range = range;
   2171      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
   2172      probs = LIT_PROBS(nowPos32, *(data - 1));
   2173      curByte = *data;
   2174      state = p->state;
   2175      p->state = kLiteralNextStates[state];
   2176      if (IsLitState(state))
   2177        LitEnc_Encode(&p->rc, probs, curByte);
   2178      else
   2179        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
   2180    }
   2181    else
   2182    {
   2183      RC_BIT_1(&p->rc, probs);
   2184      probs = &p->isRep[p->state];
   2185      RC_BIT_PRE(&p->rc, probs)
   2186      
   2187      if (dist < LZMA_NUM_REPS)
   2188      {
   2189        RC_BIT_1(&p->rc, probs);
   2190        probs = &p->isRepG0[p->state];
   2191        RC_BIT_PRE(&p->rc, probs)
   2192        if (dist == 0)
   2193        {
   2194          RC_BIT_0(&p->rc, probs);
   2195          probs = &p->isRep0Long[p->state][posState];
   2196          RC_BIT_PRE(&p->rc, probs)
   2197          if (len != 1)
   2198          {
   2199            RC_BIT_1_BASE(&p->rc, probs);
   2200          }
   2201          else
   2202          {
   2203            RC_BIT_0_BASE(&p->rc, probs);
   2204            p->state = kShortRepNextStates[p->state];
   2205          }
   2206        }
   2207        else
   2208        {
   2209          RC_BIT_1(&p->rc, probs);
   2210          probs = &p->isRepG1[p->state];
   2211          RC_BIT_PRE(&p->rc, probs)
   2212          if (dist == 1)
   2213          {
   2214            RC_BIT_0_BASE(&p->rc, probs);
   2215            dist = p->reps[1];
   2216          }
   2217          else
   2218          {
   2219            RC_BIT_1(&p->rc, probs);
   2220            probs = &p->isRepG2[p->state];
   2221            RC_BIT_PRE(&p->rc, probs)
   2222            if (dist == 2)
   2223            {
   2224              RC_BIT_0_BASE(&p->rc, probs);
   2225              dist = p->reps[2];
   2226            }
   2227            else
   2228            {
   2229              RC_BIT_1_BASE(&p->rc, probs);
   2230              dist = p->reps[3];
   2231              p->reps[3] = p->reps[2];
   2232            }
   2233            p->reps[2] = p->reps[1];
   2234          }
   2235          p->reps[1] = p->reps[0];
   2236          p->reps[0] = dist;
   2237        }
   2238 
   2239        RC_NORM(&p->rc)
   2240 
   2241        p->rc.range = range;
   2242 
   2243        if (len != 1)
   2244        {
   2245          LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
   2246          if (!p->fastMode)
   2247            if (--p->repLenEnc.counters[posState] == 0)
   2248              LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);
   2249 
   2250          p->state = kRepNextStates[p->state];
   2251        }
   2252      }
   2253      else
   2254      {
   2255        unsigned posSlot;
   2256        RC_BIT_0(&p->rc, probs);
   2257        p->rc.range = range;
   2258        p->state = kMatchNextStates[p->state];
   2259 
   2260        LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
   2261        if (!p->fastMode)
   2262          if (--p->lenEnc.counters[posState] == 0)
   2263            LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);
   2264 
   2265        dist -= LZMA_NUM_REPS;
   2266        p->reps[3] = p->reps[2];
   2267        p->reps[2] = p->reps[1];
   2268        p->reps[1] = p->reps[0];
   2269        p->reps[0] = dist + 1;
   2270        
   2271        p->matchPriceCount++;
   2272        GetPosSlot(dist, posSlot);
   2273        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
   2274        {
   2275          UInt32 symbol = posSlot + (1 << kNumPosSlotBits);
   2276          range = p->rc.range;
   2277          probs = p->posSlotEncoder[GetLenToPosState(len)];
   2278          do
   2279          {
   2280            CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);
   2281            UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;
   2282            symbol <<= 1;
   2283            RC_BIT(&p->rc, prob, bit);
   2284          }
   2285          while (symbol < (1 << kNumPosSlotBits * 2));
   2286          p->rc.range = range;
   2287        }
   2288        
   2289        if (dist >= kStartPosModelIndex)
   2290        {
   2291          unsigned footerBits = ((posSlot >> 1) - 1);
   2292 
   2293          if (dist < kNumFullDistances)
   2294          {
   2295            unsigned base = ((2 | (posSlot & 1)) << footerBits);
   2296            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);
   2297          }
   2298          else
   2299          {
   2300            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
   2301            range = p->rc.range;
   2302            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
   2303            /*
   2304            do
   2305            {
   2306              range >>= 1;
   2307              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
   2308              RC_NORM(&p->rc)
   2309            }
   2310            while (footerBits > kNumAlignBits);
   2311            */
   2312            do
   2313            {
   2314              range >>= 1;
   2315              p->rc.low += range & (0 - (pos2 >> 31));
   2316              pos2 += pos2;
   2317              RC_NORM(&p->rc)
   2318            }
   2319            while (pos2 != 0xF0000000);
   2320 
   2321 
   2322            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
   2323 
   2324            {
   2325              unsigned m = 1;
   2326              unsigned bit;
   2327              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
   2328              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
   2329              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
   2330              bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
   2331              p->rc.range = range;
   2332              p->alignPriceCount++;
   2333            }
   2334          }
   2335        }
   2336      }
   2337    }
   2338 
   2339    nowPos32 += len;
   2340    p->additionalOffset -= len;
   2341    
   2342    if (p->additionalOffset == 0)
   2343    {
   2344      UInt32 processed;
   2345 
   2346      if (!p->fastMode)
   2347      {
   2348        if (p->matchPriceCount >= (1 << 7))
   2349          FillDistancesPrices(p);
   2350        if (p->alignPriceCount >= kAlignTableSize)
   2351          FillAlignPrices(p);
   2352      }
   2353    
   2354      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
   2355        break;
   2356      processed = nowPos32 - startPos32;
   2357      
   2358      if (maxPackSize)
   2359      {
   2360        if (processed + kNumOpts + 300 >= maxUnpackSize
   2361            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
   2362          break;
   2363      }
   2364      else if (processed >= (1 << 17))
   2365      {
   2366        p->nowPos64 += nowPos32 - startPos32;
   2367        return CheckErrors(p);
   2368      }
   2369    }
   2370  }
   2371 
   2372  p->nowPos64 += nowPos32 - startPos32;
   2373  return Flush(p, nowPos32);
   2374 }
   2375 
   2376 
   2377 
   2378 #define kBigHashDicLimit ((UInt32)1 << 24)
   2379 
   2380 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2381 {
   2382  UInt32 beforeSize = kNumOpts;
   2383  if (!RangeEnc_Alloc(&p->rc, alloc))
   2384    return SZ_ERROR_MEM;
   2385 
   2386  #ifndef _7ZIP_ST
   2387  p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
   2388  #endif
   2389 
   2390  {
   2391    unsigned lclp = p->lc + p->lp;
   2392    if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
   2393    {
   2394      LzmaEnc_FreeLits(p, alloc);
   2395      p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
   2396      p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
   2397      if (!p->litProbs || !p->saveState.litProbs)
   2398      {
   2399        LzmaEnc_FreeLits(p, alloc);
   2400        return SZ_ERROR_MEM;
   2401      }
   2402      p->lclp = lclp;
   2403    }
   2404  }
   2405 
   2406  p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
   2407 
   2408  if (beforeSize + p->dictSize < keepWindowSize)
   2409    beforeSize = keepWindowSize - p->dictSize;
   2410 
   2411  #ifndef _7ZIP_ST
   2412  if (p->mtMode)
   2413  {
   2414    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
   2415        LZMA_MATCH_LEN_MAX
   2416        + 1  /* 18.04 */
   2417        , allocBig));
   2418    p->matchFinderObj = &p->matchFinderMt;
   2419    p->matchFinderBase.bigHash = (Byte)(
   2420        (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
   2421    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
   2422  }
   2423  else
   2424  #endif
   2425  {
   2426    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
   2427      return SZ_ERROR_MEM;
   2428    p->matchFinderObj = &p->matchFinderBase;
   2429    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
   2430  }
   2431  
   2432  return SZ_OK;
   2433 }
   2434 
   2435 void LzmaEnc_Init(CLzmaEnc *p)
   2436 {
   2437  unsigned i;
   2438  p->state = 0;
   2439  p->reps[0] =
   2440  p->reps[1] =
   2441  p->reps[2] =
   2442  p->reps[3] = 1;
   2443 
   2444  RangeEnc_Init(&p->rc);
   2445 
   2446  for (i = 0; i < (1 << kNumAlignBits); i++)
   2447    p->posAlignEncoder[i] = kProbInitValue;
   2448 
   2449  for (i = 0; i < kNumStates; i++)
   2450  {
   2451    unsigned j;
   2452    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
   2453    {
   2454      p->isMatch[i][j] = kProbInitValue;
   2455      p->isRep0Long[i][j] = kProbInitValue;
   2456    }
   2457    p->isRep[i] = kProbInitValue;
   2458    p->isRepG0[i] = kProbInitValue;
   2459    p->isRepG1[i] = kProbInitValue;
   2460    p->isRepG2[i] = kProbInitValue;
   2461  }
   2462 
   2463  {
   2464    for (i = 0; i < kNumLenToPosStates; i++)
   2465    {
   2466      CLzmaProb *probs = p->posSlotEncoder[i];
   2467      unsigned j;
   2468      for (j = 0; j < (1 << kNumPosSlotBits); j++)
   2469        probs[j] = kProbInitValue;
   2470    }
   2471  }
   2472  {
   2473    for (i = 0; i < kNumFullDistances; i++)
   2474      p->posEncoders[i] = kProbInitValue;
   2475  }
   2476 
   2477  {
   2478    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
   2479    UInt32 k;
   2480    CLzmaProb *probs = p->litProbs;
   2481    for (k = 0; k < num; k++)
   2482      probs[k] = kProbInitValue;
   2483  }
   2484 
   2485 
   2486  LenEnc_Init(&p->lenProbs);
   2487  LenEnc_Init(&p->repLenProbs);
   2488 
   2489  p->optEnd = 0;
   2490  p->optCur = 0;
   2491  p->additionalOffset = 0;
   2492 
   2493  p->pbMask = (1 << p->pb) - 1;
   2494  p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
   2495 }
   2496 
   2497 void LzmaEnc_InitPrices(CLzmaEnc *p)
   2498 {
   2499  if (!p->fastMode)
   2500  {
   2501    FillDistancesPrices(p);
   2502    FillAlignPrices(p);
   2503  }
   2504 
   2505  p->lenEnc.tableSize =
   2506  p->repLenEnc.tableSize =
   2507      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
   2508  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
   2509  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
   2510 }
   2511 
   2512 static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2513 {
   2514  unsigned i;
   2515  for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
   2516    if (p->dictSize <= ((UInt32)1 << i))
   2517      break;
   2518  p->distTableSize = i * 2;
   2519 
   2520  p->finished = False;
   2521  p->result = SZ_OK;
   2522  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
   2523  LzmaEnc_Init(p);
   2524  LzmaEnc_InitPrices(p);
   2525  p->nowPos64 = 0;
   2526  return SZ_OK;
   2527 }
   2528 
   2529 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
   2530    ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2531 {
   2532  CLzmaEnc *p = (CLzmaEnc *)pp;
   2533  p->matchFinderBase.stream = inStream;
   2534  p->needInit = 1;
   2535  p->rc.outStream = outStream;
   2536  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
   2537 }
   2538 
   2539 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
   2540    ISeqInStream *inStream, UInt32 keepWindowSize,
   2541    ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2542 {
   2543  CLzmaEnc *p = (CLzmaEnc *)pp;
   2544  p->matchFinderBase.stream = inStream;
   2545  p->needInit = 1;
   2546  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
   2547 }
   2548 
   2549 static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
   2550 {
   2551  p->matchFinderBase.directInput = 1;
   2552  p->matchFinderBase.bufferBase = (Byte *)src;
   2553  p->matchFinderBase.directInputRem = srcLen;
   2554 }
   2555 
   2556 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
   2557    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2558 {
   2559  CLzmaEnc *p = (CLzmaEnc *)pp;
   2560  LzmaEnc_SetInputBuf(p, src, srcLen);
   2561  p->needInit = 1;
   2562 
   2563  LzmaEnc_SetDataSize(pp, srcLen);
   2564  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
   2565 }
   2566 
   2567 void LzmaEnc_Finish(CLzmaEncHandle pp)
   2568 {
   2569  #ifndef _7ZIP_ST
   2570  CLzmaEnc *p = (CLzmaEnc *)pp;
   2571  if (p->mtMode)
   2572    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
   2573  #else
   2574  UNUSED_VAR(pp);
   2575  #endif
   2576 }
   2577 
   2578 
   2579 typedef struct
   2580 {
   2581  ISeqOutStream vt;
   2582  Byte *data;
   2583  SizeT rem;
   2584  Bool overflow;
   2585 } CLzmaEnc_SeqOutStreamBuf;
   2586 
   2587 static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
   2588 {
   2589  CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
   2590  if (p->rem < size)
   2591  {
   2592    size = p->rem;
   2593    p->overflow = True;
   2594  }
   2595  memcpy(p->data, data, size);
   2596  p->rem -= size;
   2597  p->data += size;
   2598  return size;
   2599 }
   2600 
   2601 
   2602 UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
   2603 {
   2604  const CLzmaEnc *p = (CLzmaEnc *)pp;
   2605  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
   2606 }
   2607 
   2608 
   2609 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
   2610 {
   2611  const CLzmaEnc *p = (CLzmaEnc *)pp;
   2612  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
   2613 }
   2614 
   2615 
   2616 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
   2617    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
   2618 {
   2619  CLzmaEnc *p = (CLzmaEnc *)pp;
   2620  UInt64 nowPos64;
   2621  SRes res;
   2622  CLzmaEnc_SeqOutStreamBuf outStream;
   2623 
   2624  outStream.vt.Write = SeqOutStreamBuf_Write;
   2625  outStream.data = dest;
   2626  outStream.rem = *destLen;
   2627  outStream.overflow = False;
   2628 
   2629  p->writeEndMark = False;
   2630  p->finished = False;
   2631  p->result = SZ_OK;
   2632 
   2633  if (reInit)
   2634    LzmaEnc_Init(p);
   2635  LzmaEnc_InitPrices(p);
   2636 
   2637  nowPos64 = p->nowPos64;
   2638  RangeEnc_Init(&p->rc);
   2639  p->rc.outStream = &outStream.vt;
   2640 
   2641  if (desiredPackSize == 0)
   2642    return SZ_ERROR_OUTPUT_EOF;
   2643 
   2644  res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
   2645  
   2646  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
   2647  *destLen -= outStream.rem;
   2648  if (outStream.overflow)
   2649    return SZ_ERROR_OUTPUT_EOF;
   2650 
   2651  return res;
   2652 }
   2653 
   2654 
   2655 static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
   2656 {
   2657  SRes res = SZ_OK;
   2658 
   2659  #ifndef _7ZIP_ST
   2660  Byte allocaDummy[0x300];
   2661  allocaDummy[0] = 0;
   2662  allocaDummy[1] = allocaDummy[0];
   2663  #endif
   2664 
   2665  for (;;)
   2666  {
   2667    res = LzmaEnc_CodeOneBlock(p, 0, 0);
   2668    if (res != SZ_OK || p->finished)
   2669      break;
   2670    if (progress)
   2671    {
   2672      res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
   2673      if (res != SZ_OK)
   2674      {
   2675        res = SZ_ERROR_PROGRESS;
   2676        break;
   2677      }
   2678    }
   2679  }
   2680  
   2681  LzmaEnc_Finish(p);
   2682 
   2683  /*
   2684  if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
   2685    res = SZ_ERROR_FAIL;
   2686  }
   2687  */
   2688 
   2689  return res;
   2690 }
   2691 
   2692 
   2693 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
   2694    ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2695 {
   2696  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
   2697  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
   2698 }
   2699 
   2700 
   2701 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
   2702 {
   2703  CLzmaEnc *p = (CLzmaEnc *)pp;
   2704  unsigned i;
   2705  UInt32 dictSize = p->dictSize;
   2706  if (*size < LZMA_PROPS_SIZE)
   2707    return SZ_ERROR_PARAM;
   2708  *size = LZMA_PROPS_SIZE;
   2709  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
   2710 
   2711  if (dictSize >= ((UInt32)1 << 22))
   2712  {
   2713    UInt32 kDictMask = ((UInt32)1 << 20) - 1;
   2714    if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
   2715      dictSize = (dictSize + kDictMask) & ~kDictMask;
   2716  }
   2717  else for (i = 11; i <= 30; i++)
   2718  {
   2719    if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
   2720    if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
   2721  }
   2722 
   2723  for (i = 0; i < 4; i++)
   2724    props[1 + i] = (Byte)(dictSize >> (8 * i));
   2725  return SZ_OK;
   2726 }
   2727 
   2728 
   2729 unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
   2730 {
   2731  return ((CLzmaEnc *)pp)->writeEndMark;
   2732 }
   2733 
   2734 
   2735 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   2736    int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2737 {
   2738  SRes res;
   2739  CLzmaEnc *p = (CLzmaEnc *)pp;
   2740 
   2741  CLzmaEnc_SeqOutStreamBuf outStream;
   2742 
   2743  outStream.vt.Write = SeqOutStreamBuf_Write;
   2744  outStream.data = dest;
   2745  outStream.rem = *destLen;
   2746  outStream.overflow = False;
   2747 
   2748  p->writeEndMark = writeEndMark;
   2749  p->rc.outStream = &outStream.vt;
   2750 
   2751  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
   2752  
   2753  if (res == SZ_OK)
   2754  {
   2755    res = LzmaEnc_Encode2(p, progress);
   2756    if (res == SZ_OK && p->nowPos64 != srcLen)
   2757      res = SZ_ERROR_FAIL;
   2758  }
   2759 
   2760  *destLen -= outStream.rem;
   2761  if (outStream.overflow)
   2762    return SZ_ERROR_OUTPUT_EOF;
   2763  return res;
   2764 }
   2765 
   2766 
   2767 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   2768    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
   2769    ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
   2770 {
   2771  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
   2772  SRes res;
   2773  if (!p)
   2774    return SZ_ERROR_MEM;
   2775 
   2776  res = LzmaEnc_SetProps(p, props);
   2777  if (res == SZ_OK)
   2778  {
   2779    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
   2780    if (res == SZ_OK)
   2781      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
   2782          writeEndMark, progress, alloc, allocBig);
   2783  }
   2784 
   2785  LzmaEnc_Destroy(p, alloc, allocBig);
   2786  return res;
   2787 }