]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
BaseTools Lzma: Update LZMA SDK version to 18.05
[mirror_edk2.git] / BaseTools / Source / C / LzmaCompress / Sdk / C / LzmaEnc.c
index 462ca675652439ddb2dd504b600f62178ae52ea5..bebe664d3e5bbbafc415876c01fcd7265232e828 100644 (file)
@@ -1,5 +1,5 @@
 /* LzmaEnc.c -- LZMA Encoder\r
-2016-05-16 : Igor Pavlov : Public domain */\r
+2018-04-29 : Igor Pavlov : Public domain */\r
 \r
 #include "Precomp.h"\r
 \r
 static unsigned g_STAT_OFFSET = 0;\r
 #endif\r
 \r
-#define kMaxHistorySize ((UInt32)3 << 29)\r
-/* #define kMaxHistorySize ((UInt32)7 << 29) */\r
-\r
-#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)\r
-\r
-#define kBlockSize (9 << 10)\r
-#define kUnpackBlockSize (1 << 18)\r
-#define kMatchArraySize (1 << 21)\r
-#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)\r
-\r
-#define kNumMaxDirectBits (31)\r
+#define kLzmaMaxHistorySize ((UInt32)3 << 29)\r
+/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */\r
 \r
 #define kNumTopBits 24\r
 #define kTopValue ((UInt32)1 << kNumTopBits)\r
@@ -62,14 +53,15 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
   if (level < 0) level = 5;\r
   p->level = level;\r
   \r
-  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));\r
+  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));\r
   if (p->dictSize > p->reduceSize)\r
   {\r
     unsigned i;\r
+    UInt32 reduceSize = (UInt32)p->reduceSize;\r
     for (i = 11; i <= 30; i++)\r
     {\r
-      if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }\r
-      if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }\r
+      if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }\r
+      if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }\r
     }\r
   }\r
 \r
@@ -110,9 +102,9 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
 \r
 #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }\r
 \r
-static UInt32 GetPosSlot1(UInt32 pos)\r
+static unsigned GetPosSlot1(UInt32 pos)\r
 {\r
-  UInt32 res;\r
+  unsigned res;\r
   BSR2_RET(pos, res);\r
   return res;\r
 }\r
@@ -145,18 +137,18 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
 \r
 /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */\r
 /*\r
-#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \\r
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \\r
   (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \\r
   res = p->g_FastPos[pos >> zz] + (zz * 2); }\r
 */\r
 \r
 /*\r
-#define BSR2_RET(pos, res) { UInt32 zz = 6 + ((kNumLogBits - 1) & \\r
+#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \\r
   (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \\r
   res = p->g_FastPos[pos >> zz] + (zz * 2); }\r
 */\r
 \r
-#define BSR2_RET(pos, res) { UInt32 zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \\r
+#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \\r
   res = p->g_FastPos[pos >> zz] + (zz * 2); }\r
 \r
 /*\r
@@ -167,32 +159,32 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
 \r
 #define GetPosSlot1(pos) p->g_FastPos[pos]\r
 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\r
-#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }\r
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }\r
 \r
 #endif\r
 \r
 \r
 #define LZMA_NUM_REPS 4\r
 \r
-typedef unsigned CState;\r
+typedef UInt16 CState;\r
+typedef UInt16 CExtra;\r
 \r
 typedef struct\r
 {\r
   UInt32 price;\r
-\r
   CState state;\r
-  int prev1IsChar;\r
-  int prev2;\r
-\r
-  UInt32 posPrev2;\r
-  UInt32 backPrev2;\r
-\r
-  UInt32 posPrev;\r
-  UInt32 backPrev;\r
-  UInt32 backs[LZMA_NUM_REPS];\r
+  CExtra extra;\r
+      // 0   : normal\r
+      // 1   : LIT : MATCH\r
+      // > 1 : MATCH (extra-1) : LIT : REP0 (len)\r
+  UInt32 len;\r
+  UInt32 dist;\r
+  UInt32 reps[LZMA_NUM_REPS];\r
 } COptimal;\r
 \r
+\r
 #define kNumOpts (1 << 12)\r
+#define kPackReserve (1 + kNumOpts * 2)\r
 \r
 #define kNumLenToPosStates 4\r
 #define kNumPosSlotBits 6\r
@@ -200,22 +192,21 @@ typedef struct
 #define kDicLogSizeMax 32\r
 #define kDistTableSizeMax (kDicLogSizeMax * 2)\r
 \r
-\r
 #define kNumAlignBits 4\r
 #define kAlignTableSize (1 << kNumAlignBits)\r
 #define kAlignMask (kAlignTableSize - 1)\r
 \r
 #define kStartPosModelIndex 4\r
 #define kEndPosModelIndex 14\r
-#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)\r
-\r
 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
 \r
+typedef\r
 #ifdef _LZMA_PROB32\r
-#define CLzmaProb UInt32\r
+  UInt32\r
 #else\r
-#define CLzmaProb UInt16\r
+  UInt16\r
 #endif\r
+  CLzmaProb;\r
 \r
 #define LZMA_PB_MAX 4\r
 #define LZMA_LC_MAX 8\r
@@ -223,15 +214,11 @@ typedef struct
 \r
 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)\r
 \r
-\r
 #define kLenNumLowBits 3\r
 #define kLenNumLowSymbols (1 << kLenNumLowBits)\r
-#define kLenNumMidBits 3\r
-#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
 #define kLenNumHighBits 8\r
 #define kLenNumHighSymbols (1 << kLenNumHighBits)\r
-\r
-#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)\r
+#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)\r
 \r
 #define LZMA_MATCH_LEN_MIN 2\r
 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)\r
@@ -241,27 +228,23 @@ typedef struct
 \r
 typedef struct\r
 {\r
-  CLzmaProb choice;\r
-  CLzmaProb choice2;\r
-  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];\r
-  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];\r
+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];\r
   CLzmaProb high[kLenNumHighSymbols];\r
 } CLenEnc;\r
 \r
 \r
 typedef struct\r
 {\r
-  CLenEnc p;\r
-  UInt32 tableSize;\r
+  unsigned tableSize;\r
+  unsigned counters[LZMA_NUM_PB_STATES_MAX];\r
   UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];\r
-  UInt32 counters[LZMA_NUM_PB_STATES_MAX];\r
 } CLenPriceEnc;\r
 \r
 \r
 typedef struct\r
 {\r
   UInt32 range;\r
-  Byte cache;\r
+  unsigned cache;\r
   UInt64 low;\r
   UInt64 cacheSize;\r
   Byte *buf;\r
@@ -277,48 +260,54 @@ typedef struct
 {\r
   CLzmaProb *litProbs;\r
 \r
-  UInt32 state;\r
+  unsigned state;\r
   UInt32 reps[LZMA_NUM_REPS];\r
 \r
-  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
   CLzmaProb isRep[kNumStates];\r
   CLzmaProb isRepG0[kNumStates];\r
   CLzmaProb isRepG1[kNumStates];\r
   CLzmaProb isRepG2[kNumStates];\r
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
 \r
   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\r
-  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\r
-  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
+  CLzmaProb posEncoders[kNumFullDistances];\r
   \r
-  CLenPriceEnc lenEnc;\r
-  CLenPriceEnc repLenEnc;\r
+  CLenEnc lenProbs;\r
+  CLenEnc repLenProbs;\r
+\r
 } CSaveState;\r
 \r
 \r
+typedef UInt32 CProbPrice;\r
+\r
+\r
 typedef struct\r
 {\r
   void *matchFinderObj;\r
   IMatchFinder matchFinder;\r
 \r
-  UInt32 optimumEndIndex;\r
-  UInt32 optimumCurrentIndex;\r
+  unsigned optCur;\r
+  unsigned optEnd;\r
 \r
-  UInt32 longestMatchLength;\r
-  UInt32 numPairs;\r
+  unsigned longestMatchLen;\r
+  unsigned numPairs;\r
   UInt32 numAvail;\r
 \r
-  UInt32 numFastBytes;\r
-  UInt32 additionalOffset;\r
+  unsigned state;\r
+  unsigned numFastBytes;\r
+  unsigned additionalOffset;\r
   UInt32 reps[LZMA_NUM_REPS];\r
-  UInt32 state;\r
+  unsigned lpMask, pbMask;\r
+  CLzmaProb *litProbs;\r
+  CRangeEnc rc;\r
+\r
+  UInt32 backRes;\r
 \r
   unsigned lc, lp, pb;\r
-  unsigned lpMask, pbMask;\r
   unsigned lclp;\r
 \r
-  CLzmaProb *litProbs;\r
-\r
   Bool fastMode;\r
   Bool writeEndMark;\r
   Bool finished;\r
@@ -327,19 +316,19 @@ typedef struct
 \r
   UInt64 nowPos64;\r
   \r
-  UInt32 matchPriceCount;\r
-  UInt32 alignPriceCount;\r
+  unsigned matchPriceCount;\r
+  unsigned alignPriceCount;\r
 \r
-  UInt32 distTableSize;\r
+  unsigned distTableSize;\r
 \r
   UInt32 dictSize;\r
   SRes result;\r
 \r
-  CRangeEnc rc;\r
-\r
   #ifndef _7ZIP_ST\r
   Bool mtMode;\r
+  // begin of CMatchFinderMt is used in LZ thread\r
   CMatchFinderMt matchFinderMt;\r
+  // end of CMatchFinderMt is used in BT and HASH threads\r
   #endif\r
 \r
   CMatchFinder matchFinderBase;\r
@@ -348,33 +337,37 @@ typedef struct
   Byte pad[128];\r
   #endif\r
   \r
-  COptimal opt[kNumOpts];\r
-  \r
-  #ifndef LZMA_LOG_BSR\r
-  Byte g_FastPos[1 << kNumLogBits];\r
-  #endif\r
+  // LZ thread\r
+  CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
 \r
-  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\r
   UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];\r
 \r
+  UInt32 alignPrices[kAlignTableSize];\r
   UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\r
   UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];\r
-  UInt32 alignPrices[kAlignTableSize];\r
 \r
-  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
   CLzmaProb isRep[kNumStates];\r
   CLzmaProb isRepG0[kNumStates];\r
   CLzmaProb isRepG1[kNumStates];\r
   CLzmaProb isRepG2[kNumStates];\r
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\r
-\r
   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\r
-  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];\r
-  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\r
+  CLzmaProb posEncoders[kNumFullDistances];\r
   \r
+  CLenEnc lenProbs;\r
+  CLenEnc repLenProbs;\r
+\r
+  #ifndef LZMA_LOG_BSR\r
+  Byte g_FastPos[1 << kNumLogBits];\r
+  #endif\r
+\r
   CLenPriceEnc lenEnc;\r
   CLenPriceEnc repLenEnc;\r
 \r
+  COptimal opt[kNumOpts];\r
+\r
   CSaveState saveState;\r
 \r
   #ifndef _7ZIP_ST\r
@@ -383,58 +376,62 @@ typedef struct
 } CLzmaEnc;\r
 \r
 \r
+\r
+#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));\r
+\r
 void LzmaEnc_SaveState(CLzmaEncHandle pp)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
   CSaveState *dest = &p->saveState;\r
-  int i;\r
-  dest->lenEnc = p->lenEnc;\r
-  dest->repLenEnc = p->repLenEnc;\r
+  \r
   dest->state = p->state;\r
+  \r
+  dest->lenProbs = p->lenProbs;\r
+  dest->repLenProbs = p->repLenProbs;\r
+\r
+  COPY_ARR(dest, p, reps);\r
+\r
+  COPY_ARR(dest, p, posAlignEncoder);\r
+  COPY_ARR(dest, p, isRep);\r
+  COPY_ARR(dest, p, isRepG0);\r
+  COPY_ARR(dest, p, isRepG1);\r
+  COPY_ARR(dest, p, isRepG2);\r
+  COPY_ARR(dest, p, isMatch);\r
+  COPY_ARR(dest, p, isRep0Long);\r
+  COPY_ARR(dest, p, posSlotEncoder);\r
+  COPY_ARR(dest, p, posEncoders);\r
 \r
-  for (i = 0; i < kNumStates; i++)\r
-  {\r
-    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\r
-    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\r
-  }\r
-  for (i = 0; i < kNumLenToPosStates; i++)\r
-    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\r
-  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\r
-  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\r
-  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\r
-  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\r
-  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\r
-  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\r
-  memcpy(dest->reps, p->reps, sizeof(p->reps));\r
   memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));\r
 }\r
 \r
+\r
 void LzmaEnc_RestoreState(CLzmaEncHandle pp)\r
 {\r
   CLzmaEnc *dest = (CLzmaEnc *)pp;\r
   const CSaveState *p = &dest->saveState;\r
-  int i;\r
-  dest->lenEnc = p->lenEnc;\r
-  dest->repLenEnc = p->repLenEnc;\r
+\r
   dest->state = p->state;\r
 \r
-  for (i = 0; i < kNumStates; i++)\r
-  {\r
-    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));\r
-    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));\r
-  }\r
-  for (i = 0; i < kNumLenToPosStates; i++)\r
-    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));\r
-  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));\r
-  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));\r
-  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));\r
-  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));\r
-  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));\r
-  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));\r
-  memcpy(dest->reps, p->reps, sizeof(p->reps));\r
+  dest->lenProbs = p->lenProbs;\r
+  dest->repLenProbs = p->repLenProbs;\r
+  \r
+  COPY_ARR(dest, p, reps);\r
+  \r
+  COPY_ARR(dest, p, posAlignEncoder);\r
+  COPY_ARR(dest, p, isRep);\r
+  COPY_ARR(dest, p, isRepG0);\r
+  COPY_ARR(dest, p, isRepG1);\r
+  COPY_ARR(dest, p, isRepG2);\r
+  COPY_ARR(dest, p, isMatch);\r
+  COPY_ARR(dest, p, isRep0Long);\r
+  COPY_ARR(dest, p, posSlotEncoder);\r
+  COPY_ARR(dest, p, posEncoders);\r
+\r
   memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));\r
 }\r
 \r
+\r
+\r
 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
@@ -445,7 +442,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
       || props.lp > LZMA_LP_MAX\r
       || props.pb > LZMA_PB_MAX\r
       || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)\r
-      || props.dictSize > kMaxHistorySize)\r
+      || props.dictSize > kLzmaMaxHistorySize)\r
     return SZ_ERROR_PARAM;\r
 \r
   p->dictSize = props.dictSize;\r
@@ -463,7 +460,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
   p->fastMode = (props.algo == 0);\r
   p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);\r
   {\r
-    UInt32 numHashBytes = 4;\r
+    unsigned numHashBytes = 4;\r
     if (props.btMode)\r
     {\r
       if (props.numHashBytes < 2)\r
@@ -492,13 +489,27 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
   return SZ_OK;\r
 }\r
 \r
-static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\r
-static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\r
-static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\r
-static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\r
 \r
-#define IsCharState(s) ((s) < 7)\r
+void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)\r
+{\r
+  CLzmaEnc *p = (CLzmaEnc *)pp;\r
+  p->matchFinderBase.expectedDataSize = expectedDataSiize;\r
+}\r
+\r
 \r
+#define kState_Start 0\r
+#define kState_LitAfterMatch 4\r
+#define kState_LitAfterRep   5\r
+#define kState_MatchAfterLit 7\r
+#define kState_RepAfterLit   8\r
+\r
+static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\r
+static const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\r
+static const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\r
+static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\r
+\r
+#define IsLitState(s) ((s) < 7)\r
+#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)\r
 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)\r
 \r
 #define kInfinityPrice (1 << 30)\r
@@ -509,14 +520,16 @@ static void RangeEnc_Construct(CRangeEnc *p)
   p->bufBase = NULL;\r
 }\r
 \r
-#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)\r
+#define RangeEnc_GetProcessed(p)       ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)\r
+#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)\r
 \r
 #define RC_BUF_SIZE (1 << 16)\r
-static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)\r
+\r
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)\r
 {\r
   if (!p->bufBase)\r
   {\r
-    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);\r
+    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);\r
     if (!p->bufBase)\r
       return 0;\r
     p->bufLim = p->bufBase + RC_BUF_SIZE;\r
@@ -524,19 +537,19 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
   return 1;\r
 }\r
 \r
-static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)\r
+static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)\r
 {\r
-  alloc->Free(alloc, p->bufBase);\r
+  ISzAlloc_Free(alloc, p->bufBase);\r
   p->bufBase = 0;\r
 }\r
 \r
 static void RangeEnc_Init(CRangeEnc *p)\r
 {\r
   /* Stream.Init(); */\r
