Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Compress / LZMA / LZMAEncoder.cpp
1 // LZMA/Encoder.cpp
2
3 #include "StdAfx.h"
4
5 #include <stdio.h>
6
7 #ifdef _WIN32
8 #define USE_ALLOCA
9 #endif
10
11 #ifdef USE_ALLOCA
12 #ifdef _WIN32
13 #include <malloc.h>
14 #else
15 #include <stdlib.h>
16 #endif
17 #endif
18
19 #include "../../../Common/Defs.h"
20 #include "../../Common/StreamUtils.h"
21
22 #include "LZMAEncoder.h"
23
24 // extern "C" { #include "../../../../C/7zCrc.h" }
25
26 // #define SHOW_STAT
27
28
29 namespace NCompress {
30 namespace NLZMA {
31
32 // struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit;
33
34 const int kDefaultDictionaryLogSize = 22;
35 const UInt32 kNumFastBytesDefault = 0x20;
36
37 #ifndef LZMA_LOG_BSR
38 Byte g_FastPos[1 << kNumLogBits];
39
40 class CFastPosInit
41 {
42 public:
43   CFastPosInit() { Init(); }
44   void Init()
45   {
46     const Byte kFastSlots = kNumLogBits * 2;
47     int c = 2;
48     g_FastPos[0] = 0;
49     g_FastPos[1] = 1;
50
51     for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
52     {
53       UInt32 k = (1 << ((slotFast >> 1) - 1));
54       for (UInt32 j = 0; j < k; j++, c++)
55         g_FastPos[c] = slotFast;
56     }
57   }
58 } g_FastPosInit;
59 #endif
60
61 void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
62 {
63   UInt32 context = 1;
64   int i = 8;
65   do 
66   {
67     i--;
68     UInt32 bit = (symbol >> i) & 1;
69     _encoders[context].Encode(rangeEncoder, bit);
70     context = (context << 1) | bit;
71   }
72   while(i != 0);
73 }
74
75 void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, 
76     Byte matchByte, Byte symbol)
77 {
78   UInt32 context = 1;
79   int i = 8;
80   do 
81   {
82     i--;
83     UInt32 bit = (symbol >> i) & 1;
84     UInt32 matchBit = (matchByte >> i) & 1;
85     _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
86     context = (context << 1) | bit;
87     if (matchBit != bit)
88     {
89       while(i != 0)
90       {
91         i--;
92         UInt32 bit = (symbol >> i) & 1;
93         _encoders[context].Encode(rangeEncoder, bit);
94         context = (context << 1) | bit;
95       }
96       break;
97     }
98   }
99   while(i != 0);
100 }
101
102 UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
103 {
104   UInt32 price = 0;
105   UInt32 context = 1;
106   int i = 8;
107   if (matchMode)
108   {
109     do 
110     {
111       i--;
112       UInt32 matchBit = (matchByte >> i) & 1;
113       UInt32 bit = (symbol >> i) & 1;
114       price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
115       context = (context << 1) | bit;
116       if (matchBit != bit)
117         break;
118     }
119     while (i != 0);
120   }
121   while(i != 0)
122   {
123     i--;
124     UInt32 bit = (symbol >> i) & 1;
125     price += _encoders[context].GetPrice(bit);
126     context = (context << 1) | bit;
127   }
128   return price;
129 };
130
131
132 namespace NLength {
133
134 void CEncoder::Init(UInt32 numPosStates)
135 {
136   _choice.Init();
137   _choice2.Init();
138   for (UInt32 posState = 0; posState < numPosStates; posState++)
139   {
140     _lowCoder[posState].Init();
141     _midCoder[posState].Init();
142   }
143   _highCoder.Init();
144 }
145
146 void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
147 {
148   if(symbol < kNumLowSymbols)
149   {
150     _choice.Encode(rangeEncoder, 0);
151     _lowCoder[posState].Encode(rangeEncoder, symbol);
152   }
153   else
154   {
155     _choice.Encode(rangeEncoder, 1);
156     if(symbol < kNumLowSymbols + kNumMidSymbols)
157     {
158       _choice2.Encode(rangeEncoder, 0);
159       _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
160     }
161     else
162     {
163       _choice2.Encode(rangeEncoder, 1);
164       _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
165     }
166   }
167 }
168
169 void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const
170 {
171   UInt32 a0 = _choice.GetPrice0();
172   UInt32 a1 = _choice.GetPrice1();
173   UInt32 b0 = a1 + _choice2.GetPrice0();
174   UInt32 b1 = a1 + _choice2.GetPrice1();
175   UInt32 i = 0;
176   for (i = 0; i < kNumLowSymbols; i++)
177   {
178     if (i >= numSymbols)
179       return;
180     prices[i] = a0 + _lowCoder[posState].GetPrice(i);
181   }
182   for (; i < kNumLowSymbols + kNumMidSymbols; i++)
183   {
184     if (i >= numSymbols)
185       return;
186     prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);
187   }
188   for (; i < numSymbols; i++)
189     prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);
190 }
191
192 }
193
194 CEncoder::CEncoder():
195   _numFastBytes(kNumFastBytesDefault),
196   _distTableSize(kDefaultDictionaryLogSize * 2),
197   _posStateBits(2),
198   _posStateMask(4 - 1),
199   _numLiteralPosStateBits(0),
200   _numLiteralContextBits(3),
201   _dictionarySize(1 << kDefaultDictionaryLogSize),
202   _matchFinderCycles(0),
203   #ifdef COMPRESS_MF_MT
204   _multiThread(false),
205   #endif
206   _writeEndMark(false)
207 {
208   MatchFinder_Construct(&_matchFinderBase);
209   // _maxMode = false;
210   _fastMode = false;
211   #ifdef COMPRESS_MF_MT
212   MatchFinderMt_Construct(&_matchFinderMt);
213   _matchFinderMt.MatchFinder = &_matchFinderBase;
214   #endif
215 }
216
217
218 static void *SzAlloc(size_t size) { return BigAlloc(size); }
219 static void SzFree(void *address) { BigFree(address); }
220 ISzAlloc g_Alloc = { SzAlloc, SzFree };
221
222 CEncoder::~CEncoder()
223 {
224   #ifdef COMPRESS_MF_MT
225   MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc);
226   #endif
227   MatchFinder_Free(&_matchFinderBase, &g_Alloc);
228 }
229
230 static const UInt32 kBigHashDicLimit = (UInt32)1 << 24;
231
232 HRESULT CEncoder::Create()
233 {
234   if (!_rangeEncoder.Create(1 << 20))
235     return E_OUTOFMEMORY;
236   bool btMode = (_matchFinderBase.btMode != 0);
237   #ifdef COMPRESS_MF_MT
238   _mtMode = (_multiThread && !_fastMode && btMode);
239   #endif
240   
241   if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
242     return E_OUTOFMEMORY;
243
244   _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit);
245
246   UInt32 numCycles = 16 + (_numFastBytes >> 1);
247   if (!btMode)
248     numCycles >>= 1;
249   if (_matchFinderCycles != 0)
250     numCycles = _matchFinderCycles;
251   _matchFinderBase.cutValue = numCycles;
252   #ifdef COMPRESS_MF_MT
253   if (_mtMode)
254   {
255     RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc));
256     _matchFinderObj = &_matchFinderMt;
257     MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder);
258   }
259   else
260   #endif
261   {
262     if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc))
263       return E_OUTOFMEMORY;
264     _matchFinderObj = &_matchFinderBase;
265     MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder);
266   }
267   return S_OK;
268 }
269
270 inline wchar_t GetUpperChar(wchar_t c)
271 {
272   if (c >= 'a' && c <= 'z')
273     c -= 0x20;
274   return c;
275 }
276
277 static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */)
278 {
279   wchar_t c = GetUpperChar(*s++);
280   if (c == L'H')
281   {
282     if (GetUpperChar(*s++) != L'C')
283       return 0;
284     int numHashBytesLoc = (int)(*s++ - L'0');
285     if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
286       return 0;
287     if (*s++ != 0)
288       return 0;
289     *btMode = 0;
290     *numHashBytes = numHashBytesLoc;
291     return 1;
292   }
293   if (c != L'B')
294     return 0;
295
296   if (GetUpperChar(*s++) != L'T')
297     return 0;
298   int numHashBytesLoc = (int)(*s++ - L'0');
299   if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
300     return 0;
301   c = GetUpperChar(*s++);
302   /*
303   int skipModeBitsLoc = 0;
304   if (c == L'D')
305   {
306     skipModeBitsLoc = 2;
307     c = GetUpperChar(*s++);
308   }
309   */
310   if (c != L'\0')
311     return 0;
312   *btMode = 1;
313   *numHashBytes = numHashBytesLoc;
314   // *skipModeBits = skipModeBitsLoc;
315   return 1;
316 }
317
318 STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, 
319     const PROPVARIANT *properties, UInt32 numProperties)
320 {
321   for (UInt32 i = 0; i < numProperties; i++)
322   {
323     const PROPVARIANT &prop = properties[i];
324     switch(propIDs[i])
325     {
326       case NCoderPropID::kNumFastBytes:
327       {
328         if (prop.vt != VT_UI4)
329           return E_INVALIDARG;
330         UInt32 numFastBytes = prop.ulVal;
331         if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
332           return E_INVALIDARG;
333         _numFastBytes = numFastBytes;
334         break;
335       }
336       case NCoderPropID::kMatchFinderCycles:
337       {
338         if (prop.vt != VT_UI4)
339           return E_INVALIDARG;
340         _matchFinderCycles = prop.ulVal;
341         break;
342       }
343       case NCoderPropID::kAlgorithm:
344       {
345         if (prop.vt != VT_UI4)
346           return E_INVALIDARG;
347         UInt32 maximize = prop.ulVal;
348         _fastMode = (maximize == 0); 
349         // _maxMode = (maximize >= 2);
350         break;
351       }
352       case NCoderPropID::kMatchFinder:
353       {
354         if (prop.vt != VT_BSTR)
355           return E_INVALIDARG;
356         if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */))
357           return E_INVALIDARG;
358         break;
359       }
360       case NCoderPropID::kMultiThread:
361       {
362         if (prop.vt != VT_BOOL)
363           return E_INVALIDARG;
364         #ifdef COMPRESS_MF_MT
365         Bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
366         if (newMultiThread != _multiThread)
367         {
368           ReleaseMatchFinder();
369           _multiThread = newMultiThread;
370         }
371         #endif
372         break;
373       }
374       case NCoderPropID::kNumThreads:
375       {
376         if (prop.vt != VT_UI4)
377           return E_INVALIDARG;
378         #ifdef COMPRESS_MF_MT
379         Bool newMultiThread = (prop.ulVal > 1) ? True : False;
380         if (newMultiThread != _multiThread)
381         {
382           ReleaseMatchFinder();
383           _multiThread = newMultiThread;
384         }
385         #endif
386         break;
387       }
388       case NCoderPropID::kDictionarySize:
389       {
390         const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31;
391         if (prop.vt != VT_UI4)
392           return E_INVALIDARG;
393         UInt32 dictionarySize = prop.ulVal;
394         if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
395             dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
396           return E_INVALIDARG;
397         _dictionarySize = dictionarySize;
398         UInt32 dicLogSize;
399         for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
400           if (dictionarySize <= (UInt32(1) << dicLogSize))
401             break;
402         _distTableSize = dicLogSize * 2;
403         break;
404       }
405       case NCoderPropID::kPosStateBits:
406       {
407         if (prop.vt != VT_UI4)
408           return E_INVALIDARG;
409         UInt32 value = prop.ulVal;
410         if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
411           return E_INVALIDARG;
412         _posStateBits = value;
413         _posStateMask = (1 << _posStateBits) - 1;
414         break;
415       }
416       case NCoderPropID::kLitPosBits:
417       {
418         if (prop.vt != VT_UI4)
419           return E_INVALIDARG;
420         UInt32 value = prop.ulVal;
421         if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
422           return E_INVALIDARG;
423         _numLiteralPosStateBits = value;
424         break;
425       }
426       case NCoderPropID::kLitContextBits:
427       {
428         if (prop.vt != VT_UI4)
429           return E_INVALIDARG;
430         UInt32 value = prop.ulVal;
431         if (value > (UInt32)kNumLitContextBitsMax)
432           return E_INVALIDARG;
433         _numLiteralContextBits = value;
434         break;
435       }
436       case NCoderPropID::kEndMarker:
437       {
438         if (prop.vt != VT_BOOL)
439           return E_INVALIDARG;
440         SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
441         break;
442       }
443       default:
444         return E_INVALIDARG;
445     }
446   }
447   return S_OK;
448 }
449
450 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
451
452   const UInt32 kPropSize = 5;
453   Byte properties[kPropSize];
454   properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
455   for (int i = 0; i < 4; i++)
456     properties[1 + i] = Byte(_dictionarySize >> (8 * i));
457   return WriteStream(outStream, properties, kPropSize, NULL);
458 }
459
460 STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
461 {
462   _rangeEncoder.SetStream(outStream);
463   return S_OK;
464 }
465
466 STDMETHODIMP CEncoder::ReleaseOutStream()
467 {
468   _rangeEncoder.ReleaseStream();
469   return S_OK;
470 }
471
472 HRESULT CEncoder::Init()
473 {
474   CBaseState::Init();
475
476   _rangeEncoder.Init();
477
478   for(int i = 0; i < kNumStates; i++)
479   {
480     for (UInt32 j = 0; j <= _posStateMask; j++)
481     {
482       _isMatch[i][j].Init();
483       _isRep0Long[i][j].Init();
484     }
485     _isRep[i].Init();
486     _isRepG0[i].Init();
487     _isRepG1[i].Init();
488     _isRepG2[i].Init();
489   }
490
491   _literalEncoder.Init();
492
493   {
494     for(UInt32 i = 0; i < kNumLenToPosStates; i++)
495       _posSlotEncoder[i].Init();
496   }
497   {
498     for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
499       _posEncoders[i].Init();
500   }
501
502   _lenEncoder.Init(1 << _posStateBits);
503   _repMatchLenEncoder.Init(1 << _posStateBits);
504
505   _posAlignEncoder.Init();
506
507   _longestMatchWasFound = false;
508   _optimumEndIndex = 0;
509   _optimumCurrentIndex = 0;
510   _additionalOffset = 0;
511
512   return S_OK;
513 }
514
515 #ifdef SHOW_STAT
516 static int ttt = 0;
517 #endif
518
519 void CEncoder::MovePos(UInt32 num)
520 {
521   #ifdef SHOW_STAT
522   ttt += num;
523   printf("\n MovePos %d", num);
524   #endif
525   if (num != 0)
526   {
527     _additionalOffset += num;
528     _matchFinder.Skip(_matchFinderObj, num);
529   }
530 }
531
532 UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
533 {
534   _optimumEndIndex = cur;
535   UInt32 posMem = _optimum[cur].PosPrev;
536   UInt32 backMem = _optimum[cur].BackPrev;
537   do
538   {
539     if (_optimum[cur].Prev1IsChar)
540     {
541       _optimum[posMem].MakeAsChar();
542       _optimum[posMem].PosPrev = posMem - 1;
543       if (_optimum[cur].Prev2)
544       {
545         _optimum[posMem - 1].Prev1IsChar = false;
546         _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
547         _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
548       }
549     }
550     UInt32 posPrev = posMem;
551     UInt32 backCur = backMem;
552
553     backMem = _optimum[posPrev].BackPrev;
554     posMem = _optimum[posPrev].PosPrev;
555
556     _optimum[posPrev].BackPrev = backCur;
557     _optimum[posPrev].PosPrev = cur;
558     cur = posPrev;
559   }
560   while(cur != 0);
561   backRes = _optimum[0].BackPrev;
562   _optimumCurrentIndex  = _optimum[0].PosPrev;
563   return _optimumCurrentIndex; 
564 }
565
566 /*
567 Out:
568   (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
569 */
570
571 UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes)
572 {
573   if(_optimumEndIndex != _optimumCurrentIndex)
574   {
575     const COptimal &optimum = _optimum[_optimumCurrentIndex];
576     UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex;
577     backRes = optimum.BackPrev;
578     _optimumCurrentIndex = optimum.PosPrev;
579     return lenRes;
580   }
581   _optimumCurrentIndex = _optimumEndIndex = 0;
582   
583   UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
584
585   UInt32 lenMain, numDistancePairs;
586   if (!_longestMatchWasFound)
587   {
588     lenMain = ReadMatchDistances(numDistancePairs);
589   }
590   else
591   {
592     lenMain = _longestMatchLength;
593     numDistancePairs = _numDistancePairs;
594     _longestMatchWasFound = false;
595   }
596
597   const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
598   if (numAvailableBytes < 2)
599   {
600     backRes = (UInt32)(-1);
601     return 1;
602   }
603   if (numAvailableBytes > kMatchMaxLen)
604     numAvailableBytes = kMatchMaxLen;
605
606   UInt32 reps[kNumRepDistances];
607   UInt32 repLens[kNumRepDistances];
608   UInt32 repMaxIndex = 0;
609   UInt32 i;
610   for(i = 0; i < kNumRepDistances; i++)
611   {
612     reps[i] = _repDistances[i];
613     const Byte *data2 = data - (reps[i] + 1);
614     if (data[0] != data2[0] || data[1] != data2[1])
615     {
616       repLens[i] = 0;
617       continue;
618     }
619     UInt32 lenTest;
620     for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
621     repLens[i] = lenTest;
622     if (lenTest > repLens[repMaxIndex])
623       repMaxIndex = i;
624   }
625   if(repLens[repMaxIndex] >= _numFastBytes)
626   {
627     backRes = repMaxIndex;
628     UInt32 lenRes = repLens[repMaxIndex];
629     MovePos(lenRes - 1);
630     return lenRes;
631   }
632
633   UInt32 *matchDistances = _matchDistances;
634   if(lenMain >= _numFastBytes)
635   {
636     backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; 
637     MovePos(lenMain - 1);
638     return lenMain;
639   }
640   Byte currentByte = *data;
641   Byte matchByte = *(data - (reps[0] + 1));
642
643   if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
644   {
645     backRes = (UInt32)-1;
646     return 1;
647   }
648
649   _optimum[0].State = _state;
650
651   UInt32 posState = (position & _posStateMask);
652
653   _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + 
654       _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);
655   _optimum[1].MakeAsChar();
656
657   UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
658   UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
659
660   if(matchByte == currentByte)
661   {
662     UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
663     if(shortRepPrice < _optimum[1].Price)
664     {
665       _optimum[1].Price = shortRepPrice;
666       _optimum[1].MakeAsShortRep();
667     }
668   }
669   UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
670
671   if(lenEnd < 2)
672   {
673     backRes = _optimum[1].BackPrev;
674     return 1;
675   }
676
677   _optimum[1].PosPrev = 0;
678   for (i = 0; i < kNumRepDistances; i++)
679     _optimum[0].Backs[i] = reps[i];
680
681   UInt32 len = lenEnd;
682   do
683     _optimum[len--].Price = kIfinityPrice;
684   while (len >= 2);
685
686   for(i = 0; i < kNumRepDistances; i++)
687   {
688     UInt32 repLen = repLens[i];
689     if (repLen < 2)
690       continue;
691     UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
692     do
693     {
694       UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
695       COptimal &optimum = _optimum[repLen];
696       if (curAndLenPrice < optimum.Price) 
697       {
698         optimum.Price = curAndLenPrice;
699         optimum.PosPrev = 0;
700         optimum.BackPrev = i;
701         optimum.Prev1IsChar = false;
702       }
703     }
704     while(--repLen >= 2);
705   }
706
707   UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
708
709   len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
710   if (len <= lenMain)
711   {
712     UInt32 offs = 0;
713     while (len > matchDistances[offs])
714       offs += 2;
715     for(; ; len++)
716     {
717       UInt32 distance = matchDistances[offs + 1];
718       UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
719       COptimal &optimum = _optimum[len];
720       if (curAndLenPrice < optimum.Price) 
721       {
722         optimum.Price = curAndLenPrice;
723         optimum.PosPrev = 0;
724         optimum.BackPrev = distance + kNumRepDistances;
725         optimum.Prev1IsChar = false;
726       }
727       if (len == matchDistances[offs])
728       {
729         offs += 2;
730         if (offs == numDistancePairs)
731           break;
732       }
733     }
734   }
735
736   UInt32 cur = 0;
737
738   for (;;)
739   {
740     cur++;
741     if(cur == lenEnd)
742     {
743       return Backward(backRes, cur);
744     }
745     UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
746     UInt32 newLen, numDistancePairs;
747     newLen = ReadMatchDistances(numDistancePairs);
748     if(newLen >= _numFastBytes)
749     {
750       _numDistancePairs = numDistancePairs;
751       _longestMatchLength = newLen;
752       _longestMatchWasFound = true;
753       return Backward(backRes, cur);
754     }
755     position++;
756     COptimal &curOptimum = _optimum[cur];
757     UInt32 posPrev = curOptimum.PosPrev;
758     CState state;
759     if (curOptimum.Prev1IsChar)
760     {
761       posPrev--;
762       if (curOptimum.Prev2)
763       {
764         state = _optimum[curOptimum.PosPrev2].State;
765         if (curOptimum.BackPrev2 < kNumRepDistances)
766           state.UpdateRep();
767         else
768           state.UpdateMatch();
769       }
770       else
771         state = _optimum[posPrev].State;
772       state.UpdateChar();
773     }
774     else
775       state = _optimum[posPrev].State;
776     if (posPrev == cur - 1)
777     {
778       if (curOptimum.IsShortRep())
779         state.UpdateShortRep();
780       else
781         state.UpdateChar();
782     }
783     else
784     {
785       UInt32 pos;
786       if (curOptimum.Prev1IsChar && curOptimum.Prev2)
787       {
788         posPrev = curOptimum.PosPrev2;
789         pos = curOptimum.BackPrev2;
790         state.UpdateRep();
791       }
792       else
793       {
794         pos = curOptimum.BackPrev;
795         if (pos < kNumRepDistances)
796           state.UpdateRep();
797         else
798           state.UpdateMatch();
799       }
800       const COptimal &prevOptimum = _optimum[posPrev];
801       if (pos < kNumRepDistances)
802       {
803         reps[0] = prevOptimum.Backs[pos];
804         UInt32 i;
805         for(i = 1; i <= pos; i++)
806           reps[i] = prevOptimum.Backs[i - 1];
807         for(; i < kNumRepDistances; i++)
808           reps[i] = prevOptimum.Backs[i];
809       }
810       else
811       {
812         reps[0] = (pos - kNumRepDistances);
813         for(UInt32 i = 1; i < kNumRepDistances; i++)
814           reps[i] = prevOptimum.Backs[i - 1];
815       }
816     }
817     curOptimum.State = state;
818     for(UInt32 i = 0; i < kNumRepDistances; i++)
819       curOptimum.Backs[i] = reps[i];
820     UInt32 curPrice = curOptimum.Price; 
821     const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
822     const Byte currentByte = *data;
823     const Byte matchByte = *(data - (reps[0] + 1));
824
825     UInt32 posState = (position & _posStateMask);
826
827     UInt32 curAnd1Price = curPrice +
828         _isMatch[state.Index][posState].GetPrice0() +
829         _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte);
830
831     COptimal &nextOptimum = _optimum[cur + 1];
832
833     bool nextIsChar = false;
834     if (curAnd1Price < nextOptimum.Price) 
835     {
836       nextOptimum.Price = curAnd1Price;
837       nextOptimum.PosPrev = cur;
838       nextOptimum.MakeAsChar();
839       nextIsChar = true;
840     }
841
842     UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
843     UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
844     
845     if(matchByte == currentByte &&
846         !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
847     {
848       UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
849       if(shortRepPrice <= nextOptimum.Price)
850       {
851         nextOptimum.Price = shortRepPrice;
852         nextOptimum.PosPrev = cur;
853         nextOptimum.MakeAsShortRep();
854         nextIsChar = true;
855       }
856     }
857     /*
858     if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
859       continue;
860     */
861
862     numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
863     UInt32 numAvailableBytes = numAvailableBytesFull;
864
865     if (numAvailableBytes < 2)
866       continue;
867     if (numAvailableBytes > _numFastBytes)
868       numAvailableBytes = _numFastBytes;
869     if (!nextIsChar && matchByte != currentByte) // speed optimization
870     {
871       // try Literal + rep0
872       const Byte *data2 = data - (reps[0] + 1);
873       UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1);
874       UInt32 temp;
875       for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
876       UInt32 lenTest2 = temp - 1;
877       if (lenTest2 >= 2)
878       {
879         CState state2 = state;
880         state2.UpdateChar();
881         UInt32 posStateNext = (position + 1) & _posStateMask;
882         UInt32 nextRepMatchPrice = curAnd1Price + 
883             _isMatch[state2.Index][posStateNext].GetPrice1() +
884             _isRep[state2.Index].GetPrice1();
885         // for (; lenTest2 >= 2; lenTest2--)
886         {
887           UInt32 offset = cur + 1 + lenTest2;
888           while(lenEnd < offset)
889             _optimum[++lenEnd].Price = kIfinityPrice;
890           UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
891               0, lenTest2, state2, posStateNext);
892           COptimal &optimum = _optimum[offset];
893           if (curAndLenPrice < optimum.Price) 
894           {
895             optimum.Price = curAndLenPrice;
896             optimum.PosPrev = cur + 1;
897             optimum.BackPrev = 0;
898             optimum.Prev1IsChar = true;
899             optimum.Prev2 = false;
900           }
901         }
902       }
903     }
904     
905     UInt32 startLen = 2; // speed optimization 
906     for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
907     {
908       // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
909       const Byte *data2 = data - (reps[repIndex] + 1);
910       if (data[0] != data2[0] || data[1] != data2[1])
911         continue;
912       UInt32 lenTest;
913       for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
914       while(lenEnd < cur + lenTest)
915         _optimum[++lenEnd].Price = kIfinityPrice;
916       UInt32 lenTestTemp = lenTest;
917       UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);
918       do
919       {
920         UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);
921         COptimal &optimum = _optimum[cur + lenTest];
922         if (curAndLenPrice < optimum.Price) 
923         {
924           optimum.Price = curAndLenPrice;
925           optimum.PosPrev = cur;
926           optimum.BackPrev = repIndex;
927           optimum.Prev1IsChar = false;
928         }
929       }
930       while(--lenTest >= 2);
931       lenTest = lenTestTemp;
932       
933       if (repIndex == 0)
934         startLen = lenTest + 1;
935         
936       // if (_maxMode)
937         {
938           UInt32 lenTest2 = lenTest + 1;
939           UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
940           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
941           lenTest2 -= lenTest + 1;
942           if (lenTest2 >= 2)
943           {
944             CState state2 = state;
945             state2.UpdateRep();
946             UInt32 posStateNext = (position + lenTest) & _posStateMask;
947             UInt32 curAndLenCharPrice = 
948                 price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + 
949                 _isMatch[state2.Index][posStateNext].GetPrice0() +
950                 _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice(
951                 true, data2[lenTest], data[lenTest]);
952             state2.UpdateChar();
953             posStateNext = (position + lenTest + 1) & _posStateMask;
954             UInt32 nextRepMatchPrice = curAndLenCharPrice + 
955                 _isMatch[state2.Index][posStateNext].GetPrice1() +
956                 _isRep[state2.Index].GetPrice1();
957             
958             // for(; lenTest2 >= 2; lenTest2--)
959             {
960               UInt32 offset = cur + lenTest + 1 + lenTest2;
961               while(lenEnd < offset)
962                 _optimum[++lenEnd].Price = kIfinityPrice;
963               UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
964                   0, lenTest2, state2, posStateNext);
965               COptimal &optimum = _optimum[offset];
966               if (curAndLenPrice < optimum.Price) 
967               {
968                 optimum.Price = curAndLenPrice;
969                 optimum.PosPrev = cur + lenTest + 1;
970                 optimum.BackPrev = 0;
971                 optimum.Prev1IsChar = true;
972                 optimum.Prev2 = true;
973                 optimum.PosPrev2 = cur;
974                 optimum.BackPrev2 = repIndex;
975               }
976             }
977           }
978         }
979       }
980     
981     //    for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
982     if (newLen > numAvailableBytes)
983     {
984       newLen = numAvailableBytes;
985       for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
986       matchDistances[numDistancePairs] = newLen;
987       numDistancePairs += 2;
988     }
989     if (newLen >= startLen)
990     {
991       UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
992       while(lenEnd < cur + newLen)
993         _optimum[++lenEnd].Price = kIfinityPrice;
994
995       UInt32 offs = 0;
996       while(startLen > matchDistances[offs])
997         offs += 2;
998       UInt32 curBack = matchDistances[offs + 1];
999       UInt32 posSlot = GetPosSlot2(curBack);
1000       for(UInt32 lenTest = /*2*/ startLen; ; lenTest++)
1001       {
1002         UInt32 curAndLenPrice = normalMatchPrice;
1003         UInt32 lenToPosState = GetLenToPosState(lenTest);
1004         if (curBack < kNumFullDistances)
1005           curAndLenPrice += _distancesPrices[lenToPosState][curBack];
1006         else
1007           curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask];
1008   
1009         curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);
1010         
1011         COptimal &optimum = _optimum[cur + lenTest];
1012         if (curAndLenPrice < optimum.Price) 
1013         {
1014           optimum.Price = curAndLenPrice;
1015           optimum.PosPrev = cur;
1016           optimum.BackPrev = curBack + kNumRepDistances;
1017           optimum.Prev1IsChar = false;
1018         }
1019
1020         if (/*_maxMode && */lenTest == matchDistances[offs])
1021         {
1022           // Try Match + Literal + Rep0
1023           const Byte *data2 = data - (curBack + 1);
1024           UInt32 lenTest2 = lenTest + 1;
1025           UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
1026           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
1027           lenTest2 -= lenTest + 1;
1028           if (lenTest2 >= 2)
1029           {
1030             CState state2 = state;
1031             state2.UpdateMatch();
1032             UInt32 posStateNext = (position + lenTest) & _posStateMask;
1033             UInt32 curAndLenCharPrice = curAndLenPrice + 
1034                 _isMatch[state2.Index][posStateNext].GetPrice0() +
1035                 _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( 
1036                 true, data2[lenTest], data[lenTest]);
1037             state2.UpdateChar();
1038             posStateNext = (posStateNext + 1) & _posStateMask;
1039             UInt32 nextRepMatchPrice = curAndLenCharPrice + 
1040                 _isMatch[state2.Index][posStateNext].GetPrice1() +
1041                 _isRep[state2.Index].GetPrice1();
1042             
1043             // for(; lenTest2 >= 2; lenTest2--)
1044             {
1045               UInt32 offset = cur + lenTest + 1 + lenTest2;
1046               while(lenEnd < offset)
1047                 _optimum[++lenEnd].Price = kIfinityPrice;
1048               UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
1049               COptimal &optimum = _optimum[offset];
1050               if (curAndLenPrice < optimum.Price) 
1051               {
1052                 optimum.Price = curAndLenPrice;
1053                 optimum.PosPrev = cur + lenTest + 1;
1054                 optimum.BackPrev = 0;
1055                 optimum.Prev1IsChar = true;
1056                 optimum.Prev2 = true;
1057                 optimum.PosPrev2 = cur;
1058                 optimum.BackPrev2 = curBack + kNumRepDistances;
1059               }
1060             }
1061           }
1062           offs += 2;
1063           if (offs == numDistancePairs)
1064             break;
1065           curBack = matchDistances[offs + 1];
1066           if (curBack >= kNumFullDistances)
1067             posSlot = GetPosSlot2(curBack);
1068         }
1069       }
1070     }
1071   }
1072 }
1073
1074 static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
1075 {
1076   return ((bigDist >> 7) > smallDist);
1077 }
1078
1079 UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs)
1080 {
1081   UInt32 lenRes = 0;
1082   numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances);
1083   #ifdef SHOW_STAT
1084   printf("\n i = %d numPairs = %d    ", ttt, numDistancePairs / 2);
1085   if (ttt >= 61994)
1086     ttt = ttt;
1087
1088   ttt++;
1089   for (UInt32 i = 0; i < numDistancePairs; i += 2)
1090     printf("%2d %6d   | ", _matchDistances[i], _matchDistances[i + 1]);
1091   #endif
1092   if (numDistancePairs > 0)
1093   {
1094     lenRes = _matchDistances[numDistancePairs - 2];
1095     if (lenRes == _numFastBytes)
1096     {
1097       UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1;
1098       const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
1099       UInt32 distance = _matchDistances[numDistancePairs - 1] + 1;
1100       if (numAvail > kMatchMaxLen)
1101         numAvail = kMatchMaxLen;
1102
1103       const Byte *pby2 = pby - distance;
1104       for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
1105     }
1106   }
1107   _additionalOffset++;
1108   return lenRes;
1109 }
1110
1111 UInt32 CEncoder::GetOptimumFast(UInt32 &backRes)
1112 {
1113   UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
1114   UInt32 lenMain, numDistancePairs;
1115   if (!_longestMatchWasFound)
1116   {
1117     lenMain = ReadMatchDistances(numDistancePairs);
1118   }
1119   else
1120   {
1121     lenMain = _longestMatchLength;
1122     numDistancePairs = _numDistancePairs;
1123     _longestMatchWasFound = false;
1124   }
1125
1126   const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
1127   if (numAvailableBytes > kMatchMaxLen)
1128     numAvailableBytes = kMatchMaxLen;
1129   if (numAvailableBytes < 2)
1130   {
1131     backRes = (UInt32)(-1);
1132     return 1;
1133   }
1134
1135   UInt32 repLens[kNumRepDistances];
1136   UInt32 repMaxIndex = 0;
1137
1138   for(UInt32 i = 0; i < kNumRepDistances; i++)
1139   {
1140     const Byte *data2 = data - (_repDistances[i] + 1);
1141     if (data[0] != data2[0] || data[1] != data2[1])
1142     {
1143       repLens[i] = 0;
1144       continue;
1145     }
1146     UInt32 len;
1147     for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
1148     if(len >= _numFastBytes)
1149     {
1150       backRes = i;
1151       MovePos(len - 1);
1152       return len;
1153     }
1154     repLens[i] = len;
1155     if (len > repLens[repMaxIndex])
1156       repMaxIndex = i;
1157   }
1158   UInt32 *matchDistances = _matchDistances;
1159   if(lenMain >= _numFastBytes)
1160   {
1161     backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; 
1162     MovePos(lenMain - 1);
1163     return lenMain;
1164   }
1165
1166   UInt32 backMain = 0; // for GCC
1167   if (lenMain >= 2)
1168   {
1169     backMain = matchDistances[numDistancePairs - 1];
1170     while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
1171     {
1172       if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
1173         break;
1174       numDistancePairs -= 2;
1175       lenMain = matchDistances[numDistancePairs - 2];
1176       backMain = matchDistances[numDistancePairs - 1];
1177     }
1178     if (lenMain == 2 && backMain >= 0x80)
1179       lenMain = 1;
1180   }
1181
1182   if (repLens[repMaxIndex] >= 2)
1183   {
1184     if (repLens[repMaxIndex] + 1 >= lenMain || 
1185         repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
1186         repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
1187     {
1188       backRes = repMaxIndex;
1189       UInt32 lenRes = repLens[repMaxIndex];
1190       MovePos(lenRes - 1);
1191       return lenRes;
1192     }
1193   }
1194   
1195   if (lenMain >= 2 && numAvailableBytes > 2)
1196   {
1197     numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
1198     _longestMatchLength = ReadMatchDistances(_numDistancePairs);
1199     if (_longestMatchLength >= 2)
1200     {
1201       UInt32 newDistance = matchDistances[_numDistancePairs - 1];
1202       if (_longestMatchLength >= lenMain && newDistance < backMain || 
1203           _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
1204           _longestMatchLength > lenMain + 1 ||
1205           _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
1206       {
1207         _longestMatchWasFound = true;
1208         backRes = UInt32(-1);
1209         return 1;
1210       }
1211     }
1212     data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
1213     for(UInt32 i = 0; i < kNumRepDistances; i++)
1214     {
1215       const Byte *data2 = data - (_repDistances[i] + 1);
1216       if (data[1] != data2[1] || data[2] != data2[2])
1217       {
1218         repLens[i] = 0;
1219         continue;
1220       }
1221       UInt32 len;
1222       for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
1223       if (len + 1 >= lenMain)
1224       {
1225         _longestMatchWasFound = true;
1226         backRes = UInt32(-1);
1227         return 1;
1228       }
1229     }
1230     backRes = backMain + kNumRepDistances; 
1231     MovePos(lenMain - 2);
1232     return lenMain;
1233   }
1234   backRes = UInt32(-1);
1235   return 1;
1236 }
1237
1238 HRESULT CEncoder::Flush(UInt32 nowPos)
1239 {
1240   // ReleaseMFStream();
1241   if (_matchFinderBase.result != SZ_OK)
1242     return _matchFinderBase.result;
1243   WriteEndMarker(nowPos & _posStateMask);
1244   _rangeEncoder.FlushData();
1245   return _rangeEncoder.FlushStream();
1246 }
1247
1248 void CEncoder::WriteEndMarker(UInt32 posState)
1249 {
1250   // This function for writing End Mark for stream version of LZMA. 
1251   // In current version this feature is not used.
1252   if (!_writeEndMark)
1253     return;
1254
1255   _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
1256   _isRep[_state.Index].Encode(&_rangeEncoder, 0);
1257   _state.UpdateMatch();
1258   UInt32 len = kMatchMinLen; // kMatchMaxLen;
1259   _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
1260   UInt32 posSlot = (1 << kNumPosSlotBits)  - 1;
1261   UInt32 lenToPosState = GetLenToPosState(len);
1262   _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
1263   UInt32 footerBits = 30;
1264   UInt32 posReduced = (UInt32(1) << footerBits) - 1;
1265   _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1266   _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
1267 }
1268
1269 HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
1270       ISequentialOutStream *outStream, 
1271       const UInt64 *inSize, const UInt64 *outSize,
1272       ICompressProgressInfo *progress)
1273 {
1274   // _needReleaseMFStream = false;
1275   #ifdef COMPRESS_MF_MT
1276   #ifdef USE_ALLOCA
1277   alloca(0x300);
1278   #endif
1279   #endif
1280   CCoderReleaser coderReleaser(this);
1281   RINOK(SetStreams(inStream, outStream, inSize, outSize));
1282   for (;;)
1283   {
1284     UInt64 processedInSize;
1285     UInt64 processedOutSize;
1286     Int32 finished;
1287     RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
1288     if (finished != 0)
1289       break;
1290     if (progress != 0)
1291     {
1292       RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
1293     }
1294   }
1295   return S_OK;
1296 }
1297
1298 HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
1299       ISequentialOutStream *outStream, 
1300       const UInt64 * /* inSize */, const UInt64 * /* outSize */)
1301 {
1302   _inStream = inStream;
1303   _finished = false;
1304   RINOK(Create());
1305   RINOK(SetOutStream(outStream));
1306   RINOK(Init());
1307   
1308   if (!_fastMode)
1309   {
1310     FillDistancesPrices();
1311     FillAlignPrices();
1312   }
1313
1314   _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
1315   _lenEncoder.UpdateTables(1 << _posStateBits);
1316   _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
1317   _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
1318
1319   nowPos64 = 0;
1320   return S_OK;
1321 }
1322
1323 static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize)
1324 {
1325   return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize);
1326 }
1327
1328 HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
1329 {
1330   if (_inStream != 0)
1331   {
1332     _seqInStream.RealStream = _inStream;
1333     _seqInStream.SeqInStream.Read = MyRead;
1334     _matchFinderBase.stream = &_seqInStream.SeqInStream;
1335     _matchFinder.Init(_matchFinderObj);
1336     _needReleaseMFStream = true;
1337     _inStream = 0;
1338   }
1339
1340
1341   *finished = 1;
1342   if (_finished)
1343     return _matchFinderBase.result;
1344   _finished = true;
1345
1346   if (nowPos64 == 0)
1347   {
1348     if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
1349       return Flush((UInt32)nowPos64);
1350     UInt32 len, numDistancePairs;
1351     len = ReadMatchDistances(numDistancePairs);
1352     UInt32 posState = UInt32(nowPos64) & _posStateMask;
1353     _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
1354     _state.UpdateChar();
1355     Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
1356     _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
1357     _previousByte = curByte;
1358     _additionalOffset--;
1359     nowPos64++;
1360   }
1361
1362   UInt32 nowPos32 = (UInt32)nowPos64;
1363   UInt32 progressPosValuePrev = nowPos32;
1364
1365   if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
1366     return Flush(nowPos32);
1367
1368   for (;;)
1369   {
1370     #ifdef _NO_EXCEPTIONS
1371     if (_rangeEncoder.Stream.ErrorCode != S_OK)
1372       return _rangeEncoder.Stream.ErrorCode;
1373     #endif
1374     UInt32 pos, len;
1375
1376     if (_fastMode)
1377       len = GetOptimumFast(pos);
1378     else
1379       len = GetOptimum(nowPos32, pos);
1380
1381     UInt32 posState = nowPos32 & _posStateMask;
1382     if(len == 1 && pos == 0xFFFFFFFF)
1383     {
1384       _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
1385       Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
1386       CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);
1387       if(_state.IsCharState())
1388         subCoder->Encode(&_rangeEncoder, curByte);
1389       else
1390       {
1391         Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset);
1392         subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
1393       }
1394       _state.UpdateChar();
1395       _previousByte = curByte;
1396     }
1397     else
1398     {
1399       _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
1400       if(pos < kNumRepDistances)
1401       {
1402         _isRep[_state.Index].Encode(&_rangeEncoder, 1);
1403         if(pos == 0)
1404         {
1405           _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
1406           _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));
1407         }
1408         else
1409         {
1410           UInt32 distance = _repDistances[pos];
1411           _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
1412           if (pos == 1)
1413             _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
1414           else
1415           {
1416             _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
1417             _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
1418             if (pos == 3)
1419               _repDistances[3] = _repDistances[2];
1420             _repDistances[2] = _repDistances[1];
1421           }
1422           _repDistances[1] = _repDistances[0];
1423           _repDistances[0] = distance;
1424         }
1425         if (len == 1)
1426           _state.UpdateShortRep();
1427         else
1428         {
1429           _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
1430           _state.UpdateRep();
1431         }
1432       }
1433       else
1434       {
1435         _isRep[_state.Index].Encode(&_rangeEncoder, 0);
1436         _state.UpdateMatch();
1437         _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
1438         pos -= kNumRepDistances;
1439         UInt32 posSlot = GetPosSlot(pos);
1440         _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);
1441         
1442         if (posSlot >= kStartPosModelIndex)
1443         {
1444           UInt32 footerBits = ((posSlot >> 1) - 1);
1445           UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1446           UInt32 posReduced = pos - base;
1447
1448           if (posSlot < kEndPosModelIndex)
1449             NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, 
1450                 &_rangeEncoder, footerBits, posReduced);
1451           else
1452           {
1453             _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1454             _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
1455             _alignPriceCount++;
1456           }
1457         }
1458         _repDistances[3] = _repDistances[2];
1459         _repDistances[2] = _repDistances[1];
1460         _repDistances[1] = _repDistances[0];
1461         _repDistances[0] = pos;
1462         _matchPriceCount++;
1463       }
1464       _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset);
1465     }
1466     _additionalOffset -= len;
1467     nowPos32 += len;
1468     if (_additionalOffset == 0)
1469     {
1470       if (!_fastMode)
1471       {
1472         if (_matchPriceCount >= (1 << 7))
1473           FillDistancesPrices();
1474         if (_alignPriceCount >= kAlignTableSize)
1475           FillAlignPrices();
1476       }
1477       if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
1478         return Flush(nowPos32);
1479       if (nowPos32 - progressPosValuePrev >= (1 << 14))
1480       {
1481         nowPos64 += nowPos32 - progressPosValuePrev;
1482         *inSize = nowPos64;
1483         *outSize = _rangeEncoder.GetProcessedSize();
1484         _finished = false;
1485         *finished = 0;
1486         return _matchFinderBase.result;
1487       }
1488     }
1489   }
1490 }
1491
1492 STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
1493     ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
1494     ICompressProgressInfo *progress)
1495 {
1496   #ifndef _NO_EXCEPTIONS
1497   try 
1498   { 
1499   #endif
1500     return CodeReal(inStream, outStream, inSize, outSize, progress); 
1501   #ifndef _NO_EXCEPTIONS
1502   }
1503   catch(const COutBufferException &e) { return e.ErrorCode; }
1504   catch(...) { return E_FAIL; }
1505   #endif
1506 }
1507   
1508 void CEncoder::FillDistancesPrices()
1509 {
1510   UInt32 tempPrices[kNumFullDistances];
1511   for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)
1512   { 
1513     UInt32 posSlot = GetPosSlot(i);
1514     UInt32 footerBits = ((posSlot >> 1) - 1);
1515     UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1516     tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + 
1517       base - posSlot - 1, footerBits, i - base);
1518   }
1519
1520   for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1521   {
1522     UInt32 posSlot;
1523     NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];
1524     UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];
1525     for (posSlot = 0; posSlot < _distTableSize; posSlot++)
1526       posSlotPrices[posSlot] = encoder.GetPrice(posSlot);
1527     for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
1528       posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
1529
1530     UInt32 *distancesPrices = _distancesPrices[lenToPosState];
1531     UInt32 i;
1532     for (i = 0; i < kStartPosModelIndex; i++)
1533       distancesPrices[i] = posSlotPrices[i];
1534     for (; i < kNumFullDistances; i++)
1535       distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];
1536   }
1537   _matchPriceCount = 0;
1538 }
1539
1540 void CEncoder::FillAlignPrices()
1541 {
1542   for (UInt32 i = 0; i < kAlignTableSize; i++)
1543     _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
1544   _alignPriceCount = 0;
1545 }
1546
1547 }}