]> git.cworth.org Git - vogl/blob - src/voglcore/lzma_LzmaEnc.cpp
Initial vogl checkin
[vogl] / src / voglcore / lzma_LzmaEnc.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 /* LzmaEnc.c -- LZMA Encoder
28 2008-10-04 : Igor Pavlov : Public domain */
29 #include "vogl_core.h"
30 #include <string.h>
31
32 /* #define SHOW_STAT */
33 /* #define SHOW_STAT2 */
34
35 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
36 #include <stdio.h>
37 #endif
38
39 #include "lzma_LzmaEnc.h"
40
41 #include "lzma_LzFind.h"
42 #ifdef COMPRESS_MF_MT
43 #include "lzma_LzFindMt.h"
44 #endif
45
46 namespace vogl
47 {
48
49 #ifdef SHOW_STAT
50     static int ttt = 0;
51 #endif
52
53 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
54
55 #define kBlockSize (9 << 10)
56 #define kUnpackBlockSize (1 << 18)
57 #define kMatchArraySize (1 << 21)
58 #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
59
60 #define kNumMaxDirectBits (31)
61
62 #define kNumTopBits 24
63 #define kTopValue ((UInt32)1 << kNumTopBits)
64
65 #define kNumBitModelTotalBits 11
66 #define kBitModelTotal (1 << kNumBitModelTotalBits)
67 #define kNumMoveBits 5
68 #define kProbInitValue (kBitModelTotal >> 1)
69
70 #define kNumMoveReducingBits 4
71 #define kNumBitPriceShiftBits 4
72 #define kBitPrice (1 << kNumBitPriceShiftBits)
73
74     void LzmaEncProps_Init(CLzmaEncProps *p)
75     {
76         p->level = 5;
77         p->dictSize = p->mc = 0;
78         p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
79         p->writeEndMark = 0;
80     }
81
82     void LzmaEncProps_Normalize(CLzmaEncProps *p)
83     {
84         int level = p->level;
85         if (level < 0)
86             level = 5;
87         p->level = level;
88         if (p->dictSize == 0)
89             p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
90         if (p->lc < 0)
91             p->lc = 3;
92         if (p->lp < 0)
93             p->lp = 0;
94         if (p->pb < 0)
95             p->pb = 2;
96         if (p->algo < 0)
97             p->algo = (level < 5 ? 0 : 1);
98         if (p->fb < 0)
99             p->fb = (level < 7 ? 32 : 64);
100         if (p->btMode < 0)
101             p->btMode = (p->algo == 0 ? 0 : 1);
102         if (p->numHashBytes < 0)
103             p->numHashBytes = 4;
104         if (p->mc == 0)
105             p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
106         if (p->numThreads < 0)
107             p->numThreads = ((p->btMode && p->algo) ? 2 : 1);
108     }
109
110     UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
111     {
112         CLzmaEncProps props = *props2;
113         LzmaEncProps_Normalize(&props);
114         return props.dictSize;
115     }
116
117 /* #define LZMA_LOG_BSR */
118 /* Define it for Intel's CPU */
119
120 #ifdef LZMA_LOG_BSR
121
122 #define kDicLogSizeMaxCompress 30
123
124 #define BSR2_RET(pos, res)                      \
125     {                                           \
126         unsigned long i;                        \
127         _BitScanReverse(&i, (pos));             \
128         res = (i + i) + ((pos >> (i - 1)) & 1); \
129     }
130
131     UInt32 GetPosSlot1(UInt32 pos)
132     {
133         UInt32 res;
134         BSR2_RET(pos, res);
135         return res;
136     }
137 #define GetPosSlot2(pos, res) \
138     {                         \
139         BSR2_RET(pos, res);   \
140     }
141 #define GetPosSlot(pos, res)    \
142     {                           \
143         if (pos < 2)            \
144             res = pos;          \
145         else                    \
146             BSR2_RET(pos, res); \
147     }
148
149 #else
150
151 #define kNumLogBits (9 + (int)sizeof(size_t) / 2)
152 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
153
154     void LzmaEnc_FastPosInit(Byte *g_FastPos)
155     {
156         int c = 2, slotFast;
157         g_FastPos[0] = 0;
158         g_FastPos[1] = 1;
159
160         for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
161         {
162             UInt32 k = (1 << ((slotFast >> 1) - 1));
163             UInt32 j;
164             for (j = 0; j < k; j++, c++)
165                 g_FastPos[c] = (Byte)slotFast;
166         }
167     }
168
169 #define BSR2_RET(pos, res)                                                                                 \
170     {                                                                                                      \
171         UInt32 i = 6 + ((kNumLogBits - 1) & (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
172         res = p->g_FastPos[pos >> i] + (i * 2);                                                            \
173     }
174 /*
175 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
176   p->g_FastPos[pos >> 6] + 12 : \
177   p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
178 */
179
180 #define GetPosSlot1(pos) p->g_FastPos[pos]
181 #define GetPosSlot2(pos, res) \
182     {                         \
183         BSR2_RET(pos, res);   \
184     }
185 #define GetPosSlot(pos, res)         \
186     {                                \
187         if (pos < kNumFullDistances) \
188             res = p->g_FastPos[pos]; \
189         else                         \
190             BSR2_RET(pos, res);      \
191     }
192
193 #endif
194
195 #define LZMA_NUM_REPS 4
196
197     typedef unsigned CState;
198
199     typedef struct _COptimal
200     {
201         UInt32 price;
202
203         CState state;
204         int prev1IsChar;
205         int prev2;
206
207         UInt32 posPrev2;
208         UInt32 backPrev2;
209
210         UInt32 posPrev;
211         UInt32 backPrev;
212         UInt32 backs[LZMA_NUM_REPS];
213     } COptimal;
214
215 #define kNumOpts (1 << 12)
216
217 #define kNumLenToPosStates 4
218 #define kNumPosSlotBits 6
219 #define kDicLogSizeMin 0
220 #define kDicLogSizeMax 32
221 #define kDistTableSizeMax (kDicLogSizeMax * 2)
222
223 #define kNumAlignBits 4
224 #define kAlignTableSize (1 << kNumAlignBits)
225 #define kAlignMask (kAlignTableSize - 1)
226
227 #define kStartPosModelIndex 4
228 #define kEndPosModelIndex 14
229 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
230
231 #define kNumFullDistances (1 << (kEndPosModelIndex / 2))
232
233 #ifdef _LZMA_PROB32
234 #define CLzmaProb UInt32
235 #else
236 #define CLzmaProb UInt16
237 #endif
238
239 #define LZMA_PB_MAX 4
240 #define LZMA_LC_MAX 8
241 #define LZMA_LP_MAX 4
242
243 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
244
245 #define kLenNumLowBits 3
246 #define kLenNumLowSymbols (1 << kLenNumLowBits)
247 #define kLenNumMidBits 3
248 #define kLenNumMidSymbols (1 << kLenNumMidBits)
249 #define kLenNumHighBits 8
250 #define kLenNumHighSymbols (1 << kLenNumHighBits)
251
252 #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
253
254 #define LZMA_MATCH_LEN_MIN 2
255 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
256
257 #define kNumStates 12
258
259     typedef struct
260     {
261         CLzmaProb choice;
262         CLzmaProb choice2;
263         CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
264         CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
265         CLzmaProb high[kLenNumHighSymbols];
266     } CLenEnc;
267
268     typedef struct
269     {
270         CLenEnc p;
271         UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
272         UInt32 tableSize;
273         UInt32 counters[LZMA_NUM_PB_STATES_MAX];
274     } CLenPriceEnc;
275
276     typedef struct _CRangeEnc
277     {
278         UInt32 range;
279         Byte cache;
280         UInt64 low;
281         UInt64 cacheSize;
282         Byte *buf;
283         Byte *bufLim;
284         Byte *bufBase;
285         ISeqOutStream *outStream;
286         UInt64 processed;
287         SRes res;
288     } CRangeEnc;
289
290     typedef struct _CSeqInStreamBuf
291     {
292         ISeqInStream funcTable;
293         const Byte *data;
294         SizeT rem;
295     } CSeqInStreamBuf;
296
297     static SRes MyRead(void *pp, void *data, size_t *size)
298     {
299         size_t curSize = *size;
300         CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
301         if (p->rem < curSize)
302             curSize = p->rem;
303         memcpy(data, p->data, curSize);
304         p->rem -= curSize;
305         p->data += curSize;
306         *size = curSize;
307         return SZ_OK;
308     }
309
310     typedef struct
311     {
312         CLzmaProb *litProbs;
313
314         CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
315         CLzmaProb isRep[kNumStates];
316         CLzmaProb isRepG0[kNumStates];
317         CLzmaProb isRepG1[kNumStates];
318         CLzmaProb isRepG2[kNumStates];
319         CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
320
321         CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
322         CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
323         CLzmaProb posAlignEncoder[1 << kNumAlignBits];
324
325         CLenPriceEnc lenEnc;
326         CLenPriceEnc repLenEnc;
327
328         UInt32 reps[LZMA_NUM_REPS];
329         UInt32 state;
330     } CSaveState;
331
332     typedef struct _CLzmaEnc
333     {
334         IMatchFinder matchFinder;
335         void *matchFinderObj;
336
337 #ifdef COMPRESS_MF_MT
338         Bool mtMode;
339         CMatchFinderMt matchFinderMt;
340 #endif
341
342         CMatchFinder matchFinderBase;
343
344 #ifdef COMPRESS_MF_MT
345         Byte pad[128];
346 #endif
347
348         UInt32 optimumEndIndex;
349         UInt32 optimumCurrentIndex;
350
351         UInt32 longestMatchLength;
352         UInt32 numPairs;
353         UInt32 numAvail;
354         COptimal opt[kNumOpts];
355
356 #ifndef LZMA_LOG_BSR
357         Byte g_FastPos[1 << kNumLogBits];
358 #endif
359
360         UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
361         UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
362         UInt32 numFastBytes;
363         UInt32 additionalOffset;
364         UInt32 reps[LZMA_NUM_REPS];
365         UInt32 state;
366
367         UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
368         UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
369         UInt32 alignPrices[kAlignTableSize];
370         UInt32 alignPriceCount;
371
372         UInt32 distTableSize;
373
374         unsigned lc, lp, pb;
375         unsigned lpMask, pbMask;
376
377         CLzmaProb *litProbs;
378
379         CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
380         CLzmaProb isRep[kNumStates];
381         CLzmaProb isRepG0[kNumStates];
382         CLzmaProb isRepG1[kNumStates];
383         CLzmaProb isRepG2[kNumStates];
384         CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
385
386         CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
387         CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
388         CLzmaProb posAlignEncoder[1 << kNumAlignBits];
389
390         CLenPriceEnc lenEnc;
391         CLenPriceEnc repLenEnc;
392
393         unsigned lclp;
394
395         Bool fastMode;
396
397         CRangeEnc rc;
398
399         Bool writeEndMark;
400         UInt64 nowPos64;
401         UInt32 matchPriceCount;
402         Bool finished;
403         Bool multiThread;
404
405         SRes result;
406         UInt32 dictSize;
407         UInt32 matchFinderCycles;
408
409         ISeqInStream *inStream;
410         CSeqInStreamBuf seqBufInStream;
411
412         CSaveState saveState;
413     } CLzmaEnc;
414
415     void LzmaEnc_SaveState(CLzmaEncHandle pp)
416     {
417         CLzmaEnc *p = (CLzmaEnc *)pp;
418         CSaveState *dest = &p->saveState;
419         int i;
420         dest->lenEnc = p->lenEnc;
421         dest->repLenEnc = p->repLenEnc;
422         dest->state = p->state;
423
424         for (i = 0; i < kNumStates; i++)
425         {
426             memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
427             memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
428         }
429         for (i = 0; i < kNumLenToPosStates; i++)
430             memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
431         memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
432         memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
433         memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
434         memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
435         memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
436         memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
437         memcpy(dest->reps, p->reps, sizeof(p->reps));
438         memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
439     }
440
441     void LzmaEnc_RestoreState(CLzmaEncHandle pp)
442     {
443         CLzmaEnc *dest = (CLzmaEnc *)pp;
444         const CSaveState *p = &dest->saveState;
445         int i;
446         dest->lenEnc = p->lenEnc;
447         dest->repLenEnc = p->repLenEnc;
448         dest->state = p->state;
449
450         for (i = 0; i < kNumStates; i++)
451         {
452             memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
453             memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
454         }
455         for (i = 0; i < kNumLenToPosStates; i++)
456             memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
457         memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
458         memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
459         memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
460         memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
461         memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
462         memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
463         memcpy(dest->reps, p->reps, sizeof(p->reps));
464         memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
465     }
466
467     SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
468     {
469         CLzmaEnc *p = (CLzmaEnc *)pp;
470         CLzmaEncProps props = *props2;
471         LzmaEncProps_Normalize(&props);
472
473         if (props.lc > LZMA_LC_MAX ||
474             props.lp > LZMA_LP_MAX ||
475             props.pb > LZMA_PB_MAX ||
476             props.dictSize > (1U << kDicLogSizeMaxCompress) ||
477             props.dictSize > (1 << 30))
478             return SZ_ERROR_PARAM;
479         p->dictSize = props.dictSize;
480         p->matchFinderCycles = props.mc;
481         {
482             unsigned fb = props.fb;
483             if (fb < 5)
484                 fb = 5;
485             if (fb > LZMA_MATCH_LEN_MAX)
486                 fb = LZMA_MATCH_LEN_MAX;
487             p->numFastBytes = fb;
488         }
489         p->lc = props.lc;
490         p->lp = props.lp;
491         p->pb = props.pb;
492         p->fastMode = (props.algo == 0);
493         p->matchFinderBase.btMode = props.btMode;
494         {
495             UInt32 numHashBytes = 4;
496             if (props.btMode)
497             {
498                 if (props.numHashBytes < 2)
499                     numHashBytes = 2;
500                 else if (props.numHashBytes < 4)
501                     numHashBytes = props.numHashBytes;
502             }
503             p->matchFinderBase.numHashBytes = numHashBytes;
504         }
505
506         p->matchFinderBase.cutValue = props.mc;
507
508         p->writeEndMark = props.writeEndMark;
509
510 #ifdef COMPRESS_MF_MT
511         /*
512         if (newMultiThread != _multiThread)
513         {
514           ReleaseMatchFinder();
515           _multiThread = newMultiThread;
516         }
517         */
518         p->multiThread = (props.numThreads > 1);
519 #endif
520
521         return SZ_OK;
522     }
523
524     static const int kLiteralNextStates[kNumStates] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
525     static const int kMatchNextStates[kNumStates] = { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 };
526     static const int kRepNextStates[kNumStates] = { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 };
527     static const int kShortRepNextStates[kNumStates] = { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 };
528
529 #define IsCharState(s) ((s) < 7)
530
531 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
532
533 #define kInfinityPrice (1 << 30)
534
535     static void RangeEnc_Construct(CRangeEnc *p)
536     {
537         p->outStream = 0;
538         p->bufBase = 0;
539     }
540
541 #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
542
543 #define RC_BUF_SIZE (1 << 16)
544     static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
545     {
546         if (p->bufBase == 0)
547         {
548             p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
549             if (p->bufBase == 0)
550                 return 0;
551             p->bufLim = p->bufBase + RC_BUF_SIZE;
552         }
553         return 1;
554     }
555
556     static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
557     {
558         alloc->Free(alloc, p->bufBase);
559         p->bufBase = 0;
560     }
561
562     static void RangeEnc_Init(CRangeEnc *p)
563     {
564         /* Stream.Init(); */
565         p->low = 0;
566         p->range = 0xFFFFFFFF;
567         p->cacheSize = 1;
568         p->cache = 0;
569
570         p->buf = p->bufBase;
571
572         p->processed = 0;
573         p->res = SZ_OK;
574     }
575
576     static void RangeEnc_FlushStream(CRangeEnc *p)
577     {
578         size_t num;
579         if (p->res != SZ_OK)
580             return;
581         num = p->buf - p->bufBase;
582         if (num != p->outStream->Write(p->outStream, p->bufBase, num))
583             p->res = SZ_ERROR_WRITE;
584         p->processed += num;
585         p->buf = p->bufBase;
586     }
587
588     static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
589     {
590         if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
591         {
592             Byte temp = p->cache;
593             do
594             {
595                 Byte *buf = p->buf;
596                 *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
597                 p->buf = buf;
598                 if (buf == p->bufLim)
599                     RangeEnc_FlushStream(p);
600                 temp = 0xFF;
601             } while (--p->cacheSize != 0);
602             p->cache = (Byte)((UInt32)p->low >> 24);
603         }
604         p->cacheSize++;
605         p->low = (UInt32)p->low << 8;
606     }
607
608     static void RangeEnc_FlushData(CRangeEnc *p)
609     {
610         int i;
611         for (i = 0; i < 5; i++)
612             RangeEnc_ShiftLow(p);
613     }
614
615     static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
616     {
617         do
618         {
619             p->range >>= 1;
620             p->low += p->range & (0 - ((value >> --numBits) & 1));
621             if (p->range < kTopValue)
622             {
623                 p->range <<= 8;
624                 RangeEnc_ShiftLow(p);
625             }
626         } while (numBits != 0);
627     }
628
629     static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
630     {
631         UInt32 ttt = *prob;
632         UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
633         if (symbol == 0)
634         {
635             p->range = newBound;
636             ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
637         }
638         else
639         {
640             p->low += newBound;
641             p->range -= newBound;
642             ttt -= ttt >> kNumMoveBits;
643         }
644         *prob = (CLzmaProb)ttt;
645         if (p->range < kTopValue)
646         {
647             p->range <<= 8;
648             RangeEnc_ShiftLow(p);
649         }
650     }
651
652     static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
653     {
654         symbol |= 0x100;
655         do
656         {
657             RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
658             symbol <<= 1;
659         } while (symbol < 0x10000);
660     }
661
662     static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
663     {
664         UInt32 offs = 0x100;
665         symbol |= 0x100;
666         do
667         {
668             matchByte <<= 1;
669             RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
670             symbol <<= 1;
671             offs &= ~(matchByte ^ symbol);
672         } while (symbol < 0x10000);
673     }
674
675     void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
676     {
677         UInt32 i;
678         for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
679         {
680             const int kCyclesBits = kNumBitPriceShiftBits;
681             UInt32 w = i;
682             UInt32 bitCount = 0;
683             int j;
684             for (j = 0; j < kCyclesBits; j++)
685             {
686                 w = w * w;
687                 bitCount <<= 1;
688                 while (w >= ((UInt32)1 << 16))
689                 {
690                     w >>= 1;
691                     bitCount++;
692                 }
693             }
694             ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
695         }
696     }
697
698 #define GET_PRICE(prob, symbol) \
699     p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
700
701 #define GET_PRICEa(prob, symbol) \
702     ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
703
704 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
705 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
706
707 #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
708 #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
709
710     static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
711     {
712         UInt32 price = 0;
713         symbol |= 0x100;
714         do
715         {
716             price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
717             symbol <<= 1;
718         } while (symbol < 0x10000);
719         return price;
720     }
721
722     static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
723     {
724         UInt32 price = 0;
725         UInt32 offs = 0x100;
726         symbol |= 0x100;
727         do
728         {
729             matchByte <<= 1;
730             price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
731             symbol <<= 1;
732             offs &= ~(matchByte ^ symbol);
733         } while (symbol < 0x10000);
734         return price;
735     }
736
737     static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
738     {
739         UInt32 m = 1;
740         int i;
741         for (i = numBitLevels; i != 0;)
742         {
743             UInt32 bit;
744             i--;
745             bit = (symbol >> i) & 1;
746             RangeEnc_EncodeBit(rc, probs + m, bit);
747             m = (m << 1) | bit;
748         }
749     }
750
751     static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
752     {
753         UInt32 m = 1;
754         int i;
755         for (i = 0; i < numBitLevels; i++)
756         {
757             UInt32 bit = symbol & 1;
758             RangeEnc_EncodeBit(rc, probs + m, bit);
759             m = (m << 1) | bit;
760             symbol >>= 1;
761         }
762     }
763
764     static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
765     {
766         UInt32 price = 0;
767         symbol |= (1 << numBitLevels);
768         while (symbol != 1)
769         {
770             price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
771             symbol >>= 1;
772         }
773         return price;
774     }
775
776     static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
777     {
778         UInt32 price = 0;
779         UInt32 m = 1;
780         int i;
781         for (i = numBitLevels; i != 0; i--)
782         {
783             UInt32 bit = symbol & 1;
784             symbol >>= 1;
785             price += GET_PRICEa(probs[m], bit);
786             m = (m << 1) | bit;
787         }
788         return price;
789     }
790
791     static void LenEnc_Init(CLenEnc *p)
792     {
793         unsigned i;
794         p->choice = p->choice2 = kProbInitValue;
795         for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
796             p->low[i] = kProbInitValue;
797         for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
798             p->mid[i] = kProbInitValue;
799         for (i = 0; i < kLenNumHighSymbols; i++)
800             p->high[i] = kProbInitValue;
801     }
802
803     static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
804     {
805         if (symbol < kLenNumLowSymbols)
806         {
807             RangeEnc_EncodeBit(rc, &p->choice, 0);
808             RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
809         }
810         else
811         {
812             RangeEnc_EncodeBit(rc, &p->choice, 1);
813             if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
814             {
815                 RangeEnc_EncodeBit(rc, &p->choice2, 0);
816                 RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
817             }
818             else
819             {
820                 RangeEnc_EncodeBit(rc, &p->choice2, 1);
821                 RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
822             }
823         }
824     }
825
826     static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
827     {
828         UInt32 a0 = GET_PRICE_0a(p->choice);
829         UInt32 a1 = GET_PRICE_1a(p->choice);
830         UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
831         UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
832         UInt32 i = 0;
833         for (i = 0; i < kLenNumLowSymbols; i++)
834         {
835             if (i >= numSymbols)
836                 return;
837             prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
838         }
839         for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
840         {
841             if (i >= numSymbols)
842                 return;
843             prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
844         }
845         for (; i < numSymbols; i++)
846             prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
847     }
848
849     static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
850     {
851         LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
852         p->counters[posState] = p->tableSize;
853     }
854
855     static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
856     {
857         UInt32 posState;
858         for (posState = 0; posState < numPosStates; posState++)
859             LenPriceEnc_UpdateTable(p, posState, ProbPrices);
860     }
861
862     static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
863     {
864         LenEnc_Encode(&p->p, rc, symbol, posState);
865         if (updatePrice)
866             if (--p->counters[posState] == 0)
867                 LenPriceEnc_UpdateTable(p, posState, ProbPrices);
868     }
869
870     static void MovePos(CLzmaEnc *p, UInt32 num)
871     {
872 #ifdef SHOW_STAT
873         ttt += num;
874         printf("\n MovePos %d", num);
875 #endif
876         if (num != 0)
877         {
878             p->additionalOffset += num;
879             p->matchFinder.Skip(p->matchFinderObj, num);
880         }
881     }
882
883     static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
884     {
885         UInt32 lenRes = 0, numPairs;
886         p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
887         numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
888 #ifdef SHOW_STAT
889         printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);
890         ttt++;
891         {
892             UInt32 i;
893             for (i = 0; i < numPairs; i += 2)
894                 printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);
895         }
896 #endif
897         if (numPairs > 0)
898         {
899             lenRes = p->matches[numPairs - 2];
900             if (lenRes == p->numFastBytes)
901             {
902                 const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
903                 UInt32 distance = p->matches[numPairs - 1] + 1;
904                 UInt32 numAvail = p->numAvail;
905                 if (numAvail > LZMA_MATCH_LEN_MAX)
906                     numAvail = LZMA_MATCH_LEN_MAX;
907                 {
908                     const Byte *pby2 = pby - distance;
909                     for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++)
910                         ;
911                 }
912             }
913         }
914         p->additionalOffset++;
915         *numDistancePairsRes = numPairs;
916         return lenRes;
917     }
918
919 #define MakeAsChar(p)             \
920     (p)->backPrev = (UInt32)(-1); \
921     (p)->prev1IsChar = False;
922 #define MakeAsShortRep(p) \
923     (p)->backPrev = 0;    \
924     (p)->prev1IsChar = False;
925 #define IsShortRep(p) ((p)->backPrev == 0)
926
927     static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
928     {
929         return GET_PRICE_0(p->isRepG0[state]) +
930                GET_PRICE_0(p->isRep0Long[state][posState]);
931     }
932
933     static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
934     {
935         UInt32 price;
936         if (repIndex == 0)
937         {
938             price = GET_PRICE_0(p->isRepG0[state]);
939             price += GET_PRICE_1(p->isRep0Long[state][posState]);
940         }
941         else
942         {
943             price = GET_PRICE_1(p->isRepG0[state]);
944             if (repIndex == 1)
945                 price += GET_PRICE_0(p->isRepG1[state]);
946             else
947             {
948                 price += GET_PRICE_1(p->isRepG1[state]);
949                 price += GET_PRICE(p->isRepG2[state], repIndex - 2);
950             }
951         }
952         return price;
953     }
954
955     static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
956     {
957         return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
958                GetPureRepPrice(p, repIndex, state, posState);
959     }
960
961     static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
962     {
963         UInt32 posMem = p->opt[cur].posPrev;
964         UInt32 backMem = p->opt[cur].backPrev;
965         p->optimumEndIndex = cur;
966         do
967         {
968             if (p->opt[cur].prev1IsChar)
969             {
970                 MakeAsChar(&p->opt[posMem])
971                 p->opt[posMem].posPrev = posMem - 1;
972                 if (p->opt[cur].prev2)
973                 {
974                     p->opt[posMem - 1].prev1IsChar = False;
975                     p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
976                     p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
977                 }
978             }
979             {
980                 UInt32 posPrev = posMem;
981                 UInt32 backCur = backMem;
982
983                 backMem = p->opt[posPrev].backPrev;
984                 posMem = p->opt[posPrev].posPrev;
985
986                 p->opt[posPrev].backPrev = backCur;
987                 p->opt[posPrev].posPrev = cur;
988                 cur = posPrev;
989             }
990         } while (cur != 0);
991         *backRes = p->opt[0].backPrev;
992         p->optimumCurrentIndex = p->opt[0].posPrev;
993         return p->optimumCurrentIndex;
994     }
995
996 #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
997
998     static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
999     {
1000         UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
1001         UInt32 matchPrice, repMatchPrice, normalMatchPrice;
1002         UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
1003         UInt32 *matches;
1004         const Byte *data;
1005         Byte curByte, matchByte;
1006         if (p->optimumEndIndex != p->optimumCurrentIndex)
1007         {
1008             const COptimal *opt = &p->opt[p->optimumCurrentIndex];
1009             UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
1010             *backRes = opt->backPrev;
1011             p->optimumCurrentIndex = opt->posPrev;
1012             return lenRes;
1013         }
1014         p->optimumCurrentIndex = p->optimumEndIndex = 0;
1015
1016         if (p->additionalOffset == 0)
1017             mainLen = ReadMatchDistances(p, &numPairs);
1018         else
1019         {
1020             mainLen = p->longestMatchLength;
1021             numPairs = p->numPairs;
1022         }
1023
1024         numAvail = p->numAvail;
1025         if (numAvail < 2)
1026         {
1027             *backRes = (UInt32)(-1);
1028             return 1;
1029         }
1030         if (numAvail > LZMA_MATCH_LEN_MAX)
1031             numAvail = LZMA_MATCH_LEN_MAX;
1032
1033         data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1034         repMaxIndex = 0;
1035         for (i = 0; i < LZMA_NUM_REPS; i++)
1036         {
1037             UInt32 lenTest;
1038             const Byte *data2;
1039             reps[i] = p->reps[i];
1040             data2 = data - (reps[i] + 1);
1041             if (data[0] != data2[0] || data[1] != data2[1])
1042             {
1043                 repLens[i] = 0;
1044                 continue;
1045             }
1046             for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++)
1047                 ;
1048             repLens[i] = lenTest;
1049             if (lenTest > repLens[repMaxIndex])
1050                 repMaxIndex = i;
1051         }
1052         if (repLens[repMaxIndex] >= p->numFastBytes)
1053         {
1054             UInt32 lenRes;
1055             *backRes = repMaxIndex;
1056             lenRes = repLens[repMaxIndex];
1057             MovePos(p, lenRes - 1);
1058             return lenRes;
1059         }
1060
1061         matches = p->matches;
1062         if (mainLen >= p->numFastBytes)
1063         {
1064             *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
1065             MovePos(p, mainLen - 1);
1066             return mainLen;
1067         }
1068         curByte = *data;
1069         matchByte = *(data - (reps[0] + 1));
1070
1071         if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
1072         {
1073             *backRes = (UInt32) - 1;
1074             return 1;
1075         }
1076
1077         p->opt[0].state = (CState)p->state;
1078
1079         posState = (position & p->pbMask);
1080
1081         {
1082             const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1083             p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
1084                               (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1085         }
1086
1087         MakeAsChar(&p->opt[1]);
1088
1089         matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
1090         repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
1091
1092         if (matchByte == curByte)
1093         {
1094             UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
1095             if (shortRepPrice < p->opt[1].price)
1096             {
1097                 p->opt[1].price = shortRepPrice;
1098                 MakeAsShortRep(&p->opt[1]);
1099             }
1100         }
1101         lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
1102
1103         if (lenEnd < 2)
1104         {
1105             *backRes = p->opt[1].backPrev;
1106             return 1;
1107         }
1108
1109         p->opt[1].posPrev = 0;
1110         for (i = 0; i < LZMA_NUM_REPS; i++)
1111             p->opt[0].backs[i] = reps[i];
1112
1113         len = lenEnd;
1114         do
1115             p->opt[len--].price = kInfinityPrice;
1116         while (len >= 2);
1117
1118         for (i = 0; i < LZMA_NUM_REPS; i++)
1119         {
1120             UInt32 repLen = repLens[i];
1121             UInt32 price;
1122             if (repLen < 2)
1123                 continue;
1124             price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
1125             do
1126             {
1127                 UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
1128                 COptimal *opt = &p->opt[repLen];
1129                 if (curAndLenPrice < opt->price)
1130                 {
1131                     opt->price = curAndLenPrice;
1132                     opt->posPrev = 0;
1133                     opt->backPrev = i;
1134                     opt->prev1IsChar = False;
1135                 }
1136             } while (--repLen >= 2);
1137         }
1138
1139         normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
1140
1141         len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
1142         if (len <= mainLen)
1143         {
1144             UInt32 offs = 0;
1145             while (len > matches[offs])
1146                 offs += 2;
1147             for (;; len++)
1148             {
1149                 COptimal *opt;
1150                 UInt32 distance = matches[offs + 1];
1151
1152                 UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
1153                 UInt32 lenToPosState = GetLenToPosState(len);
1154                 if (distance < kNumFullDistances)
1155                     curAndLenPrice += p->distancesPrices[lenToPosState][distance];
1156                 else
1157                 {
1158                     UInt32 slot;
1159                     GetPosSlot2(distance, slot);
1160                     curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
1161                 }
1162                 opt = &p->opt[len];
1163                 if (curAndLenPrice < opt->price)
1164                 {
1165                     opt->price = curAndLenPrice;
1166                     opt->posPrev = 0;
1167                     opt->backPrev = distance + LZMA_NUM_REPS;
1168                     opt->prev1IsChar = False;
1169                 }
1170                 if (len == matches[offs])
1171                 {
1172                     offs += 2;
1173                     if (offs == numPairs)
1174                         break;
1175                 }
1176             }
1177         }
1178
1179         cur = 0;
1180
1181 #ifdef SHOW_STAT2
1182         if (position >= 0)
1183         {
1184             unsigned i;
1185             printf("\n pos = %4X", position);
1186             for (i = cur; i <= lenEnd; i++)
1187                 printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
1188         }
1189 #endif
1190
1191         for (;;)
1192         {
1193             UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
1194             UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
1195             Bool nextIsChar;
1196             Byte curByte, matchByte;
1197             const Byte *data;
1198             COptimal *curOpt;
1199             COptimal *nextOpt;
1200
1201             cur++;
1202             if (cur == lenEnd)
1203                 return Backward(p, backRes, cur);
1204
1205             newLen = ReadMatchDistances(p, &numPairs);
1206             if (newLen >= p->numFastBytes)
1207             {
1208                 p->numPairs = numPairs;
1209                 p->longestMatchLength = newLen;
1210                 return Backward(p, backRes, cur);
1211             }
1212             position++;
1213             curOpt = &p->opt[cur];
1214             posPrev = curOpt->posPrev;
1215             if (curOpt->prev1IsChar)
1216             {
1217                 posPrev--;
1218                 if (curOpt->prev2)
1219                 {
1220                     state = p->opt[curOpt->posPrev2].state;
1221                     if (curOpt->backPrev2 < LZMA_NUM_REPS)
1222                         state = kRepNextStates[state];
1223                     else
1224                         state = kMatchNextStates[state];
1225                 }
1226                 else
1227                     state = p->opt[posPrev].state;
1228                 state = kLiteralNextStates[state];
1229             }
1230             else
1231                 state = p->opt[posPrev].state;
1232             if (posPrev == cur - 1)
1233             {
1234                 if (IsShortRep(curOpt))
1235                     state = kShortRepNextStates[state];
1236                 else
1237                     state = kLiteralNextStates[state];
1238             }
1239             else
1240             {
1241                 UInt32 pos;
1242                 const COptimal *prevOpt;
1243                 if (curOpt->prev1IsChar && curOpt->prev2)
1244                 {
1245                     posPrev = curOpt->posPrev2;
1246                     pos = curOpt->backPrev2;
1247                     state = kRepNextStates[state];
1248                 }
1249                 else
1250                 {
1251                     pos = curOpt->backPrev;
1252                     if (pos < LZMA_NUM_REPS)
1253                         state = kRepNextStates[state];
1254                     else
1255                         state = kMatchNextStates[state];
1256                 }
1257                 prevOpt = &p->opt[posPrev];
1258                 if (pos < LZMA_NUM_REPS)
1259                 {
1260                     UInt32 i;
1261                     reps[0] = prevOpt->backs[pos];
1262                     for (i = 1; i <= pos; i++)
1263                         reps[i] = prevOpt->backs[i - 1];
1264                     for (; i < LZMA_NUM_REPS; i++)
1265                         reps[i] = prevOpt->backs[i];
1266                 }
1267                 else
1268                 {
1269                     UInt32 i;
1270                     reps[0] = (pos - LZMA_NUM_REPS);
1271                     for (i = 1; i < LZMA_NUM_REPS; i++)
1272                         reps[i] = prevOpt->backs[i - 1];
1273                 }
1274             }
1275             curOpt->state = (CState)state;
1276
1277             curOpt->backs[0] = reps[0];
1278             curOpt->backs[1] = reps[1];
1279             curOpt->backs[2] = reps[2];
1280             curOpt->backs[3] = reps[3];
1281
1282             curPrice = curOpt->price;
1283             nextIsChar = False;
1284             data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1285             curByte = *data;
1286             matchByte = *(data - (reps[0] + 1));
1287
1288             posState = (position & p->pbMask);
1289
1290             curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
1291             {
1292                 const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1293                 curAnd1Price +=
1294                     (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1295             }
1296
1297             nextOpt = &p->opt[cur + 1];
1298
1299             if (curAnd1Price < nextOpt->price)
1300             {
1301                 nextOpt->price = curAnd1Price;
1302                 nextOpt->posPrev = cur;
1303                 MakeAsChar(nextOpt);
1304                 nextIsChar = True;
1305             }
1306
1307             matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
1308             repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
1309
1310             if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
1311             {
1312                 UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
1313                 if (shortRepPrice <= nextOpt->price)
1314                 {
1315                     nextOpt->price = shortRepPrice;
1316                     nextOpt->posPrev = cur;
1317                     MakeAsShortRep(nextOpt);
1318                     nextIsChar = True;
1319                 }
1320             }
1321             numAvailFull = p->numAvail;
1322             {
1323                 UInt32 temp = kNumOpts - 1 - cur;
1324                 if (temp < numAvailFull)
1325                     numAvailFull = temp;
1326             }
1327
1328             if (numAvailFull < 2)
1329                 continue;
1330             numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
1331
1332             if (!nextIsChar && matchByte != curByte) /* speed optimization */
1333             {
1334                 /* try Literal + rep0 */
1335                 UInt32 temp;
1336                 UInt32 lenTest2;
1337                 const Byte *data2 = data - (reps[0] + 1);
1338                 UInt32 limit = p->numFastBytes + 1;
1339                 if (limit > numAvailFull)
1340                     limit = numAvailFull;
1341
1342                 for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++)
1343                     ;
1344                 lenTest2 = temp - 1;
1345                 if (lenTest2 >= 2)
1346                 {
1347                     UInt32 state2 = kLiteralNextStates[state];
1348                     UInt32 posStateNext = (position + 1) & p->pbMask;
1349                     UInt32 nextRepMatchPrice = curAnd1Price +
1350                                                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1351                                                GET_PRICE_1(p->isRep[state2]);
1352                     /* for (; lenTest2 >= 2; lenTest2--) */
1353                     {
1354                         UInt32 curAndLenPrice;
1355                         COptimal *opt;
1356                         UInt32 offset = cur + 1 + lenTest2;
1357                         while (lenEnd < offset)
1358                             p->opt[++lenEnd].price = kInfinityPrice;
1359                         curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1360                         opt = &p->opt[offset];
1361                         if (curAndLenPrice < opt->price)
1362                         {
1363                             opt->price = curAndLenPrice;
1364                             opt->posPrev = cur + 1;
1365                             opt->backPrev = 0;
1366                             opt->prev1IsChar = True;
1367                             opt->prev2 = False;
1368                         }
1369                     }
1370                 }
1371             }
1372
1373             startLen = 2; /* speed optimization */
1374             {
1375                 UInt32 repIndex;
1376                 for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
1377                 {
1378                     UInt32 lenTest;
1379                     UInt32 lenTestTemp;
1380                     UInt32 price;
1381                     const Byte *data2 = data - (reps[repIndex] + 1);
1382                     if (data[0] != data2[0] || data[1] != data2[1])
1383                         continue;
1384                     for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++)
1385                         ;
1386                     while (lenEnd < cur + lenTest)
1387                         p->opt[++lenEnd].price = kInfinityPrice;
1388                     lenTestTemp = lenTest;
1389                     price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
1390                     do
1391                     {
1392                         UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
1393                         COptimal *opt = &p->opt[cur + lenTest];
1394                         if (curAndLenPrice < opt->price)
1395                         {
1396                             opt->price = curAndLenPrice;
1397                             opt->posPrev = cur;
1398                             opt->backPrev = repIndex;
1399                             opt->prev1IsChar = False;
1400                         }
1401                     } while (--lenTest >= 2);
1402                     lenTest = lenTestTemp;
1403
1404                     if (repIndex == 0)
1405                         startLen = lenTest + 1;
1406
1407                     /* if (_maxMode) */
1408                     {
1409                         UInt32 lenTest2 = lenTest + 1;
1410                         UInt32 limit = lenTest2 + p->numFastBytes;
1411                         UInt32 nextRepMatchPrice;
1412                         if (limit > numAvailFull)
1413                             limit = numAvailFull;
1414                         for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++)
1415                             ;
1416                         lenTest2 -= lenTest + 1;
1417                         if (lenTest2 >= 2)
1418                         {
1419                             UInt32 state2 = kRepNextStates[state];
1420                             UInt32 posStateNext = (position + lenTest) & p->pbMask;
1421                             UInt32 curAndLenCharPrice =
1422                                 price + p->repLenEnc.prices[posState][lenTest - 2] +
1423                                 GET_PRICE_0(p->isMatch[state2][posStateNext]) +
1424                                 LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
1425                                                        data[lenTest], data2[lenTest], p->ProbPrices);
1426                             state2 = kLiteralNextStates[state2];
1427                             posStateNext = (position + lenTest + 1) & p->pbMask;
1428                             nextRepMatchPrice = curAndLenCharPrice +
1429                                                 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1430                                                 GET_PRICE_1(p->isRep[state2]);
1431
1432                             /* for (; lenTest2 >= 2; lenTest2--) */
1433                             {
1434                                 UInt32 curAndLenPrice;
1435                                 COptimal *opt;
1436                                 UInt32 offset = cur + lenTest + 1 + lenTest2;
1437                                 while (lenEnd < offset)
1438                                     p->opt[++lenEnd].price = kInfinityPrice;
1439                                 curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1440                                 opt = &p->opt[offset];
1441                                 if (curAndLenPrice < opt->price)
1442                                 {
1443                                     opt->price = curAndLenPrice;
1444                                     opt->posPrev = cur + lenTest + 1;
1445                                     opt->backPrev = 0;
1446                                     opt->prev1IsChar = True;
1447                                     opt->prev2 = True;
1448                                     opt->posPrev2 = cur;
1449                                     opt->backPrev2 = repIndex;
1450                                 }
1451                             }
1452                         }
1453                     }
1454                 }
1455             }
1456             /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
1457             if (newLen > numAvail)
1458             {
1459                 newLen = numAvail;
1460                 for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2)
1461                     ;
1462                 matches[numPairs] = newLen;
1463                 numPairs += 2;
1464             }
1465             if (newLen >= startLen)
1466             {
1467                 UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
1468                 UInt32 offs, curBack, posSlot;
1469                 UInt32 lenTest;
1470                 while (lenEnd < cur + newLen)
1471                     p->opt[++lenEnd].price = kInfinityPrice;
1472
1473                 offs = 0;
1474                 while (startLen > matches[offs])
1475                     offs += 2;
1476                 curBack = matches[offs + 1];
1477                 GetPosSlot2(curBack, posSlot);
1478                 for (lenTest = /*2*/ startLen;; lenTest++)
1479                 {
1480                     UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
1481                     UInt32 lenToPosState = GetLenToPosState(lenTest);
1482                     COptimal *opt;
1483                     if (curBack < kNumFullDistances)
1484                         curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
1485                     else
1486                         curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
1487
1488                     opt = &p->opt[cur + lenTest];
1489                     if (curAndLenPrice < opt->price)
1490                     {
1491                         opt->price = curAndLenPrice;
1492                         opt->posPrev = cur;
1493                         opt->backPrev = curBack + LZMA_NUM_REPS;
1494                         opt->prev1IsChar = False;
1495                     }
1496
1497                     if (/*_maxMode && */ lenTest == matches[offs])
1498                     {
1499                         /* Try Match + Literal + Rep0 */
1500                         const Byte *data2 = data - (curBack + 1);
1501                         UInt32 lenTest2 = lenTest + 1;
1502                         UInt32 limit = lenTest2 + p->numFastBytes;
1503                         UInt32 nextRepMatchPrice;
1504                         if (limit > numAvailFull)
1505                             limit = numAvailFull;
1506                         for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++)
1507                             ;
1508                         lenTest2 -= lenTest + 1;
1509                         if (lenTest2 >= 2)
1510                         {
1511                             UInt32 state2 = kMatchNextStates[state];
1512                             UInt32 posStateNext = (position + lenTest) & p->pbMask;
1513                             UInt32 curAndLenCharPrice = curAndLenPrice +
1514                                                         GET_PRICE_0(p->isMatch[state2][posStateNext]) +
1515                                                         LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
1516                                                                                data[lenTest], data2[lenTest], p->ProbPrices);
1517                             state2 = kLiteralNextStates[state2];
1518                             posStateNext = (posStateNext + 1) & p->pbMask;
1519                             nextRepMatchPrice = curAndLenCharPrice +
1520                                                 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1521                                                 GET_PRICE_1(p->isRep[state2]);
1522
1523                             /* for (; lenTest2 >= 2; lenTest2--) */
1524                             {
1525                                 UInt32 offset = cur + lenTest + 1 + lenTest2;
1526                                 UInt32 curAndLenPrice;
1527                                 COptimal *opt;
1528                                 while (lenEnd < offset)
1529                                     p->opt[++lenEnd].price = kInfinityPrice;
1530                                 curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1531                                 opt = &p->opt[offset];
1532                                 if (curAndLenPrice < opt->price)
1533                                 {
1534                                     opt->price = curAndLenPrice;
1535                                     opt->posPrev = cur + lenTest + 1;
1536                                     opt->backPrev = 0;
1537                                     opt->prev1IsChar = True;
1538                                     opt->prev2 = True;
1539                                     opt->posPrev2 = cur;
1540                                     opt->backPrev2 = curBack + LZMA_NUM_REPS;
1541                                 }
1542                             }
1543                         }
1544                         offs += 2;
1545                         if (offs == numPairs)
1546                             break;
1547                         curBack = matches[offs + 1];
1548                         if (curBack >= kNumFullDistances)
1549                             GetPosSlot2(curBack, posSlot);
1550                     }
1551                 }
1552             }
1553         }
1554     }
1555
1556 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1557
1558     static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
1559     {
1560         UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
1561         const Byte *data;
1562         const UInt32 *matches;
1563
1564         if (p->additionalOffset == 0)
1565             mainLen = ReadMatchDistances(p, &numPairs);
1566         else
1567         {
1568             mainLen = p->longestMatchLength;
1569             numPairs = p->numPairs;
1570         }
1571
1572         numAvail = p->numAvail;
1573         *backRes = (UInt32) - 1;
1574         if (numAvail < 2)
1575             return 1;
1576         if (numAvail > LZMA_MATCH_LEN_MAX)
1577             numAvail = LZMA_MATCH_LEN_MAX;
1578         data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1579
1580         repLen = repIndex = 0;
1581         for (i = 0; i < LZMA_NUM_REPS; i++)
1582         {
1583             UInt32 len;
1584             const Byte *data2 = data - (p->reps[i] + 1);
1585             if (data[0] != data2[0] || data[1] != data2[1])
1586                 continue;
1587             for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1588                 ;
1589             if (len >= p->numFastBytes)
1590             {
1591                 *backRes = i;
1592                 MovePos(p, len - 1);
1593                 return len;
1594             }
1595             if (len > repLen)
1596             {
1597                 repIndex = i;
1598                 repLen = len;
1599             }
1600         }
1601
1602         matches = p->matches;
1603         if (mainLen >= p->numFastBytes)
1604         {
1605             *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
1606             MovePos(p, mainLen - 1);
1607             return mainLen;
1608         }
1609
1610         mainDist = 0; /* for GCC */
1611         if (mainLen >= 2)
1612         {
1613             mainDist = matches[numPairs - 1];
1614             while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
1615             {
1616                 if (!ChangePair(matches[numPairs - 3], mainDist))
1617                     break;
1618                 numPairs -= 2;
1619                 mainLen = matches[numPairs - 2];
1620                 mainDist = matches[numPairs - 1];
1621             }
1622             if (mainLen == 2 && mainDist >= 0x80)
1623                 mainLen = 1;
1624         }
1625
1626         if (repLen >= 2 && ((repLen + 1 >= mainLen) ||
1627                             (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
1628                             (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
1629         {
1630             *backRes = repIndex;
1631             MovePos(p, repLen - 1);
1632             return repLen;
1633         }
1634
1635         if (mainLen < 2 || numAvail <= 2)
1636             return 1;
1637
1638         p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
1639         if (p->longestMatchLength >= 2)
1640         {
1641             UInt32 newDistance = matches[p->numPairs - 1];
1642             if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
1643                 (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
1644                 (p->longestMatchLength > mainLen + 1) ||
1645                 (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
1646                 return 1;
1647         }
1648
1649         data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1650         for (i = 0; i < LZMA_NUM_REPS; i++)
1651         {
1652             UInt32 len, limit;
1653             const Byte *data2 = data - (p->reps[i] + 1);
1654             if (data[0] != data2[0] || data[1] != data2[1])
1655                 continue;
1656             limit = mainLen - 1;
1657             for (len = 2; len < limit && data[len] == data2[len]; len++)
1658                 ;
1659             if (len >= limit)
1660                 return 1;
1661         }
1662         *backRes = mainDist + LZMA_NUM_REPS;
1663         MovePos(p, mainLen - 2);
1664         return mainLen;
1665     }
1666
1667     static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
1668     {
1669         UInt32 len;
1670         RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
1671         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
1672         p->state = kMatchNextStates[p->state];
1673         len = LZMA_MATCH_LEN_MIN;
1674         LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1675         RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
1676         RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
1677         RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
1678     }
1679
1680     static SRes CheckErrors(CLzmaEnc *p)
1681     {
1682         if (p->result != SZ_OK)
1683             return p->result;
1684         if (p->rc.res != SZ_OK)
1685             p->result = SZ_ERROR_WRITE;
1686         if (p->matchFinderBase.result != SZ_OK)
1687             p->result = SZ_ERROR_READ;
1688         if (p->result != SZ_OK)
1689             p->finished = True;
1690         return p->result;
1691     }
1692
1693     static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
1694     {
1695         /* ReleaseMFStream(); */
1696         p->finished = True;
1697         if (p->writeEndMark)
1698             WriteEndMarker(p, nowPos & p->pbMask);
1699         RangeEnc_FlushData(&p->rc);
1700         RangeEnc_FlushStream(&p->rc);
1701         return CheckErrors(p);
1702     }
1703
1704     static void FillAlignPrices(CLzmaEnc *p)
1705     {
1706         UInt32 i;
1707         for (i = 0; i < kAlignTableSize; i++)
1708             p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
1709         p->alignPriceCount = 0;
1710     }
1711
1712     static void FillDistancesPrices(CLzmaEnc *p)
1713     {
1714         UInt32 tempPrices[kNumFullDistances];
1715         UInt32 i, lenToPosState;
1716         for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
1717         {
1718             UInt32 posSlot = GetPosSlot1(i);
1719             UInt32 footerBits = ((posSlot >> 1) - 1);
1720             UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1721             tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
1722         }
1723
1724         for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1725         {
1726             UInt32 posSlot;
1727             const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
1728             UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
1729             for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
1730                 posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
1731             for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
1732                 posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
1733
1734             {
1735                 UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
1736                 UInt32 i;
1737                 for (i = 0; i < kStartPosModelIndex; i++)
1738                     distancesPrices[i] = posSlotPrices[i];
1739                 for (; i < kNumFullDistances; i++)
1740                     distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
1741             }
1742         }
1743         p->matchPriceCount = 0;
1744     }
1745
1746     void LzmaEnc_Construct(CLzmaEnc *p)
1747     {
1748         RangeEnc_Construct(&p->rc);
1749         MatchFinder_Construct(&p->matchFinderBase);
1750 #ifdef COMPRESS_MF_MT
1751         MatchFinderMt_Construct(&p->matchFinderMt);
1752         p->matchFinderMt.MatchFinder = &p->matchFinderBase;
1753 #endif
1754
1755         {
1756             CLzmaEncProps props;
1757             LzmaEncProps_Init(&props);
1758             LzmaEnc_SetProps(p, &props);
1759         }
1760
1761 #ifndef LZMA_LOG_BSR
1762         LzmaEnc_FastPosInit(p->g_FastPos);
1763 #endif
1764
1765         LzmaEnc_InitPriceTables(p->ProbPrices);
1766         p->litProbs = 0;
1767         p->saveState.litProbs = 0;
1768     }
1769
1770     CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
1771     {
1772         void *p;
1773         p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
1774         if (p != 0)
1775             LzmaEnc_Construct((CLzmaEnc *)p);
1776         return p;
1777     }
1778
1779     void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
1780     {
1781         alloc->Free(alloc, p->litProbs);
1782         alloc->Free(alloc, p->saveState.litProbs);
1783         p->litProbs = 0;
1784         p->saveState.litProbs = 0;
1785     }
1786
1787     void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
1788     {
1789 #ifdef COMPRESS_MF_MT
1790         MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
1791 #endif
1792         MatchFinder_Free(&p->matchFinderBase, allocBig);
1793         LzmaEnc_FreeLits(p, alloc);
1794         RangeEnc_Free(&p->rc, alloc);
1795     }
1796
1797     void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
1798     {
1799         LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
1800         alloc->Free(alloc, p);
1801     }
1802
1803     static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
1804     {
1805         UInt32 nowPos32, startPos32;
1806         if (p->inStream != 0)
1807         {
1808             p->matchFinderBase.stream = p->inStream;
1809             p->matchFinder.Init(p->matchFinderObj);
1810             p->inStream = 0;
1811         }
1812
1813         if (p->finished)
1814             return p->result;
1815         RINOK(CheckErrors(p));
1816
1817         nowPos32 = (UInt32)p->nowPos64;
1818         startPos32 = nowPos32;
1819
1820         if (p->nowPos64 == 0)
1821         {
1822             UInt32 numPairs;
1823             Byte curByte;
1824             if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
1825                 return Flush(p, nowPos32);
1826             ReadMatchDistances(p, &numPairs);
1827             RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
1828             p->state = kLiteralNextStates[p->state];
1829             curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
1830             LitEnc_Encode(&p->rc, p->litProbs, curByte);
1831             p->additionalOffset--;
1832             nowPos32++;
1833         }
1834
1835         if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
1836             for (;;)
1837             {
1838                 UInt32 pos, len, posState;
1839
1840                 if (p->fastMode)
1841                     len = GetOptimumFast(p, &pos);
1842                 else
1843                     len = GetOptimum(p, nowPos32, &pos);
1844
1845 #ifdef SHOW_STAT2
1846                 printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
1847 #endif
1848
1849                 posState = nowPos32 & p->pbMask;
1850                 if (len == 1 && pos == (UInt32) - 1)
1851                 {
1852                     Byte curByte;
1853                     CLzmaProb *probs;
1854                     const Byte *data;
1855
1856                     RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
1857                     data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
1858                     curByte = *data;
1859                     probs = LIT_PROBS(nowPos32, *(data - 1));
1860                     if (IsCharState(p->state))
1861                         LitEnc_Encode(&p->rc, probs, curByte);
1862                     else
1863                         LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
1864                     p->state = kLiteralNextStates[p->state];
1865                 }
1866                 else
1867                 {
1868                     RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
1869                     if (pos < LZMA_NUM_REPS)
1870                     {
1871                         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
1872                         if (pos == 0)
1873                         {
1874                             RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
1875                             RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
1876                         }
1877                         else
1878                         {
1879                             UInt32 distance = p->reps[pos];
1880                             RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
1881                             if (pos == 1)
1882                                 RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
1883                             else
1884                             {
1885                                 RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
1886                                 RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
1887                                 if (pos == 3)
1888                                     p->reps[3] = p->reps[2];
1889                                 p->reps[2] = p->reps[1];
1890                             }
1891                             p->reps[1] = p->reps[0];
1892                             p->reps[0] = distance;
1893                         }
1894                         if (len == 1)
1895                             p->state = kShortRepNextStates[p->state];
1896                         else
1897                         {
1898                             LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1899                             p->state = kRepNextStates[p->state];
1900                         }
1901                     }
1902                     else
1903                     {
1904                         UInt32 posSlot;
1905                         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
1906                         p->state = kMatchNextStates[p->state];
1907                         LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1908                         pos -= LZMA_NUM_REPS;
1909                         GetPosSlot(pos, posSlot);
1910                         RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
1911
1912                         if (posSlot >= kStartPosModelIndex)
1913                         {
1914                             UInt32 footerBits = ((posSlot >> 1) - 1);
1915                             UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1916                             UInt32 posReduced = pos - base;
1917
1918                             if (posSlot < kEndPosModelIndex)
1919                                 RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
1920                             else
1921                             {
1922                                 RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1923                                 RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
1924                                 p->alignPriceCount++;
1925                             }
1926                         }
1927                         p->reps[3] = p->reps[2];
1928                         p->reps[2] = p->reps[1];
1929                         p->reps[1] = p->reps[0];
1930                         p->reps[0] = pos;
1931                         p->matchPriceCount++;
1932                     }
1933                 }
1934                 p->additionalOffset -= len;
1935                 nowPos32 += len;
1936                 if (p->additionalOffset == 0)
1937                 {
1938                     UInt32 processed;
1939                     if (!p->fastMode)
1940                     {
1941                         if (p->matchPriceCount >= (1 << 7))
1942                             FillDistancesPrices(p);
1943                         if (p->alignPriceCount >= kAlignTableSize)
1944                             FillAlignPrices(p);
1945                     }
1946                     if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
1947                         break;
1948                     processed = nowPos32 - startPos32;
1949                     if (useLimits)
1950                     {
1951                         if (processed + kNumOpts + 300 >= maxUnpackSize ||
1952                             RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
1953                             break;
1954                     }
1955                     else if (processed >= (1 << 15))
1956                     {
1957                         p->nowPos64 += nowPos32 - startPos32;
1958                         return CheckErrors(p);
1959                     }
1960                 }
1961             }
1962         p->nowPos64 += nowPos32 - startPos32;
1963         return Flush(p, nowPos32);
1964     }
1965
1966 #define kBigHashDicLimit ((UInt32)1 << 24)
1967
1968     static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
1969     {
1970         UInt32 beforeSize = kNumOpts;
1971         Bool btMode;
1972         (void)btMode;
1973         if (!RangeEnc_Alloc(&p->rc, alloc))
1974             return SZ_ERROR_MEM;
1975         btMode = (p->matchFinderBase.btMode != 0);
1976 #ifdef COMPRESS_MF_MT
1977         p->mtMode = (p->multiThread && !p->fastMode && btMode);
1978 #endif
1979
1980         {
1981             unsigned lclp = p->lc + p->lp;
1982             if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
1983             {
1984                 LzmaEnc_FreeLits(p, alloc);
1985                 p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
1986                 p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
1987                 if (p->litProbs == 0 || p->saveState.litProbs == 0)
1988                 {
1989                     LzmaEnc_FreeLits(p, alloc);
1990                     return SZ_ERROR_MEM;
1991                 }
1992                 p->lclp = lclp;
1993             }
1994         }
1995
1996         p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
1997
1998         if (beforeSize + p->dictSize < keepWindowSize)
1999             beforeSize = keepWindowSize - p->dictSize;
2000
2001 #ifdef COMPRESS_MF_MT
2002         if (p->mtMode)
2003         {
2004             RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
2005             p->matchFinderObj = &p->matchFinderMt;
2006             MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
2007         }
2008         else
2009 #endif
2010         {
2011             if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
2012                 return SZ_ERROR_MEM;
2013             p->matchFinderObj = &p->matchFinderBase;
2014             MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
2015         }
2016         return SZ_OK;
2017     }
2018
2019     void LzmaEnc_Init(CLzmaEnc *p)
2020     {
2021         UInt32 i;
2022         p->state = 0;
2023         for (i = 0; i < LZMA_NUM_REPS; i++)
2024             p->reps[i] = 0;
2025
2026         RangeEnc_Init(&p->rc);
2027
2028         for (i = 0; i < kNumStates; i++)
2029         {
2030             UInt32 j;
2031             for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
2032             {
2033                 p->isMatch[i][j] = kProbInitValue;
2034                 p->isRep0Long[i][j] = kProbInitValue;
2035             }
2036             p->isRep[i] = kProbInitValue;
2037             p->isRepG0[i] = kProbInitValue;
2038             p->isRepG1[i] = kProbInitValue;
2039             p->isRepG2[i] = kProbInitValue;
2040         }
2041
2042         {
2043             UInt32 num = 0x300 << (p->lp + p->lc);
2044             for (i = 0; i < num; i++)
2045                 p->litProbs[i] = kProbInitValue;
2046         }
2047
2048         {
2049             for (i = 0; i < kNumLenToPosStates; i++)
2050             {
2051                 CLzmaProb *probs = p->posSlotEncoder[i];
2052                 UInt32 j;
2053                 for (j = 0; j < (1 << kNumPosSlotBits); j++)
2054                     probs[j] = kProbInitValue;
2055             }
2056         }
2057         {
2058             for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
2059                 p->posEncoders[i] = kProbInitValue;
2060         }
2061
2062         LenEnc_Init(&p->lenEnc.p);
2063         LenEnc_Init(&p->repLenEnc.p);
2064
2065         for (i = 0; i < (1 << kNumAlignBits); i++)
2066             p->posAlignEncoder[i] = kProbInitValue;
2067
2068         p->optimumEndIndex = 0;
2069         p->optimumCurrentIndex = 0;
2070         p->additionalOffset = 0;
2071
2072         p->pbMask = (1 << p->pb) - 1;
2073         p->lpMask = (1 << p->lp) - 1;
2074     }
2075
2076     void LzmaEnc_InitPrices(CLzmaEnc *p)
2077     {
2078         if (!p->fastMode)
2079         {
2080             FillDistancesPrices(p);
2081             FillAlignPrices(p);
2082         }
2083
2084         p->lenEnc.tableSize =
2085             p->repLenEnc.tableSize =
2086                 p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
2087         LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
2088         LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
2089     }
2090
2091     static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
2092     {
2093         UInt32 i;
2094         for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
2095             if (p->dictSize <= ((UInt32)1 << i))
2096                 break;
2097         p->distTableSize = i * 2;
2098
2099         p->finished = False;
2100         p->result = SZ_OK;
2101         RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
2102         LzmaEnc_Init(p);
2103         LzmaEnc_InitPrices(p);
2104         p->nowPos64 = 0;
2105         return SZ_OK;
2106     }
2107
2108     static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
2109                                 ISzAlloc *alloc, ISzAlloc *allocBig)
2110     {
2111         CLzmaEnc *p = (CLzmaEnc *)pp;
2112         p->inStream = inStream;
2113         p->rc.outStream = outStream;
2114         return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
2115     }
2116
2117     SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
2118                                  ISeqInStream *inStream, UInt32 keepWindowSize,
2119                                  ISzAlloc *alloc, ISzAlloc *allocBig)
2120     {
2121         CLzmaEnc *p = (CLzmaEnc *)pp;
2122         p->inStream = inStream;
2123         return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2124     }
2125
2126     static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
2127     {
2128         p->seqBufInStream.funcTable.Read = MyRead;
2129         p->seqBufInStream.data = src;
2130         p->seqBufInStream.rem = srcLen;
2131     }
2132
2133     SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
2134                             UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
2135     {
2136         CLzmaEnc *p = (CLzmaEnc *)pp;
2137         LzmaEnc_SetInputBuf(p, src, srcLen);
2138         p->inStream = &p->seqBufInStream.funcTable;
2139         return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2140     }
2141
2142     void LzmaEnc_Finish(CLzmaEncHandle pp)
2143     {
2144 #ifdef COMPRESS_MF_MT
2145         CLzmaEnc *p = (CLzmaEnc *)pp;
2146         if (p->mtMode)
2147             MatchFinderMt_ReleaseStream(&p->matchFinderMt);
2148 #else
2149         //pp = pp;
2150         (void)pp;
2151 #endif
2152     }
2153
2154     typedef struct _CSeqOutStreamBuf
2155     {
2156         ISeqOutStream funcTable;
2157         Byte *data;
2158         SizeT rem;
2159         Bool overflow;
2160     } CSeqOutStreamBuf;
2161
2162     static size_t MyWrite(void *pp, const void *data, size_t size)
2163     {
2164         CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
2165         if (p->rem < size)
2166         {
2167             size = p->rem;
2168             p->overflow = True;
2169         }
2170         memcpy(p->data, data, size);
2171         p->rem -= size;
2172         p->data += size;
2173         return size;
2174     }
2175
2176     UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
2177     {
2178         const CLzmaEnc *p = (CLzmaEnc *)pp;
2179         return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
2180     }
2181
2182     const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
2183     {
2184         const CLzmaEnc *p = (CLzmaEnc *)pp;
2185         return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2186     }
2187
2188     SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
2189                                  Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
2190     {
2191         CLzmaEnc *p = (CLzmaEnc *)pp;
2192         UInt64 nowPos64;
2193         SRes res;
2194         CSeqOutStreamBuf outStream;
2195
2196         outStream.funcTable.Write = MyWrite;
2197         outStream.data = dest;
2198         outStream.rem = *destLen;
2199         outStream.overflow = False;
2200
2201         p->writeEndMark = False;
2202         p->finished = False;
2203         p->result = SZ_OK;
2204
2205         if (reInit)
2206             LzmaEnc_Init(p);
2207         LzmaEnc_InitPrices(p);
2208         nowPos64 = p->nowPos64;
2209         RangeEnc_Init(&p->rc);
2210         p->rc.outStream = &outStream.funcTable;
2211
2212         res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
2213
2214         *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
2215         *destLen -= outStream.rem;
2216         if (outStream.overflow)
2217             return SZ_ERROR_OUTPUT_EOF;
2218
2219         return res;
2220     }
2221
2222     SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
2223                         ISzAlloc *alloc, ISzAlloc *allocBig)
2224     {
2225         CLzmaEnc *p = (CLzmaEnc *)pp;
2226         SRes res = SZ_OK;
2227
2228 #ifdef COMPRESS_MF_MT
2229         Byte allocaDummy[0x300];
2230         (void)allocaDummy;
2231         int i = 0;
2232         for (i = 0; i < 16; i++)
2233             allocaDummy[i] = (Byte)i;
2234 #endif
2235
2236         RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
2237
2238         for (;;)
2239         {
2240             res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
2241             if (res != SZ_OK || p->finished != 0)
2242                 break;
2243             if (progress != 0)
2244             {
2245                 res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
2246                 if (res != SZ_OK)
2247                 {
2248                     res = SZ_ERROR_PROGRESS;
2249                     break;
2250                 }
2251             }
2252         }
2253         LzmaEnc_Finish(pp);
2254         return res;
2255     }
2256
2257     SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
2258     {
2259         CLzmaEnc *p = (CLzmaEnc *)pp;
2260         int i;
2261         UInt32 dictSize = p->dictSize;
2262         if (*size < LZMA_PROPS_SIZE)
2263             return SZ_ERROR_PARAM;
2264         *size = LZMA_PROPS_SIZE;
2265         props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
2266
2267         for (i = 11; i <= 30; i++)
2268         {
2269             if (dictSize <= ((UInt32)2 << i))
2270             {
2271                 dictSize = (2 << i);
2272                 break;
2273             }
2274             if (dictSize <= ((UInt32)3 << i))
2275             {
2276                 dictSize = (3 << i);
2277                 break;
2278             }
2279         }
2280
2281         for (i = 0; i < 4; i++)
2282             props[1 + i] = (Byte)(dictSize >> (8 * i));
2283         return SZ_OK;
2284     }
2285
2286     SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2287                            int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
2288     {
2289         SRes res;
2290         CLzmaEnc *p = (CLzmaEnc *)pp;
2291
2292         CSeqOutStreamBuf outStream;
2293
2294         LzmaEnc_SetInputBuf(p, src, srcLen);
2295
2296         outStream.funcTable.Write = MyWrite;
2297         outStream.data = dest;
2298         outStream.rem = *destLen;
2299         outStream.overflow = False;
2300
2301         p->writeEndMark = writeEndMark;
2302         res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
2303                              progress, alloc, allocBig);
2304
2305         *destLen -= outStream.rem;
2306         if (outStream.overflow)
2307             return SZ_ERROR_OUTPUT_EOF;
2308         return res;
2309     }
2310
2311     SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2312                     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
2313                     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
2314     {
2315         CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
2316         SRes res;
2317         if (p == 0)
2318             return SZ_ERROR_MEM;
2319
2320         res = LzmaEnc_SetProps(p, props);
2321         if (res == SZ_OK)
2322         {
2323             res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
2324             if (res == SZ_OK)
2325                 res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
2326                                         writeEndMark, progress, alloc, allocBig);
2327         }
2328
2329         LzmaEnc_Destroy(p, alloc, allocBig);
2330         return res;
2331     }
2332 }