-  p->low = 0;\r
   p->range = 0xFFFFFFFF;\r
-  p->cacheSize = 1;\r
   p->cache = 0;\r
+  p->low = 0;\r
+  p->cacheSize = 0;\r
 \r
   p->buf = p->bufBase;\r
 \r
@@ -544,37 +557,48 @@ static void RangeEnc_Init(CRangeEnc *p)
   p->res = SZ_OK;\r
 }\r
 \r
-static void RangeEnc_FlushStream(CRangeEnc *p)\r
+MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)\r
 {\r
   size_t num;\r
   if (p->res != SZ_OK)\r
     return;\r
   num = p->buf - p->bufBase;\r
-  if (num != p->outStream->Write(p->outStream, p->bufBase, num))\r
+  if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))\r
     p->res = SZ_ERROR_WRITE;\r
   p->processed += num;\r
   p->buf = p->bufBase;\r
 }\r
 \r
-static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)\r
+MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)\r
 {\r
-  if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)\r
+  UInt32 low = (UInt32)p->low;\r
+  unsigned high = (unsigned)(p->low >> 32);\r
+  p->low = (UInt32)(low << 8);\r
+  if (low < (UInt32)0xFF000000 || high != 0)\r
   {\r
-    Byte temp = p->cache;\r
-    do\r
     {\r
       Byte *buf = p->buf;\r
-      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));\r
+      *buf++ = (Byte)(p->cache + high);\r
+      p->cache = (unsigned)(low >> 24);\r
       p->buf = buf;\r
       if (buf == p->bufLim)\r
         RangeEnc_FlushStream(p);\r
-      temp = 0xFF;\r
+      if (p->cacheSize == 0)\r
+        return;\r
+    }\r
+    high += 0xFF;\r
+    for (;;)\r
+    {\r
+      Byte *buf = p->buf;\r
+      *buf++ = (Byte)(high);\r
+      p->buf = buf;\r
+      if (buf == p->bufLim)\r
+        RangeEnc_FlushStream(p);\r
+      if (--p->cacheSize == 0)\r
+        return;\r
     }\r
-    while (--p->cacheSize != 0);\r
-    p->cache = (Byte)((UInt32)p->low >> 24);\r
   }\r
   p->cacheSize++;\r
-  p->low = (UInt32)p->low << 8;\r
 }\r
 \r
 static void RangeEnc_FlushData(CRangeEnc *p)\r
@@ -584,78 +608,121 @@ static void RangeEnc_FlushData(CRangeEnc *p)
     RangeEnc_ShiftLow(p);\r
 }\r
 \r
-static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)\r
-{\r
-  do\r
-  {\r
-    p->range >>= 1;\r
-    p->low += p->range & (0 - ((value >> --numBits) & 1));\r
-    if (p->range < kTopValue)\r
-    {\r
-      p->range <<= 8;\r
-      RangeEnc_ShiftLow(p);\r
-    }\r
-  }\r
-  while (numBits != 0);\r
-}\r
+#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }\r
 \r
-static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)\r
-{\r
-  UInt32 ttt = *prob;\r
-  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;\r
-  if (symbol == 0)\r
-  {\r
-    p->range = newBound;\r
-    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;\r
-  }\r
-  else\r
-  {\r
-    p->low += newBound;\r
-    p->range -= newBound;\r
-    ttt -= ttt >> kNumMoveBits;\r
+#define RC_BIT_PRE(p, prob) \\r
+  ttt = *(prob); \\r
+  newBound = (range >> kNumBitModelTotalBits) * ttt;\r
+\r
+// #define _LZMA_ENC_USE_BRANCH\r
+\r
+#ifdef _LZMA_ENC_USE_BRANCH\r
+\r
+#define RC_BIT(p, prob, symbol) { \\r
+  RC_BIT_PRE(p, prob) \\r
+  if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \\r
+  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \\r
+  *(prob) = (CLzmaProb)ttt; \\r
+  RC_NORM(p) \\r
   }\r
-  *prob = (CLzmaProb)ttt;\r
-  if (p->range < kTopValue)\r
-  {\r
-    p->range <<= 8;\r
-    RangeEnc_ShiftLow(p);\r
+\r
+#else\r
+\r
+#define RC_BIT(p, prob, symbol) { \\r
+  UInt32 mask; \\r
+  RC_BIT_PRE(p, prob) \\r
+  mask = 0 - (UInt32)symbol; \\r
+  range &= mask; \\r
+  mask &= newBound; \\r
+  range -= mask; \\r
+  (p)->low += mask; \\r
+  mask = (UInt32)symbol - 1; \\r
+  range += newBound & mask; \\r
+  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \\r
+  mask += ((1 << kNumMoveBits) - 1); \\r
+  ttt += (Int32)(mask - ttt) >> kNumMoveBits; \\r
+  *(prob) = (CLzmaProb)ttt; \\r
+  RC_NORM(p) \\r
   }\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+#define RC_BIT_0_BASE(p, prob) \\r
+  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r
+\r
+#define RC_BIT_1_BASE(p, prob) \\r
+  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \\r
+\r
+#define RC_BIT_0(p, prob) \\r
+  RC_BIT_0_BASE(p, prob) \\r
+  RC_NORM(p)\r
+\r
+#define RC_BIT_1(p, prob) \\r
+  RC_BIT_1_BASE(p, prob) \\r
+  RC_NORM(p)\r
+\r
+static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)\r
+{\r
+  UInt32 range, ttt, newBound;\r
+  range = p->range;\r
+  RC_BIT_PRE(p, prob)\r
+  RC_BIT_0(p, prob)\r
+  p->range = range;\r
 }\r
 \r
 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)\r
 {\r
+  UInt32 range = p->range;\r
   symbol |= 0x100;\r
   do\r
   {\r
-    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);\r
+    UInt32 ttt, newBound;\r
+    // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);\r
+    CLzmaProb *prob = probs + (symbol >> 8);\r
+    UInt32 bit = (symbol >> 7) & 1;\r
     symbol <<= 1;\r
+    RC_BIT(p, prob, bit);\r
   }\r
   while (symbol < 0x10000);\r
+  p->range = range;\r
 }\r
 \r
 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)\r
 {\r
+  UInt32 range = p->range;\r
   UInt32 offs = 0x100;\r
   symbol |= 0x100;\r
   do\r
   {\r
+    UInt32 ttt, newBound;\r
+    CLzmaProb *prob;\r
+    UInt32 bit;\r
     matchByte <<= 1;\r
-    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);\r
+    // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);\r
+    prob = probs + (offs + (matchByte & offs) + (symbol >> 8));\r
+    bit = (symbol >> 7) & 1;\r
     symbol <<= 1;\r
     offs &= ~(matchByte ^ symbol);\r
+    RC_BIT(p, prob, bit);\r
   }\r
   while (symbol < 0x10000);\r
+  p->range = range;\r
 }\r
 \r
-static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)\r
+\r
+\r
+static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)\r
 {\r
   UInt32 i;\r
-  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))\r
+  for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)\r
   {\r
-    const int kCyclesBits = kNumBitPriceShiftBits;\r
-    UInt32 w = i;\r
-    UInt32 bitCount = 0;\r
-    int j;\r
+    const unsigned kCyclesBits = kNumBitPriceShiftBits;\r
+    UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));\r
+    unsigned bitCount = 0;\r
+    unsigned j;\r
     for (j = 0; j < kCyclesBits; j++)\r
     {\r
       w = w * w;\r
@@ -666,37 +733,41 @@ static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
         bitCount++;\r
       }\r
     }\r
-    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);\r
+    ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);\r
+    // printf("\n%3d: %5d", i, ProbPrices[i]);\r
   }\r
 }\r
 \r
 \r
 #define GET_PRICE(prob, symbol) \\r
-  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
+  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
 \r
 #define GET_PRICEa(prob, symbol) \\r
-  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
+     ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];\r
 \r
 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]\r
 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\r
 \r
-#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]\r
-#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\r
+#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]\r
+#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\r
+\r
 \r
-static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)\r
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices)\r
 {\r
   UInt32 price = 0;\r
   symbol |= 0x100;\r
   do\r
   {\r
-    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);\r
-    symbol <<= 1;\r
+    unsigned bit = symbol & 1;\r
+    symbol >>= 1;\r
+    price += GET_PRICEa(probs[symbol], bit);\r
   }\r
-  while (symbol < 0x10000);\r
+  while (symbol >= 2);\r
   return price;\r
 }\r
 \r
-static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)\r
+\r
+static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices)\r
 {\r
   UInt32 price = 0;\r
   UInt32 offs = 0x100;\r
@@ -713,520 +784,525 @@ static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt
 }\r
 \r
 \r
-static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\r
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol)\r
 {\r
-  UInt32 m = 1;\r
-  int i;\r
-  for (i = numBitLevels; i != 0;)\r
-  {\r
-    UInt32 bit;\r
-    i--;\r
-    bit = (symbol >> i) & 1;\r
-    RangeEnc_EncodeBit(rc, probs + m, bit);\r
-    m = (m << 1) | bit;\r
-  }\r
-}\r
-\r
-static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)\r
-{\r
-  UInt32 m = 1;\r
-  int i;\r
-  for (i = 0; i < numBitLevels; i++)\r
-  {\r
-    UInt32 bit = symbol & 1;\r
-    RangeEnc_EncodeBit(rc, probs + m, bit);\r
-    m = (m << 1) | bit;\r
-    symbol >>= 1;\r
-  }\r
-}\r
-\r
-static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)\r
-{\r
-  UInt32 price = 0;\r
-  symbol |= (1 << numBitLevels);\r
-  while (symbol != 1)\r
-  {\r
-    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);\r
-    symbol >>= 1;\r
-  }\r
-  return price;\r
-}\r
-\r
-static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)\r
-{\r
-  UInt32 price = 0;\r
-  UInt32 m = 1;\r
-  int i;\r
-  for (i = numBitLevels; i != 0; i--)\r
+  UInt32 range = rc->range;\r
+  unsigned m = 1;\r
+  do\r
   {\r
-    UInt32 bit = symbol & 1;\r
+    UInt32 ttt, newBound;\r
+    unsigned bit = symbol & 1;\r
+    // RangeEnc_EncodeBit(rc, probs + m, bit);\r
     symbol >>= 1;\r
-    price += GET_PRICEa(probs[m], bit);\r
+    RC_BIT(rc, probs + m, bit);\r
     m = (m << 1) | bit;\r
   }\r
-  return price;\r
+  while (--numBits);\r
+  rc->range = range;\r
 }\r
 \r
 \r
+\r
 static void LenEnc_Init(CLenEnc *p)\r
 {\r
   unsigned i;\r
-  p->choice = p->choice2 = kProbInitValue;\r
-  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)\r
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)\r
     p->low[i] = kProbInitValue;\r
-  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)\r
-    p->mid[i] = kProbInitValue;\r
   for (i = 0; i < kLenNumHighSymbols; i++)\r
     p->high[i] = kProbInitValue;\r
 }\r
 \r
-static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)\r
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState)\r
 {\r
-  if (symbol < kLenNumLowSymbols)\r
+  UInt32 range, ttt, newBound;\r
+  CLzmaProb *probs = p->low;\r
+  range = rc->range;\r
+  RC_BIT_PRE(rc, probs);\r
+  if (symbol >= kLenNumLowSymbols)\r
   {\r
-    RangeEnc_EncodeBit(rc, &p->choice, 0);\r
-    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);\r
-  }\r
-  else\r
-  {\r
-    RangeEnc_EncodeBit(rc, &p->choice, 1);\r
-    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)\r
+    RC_BIT_1(rc, probs);\r
+    probs += kLenNumLowSymbols;\r
+    RC_BIT_PRE(rc, probs);\r
+    if (symbol >= kLenNumLowSymbols * 2)\r
     {\r
-      RangeEnc_EncodeBit(rc, &p->choice2, 0);\r
-      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);\r
-    }\r
-    else\r
-    {\r
-      RangeEnc_EncodeBit(rc, &p->choice2, 1);\r
-      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);\r
+      RC_BIT_1(rc, probs);\r
+      rc->range = range;\r
+      // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2);\r
+      LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2);\r
+      return;\r
     }\r
+    symbol -= kLenNumLowSymbols;\r
   }\r
-}\r
 \r
-static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)\r
-{\r
-  UInt32 a0 = GET_PRICE_0a(p->choice);\r
-  UInt32 a1 = GET_PRICE_1a(p->choice);\r
-  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);\r
-  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);\r
-  UInt32 i = 0;\r
-  for (i = 0; i < kLenNumLowSymbols; i++)\r
+  // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol);\r
   {\r
-    if (i >= numSymbols)\r
-      return;\r
-    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);\r
+    unsigned m;\r
+    unsigned bit;\r
+    RC_BIT_0(rc, probs);\r
+    probs += (posState << (1 + kLenNumLowBits));\r
+    bit = (symbol >> 2)    ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;\r
+    bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;\r
+    bit =  symbol       & 1; RC_BIT(rc, probs + m, bit);\r
+    rc->range = range;\r
   }\r
-  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)\r
-  {\r
-    if (i >= numSymbols)\r
-      return;\r
-    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);\r
-  }\r
-  for (; i < numSymbols; i++)\r
-    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);\r
 }\r
 \r
-static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)\r
+static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)\r
 {\r
-  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);\r
-  p->counters[posState] = p->tableSize;\r
+  unsigned i;\r
+  for (i = 0; i < 8; i += 2)\r
+  {\r
+    UInt32 price = startPrice;\r
+    UInt32 prob;\r
+    price += GET_PRICEa(probs[1           ], (i >> 2));\r
+    price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);\r
+    prob = probs[4 + (i >> 1)];\r
+    prices[i    ] = price + GET_PRICEa_0(prob);\r
+    prices[i + 1] = price + GET_PRICEa_1(prob);\r
+  }\r
 }\r
 \r
-static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)\r
+\r
+MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable(\r
+    CLenPriceEnc *p, unsigned posState,\r
+    const CLenEnc *enc,\r
+    const CProbPrice *ProbPrices)\r
 {\r
-  UInt32 posState;\r
-  for (posState = 0; posState < numPosStates; posState++)\r
-    LenPriceEnc_UpdateTable(p, posState, ProbPrices);\r
+  // int y; for (y = 0; y < 100; y++) {\r
+  UInt32 a;\r
+  unsigned i, numSymbols;\r
+\r
+  UInt32 *prices = p->prices[posState];\r
+  {\r
+    const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));\r
+    SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices);\r
+    a = GET_PRICEa_1(enc->low[0]);\r
+    SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices);\r
+    a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);\r
+  }\r
+  numSymbols = p->tableSize;\r
+  p->counters[posState] = numSymbols;\r
+  for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1)\r
+  {\r
+    prices[i] = a +\r
+       // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);\r
+       LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices);\r
+    /*\r
+    unsigned sym = (i - kLenNumLowSymbols * 2) >> 1;\r
+    UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices);\r
+    UInt32 prob = enc->high[(1 << 7) + sym];\r
+    prices[i    ] = price + GET_PRICEa_0(prob);\r
+    prices[i + 1] = price + GET_PRICEa_1(prob);\r
+    */\r
+  }\r
+  // }\r
 }\r
 \r
-static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)\r
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,\r
+    const CLenEnc *enc,\r
+    const CProbPrice *ProbPrices)\r
 {\r
-  LenEnc_Encode(&p->p, rc, symbol, posState);\r
-  if (updatePrice)\r
-    if (--p->counters[posState] == 0)\r
-      LenPriceEnc_UpdateTable(p, posState, ProbPrices);\r
+  unsigned posState;\r
+  for (posState = 0; posState < numPosStates; posState++)\r
+    LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices);\r
 }\r
 \r
 \r
-\r
-\r
-static void MovePos(CLzmaEnc *p, UInt32 num)\r
-{\r
+/*\r
   #ifdef SHOW_STAT\r
   g_STAT_OFFSET += num;\r
   printf("\n MovePos %u", num);\r
   #endif\r
+*/\r
   \r
-  if (num != 0)\r
-  {\r
-    p->additionalOffset += num;\r
-    p->matchFinder.Skip(p->matchFinderObj, num);\r
-  }\r
-}\r
+#define MOVE_POS(p, num) { \\r
+    p->additionalOffset += (num); \\r
+    p->matchFinder.Skip(p->matchFinderObj, (num)); }\r
+\r
 \r
-static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)\r
+static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)\r
 {\r
-  UInt32 lenRes = 0, numPairs;\r
+  unsigned numPairs;\r
+  \r
+  p->additionalOffset++;\r
   p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\r
   numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);\r
+  *numPairsRes = numPairs;\r
   \r
   #ifdef SHOW_STAT\r
   printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);\r
   g_STAT_OFFSET++;\r
   {\r
-    UInt32 i;\r
+    unsigned i;\r
     for (i = 0; i < numPairs; i += 2)\r
       printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);\r
   }\r
   #endif\r
   \r
-  if (numPairs > 0)\r
+  if (numPairs == 0)\r
+    return 0;\r
   {\r
-    lenRes = p->matches[numPairs - 2];\r
-    if (lenRes == p->numFastBytes)\r
+    unsigned len = p->matches[(size_t)numPairs - 2];\r
+    if (len != p->numFastBytes)\r
+      return len;\r
     {\r
       UInt32 numAvail = p->numAvail;\r
       if (numAvail > LZMA_MATCH_LEN_MAX)\r
         numAvail = LZMA_MATCH_LEN_MAX;\r
       {\r
-        const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
-        const Byte *pby = pbyCur + lenRes;\r
-        ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];\r
-        const Byte *pbyLim = pbyCur + numAvail;\r
-        for (; pby != pbyLim && *pby == pby[dif]; pby++);\r
-        lenRes = (UInt32)(pby - pbyCur);\r
+        const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+        const Byte *p2 = p1 + len;\r
+        ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];\r
+        const Byte *lim = p1 + numAvail;\r
+        for (; p2 != lim && *p2 == p2[dif]; p2++);\r
+        return (unsigned)(p2 - p1);\r
       }\r
     }\r
   }\r
-  p->additionalOffset++;\r
-  *numDistancePairsRes = numPairs;\r
-  return lenRes;\r
 }\r
 \r
+#define MARK_LIT ((UInt32)(Int32)-1)\r
 \r
-#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;\r
-#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;\r
-#define IsShortRep(p) ((p)->backPrev == 0)\r
+#define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }\r
+#define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }\r
+#define IsShortRep(p)       ((p)->dist == 0)\r
 \r
-static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)\r
-{\r
-  return\r
-    GET_PRICE_0(p->isRepG0[state]) +\r
-    GET_PRICE_0(p->isRep0Long[state][posState]);\r
-}\r
 \r
-static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)\r
+#define GetPrice_ShortRep(p, state, posState) \\r
+  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))\r
+\r
+#define GetPrice_Rep_0(p, state, posState) ( \\r
+    GET_PRICE_1(p->isMatch[state][posState]) \\r
+  + GET_PRICE_1(p->isRep0Long[state][posState])) \\r
+  + GET_PRICE_1(p->isRep[state]) \\r
+  + GET_PRICE_0(p->isRepG0[state])\r
+  \r
+\r
+static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)\r
 {\r
   UInt32 price;\r
+  UInt32 prob = p->isRepG0[state];\r
   if (repIndex == 0)\r
   {\r
-    price = GET_PRICE_0(p->isRepG0[state]);\r
+    price = GET_PRICE_0(prob);\r
     price += GET_PRICE_1(p->isRep0Long[state][posState]);\r
   }\r
   else\r
   {\r
-    price = GET_PRICE_1(p->isRepG0[state]);\r
+    price = GET_PRICE_1(prob);\r
+    prob = p->isRepG1[state];\r
     if (repIndex == 1)\r
-      price += GET_PRICE_0(p->isRepG1[state]);\r
+      price += GET_PRICE_0(prob);\r
     else\r
     {\r
-      price += GET_PRICE_1(p->isRepG1[state]);\r
+      price += GET_PRICE_1(prob);\r
       price += GET_PRICE(p->isRepG2[state], repIndex - 2);\r
     }\r
   }\r
   return price;\r
 }\r
 \r
-static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)\r
-{\r
-  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +\r
-    GetPureRepPrice(p, repIndex, state, posState);\r
-}\r
 \r
-static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)\r
+static unsigned Backward(CLzmaEnc *p, unsigned cur)\r
 {\r
-  UInt32 posMem = p->opt[cur].posPrev;\r
-  UInt32 backMem = p->opt[cur].backPrev;\r
-  p->optimumEndIndex = cur;\r
-  do\r
+  unsigned wr = cur + 1;\r
+  p->optEnd = wr;\r
+\r
+  for (;;)\r
   {\r
-    if (p->opt[cur].prev1IsChar)\r
+    UInt32 dist = p->opt[cur].dist;\r
+    UInt32 len = p->opt[cur].len;\r
+    UInt32 extra = p->opt[cur].extra;\r
+    cur -= len;\r
+\r
+    if (extra)\r
     {\r
-      MakeAsChar(&p->opt[posMem])\r
-      p->opt[posMem].posPrev = posMem - 1;\r
-      if (p->opt[cur].prev2)\r
+      wr--;\r
+      p->opt[wr].len = len;\r
+      cur -= extra;\r
+      len = extra;\r
+      if (extra == 1)\r
+      {\r
+        p->opt[wr].dist = dist;\r
+        dist = MARK_LIT;\r
+      }\r
+      else\r
       {\r
-        p->opt[posMem - 1].prev1IsChar = False;\r
-        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;\r
-        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;\r
+        p->opt[wr].dist = 0;\r
+        len--;\r
+        wr--;\r
+        p->opt[wr].dist = MARK_LIT;\r
+        p->opt[wr].len = 1;\r
       }\r
     }\r
+\r
+    if (cur == 0)\r
     {\r
-      UInt32 posPrev = posMem;\r
-      UInt32 backCur = backMem;\r
-      \r
-      backMem = p->opt[posPrev].backPrev;\r
-      posMem = p->opt[posPrev].posPrev;\r
-      \r
-      p->opt[posPrev].backPrev = backCur;\r
-      p->opt[posPrev].posPrev = cur;\r
-      cur = posPrev;\r
+      p->backRes = dist;\r
+      p->optCur = wr;\r
+      return len;\r
     }\r
+    \r
+    wr--;\r
+    p->opt[wr].dist = dist;\r
+    p->opt[wr].len = len;\r
   }\r
-  while (cur != 0);\r
-  *backRes = p->opt[0].backPrev;\r
-  p->optimumCurrentIndex  = p->opt[0].posPrev;\r
-  return p->optimumCurrentIndex;\r
 }\r
 \r
-#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)\r
 \r
-static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)\r
-{\r
-  UInt32 lenEnd, cur;\r
-  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];\r
-  UInt32 *matches;\r
 \r
-  {\r
+#define LIT_PROBS(pos, prevByte) \\r
+  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))\r
 \r
-  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, len;\r
-  UInt32 matchPrice, repMatchPrice, normalMatchPrice;\r
-  const Byte *data;\r
-  Byte curByte, matchByte;\r
 \r
-  if (p->optimumEndIndex != p->optimumCurrentIndex)\r
-  {\r
-    const COptimal *opt = &p->opt[p->optimumCurrentIndex];\r
-    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;\r
-    *backRes = opt->backPrev;\r
-    p->optimumCurrentIndex = opt->posPrev;\r
-    return lenRes;\r
-  }\r
-  p->optimumCurrentIndex = p->optimumEndIndex = 0;\r
-  \r
-  if (p->additionalOffset == 0)\r
-    mainLen = ReadMatchDistances(p, &numPairs);\r
-  else\r
-  {\r
-    mainLen = p->longestMatchLength;\r
-    numPairs = p->numPairs;\r
-  }\r
-\r
-  numAvail = p->numAvail;\r
-  if (numAvail < 2)\r
-  {\r
-    *backRes = (UInt32)(-1);\r
-    return 1;\r
-  }\r
-  if (numAvail > LZMA_MATCH_LEN_MAX)\r
-    numAvail = LZMA_MATCH_LEN_MAX;\r
+static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)\r
+{\r
+  unsigned last, cur;\r
+  UInt32 reps[LZMA_NUM_REPS];\r
+  unsigned repLens[LZMA_NUM_REPS];\r
+  UInt32 *matches;\r
 \r
-  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
-  repMaxIndex = 0;\r
-  for (i = 0; i < LZMA_NUM_REPS; i++)\r
   {\r
-    UInt32 lenTest;\r
-    const Byte *data2;\r
-    reps[i] = p->reps[i];\r
-    data2 = data - reps[i] - 1;\r
-    if (data[0] != data2[0] || data[1] != data2[1])\r
+    UInt32 numAvail;\r
+    unsigned numPairs, mainLen, repMaxIndex, i, posState;\r
+    UInt32 matchPrice, repMatchPrice;\r
+    const Byte *data;\r
+    Byte curByte, matchByte;\r
+    \r
+    p->optCur = p->optEnd = 0;\r
+    \r
+    if (p->additionalOffset == 0)\r
+      mainLen = ReadMatchDistances(p, &numPairs);\r
+    else\r
     {\r
-      repLens[i] = 0;\r
-      continue;\r
+      mainLen = p->longestMatchLen;\r
+      numPairs = p->numPairs;\r
     }\r
-    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\r
-    repLens[i] = lenTest;\r
-    if (lenTest > repLens[repMaxIndex])\r
-      repMaxIndex = i;\r
-  }\r
-  if (repLens[repMaxIndex] >= p->numFastBytes)\r
-  {\r
-    UInt32 lenRes;\r
-    *backRes = repMaxIndex;\r
-    lenRes = repLens[repMaxIndex];\r
-    MovePos(p, lenRes - 1);\r
-    return lenRes;\r
-  }\r
-\r
-  matches = p->matches;\r
-  if (mainLen >= p->numFastBytes)\r
-  {\r
-    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\r
-    MovePos(p, mainLen - 1);\r
-    return mainLen;\r
-  }\r
-  curByte = *data;\r
-  matchByte = *(data - (reps[0] + 1));\r
-\r
-  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)\r
-  {\r
-    *backRes = (UInt32)-1;\r
-    return 1;\r
-  }\r
-\r
-  p->opt[0].state = (CState)p->state;\r
-\r
-  posState = (position & p->pbMask);\r
-\r
-  {\r
-    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
-    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +\r
-        (!IsCharState(p->state) ?\r
-          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\r
-          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
-  }\r
-\r
-  MakeAsChar(&p->opt[1]);\r
-\r
-  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);\r
-  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);\r
-\r
-  if (matchByte == curByte)\r
-  {\r
-    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);\r
-    if (shortRepPrice < p->opt[1].price)\r
+    \r
+    numAvail = p->numAvail;\r
+    if (numAvail < 2)\r
     {\r
-      p->opt[1].price = shortRepPrice;\r
-      MakeAsShortRep(&p->opt[1]);\r
+      p->backRes = MARK_LIT;\r
+      return 1;\r
     }\r
-  }\r
-  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);\r
-\r
-  if (lenEnd < 2)\r
-  {\r
-    *backRes = p->opt[1].backPrev;\r
-    return 1;\r
-  }\r
-\r
-  p->opt[1].posPrev = 0;\r
-  for (i = 0; i < LZMA_NUM_REPS; i++)\r
-    p->opt[0].backs[i] = reps[i];\r
-\r
-  len = lenEnd;\r
-  do\r
-    p->opt[len--].price = kInfinityPrice;\r
-  while (len >= 2);\r
-\r
-  for (i = 0; i < LZMA_NUM_REPS; i++)\r
-  {\r
-    UInt32 repLen = repLens[i];\r
-    UInt32 price;\r
-    if (repLen < 2)\r
-      continue;\r
-    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);\r
-    do\r
+    if (numAvail > LZMA_MATCH_LEN_MAX)\r
+      numAvail = LZMA_MATCH_LEN_MAX;\r
+    \r
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+    repMaxIndex = 0;\r
+    \r
+    for (i = 0; i < LZMA_NUM_REPS; i++)\r
     {\r
-      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];\r
-      COptimal *opt = &p->opt[repLen];\r
-      if (curAndLenPrice < opt->price)\r
+      unsigned len;\r
+      const Byte *data2;\r
+      reps[i] = p->reps[i];\r
+      data2 = data - reps[i];\r
+      if (data[0] != data2[0] || data[1] != data2[1])\r
       {\r
-        opt->price = curAndLenPrice;\r
-        opt->posPrev = 0;\r
-        opt->backPrev = i;\r
-        opt->prev1IsChar = False;\r
+        repLens[i] = 0;\r
+        continue;\r
       }\r
+      for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
+      repLens[i] = len;\r
+      if (len > repLens[repMaxIndex])\r
+        repMaxIndex = i;\r
     }\r
-    while (--repLen >= 2);\r
-  }\r
-\r
-  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);\r
-\r
-  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\r
-  if (len <= mainLen)\r
-  {\r
-    UInt32 offs = 0;\r
-    while (len > matches[offs])\r
-      offs += 2;\r
-    for (; ; len++)\r
+    \r
+    if (repLens[repMaxIndex] >= p->numFastBytes)\r
     {\r
-      COptimal *opt;\r
-      UInt32 distance = matches[offs + 1];\r
-\r
-      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];\r
-      UInt32 lenToPosState = GetLenToPosState(len);\r
-      if (distance < kNumFullDistances)\r
-        curAndLenPrice += p->distancesPrices[lenToPosState][distance];\r
-      else\r
+      unsigned len;\r
+      p->backRes = repMaxIndex;\r
+      len = repLens[repMaxIndex];\r
+      MOVE_POS(p, len - 1)\r
+      return len;\r
+    }\r
+    \r
+    matches = p->matches;\r
+    \r
+    if (mainLen >= p->numFastBytes)\r
+    {\r
+      p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;\r
+      MOVE_POS(p, mainLen - 1)\r
+      return mainLen;\r
+    }\r
+    \r
+    curByte = *data;\r
+    matchByte = *(data - reps[0]);\r
+    \r
+    if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)\r
+    {\r
+      p->backRes = MARK_LIT;\r
+      return 1;\r
+    }\r
+    \r
+    p->opt[0].state = (CState)p->state;\r
+    \r
+    posState = (position & p->pbMask);\r
+    \r
+    {\r
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
+      p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +\r
+        (!IsLitState(p->state) ?\r
+          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :\r
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
+    }\r
+    \r
+    MakeAs_Lit(&p->opt[1]);\r
+    \r
+    matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);\r
+    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);\r
+    \r
+    if (matchByte == curByte)\r
+    {\r
+      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);\r
+      if (shortRepPrice < p->opt[1].price)\r
       {\r
-        UInt32 slot;\r
-        GetPosSlot2(distance, slot);\r
-        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];\r
+        p->opt[1].price = shortRepPrice;\r
+        MakeAs_ShortRep(&p->opt[1]);\r
       }\r
-      opt = &p->opt[len];\r
-      if (curAndLenPrice < opt->price)\r
+    }\r
+    \r
+    last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]);\r
+    \r
+    if (last < 2)\r
+    {\r
+      p->backRes = p->opt[1].dist;\r
+      return 1;\r
+    }\r
+    \r
+    p->opt[1].len = 1;\r
+    \r
+    p->opt[0].reps[0] = reps[0];\r
+    p->opt[0].reps[1] = reps[1];\r
+    p->opt[0].reps[2] = reps[2];\r
+    p->opt[0].reps[3] = reps[3];\r
+    \r
+    {\r
+      unsigned len = last;\r
+      do\r
+        p->opt[len--].price = kInfinityPrice;\r
+      while (len >= 2);\r
+    }\r
+\r
+    // ---------- REP ----------\r
+    \r
+    for (i = 0; i < LZMA_NUM_REPS; i++)\r
+    {\r
+      unsigned repLen = repLens[i];\r
+      UInt32 price;\r
+      if (repLen < 2)\r
+        continue;\r
+      price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);\r
+      do\r
       {\r
-        opt->price = curAndLenPrice;\r
-        opt->posPrev = 0;\r
-        opt->backPrev = distance + LZMA_NUM_REPS;\r
-        opt->prev1IsChar = False;\r
+        UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2];\r
+        COptimal *opt = &p->opt[repLen];\r
+        if (price2 < opt->price)\r
+        {\r
+          opt->price = price2;\r
+          opt->len = repLen;\r
+          opt->dist = i;\r
+          opt->extra = 0;\r
+        }\r
       }\r
-      if (len == matches[offs])\r
+      while (--repLen >= 2);\r
+    }\r
+    \r
+    \r
+    // ---------- MATCH ----------\r
+    {\r
+      unsigned len  = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\r
+      if (len <= mainLen)\r
       {\r
-        offs += 2;\r
-        if (offs == numPairs)\r
-          break;\r
+        unsigned offs = 0;\r
+        UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);\r
+\r
+        while (len > matches[offs])\r
+          offs += 2;\r
+    \r
+        for (; ; len++)\r
+        {\r
+          COptimal *opt;\r
+          UInt32 dist = matches[(size_t)offs + 1];\r
+          UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];\r
+          unsigned lenToPosState = GetLenToPosState(len);\r
+       \r
+          if (dist < kNumFullDistances)\r
+            price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];\r
+          else\r
+          {\r
+            unsigned slot;\r
+            GetPosSlot2(dist, slot);\r
+            price2 += p->alignPrices[dist & kAlignMask];\r
+            price2 += p->posSlotPrices[lenToPosState][slot];\r
+          }\r
+          \r
+          opt = &p->opt[len];\r
+          \r
+          if (price2 < opt->price)\r
+          {\r
+            opt->price = price2;\r
+            opt->len = len;\r
+            opt->dist = dist + LZMA_NUM_REPS;\r
+            opt->extra = 0;\r
+          }\r
+          \r
+          if (len == matches[offs])\r
+          {\r
+            offs += 2;\r
+            if (offs == numPairs)\r
+              break;\r
+          }\r
+        }\r
       }\r
     }\r
-  }\r
+    \r
 \r
-  cur = 0;\r
+    cur = 0;\r
 \r
     #ifdef SHOW_STAT2\r
     /* if (position >= 0) */\r
     {\r
       unsigned i;\r
       printf("\n pos = %4X", position);\r
-      for (i = cur; i <= lenEnd; i++)\r
+      for (i = cur; i <= last; i++)\r
       printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);\r
     }\r
     #endif\r
+  }\r
+\r
 \r
-  }\r
+  \r
+  // ---------- Optimal Parsing ----------\r
 \r
   for (;;)\r
   {\r
-    UInt32 numAvail;\r
-    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;\r
-    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;\r
-    Bool nextIsChar;\r
+    UInt32 numAvail, numAvailFull;\r
+    unsigned newLen, numPairs, prev, state, posState, startLen;\r
+    UInt32 curPrice, litPrice, matchPrice, repMatchPrice;\r
+    Bool nextIsLit;\r
     Byte curByte, matchByte;\r
     const Byte *data;\r
-    COptimal *curOpt;\r
-    COptimal *nextOpt;\r
+    COptimal *curOpt, *nextOpt;\r
 \r
-    cur++;\r
-    if (cur == lenEnd)\r
-      return Backward(p, backRes, cur);\r
+    if (++cur == last)\r
+      return Backward(p, cur);\r
 \r
     newLen = ReadMatchDistances(p, &numPairs);\r
+    \r
     if (newLen >= p->numFastBytes)\r
     {\r
       p->numPairs = numPairs;\r
-      p->longestMatchLength = newLen;\r
-      return Backward(p, backRes, cur);\r
+      p->longestMatchLen = newLen;\r
+      return Backward(p, cur);\r
     }\r
-    position++;\r
+    \r
     curOpt = &p->opt[cur];\r
-    posPrev = curOpt->posPrev;\r
-    if (curOpt->prev1IsChar)\r
-    {\r
-      posPrev--;\r
-      if (curOpt->prev2)\r
-      {\r
-        state = p->opt[curOpt->posPrev2].state;\r
-        if (curOpt->backPrev2 < LZMA_NUM_REPS)\r
-          state = kRepNextStates[state];\r
-        else\r
-          state = kMatchNextStates[state];\r
-      }\r
-      else\r
-        state = p->opt[posPrev].state;\r
-      state = kLiteralNextStates[state];\r
-    }\r
-    else\r
-      state = p->opt[posPrev].state;\r
-    if (posPrev == cur - 1)\r
+    prev = cur - curOpt->len;\r
+    \r
+    if (curOpt->len == 1)\r
     {\r
+      state = p->opt[prev].state;\r
       if (IsShortRep(curOpt))\r
         state = kShortRepNextStates[state];\r
       else\r
@@ -1234,92 +1310,136 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
     }\r
     else\r
     {\r
-      UInt32 pos;\r
       const COptimal *prevOpt;\r
-      if (curOpt->prev1IsChar && curOpt->prev2)\r
+      UInt32 b0;\r
+      UInt32 dist = curOpt->dist;\r
+\r
+      if (curOpt->extra)\r
       {\r
-        posPrev = curOpt->posPrev2;\r
-        pos = curOpt->backPrev2;\r
-        state = kRepNextStates[state];\r
+        prev -= curOpt->extra;\r
+        state = kState_RepAfterLit;\r
+        if (curOpt->extra == 1)\r
+          state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit;\r
       }\r
       else\r
       {\r
-        pos = curOpt->backPrev;\r
-        if (pos < LZMA_NUM_REPS)\r
+        state = p->opt[prev].state;\r
+        if (dist < LZMA_NUM_REPS)\r
           state = kRepNextStates[state];\r
         else\r
           state = kMatchNextStates[state];\r
       }\r
-      prevOpt = &p->opt[posPrev];\r
-      if (pos < LZMA_NUM_REPS)\r
+\r
+      prevOpt = &p->opt[prev];\r
+      b0 = prevOpt->reps[0];\r
+\r
+      if (dist < LZMA_NUM_REPS)\r
       {\r
-        UInt32 i;\r
-        reps[0] = prevOpt->backs[pos];\r
-        for (i = 1; i <= pos; i++)\r
-          reps[i] = prevOpt->backs[i - 1];\r
-        for (; i < LZMA_NUM_REPS; i++)\r
-          reps[i] = prevOpt->backs[i];\r
+        if (dist == 0)\r
+        {\r
+          reps[0] = b0;\r
+          reps[1] = prevOpt->reps[1];\r
+          reps[2] = prevOpt->reps[2];\r
+          reps[3] = prevOpt->reps[3];\r
+        }\r
+        else\r
+        {\r
+          reps[1] = b0;\r
+          b0 = prevOpt->reps[1];\r
+          if (dist == 1)\r
+          {\r
+            reps[0] = b0;\r
+            reps[2] = prevOpt->reps[2];\r
+            reps[3] = prevOpt->reps[3];\r
+          }\r
+          else\r
+          {\r
+            reps[2] = b0;\r
+            reps[0] = prevOpt->reps[dist];\r
+            reps[3] = prevOpt->reps[dist ^ 1];\r
+          }\r
+        }\r
       }\r
       else\r
       {\r
-        UInt32 i;\r
-        reps[0] = (pos - LZMA_NUM_REPS);\r
-        for (i = 1; i < LZMA_NUM_REPS; i++)\r
-          reps[i] = prevOpt->backs[i - 1];\r
+        reps[0] = (dist - LZMA_NUM_REPS + 1);\r
+        reps[1] = b0;\r
+        reps[2] = prevOpt->reps[1];\r
+        reps[3] = prevOpt->reps[2];\r
       }\r
     }\r
+    \r
     curOpt->state = (CState)state;\r
+    curOpt->reps[0] = reps[0];\r
+    curOpt->reps[1] = reps[1];\r
+    curOpt->reps[2] = reps[2];\r
+    curOpt->reps[3] = reps[3];\r
 \r
-    curOpt->backs[0] = reps[0];\r
-    curOpt->backs[1] = reps[1];\r
-    curOpt->backs[2] = reps[2];\r
-    curOpt->backs[3] = reps[3];\r
-\r
-    curPrice = curOpt->price;\r
-    nextIsChar = False;\r
     data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
     curByte = *data;\r
-    matchByte = *(data - (reps[0] + 1));\r
+    matchByte = *(data - reps[0]);\r
 \r
+    position++;\r
     posState = (position & p->pbMask);\r
 \r
-    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);\r
-    {\r
-      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
-      curAnd1Price +=\r
-        (!IsCharState(state) ?\r
-          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :\r
-          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
-    }\r
+    /*\r
+    The order of Price checks:\r
+       <  LIT\r
+       <= SHORT_REP\r
+       <  LIT : REP_0\r
+       <  REP    [ : LIT : REP_0 ]\r
+       <  MATCH  [ : LIT : REP_0 ]\r
+    */\r
+\r
+    curPrice = curOpt->price;\r
+    litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]);\r
 \r
-    nextOpt = &p->opt[cur + 1];\r
+    nextOpt = &p->opt[(size_t)cur + 1];\r
+    nextIsLit = False;\r
 \r
-    if (curAnd1Price < nextOpt->price)\r
+    // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new\r
     {\r
-      nextOpt->price = curAnd1Price;\r
-      nextOpt->posPrev = cur;\r
-      MakeAsChar(nextOpt);\r
-      nextIsChar = True;\r
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\r
+      litPrice += (!IsLitState(state) ?\r
+          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :\r
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\r
+      \r
+      if (litPrice < nextOpt->price)\r
+      {\r
+        nextOpt->price = litPrice;\r
+        nextOpt->len = 1;\r
+        MakeAs_Lit(nextOpt);\r
+        nextIsLit = True;\r
+      }\r
     }\r
 \r
     matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);\r
     repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);\r
     \r
-    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))\r
+    // ---------- SHORT_REP ----------\r
+    // if (IsLitState(state)) // 18.new\r
+    if (matchByte == curByte)\r
+    // if (repMatchPrice < nextOpt->price) // 18.new\r
+    if (nextOpt->len < 2\r
+        || (nextOpt->dist != 0\r
+            && nextOpt->extra <= 1 // 17.old\r
+        ))\r
     {\r
-      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);\r
-      if (shortRepPrice <= nextOpt->price)\r
+      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);\r
+      if (shortRepPrice <= nextOpt->price) // 17.old\r
+      // if (shortRepPrice < nextOpt->price)  // 18.new\r
       {\r
         nextOpt->price = shortRepPrice;\r
-        nextOpt->posPrev = cur;\r
-        MakeAsShortRep(nextOpt);\r
-        nextIsChar = True;\r
+        nextOpt->len = 1;\r
+        MakeAs_ShortRep(nextOpt);\r
+        nextIsLit = False;\r
       }\r
     }\r
+    \r
     numAvailFull = p->numAvail;\r
     {\r
       UInt32 temp = kNumOpts - 1 - cur;\r
-      if (temp < numAvailFull)\r
+      if (numAvailFull > temp)\r
         numAvailFull = temp;\r
     }\r
 \r
@@ -1327,41 +1447,53 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
       continue;\r
     numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);\r
 \r
-    if (!nextIsChar && matchByte != curByte) /* speed optimization */\r
+    // numAvail <= p->numFastBytes\r
+\r
+    // ---------- LIT : REP_0 ----------\r
+\r
+    if (\r
+        // litPrice != 0 && // 18.new\r
+        !nextIsLit\r
+        && matchByte != curByte\r
+        && numAvailFull > 2)\r
     {\r
-      /* try Literal + rep0 */\r
-      UInt32 temp;\r
-      UInt32 lenTest2;\r
-      const Byte *data2 = data - reps[0] - 1;\r
-      UInt32 limit = p->numFastBytes + 1;\r
-      if (limit > numAvailFull)\r
-        limit = numAvailFull;\r
-\r
-      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);\r
-      lenTest2 = temp - 1;\r
-      if (lenTest2 >= 2)\r
+      const Byte *data2 = data - reps[0];\r
+      if (data[1] == data2[1] && data[2] == data2[2])\r
       {\r
-        UInt32 state2 = kLiteralNextStates[state];\r
-        UInt32 posStateNext = (position + 1) & p->pbMask;\r
-        UInt32 nextRepMatchPrice = curAnd1Price +\r
-            GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
-            GET_PRICE_1(p->isRep[state2]);\r
-        /* for (; lenTest2 >= 2; lenTest2--) */\r
+        unsigned len;\r
+        unsigned limit = p->numFastBytes + 1;\r
+        if (limit > numAvailFull)\r
+          limit = numAvailFull;\r
+        for (len = 3; len < limit && data[len] == data2[len]; len++);\r
+        \r
         {\r
-          UInt32 curAndLenPrice;\r
-          COptimal *opt;\r
-          UInt32 offset = cur + 1 + lenTest2;\r
-          while (lenEnd < offset)\r
-            p->opt[++lenEnd].price = kInfinityPrice;\r
-          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
-          opt = &p->opt[offset];\r
-          if (curAndLenPrice < opt->price)\r
+          unsigned state2 = kLiteralNextStates[state];\r
+          unsigned posState2 = (position + 1) & p->pbMask;\r
+          UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);\r
           {\r
-            opt->price = curAndLenPrice;\r
-            opt->posPrev = cur + 1;\r
-            opt->backPrev = 0;\r
-            opt->prev1IsChar = True;\r
-            opt->prev2 = False;\r
+            unsigned offset = cur + len;\r
+            while (last < offset)\r
+              p->opt[++last].price = kInfinityPrice;\r
+          \r
+            // do\r
+            {\r
+              UInt32 price2;\r
+              COptimal *opt;\r
+              len--;\r
+              // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);\r
+              price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];\r
+\r
+              opt = &p->opt[offset];\r
+              // offset--;\r
+              if (price2 < opt->price)\r
+              {\r
+                opt->price = price2;\r
+                opt->len = len;\r
+                opt->dist = 0;\r
+                opt->extra = 1;\r
+              }\r
+            }\r
+            // while (len >= 3);\r
           }\r
         }\r
       }\r
@@ -1369,87 +1501,105 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
     \r
     startLen = 2; /* speed optimization */\r
     {\r
-    UInt32 repIndex;\r
-    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)\r
-    {\r
-      UInt32 lenTest;\r
-      UInt32 lenTestTemp;\r
-      UInt32 price;\r
-      const Byte *data2 = data - reps[repIndex] - 1;\r
-      if (data[0] != data2[0] || data[1] != data2[1])\r
-        continue;\r
-      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);\r
-      while (lenEnd < cur + lenTest)\r
-        p->opt[++lenEnd].price = kInfinityPrice;\r
-      lenTestTemp = lenTest;\r
-      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);\r
-      do\r
+      // ---------- REP ----------\r
+      unsigned repIndex = 0; // 17.old\r
+      // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused\r
+      for (; repIndex < LZMA_NUM_REPS; repIndex++)\r
       {\r
-        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];\r
-        COptimal *opt = &p->opt[cur + lenTest];\r
-        if (curAndLenPrice < opt->price)\r
+        unsigned len;\r
+        UInt32 price;\r
+        const Byte *data2 = data - reps[repIndex];\r
+        if (data[0] != data2[0] || data[1] != data2[1])\r
+          continue;\r
+        \r
+        for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
+        \r
+        // if (len < startLen) continue; // 18.new: speed optimization\r
+\r
+        while (last < cur + len)\r
+          p->opt[++last].price = kInfinityPrice;\r
         {\r
-          opt->price = curAndLenPrice;\r
-          opt->posPrev = cur;\r
-          opt->backPrev = repIndex;\r
-          opt->prev1IsChar = False;\r
+          unsigned len2 = len;\r
+          price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);\r
+          do\r
+          {\r
+            UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];\r
+            COptimal *opt = &p->opt[cur + len2];\r
+            if (price2 < opt->price)\r
+            {\r
+              opt->price = price2;\r
+              opt->len = len2;\r
+              opt->dist = repIndex;\r
+              opt->extra = 0;\r
+            }\r
+          }\r
+          while (--len2 >= 2);\r
         }\r
-      }\r
-      while (--lenTest >= 2);\r
-      lenTest = lenTestTemp;\r
-      \r
-      if (repIndex == 0)\r
-        startLen = lenTest + 1;\r
         \r
-      /* if (_maxMode) */\r
+        if (repIndex == 0) startLen = len + 1;  // 17.old\r
+        // startLen = len + 1; // 18.new\r
+\r
+        /* if (_maxMode) */\r
         {\r
-          UInt32 lenTest2 = lenTest + 1;\r
-          UInt32 limit = lenTest2 + p->numFastBytes;\r
+          // ---------- REP : LIT : REP_0 ----------\r
+          // numFastBytes + 1 + numFastBytes\r
+\r
+          unsigned len2 = len + 1;\r
+          unsigned limit = len2 + p->numFastBytes;\r
           if (limit > numAvailFull)\r
             limit = numAvailFull;\r
-          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\r
-          lenTest2 -= lenTest + 1;\r
-          if (lenTest2 >= 2)\r
+          \r
+          for (; len2 < limit && data[len2] == data2[len2]; len2++);\r
+          \r
+          len2 -= len;\r
+          if (len2 >= 3)\r
           {\r
-            UInt32 nextRepMatchPrice;\r
-            UInt32 state2 = kRepNextStates[state];\r
-            UInt32 posStateNext = (position + lenTest) & p->pbMask;\r
-            UInt32 curAndLenCharPrice =\r
-                price + p->repLenEnc.prices[posState][lenTest - 2] +\r
-                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\r
-                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\r
-                    data[lenTest], data2[lenTest], p->ProbPrices);\r
-            state2 = kLiteralNextStates[state2];\r
-            posStateNext = (position + lenTest + 1) & p->pbMask;\r
-            nextRepMatchPrice = curAndLenCharPrice +\r
-                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
-                GET_PRICE_1(p->isRep[state2]);\r
+            unsigned state2 = kRepNextStates[state];\r
+            unsigned posState2 = (position + len) & p->pbMask;\r
+            price +=\r
+                  p->repLenEnc.prices[posState][(size_t)len - 2]\r
+                + GET_PRICE_0(p->isMatch[state2][posState2])\r
+                + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\r
+                    data[len], data2[len], p->ProbPrices);\r
             \r
-            /* for (; lenTest2 >= 2; lenTest2--) */\r
+            // state2 = kLiteralNextStates[state2];\r
+            state2 = kState_LitAfterRep;\r
+            posState2 = (posState2 + 1) & p->pbMask;\r
+\r
+\r
+            price += GetPrice_Rep_0(p, state2, posState2);\r
             {\r
-              UInt32 curAndLenPrice;\r
-              COptimal *opt;\r
-              UInt32 offset = cur + lenTest + 1 + lenTest2;\r
-              while (lenEnd < offset)\r
-                p->opt[++lenEnd].price = kInfinityPrice;\r
-              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
-              opt = &p->opt[offset];\r
-              if (curAndLenPrice < opt->price)\r
+              unsigned offset = cur + len + len2;\r
+              while (last < offset)\r
+                p->opt[++last].price = kInfinityPrice;\r
+              // do\r
               {\r
-                opt->price = curAndLenPrice;\r
-                opt->posPrev = cur + lenTest + 1;\r
-                opt->backPrev = 0;\r
-                opt->prev1IsChar = True;\r
-                opt->prev2 = True;\r
-                opt->posPrev2 = cur;\r
-                opt->backPrev2 = repIndex;\r
+                unsigned price2;\r
+                COptimal *opt;\r
+                len2--;\r
+                // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\r
+                price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];\r
+\r
+                opt = &p->opt[offset];\r
+                // offset--;\r
+                if (price2 < opt->price)\r
+                {\r
+                  opt->price = price2;\r
+                  opt->len = len2;\r
+                  opt->extra = (CExtra)(len + 1);\r
+                  opt->dist = repIndex;\r
+                }\r
               }\r
+              // while (len2 >= 3);\r
             }\r
           }\r
         }\r
+      }\r
     }\r
-    }\r
-    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */\r
+\r
+\r
+    // ---------- MATCH ----------\r
+    /* for (unsigned len = 2; len <= newLen; len++) */\r
     if (newLen > numAvail)\r
     {\r
       newLen = numAvail;\r
@@ -1457,134 +1607,148 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
       matches[numPairs] = newLen;\r
       numPairs += 2;\r
     }\r
+    \r
     if (newLen >= startLen)\r
     {\r
       UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);\r
-      UInt32 offs, curBack, posSlot;\r
-      UInt32 lenTest;\r
-      while (lenEnd < cur + newLen)\r
-        p->opt[++lenEnd].price = kInfinityPrice;\r
+      UInt32 dist;\r
+      unsigned offs, posSlot, len;\r
+      while (last < cur + newLen)\r
+        p->opt[++last].price = kInfinityPrice;\r
 \r
       offs = 0;\r
       while (startLen > matches[offs])\r
         offs += 2;\r
-      curBack = matches[offs + 1];\r
-      GetPosSlot2(curBack, posSlot);\r
-      for (lenTest = /*2*/ startLen; ; lenTest++)\r
+      dist = matches[(size_t)offs + 1];\r
+      \r
+      // if (dist >= kNumFullDistances)\r
+      GetPosSlot2(dist, posSlot);\r
+      \r
+      for (len = /*2*/ startLen; ; len++)\r
       {\r
-        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];\r
-        {\r
-        UInt32 lenToPosState = GetLenToPosState(lenTest);\r
-        COptimal *opt;\r
-        if (curBack < kNumFullDistances)\r
-          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];\r
-        else\r
-          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];\r
-        \r
-        opt = &p->opt[cur + lenTest];\r
-        if (curAndLenPrice < opt->price)\r
+        UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];\r
         {\r
-          opt->price = curAndLenPrice;\r
-          opt->posPrev = cur;\r
-          opt->backPrev = curBack + LZMA_NUM_REPS;\r
-          opt->prev1IsChar = False;\r
-        }\r
+          COptimal *opt;\r
+          unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);\r
+          if (dist < kNumFullDistances)\r
+            price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];\r
+          else\r
+            price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];\r
+          \r
+          opt = &p->opt[cur + len];\r
+          if (price < opt->price)\r
+          {\r
+            opt->price = price;\r
+            opt->len = len;\r
+            opt->dist = dist + LZMA_NUM_REPS;\r
+            opt->extra = 0;\r
+          }\r
         }\r
 \r
-        if (/*_maxMode && */lenTest == matches[offs])\r
+        if (/*_maxMode && */ len == matches[offs])\r
         {\r
-          /* Try Match + Literal + Rep0 */\r
-          const Byte *data2 = data - curBack - 1;\r
-          UInt32 lenTest2 = lenTest + 1;\r
-          UInt32 limit = lenTest2 + p->numFastBytes;\r
+          // MATCH : LIT : REP_0\r
+\r
+          const Byte *data2 = data - dist - 1;\r
+          unsigned len2 = len + 1;\r
+          unsigned limit = len2 + p->numFastBytes;\r
           if (limit > numAvailFull)\r
             limit = numAvailFull;\r
-          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);\r
-          lenTest2 -= lenTest + 1;\r
-          if (lenTest2 >= 2)\r
+          \r
+          for (; len2 < limit && data[len2] == data2[len2]; len2++);\r
+          \r
+          len2 -= len;\r
+          \r
+          if (len2 >= 3)\r
           {\r
-            UInt32 nextRepMatchPrice;\r
-            UInt32 state2 = kMatchNextStates[state];\r
-            UInt32 posStateNext = (position + lenTest) & p->pbMask;\r
-            UInt32 curAndLenCharPrice = curAndLenPrice +\r
-                GET_PRICE_0(p->isMatch[state2][posStateNext]) +\r
-                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),\r
-                    data[lenTest], data2[lenTest], p->ProbPrices);\r
-            state2 = kLiteralNextStates[state2];\r
-            posStateNext = (posStateNext + 1) & p->pbMask;\r
-            nextRepMatchPrice = curAndLenCharPrice +\r
-                GET_PRICE_1(p->isMatch[state2][posStateNext]) +\r
-                GET_PRICE_1(p->isRep[state2]);\r
-            \r
-            /* for (; lenTest2 >= 2; lenTest2--) */\r
+            unsigned state2 = kMatchNextStates[state];\r
+            unsigned posState2 = (position + len) & p->pbMask;\r
+            unsigned offset;\r
+            price += GET_PRICE_0(p->isMatch[state2][posState2]);\r
+            price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\r
+                    data[len], data2[len], p->ProbPrices);\r
+\r
+            // state2 = kLiteralNextStates[state2];\r
+            state2 = kState_LitAfterMatch;\r
+\r
+            posState2 = (posState2 + 1) & p->pbMask;\r
+            price += GetPrice_Rep_0(p, state2, posState2);\r
+\r
+            offset = cur + len + len2;\r
+            while (last < offset)\r
+              p->opt[++last].price = kInfinityPrice;\r
+            // do\r
             {\r
-              UInt32 offset = cur + lenTest + 1 + lenTest2;\r
-              UInt32 curAndLenPrice2;\r
+              UInt32 price2;\r
               COptimal *opt;\r
-              while (lenEnd < offset)\r
-                p->opt[++lenEnd].price = kInfinityPrice;\r
-              curAndLenPrice2 = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);\r
+              len2--;\r
+              // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\r
+              price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];\r
               opt = &p->opt[offset];\r
-              if (curAndLenPrice2 < opt->price)\r
+              // offset--;\r
+              if (price2 < opt->price)\r
               {\r
-                opt->price = curAndLenPrice2;\r
-                opt->posPrev = cur + lenTest + 1;\r
-                opt->backPrev = 0;\r
-                opt->prev1IsChar = True;\r
-                opt->prev2 = True;\r
-                opt->posPrev2 = cur;\r
-                opt->backPrev2 = curBack + LZMA_NUM_REPS;\r
+                opt->price = price2;\r
+                opt->len = len2;\r
+                opt->extra = (CExtra)(len + 1);\r
+                opt->dist = dist + LZMA_NUM_REPS;\r
               }\r
             }\r
+            // while (len2 >= 3);\r
           }\r
+        \r
           offs += 2;\r
           if (offs == numPairs)\r
             break;\r
-          curBack = matches[offs + 1];\r
-          if (curBack >= kNumFullDistances)\r
-            GetPosSlot2(curBack, posSlot);\r
+          dist = matches[(size_t)offs + 1];\r
+          // if (dist >= kNumFullDistances)\r
+            GetPosSlot2(dist, posSlot);\r
         }\r
       }\r
     }\r
   }\r
 }\r
 \r
+\r
+\r
 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))\r
 \r
-static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)\r
+\r
+\r
+static unsigned GetOptimumFast(CLzmaEnc *p)\r
 {\r
-  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;\r
+  UInt32 numAvail, mainDist;\r
+  unsigned mainLen, numPairs, repIndex, repLen, i;\r
   const Byte *data;\r
-  const UInt32 *matches;\r
 \r
   if (p->additionalOffset == 0)\r
     mainLen = ReadMatchDistances(p, &numPairs);\r
   else\r
   {\r
-    mainLen = p->longestMatchLength;\r
+    mainLen = p->longestMatchLen;\r
     numPairs = p->numPairs;\r
   }\r
 \r
   numAvail = p->numAvail;\r
-  *backRes = (UInt32)-1;\r
+  p->backRes = MARK_LIT;\r
   if (numAvail < 2)\r
     return 1;\r
   if (numAvail > LZMA_MATCH_LEN_MAX)\r
     numAvail = LZMA_MATCH_LEN_MAX;\r
   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
-\r
   repLen = repIndex = 0;\r
+  \r
   for (i = 0; i < LZMA_NUM_REPS; i++)\r
   {\r
-    UInt32 len;\r
-    const Byte *data2 = data - p->reps[i] - 1;\r
+    unsigned len;\r
+    const Byte *data2 = data - p->reps[i];\r
     if (data[0] != data2[0] || data[1] != data2[1])\r
       continue;\r
     for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
     if (len >= p->numFastBytes)\r
     {\r
-      *backRes = i;\r
-      MovePos(p, len - 1);\r
+      p->backRes = i;\r
+      MOVE_POS(p, len - 1)\r
       return len;\r
     }\r
     if (len > repLen)\r
@@ -1594,84 +1758,152 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
     }\r
   }\r
 \r
-  matches = p->matches;\r
   if (mainLen >= p->numFastBytes)\r
   {\r
-    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;\r
-    MovePos(p, mainLen - 1);\r
+    p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;\r
+    MOVE_POS(p, mainLen - 1)\r
     return mainLen;\r
   }\r
 \r
   mainDist = 0; /* for GCC */\r
+  \r
   if (mainLen >= 2)\r
   {\r
-    mainDist = matches[numPairs - 1];\r
-    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)\r
+    mainDist = p->matches[(size_t)numPairs - 1];\r
+    while (numPairs > 2)\r
     {\r
-      if (!ChangePair(matches[numPairs - 3], mainDist))\r
+      UInt32 dist2;\r
+      if (mainLen != p->matches[(size_t)numPairs - 4] + 1)\r
+        break;\r
+      dist2 = p->matches[(size_t)numPairs - 3];\r
+      if (!ChangePair(dist2, mainDist))\r
         break;\r
       numPairs -= 2;\r
-      mainLen = matches[numPairs - 2];\r
-      mainDist = matches[numPairs - 1];\r
+      mainLen--;\r
+      mainDist = dist2;\r
     }\r
     if (mainLen == 2 && mainDist >= 0x80)\r
       mainLen = 1;\r
   }\r
 \r
-  if (repLen >= 2 && (\r
-        (repLen + 1 >= mainLen) ||\r
-        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||\r
-        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))\r
+  if (repLen >= 2)\r
+    if (    repLen + 1 >= mainLen\r
+        || (repLen + 2 >= mainLen && mainDist >= (1 << 9))\r
+        || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))\r
   {\r
-    *backRes = repIndex;\r
-    MovePos(p, repLen - 1);\r
+    p->backRes = repIndex;\r
+    MOVE_POS(p, repLen - 1)\r
     return repLen;\r
   }\r
   \r
   if (mainLen < 2 || numAvail <= 2)\r
     return 1;\r
 \r
-  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);\r
-  if (p->longestMatchLength >= 2)\r
   {\r
-    UInt32 newDistance = matches[p->numPairs - 1];\r
-    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||\r
-        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||\r
-        (p->longestMatchLength > mainLen + 1) ||\r
-        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))\r
-      return 1;\r
+    unsigned len1 = ReadMatchDistances(p, &p->numPairs);\r
+    p->longestMatchLen = len1;\r
+  \r
+    if (len1 >= 2)\r
+    {\r
+      UInt32 newDist = p->matches[(size_t)p->numPairs - 1];\r
+      if (   (len1 >= mainLen && newDist < mainDist)\r
+          || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))\r
+          || (len1 >  mainLen + 1)\r
+          || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))\r
+        return 1;\r
+    }\r
   }\r
   \r
   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
+  \r
   for (i = 0; i < LZMA_NUM_REPS; i++)\r
   {\r
-    UInt32 len, limit;\r
-    const Byte *data2 = data - p->reps[i] - 1;\r
+    unsigned len, limit;\r
+    const Byte *data2 = data - p->reps[i];\r
     if (data[0] != data2[0] || data[1] != data2[1])\r
       continue;\r
     limit = mainLen - 1;\r
-    for (len = 2; len < limit && data[len] == data2[len]; len++);\r
-    if (len >= limit)\r
-      return 1;\r
+    for (len = 2;; len++)\r
+    {\r
+      if (len >= limit)\r
+        return 1;\r
+      if (data[len] != data2[len])\r
+        break;\r
+    }\r
+  }\r
+  \r
+  p->backRes = mainDist + LZMA_NUM_REPS;\r
+  if (mainLen != 2)\r
+  {\r
+    MOVE_POS(p, mainLen - 2)\r
   }\r
-  *backRes = mainDist + LZMA_NUM_REPS;\r
-  MovePos(p, mainLen - 2);\r
   return mainLen;\r
 }\r
 \r
-static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)\r
+\r
+\r
+\r
+static void WriteEndMarker(CLzmaEnc *p, unsigned posState)\r
 {\r
-  UInt32 len;\r
-  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\r
-  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\r
+  UInt32 range;\r
+  range = p->rc.range;\r
+  {\r
+    UInt32 ttt, newBound;\r
+    CLzmaProb *prob = &p->isMatch[p->state][posState];\r
+    RC_BIT_PRE(&p->rc, prob)\r
+    RC_BIT_1(&p->rc, prob)\r
+    prob = &p->isRep[p->state];\r
+    RC_BIT_PRE(&p->rc, prob)\r
+    RC_BIT_0(&p->rc, prob)\r
+  }\r
   p->state = kMatchNextStates[p->state];\r
-  len = LZMA_MATCH_LEN_MIN;\r
-  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
-  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);\r
-  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);\r
-  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\r
+  \r
+  p->rc.range = range;\r
+  LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);\r
+  range = p->rc.range;\r
+\r
+  {\r
+    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);\r
+    CLzmaProb *probs = p->posSlotEncoder[0];\r
+    unsigned m = 1;\r
+    do\r
+    {\r
+      UInt32 ttt, newBound;\r
+      RC_BIT_PRE(p, probs + m)\r
+      RC_BIT_1(&p->rc, probs + m);\r
+      m = (m << 1) + 1;\r
+    }\r
+    while (m < (1 << kNumPosSlotBits));\r
+  }\r
+  {\r
+    // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;\r
+    unsigned numBits = 30 - kNumAlignBits;\r
+    do\r
+    {\r
+      range >>= 1;\r
+      p->rc.low += range;\r
+      RC_NORM(&p->rc)\r
+    }\r
+    while (--numBits);\r
+  }\r
+   \r
+  {\r
+    // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\r
+    CLzmaProb *probs = p->posAlignEncoder;\r
+    unsigned m = 1;\r
+    do\r
+    {\r
+      UInt32 ttt, newBound;\r
+      RC_BIT_PRE(p, probs + m)\r
+      RC_BIT_1(&p->rc, probs + m);\r
+      m = (m << 1) + 1;\r
+    }\r
+    while (m < kAlignTableSize);\r
+  }\r
+  p->rc.range = range;\r
 }\r
 \r
+\r
 static SRes CheckErrors(CLzmaEnc *p)\r
 {\r
   if (p->result != SZ_OK)\r
@@ -1685,7 +1917,8 @@ static SRes CheckErrors(CLzmaEnc *p)
   return p->result;\r
 }\r
 \r
-static SRes Flush(CLzmaEnc *p, UInt32 nowPos)\r
+\r
+MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)\r
 {\r
   /* ReleaseMFStream(); */\r
   p->finished = True;\r
@@ -1696,47 +1929,108 @@ static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
   return CheckErrors(p);\r
 }\r
 \r
+\r
+\r
 static void FillAlignPrices(CLzmaEnc *p)\r
 {\r
-  UInt32 i;\r
-  for (i = 0; i < kAlignTableSize; i++)\r
-    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\r
+  unsigned i;\r
+  const CProbPrice *ProbPrices = p->ProbPrices;\r
+  const CLzmaProb *probs = p->posAlignEncoder;\r
   p->alignPriceCount = 0;\r
+  for (i = 0; i < kAlignTableSize / 2; i++)\r
+  {\r
+    UInt32 price = 0;\r
+    unsigned symbol = i;\r
+    unsigned m = 1;\r
+    unsigned bit;\r
+    UInt32 prob;\r
+    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
+    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
+    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
+    prob = probs[m];\r
+    p->alignPrices[i    ] = price + GET_PRICEa_0(prob);\r
+    p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);\r
+    // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\r
+  }\r
 }\r
 \r
+\r
 static void FillDistancesPrices(CLzmaEnc *p)\r
 {\r
   UInt32 tempPrices[kNumFullDistances];\r
-  UInt32 i, lenToPosState;\r
+  unsigned i, lenToPosState;\r
+\r
+  const CProbPrice *ProbPrices = p->ProbPrices;\r
+  p->matchPriceCount = 0;\r
+\r
   for (i = kStartPosModelIndex; i < kNumFullDistances; i++)\r
   {\r
-    UInt32 posSlot = GetPosSlot1(i);\r
-    UInt32 footerBits = ((posSlot >> 1) - 1);\r
-    UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
-    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);\r
+    unsigned posSlot = GetPosSlot1(i);\r
+    unsigned footerBits = ((posSlot >> 1) - 1);\r
+    unsigned base = ((2 | (posSlot & 1)) << footerBits);\r
+    // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);\r
+\r
+    const CLzmaProb *probs = p->posEncoders + base;\r
+    UInt32 price = 0;\r
+    unsigned m = 1;\r
+    unsigned symbol = i - base;\r
+    do\r
+    {\r
+      unsigned bit = symbol & 1;\r
+      symbol >>= 1;\r
+      price += GET_PRICEa(probs[m], bit);\r
+      m = (m << 1) + bit;\r
+    }\r
+    while (--footerBits);\r
+    tempPrices[i] = price;\r
   }\r
 \r
   for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)\r
   {\r
-    UInt32 posSlot;\r
+    unsigned posSlot;\r
     const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];\r
     UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];\r
-    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)\r
-      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);\r
-    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)\r
-      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\r
+    unsigned distTableSize = p->distTableSize;\r
+    const CLzmaProb *probs = encoder;\r
+    for (posSlot = 0; posSlot < distTableSize; posSlot += 2)\r
+    {\r
+      // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);\r
+      UInt32 price = 0;\r
+      unsigned bit;\r
+      unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));\r
+      UInt32 prob;\r
+      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
+      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
+      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
+      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
+      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
+      prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];\r
+      posSlotPrices[posSlot    ] = price + GET_PRICEa_0(prob);\r
+      posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);\r
+    }\r
+    for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)\r
+      posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\r
 \r
     {\r
       UInt32 *distancesPrices = p->distancesPrices[lenToPosState];\r
-      for (i = 0; i < kStartPosModelIndex; i++)\r
-        distancesPrices[i] = posSlotPrices[i];\r
-      for (; i < kNumFullDistances; i++)\r
-        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];\r
+      {\r
+        distancesPrices[0] = posSlotPrices[0];\r
+        distancesPrices[1] = posSlotPrices[1];\r
+        distancesPrices[2] = posSlotPrices[2];\r
+        distancesPrices[3] = posSlotPrices[3];\r
+      }\r
+      for (i = 4; i < kNumFullDistances; i += 2)\r
+      {\r
+        UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];\r
+        distancesPrices[i    ] = slotPrice + tempPrices[i];\r
+        distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];\r
+      }\r
     }\r
   }\r
-  p->matchPriceCount = 0;\r
 }\r
 \r
+\r
+\r
 void LzmaEnc_Construct(CLzmaEnc *p)\r
 {\r
   RangeEnc_Construct(&p->rc);\r
@@ -1760,26 +2054,27 @@ void LzmaEnc_Construct(CLzmaEnc *p)
   LzmaEnc_InitPriceTables(p->ProbPrices);\r
   p->litProbs = NULL;\r
   p->saveState.litProbs = NULL;\r
+\r
 }\r
 \r
-CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)\r
+CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)\r
 {\r
   void *p;\r
-  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));\r
+  p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));\r
   if (p)\r
     LzmaEnc_Construct((CLzmaEnc *)p);\r
   return p;\r
 }\r
 \r
-void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)\r
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)\r
 {\r
-  alloc->Free(alloc, p->litProbs);\r
-  alloc->Free(alloc, p->saveState.litProbs);\r
+  ISzAlloc_Free(alloc, p->litProbs);\r
+  ISzAlloc_Free(alloc, p->saveState.litProbs);\r
   p->litProbs = NULL;\r
   p->saveState.litProbs = NULL;\r
 }\r
 \r
-void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   #ifndef _7ZIP_ST\r
   MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);\r
@@ -1790,13 +2085,14 @@ void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
   RangeEnc_Free(&p->rc, alloc);\r
 }\r
 \r
-void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);\r
-  alloc->Free(alloc, p);\r
+  ISzAlloc_Free(alloc, p);\r
 }\r
 \r
-static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)\r
+\r
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)\r
 {\r
   UInt32 nowPos32, startPos32;\r
   if (p->needInit)\r
@@ -1814,13 +2110,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
 \r
   if (p->nowPos64 == 0)\r
   {\r
-    UInt32 numPairs;\r
+    unsigned numPairs;\r
     Byte curByte;\r
     if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
       return Flush(p, nowPos32);\r
     ReadMatchDistances(p, &numPairs);\r
-    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);\r
-    p->state = kLiteralNextStates[p->state];\r
+    RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);\r
+    // p->state = kLiteralNextStates[p->state];\r
     curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);\r
     LitEnc_Encode(&p->rc, p->litProbs, curByte);\r
     p->additionalOffset--;\r
@@ -1828,109 +2124,225 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
   }\r
 \r
   if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)\r
+  \r
   for (;;)\r
   {\r
-    UInt32 pos, len, posState;\r
-\r
+    UInt32 dist;\r
+    unsigned len, posState;\r
+    UInt32 range, ttt, newBound;\r
+    CLzmaProb *probs;\r
+  \r
     if (p->fastMode)\r
-      len = GetOptimumFast(p, &pos);\r
+      len = GetOptimumFast(p);\r
     else\r
-      len = GetOptimum(p, nowPos32, &pos);\r
+    {\r
+      unsigned oci = p->optCur;\r
+      if (p->optEnd == oci)\r
+        len = GetOptimum(p, nowPos32);\r
+      else\r
+      {\r
+        const COptimal *opt = &p->opt[oci];\r
+        len = opt->len;\r
+        p->backRes = opt->dist;\r
+        p->optCur = oci + 1;\r
+      }\r
+    }\r
+\r
+    posState = (unsigned)nowPos32 & p->pbMask;\r
+    range = p->rc.range;\r
+    probs = &p->isMatch[p->state][posState];\r
+    \r
+    RC_BIT_PRE(&p->rc, probs)\r
+    \r
+    dist = p->backRes;\r
 \r
     #ifdef SHOW_STAT2\r
-    printf("\n pos = %4X,   len = %u   pos = %u", nowPos32, len, pos);\r
+    printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);\r
     #endif\r
 \r
-    posState = nowPos32 & p->pbMask;\r
-    if (len == 1 && pos == (UInt32)-1)\r
+    if (dist == MARK_LIT)\r
     {\r
       Byte curByte;\r
-      CLzmaProb *probs;\r
       const Byte *data;\r
+      unsigned state;\r
 \r
-      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);\r
+      RC_BIT_0(&p->rc, probs);\r
+      p->rc.range = range;\r
       data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\r
-      curByte = *data;\r
       probs = LIT_PROBS(nowPos32, *(data - 1));\r
-      if (IsCharState(p->state))\r
+      curByte = *data;\r
+      state = p->state;\r
+      p->state = kLiteralNextStates[state];\r
+      if (IsLitState(state))\r
         LitEnc_Encode(&p->rc, probs, curByte);\r
       else\r
-        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));\r
-      p->state = kLiteralNextStates[p->state];\r
+        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));\r
     }\r
     else\r
     {\r
-      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);\r
-      if (pos < LZMA_NUM_REPS)\r
+      RC_BIT_1(&p->rc, probs);\r
+      probs = &p->isRep[p->state];\r
+      RC_BIT_PRE(&p->rc, probs)\r
+      \r
+      if (dist < LZMA_NUM_REPS)\r
       {\r
-        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);\r
-        if (pos == 0)\r
+        RC_BIT_1(&p->rc, probs);\r
+        probs = &p->isRepG0[p->state];\r
+        RC_BIT_PRE(&p->rc, probs)\r
+        if (dist == 0)\r
         {\r
-          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);\r
-          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));\r
+          RC_BIT_0(&p->rc, probs);\r
+          probs = &p->isRep0Long[p->state][posState];\r
+          RC_BIT_PRE(&p->rc, probs)\r
+          if (len != 1)\r
+          {\r
+            RC_BIT_1_BASE(&p->rc, probs);\r
+          }\r
+          else\r
+          {\r
+            RC_BIT_0_BASE(&p->rc, probs);\r
+            p->state = kShortRepNextStates[p->state];\r
+          }\r
         }\r
         else\r
         {\r
-          UInt32 distance = p->reps[pos];\r
-          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);\r
-          if (pos == 1)\r
-            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);\r
+          RC_BIT_1(&p->rc, probs);\r
+          probs = &p->isRepG1[p->state];\r
+          RC_BIT_PRE(&p->rc, probs)\r
+          if (dist == 1)\r
+          {\r
+            RC_BIT_0_BASE(&p->rc, probs);\r
+            dist = p->reps[1];\r
+          }\r
           else\r
           {\r
-            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);\r
-            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);\r
-            if (pos == 3)\r
+            RC_BIT_1(&p->rc, probs);\r
+            probs = &p->isRepG2[p->state];\r
+            RC_BIT_PRE(&p->rc, probs)\r
+            if (dist == 2)\r
+            {\r
+              RC_BIT_0_BASE(&p->rc, probs);\r
+              dist = p->reps[2];\r
+            }\r
+            else\r
+            {\r
+              RC_BIT_1_BASE(&p->rc, probs);\r
+              dist = p->reps[3];\r
               p->reps[3] = p->reps[2];\r
+            }\r
             p->reps[2] = p->reps[1];\r
           }\r
           p->reps[1] = p->reps[0];\r
-          p->reps[0] = distance;\r
+          p->reps[0] = dist;\r
         }\r
-        if (len == 1)\r
-          p->state = kShortRepNextStates[p->state];\r
-        else\r
+\r
+        RC_NORM(&p->rc)\r
+\r
+        p->rc.range = range;\r
+\r
+        if (len != 1)\r
         {\r
-          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
+          LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\r
+          if (!p->fastMode)\r
+            if (--p->repLenEnc.counters[posState] == 0)\r
+              LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);\r
+\r
           p->state = kRepNextStates[p->state];\r
         }\r
       }\r
       else\r
       {\r
-        UInt32 posSlot;\r
-        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);\r
+        unsigned posSlot;\r
+        RC_BIT_0(&p->rc, probs);\r
+        p->rc.range = range;\r
         p->state = kMatchNextStates[p->state];\r
-        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);\r
-        pos -= LZMA_NUM_REPS;\r
-        GetPosSlot(pos, posSlot);\r
-        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);\r
+\r
+        LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\r
+        if (!p->fastMode)\r
+          if (--p->lenEnc.counters[posState] == 0)\r
+            LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);\r
+\r
+        dist -= LZMA_NUM_REPS;\r
+        p->reps[3] = p->reps[2];\r
+        p->reps[2] = p->reps[1];\r
+        p->reps[1] = p->reps[0];\r
+        p->reps[0] = dist + 1;\r
         \r
-        if (posSlot >= kStartPosModelIndex)\r
+        p->matchPriceCount++;\r
+        GetPosSlot(dist, posSlot);\r
+        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);\r
+        {\r
+          UInt32 symbol = posSlot + (1 << kNumPosSlotBits);\r
+          range = p->rc.range;\r
+          probs = p->posSlotEncoder[GetLenToPosState(len)];\r
+          do\r
+          {\r
+            CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);\r
+            UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;\r
+            symbol <<= 1;\r
+            RC_BIT(&p->rc, prob, bit);\r
+          }\r
+          while (symbol < (1 << kNumPosSlotBits * 2));\r
+          p->rc.range = range;\r
+        }\r
+        \r
+        if (dist >= kStartPosModelIndex)\r
         {\r
-          UInt32 footerBits = ((posSlot >> 1) - 1);\r
-          UInt32 base = ((2 | (posSlot & 1)) << footerBits);\r
-          UInt32 posReduced = pos - base;\r
+          unsigned footerBits = ((posSlot >> 1) - 1);\r
 \r
-          if (posSlot < kEndPosModelIndex)\r
-            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);\r
+          if (dist < kNumFullDistances)\r
+          {\r
+            unsigned base = ((2 | (posSlot & 1)) << footerBits);\r
+            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);\r
+          }\r
           else\r
           {\r
-            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
-            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\r
-            p->alignPriceCount++;\r
+            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);\r
+            range = p->rc.range;\r
+            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
+            /*\r
+            do\r
+            {\r
+              range >>= 1;\r
+              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));\r
+              RC_NORM(&p->rc)\r
+            }\r
+            while (footerBits > kNumAlignBits);\r
+            */\r
+            do\r
+            {\r
+              range >>= 1;\r
+              p->rc.low += range & (0 - (pos2 >> 31));\r
+              pos2 += pos2;\r
+              RC_NORM(&p->rc)\r
+            }\r
+            while (pos2 != 0xF0000000);\r
+\r
+\r
+            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\r
+\r
+            {\r
+              unsigned m = 1;\r
+              unsigned bit;\r
+              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;\r
+              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;\r
+              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;\r
+              bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit);\r
+              p->rc.range = range;\r
+              p->alignPriceCount++;\r
+            }\r
           }\r
         }\r
-        p->reps[3] = p->reps[2];\r
-        p->reps[2] = p->reps[1];\r
-        p->reps[1] = p->reps[0];\r
-        p->reps[0] = pos;\r
-        p->matchPriceCount++;\r
       }\r
     }\r
-    p->additionalOffset -= len;\r
+\r
     nowPos32 += len;\r
+    p->additionalOffset -= len;\r
+    \r
     if (p->additionalOffset == 0)\r
     {\r
       UInt32 processed;\r
+\r
       if (!p->fastMode)\r
       {\r
         if (p->matchPriceCount >= (1 << 7))\r
@@ -1938,13 +2350,15 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
         if (p->alignPriceCount >= kAlignTableSize)\r
           FillAlignPrices(p);\r
       }\r
+    \r
       if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
         break;\r
       processed = nowPos32 - startPos32;\r
-      if (useLimits)\r
+      \r
+      if (maxPackSize)\r
       {\r
-        if (processed + kNumOpts + 300 >= maxUnpackSize ||\r
-            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)\r
+        if (processed + kNumOpts + 300 >= maxUnpackSize\r
+            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)\r
           break;\r
       }\r
       else if (processed >= (1 << 17))\r
@@ -1954,13 +2368,16 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
       }\r
     }\r
   }\r
+\r
   p->nowPos64 += nowPos32 - startPos32;\r
   return Flush(p, nowPos32);\r
 }\r
 \r
+\r
+\r
 #define kBigHashDicLimit ((UInt32)1 << 24)\r
 \r
-static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   UInt32 beforeSize = kNumOpts;\r
   if (!RangeEnc_Alloc(&p->rc, alloc))\r
@@ -1975,8 +2392,8 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
     if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)\r
     {\r
       LzmaEnc_FreeLits(p, alloc);\r
-      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
-      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
+      p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
+      p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
       if (!p->litProbs || !p->saveState.litProbs)\r
       {\r
         LzmaEnc_FreeLits(p, alloc);\r
@@ -1994,8 +2411,13 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
   #ifndef _7ZIP_ST\r
   if (p->mtMode)\r
   {\r
-    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));\r
+    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,\r
+        LZMA_MATCH_LEN_MAX\r
+        + 1  /* 18.04 */\r
+        , allocBig));\r
     p->matchFinderObj = &p->matchFinderMt;\r
+    p->matchFinderBase.bigHash = (Byte)(\r
+        (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);\r
     MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);\r
   }\r
   else\r
@@ -2012,17 +2434,21 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
 \r
 void LzmaEnc_Init(CLzmaEnc *p)\r
 {\r
-  UInt32 i;\r
+  unsigned i;\r
   p->state = 0;\r
-  for (i = 0 ; i < LZMA_NUM_REPS; i++)\r
-    p->reps[i] = 0;\r
+  p->reps[0] =\r
+  p->reps[1] =\r
+  p->reps[2] =\r
+  p->reps[3] = 1;\r
 \r
   RangeEnc_Init(&p->rc);\r
 \r
+  for (i = 0; i < (1 << kNumAlignBits); i++)\r
+    p->posAlignEncoder[i] = kProbInitValue;\r
 \r
   for (i = 0; i < kNumStates; i++)\r
   {\r
-    UInt32 j;\r
+    unsigned j;\r
     for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)\r
     {\r
       p->isMatch[i][j] = kProbInitValue;\r
@@ -2034,39 +2460,38 @@ void LzmaEnc_Init(CLzmaEnc *p)
     p->isRepG2[i] = kProbInitValue;\r
   }\r
 \r
-  {\r
-    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);\r
-    CLzmaProb *probs = p->litProbs;\r
-    for (i = 0; i < num; i++)\r
-      probs[i] = kProbInitValue;\r
-  }\r
-\r
   {\r
     for (i = 0; i < kNumLenToPosStates; i++)\r
     {\r
       CLzmaProb *probs = p->posSlotEncoder[i];\r
-      UInt32 j;\r
+      unsigned j;\r
       for (j = 0; j < (1 << kNumPosSlotBits); j++)\r
         probs[j] = kProbInitValue;\r
     }\r
   }\r
   {\r
-    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)\r
+    for (i = 0; i < kNumFullDistances; i++)\r
       p->posEncoders[i] = kProbInitValue;\r
   }\r
 \r
-  LenEnc_Init(&p->lenEnc.p);\r
-  LenEnc_Init(&p->repLenEnc.p);\r
+  {\r
+    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);\r
+    UInt32 k;\r
+    CLzmaProb *probs = p->litProbs;\r
+    for (k = 0; k < num; k++)\r
+      probs[k] = kProbInitValue;\r
+  }\r
 \r
-  for (i = 0; i < (1 << kNumAlignBits); i++)\r
-    p->posAlignEncoder[i] = kProbInitValue;\r
 \r
-  p->optimumEndIndex = 0;\r
-  p->optimumCurrentIndex = 0;\r
+  LenEnc_Init(&p->lenProbs);\r
+  LenEnc_Init(&p->repLenProbs);\r
+\r
+  p->optEnd = 0;\r
+  p->optCur = 0;\r
   p->additionalOffset = 0;\r
 \r
   p->pbMask = (1 << p->pb) - 1;\r
-  p->lpMask = (1 << p->lp) - 1;\r
+  p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);\r
 }\r
 \r
 void LzmaEnc_InitPrices(CLzmaEnc *p)\r
@@ -2080,14 +2505,14 @@ void LzmaEnc_InitPrices(CLzmaEnc *p)
   p->lenEnc.tableSize =\r
   p->repLenEnc.tableSize =\r
       p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;\r
-  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);\r
-  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);\r
+  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);\r
+  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);\r
 }\r
 \r
-static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
-  UInt32 i;\r
-  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)\r
+  unsigned i;\r
+  for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)\r
     if (p->dictSize <= ((UInt32)1 << i))\r
       break;\r
   p->distTableSize = i * 2;\r
@@ -2102,7 +2527,7 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a
 }\r
 \r
 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,\r
-    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
   p->matchFinderBase.stream = inStream;\r
@@ -2113,7 +2538,7 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInS
 \r
 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,\r
     ISeqInStream *inStream, UInt32 keepWindowSize,\r
-    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
   p->matchFinderBase.stream = inStream;\r
@@ -2129,12 +2554,13 @@ static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
 }\r
 \r
 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\r
-    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
   LzmaEnc_SetInputBuf(p, src, srcLen);\r
   p->needInit = 1;\r
 \r
+  LzmaEnc_SetDataSize(pp, srcLen);\r
   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\r
 }\r
 \r
@@ -2152,15 +2578,15 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
 \r
 typedef struct\r
 {\r
-  ISeqOutStream funcTable;\r
+  ISeqOutStream vt;\r
   Byte *data;\r
   SizeT rem;\r
   Bool overflow;\r
-} CSeqOutStreamBuf;\r
+} CLzmaEnc_SeqOutStreamBuf;\r
 \r
-static size_t MyWrite(void *pp, const void *data, size_t size)\r
+static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)\r
 {\r
-  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;\r
+  CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);\r
   if (p->rem < size)\r
   {\r
     size = p->rem;\r
@@ -2193,9 +2619,9 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
   UInt64 nowPos64;\r
   SRes res;\r
-  CSeqOutStreamBuf outStream;\r
+  CLzmaEnc_SeqOutStreamBuf outStream;\r
 \r
-  outStream.funcTable.Write = MyWrite;\r
+  outStream.vt.Write = SeqOutStreamBuf_Write;\r
   outStream.data = dest;\r
   outStream.rem = *destLen;\r
   outStream.overflow = False;\r
@@ -2207,11 +2633,15 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
   if (reInit)\r
     LzmaEnc_Init(p);\r
   LzmaEnc_InitPrices(p);\r
+\r
   nowPos64 = p->nowPos64;\r
   RangeEnc_Init(&p->rc);\r
-  p->rc.outStream = &outStream.funcTable;\r
+  p->rc.outStream = &outStream.vt;\r
+\r
+  if (desiredPackSize == 0)\r
+    return SZ_ERROR_OUTPUT_EOF;\r
 \r
-  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);\r
+  res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);\r
   \r
   *unpackSize = (UInt32)(p->nowPos64 - nowPos64);\r
   *destLen -= outStream.rem;\r
@@ -2234,12 +2664,12 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
 \r
   for (;;)\r
   {\r
-    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);\r
+    res = LzmaEnc_CodeOneBlock(p, 0, 0);\r
     if (res != SZ_OK || p->finished)\r
       break;\r
     if (progress)\r
     {\r
-      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\r
+      res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\r
       if (res != SZ_OK)\r
       {\r
         res = SZ_ERROR_PROGRESS;\r
@@ -2251,7 +2681,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
   LzmaEnc_Finish(p);\r
 \r
   /*\r
-  if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))\r
+  if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))\r
     res = SZ_ERROR_FAIL;\r
   }\r
   */\r
@@ -2261,7 +2691,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
 \r
 \r
 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,\r
-    ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));\r
   return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);\r
@@ -2296,21 +2726,27 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
 }\r
 \r
 \r
+unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)\r
+{\r
+  return ((CLzmaEnc *)pp)->writeEndMark;\r
+}\r
+\r
+\r
 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
-    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   SRes res;\r
   CLzmaEnc *p = (CLzmaEnc *)pp;\r
 \r
-  CSeqOutStreamBuf outStream;\r
+  CLzmaEnc_SeqOutStreamBuf outStream;\r
 \r
-  outStream.funcTable.Write = MyWrite;\r
+  outStream.vt.Write = SeqOutStreamBuf_Write;\r
   outStream.data = dest;\r
   outStream.rem = *destLen;\r
   outStream.overflow = False;\r
 \r
   p->writeEndMark = writeEndMark;\r
-  p->rc.outStream = &outStream.funcTable;\r
+  p->rc.outStream = &outStream.vt;\r
 \r
   res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);\r
   \r
@@ -2330,7 +2766,7 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
 \r
 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\r
-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)\r
+    ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
 {\r
   CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);\r
   SRes res;\r