1 /* LzmaEnc.c -- LZMA Encoder
\r
2 2022-07-15: Igor Pavlov : Public domain */
\r
8 /* #define SHOW_STAT */
\r
9 /* #define SHOW_STAT2 */
\r
11 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
\r
15 #include "CpuArch.h"
\r
16 #include "LzmaEnc.h"
\r
20 #include "LzFindMt.h"
\r
23 /* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */
\r
25 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
\r
26 ISzAllocPtr alloc, ISzAllocPtr allocBig);
\r
27 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
\r
28 UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
\r
29 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
\r
30 Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
\r
31 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
\r
32 void LzmaEnc_Finish(CLzmaEncHandle pp);
\r
33 void LzmaEnc_SaveState(CLzmaEncHandle pp);
\r
34 void LzmaEnc_RestoreState(CLzmaEncHandle pp);
\r
37 static unsigned g_STAT_OFFSET = 0;
\r
40 /* for good normalization speed we still reserve 256 MB before 4 GB range */
\r
41 #define kLzmaMaxHistorySize ((UInt32)15 << 28)
\r
43 #define kNumTopBits 24
\r
44 #define kTopValue ((UInt32)1 << kNumTopBits)
\r
46 #define kNumBitModelTotalBits 11
\r
47 #define kBitModelTotal (1 << kNumBitModelTotalBits)
\r
48 #define kNumMoveBits 5
\r
49 #define kProbInitValue (kBitModelTotal >> 1)
\r
51 #define kNumMoveReducingBits 4
\r
52 #define kNumBitPriceShiftBits 4
\r
53 // #define kBitPrice (1 << kNumBitPriceShiftBits)
\r
55 #define REP_LEN_COUNT 64
\r
57 void LzmaEncProps_Init(CLzmaEncProps *p)
\r
60 p->dictSize = p->mc = 0;
\r
61 p->reduceSize = (UInt64)(Int64)-1;
\r
62 p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
\r
63 p->writeEndMark = 0;
\r
67 void LzmaEncProps_Normalize(CLzmaEncProps *p)
\r
69 int level = p->level;
\r
70 if (level < 0) level = 5;
\r
73 if (p->dictSize == 0)
\r
75 ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
\r
76 ( level <= 6 ? ((UInt32)1 << (level + 19)) :
\r
77 ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
\r
80 if (p->dictSize > p->reduceSize)
\r
82 UInt32 v = (UInt32)p->reduceSize;
\r
83 const UInt32 kReduceMin = ((UInt32)1 << 12);
\r
86 if (p->dictSize > v)
\r
90 if (p->lc < 0) p->lc = 3;
\r
91 if (p->lp < 0) p->lp = 0;
\r
92 if (p->pb < 0) p->pb = 2;
\r
94 if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
\r
95 if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
\r
96 if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
\r
97 if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
\r
98 if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);
\r
100 if (p->numThreads < 0)
\r
103 ((p->btMode && p->algo) ? 2 : 1);
\r
109 UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
\r
111 CLzmaEncProps props = *props2;
\r
112 LzmaEncProps_Normalize(&props);
\r
113 return props.dictSize;
\r
121 IF (SRC == 0) ZF = 1, DEST is undefined;
\r
122 AMD : DEST is unchanged;
\r
123 IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit
\r
124 BSR is slow in some processors
\r
127 IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64)
\r
128 IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits
\r
129 IF (DEST == 0) ZF = 1;
\r
131 LZCNT works only in new processors starting from Haswell.
\r
132 if LZCNT is not supported by processor, then it's executed as BSR.
\r
133 LZCNT can be faster than BSR, if supported.
\r
136 // #define LZMA_LOG_BSR
\r
138 #if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */
\r
140 #if (defined(__clang__) && (__clang_major__ >= 6)) \
\r
141 || (defined(__GNUC__) && (__GNUC__ >= 6))
\r
142 #define LZMA_LOG_BSR
\r
143 #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
\r
144 // #if defined(MY_CPU_ARM_OR_ARM64)
\r
145 #define LZMA_LOG_BSR
\r
150 // #include <intrin.h>
\r
152 #ifdef LZMA_LOG_BSR
\r
154 #if defined(__clang__) \
\r
155 || defined(__GNUC__)
\r
158 C code: : (30 - __builtin_clz(x))
\r
159 gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31)
\r
160 clang10 for x64 : 31 + (bsr(x) xor -32)
\r
163 #define MY_clz(x) ((unsigned)__builtin_clz(x))
\r
165 // __builtin_ia32_lzcnt_u32
\r
167 #else // #if defined(_MSC_VER)
\r
169 #ifdef MY_CPU_ARM_OR_ARM64
\r
171 #define MY_clz _CountLeadingZeros
\r
173 #else // if defined(MY_CPU_X86_OR_AMD64)
\r
175 // #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU)
\r
176 // _BitScanReverse code is not optimal for some MSVC compilers
\r
177 #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \
\r
178 res = (zz + zz) + (pos >> zz); }
\r
180 #endif // MY_CPU_X86_OR_AMD64
\r
187 #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \
\r
188 res = (zz + zz) + (pos >> zz); }
\r
193 unsigned GetPosSlot1(UInt32 pos);
\r
194 unsigned GetPosSlot1(UInt32 pos)
\r
197 BSR2_RET(pos, res);
\r
200 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
\r
201 #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
\r
204 #else // ! LZMA_LOG_BSR
\r
206 #define kNumLogBits (11 + sizeof(size_t) / 8 * 3)
\r
208 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
\r
210 static void LzmaEnc_FastPosInit(Byte *g_FastPos)
\r
217 for (slot = 2; slot < kNumLogBits * 2; slot++)
\r
219 size_t k = ((size_t)1 << ((slot >> 1) - 1));
\r
221 for (j = 0; j < k; j++)
\r
222 g_FastPos[j] = (Byte)slot;
\r
227 /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
\r
229 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
\r
230 (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
\r
231 res = p->g_FastPos[pos >> zz] + (zz * 2); }
\r
235 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
\r
236 (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
\r
237 res = p->g_FastPos[pos >> zz] + (zz * 2); }
\r
240 #define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
\r
241 res = p->g_FastPos[pos >> zz] + (zz * 2); }
\r
244 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
\r
245 p->g_FastPos[pos >> 6] + 12 : \
\r
246 p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
\r
249 #define GetPosSlot1(pos) p->g_FastPos[pos]
\r
250 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
\r
251 #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
\r
253 #endif // LZMA_LOG_BSR
\r
256 #define LZMA_NUM_REPS 4
\r
258 typedef UInt16 CState;
\r
259 typedef UInt16 CExtra;
\r
268 // > 1 : MATCH (extra-1) : LIT : REP0 (len)
\r
271 UInt32 reps[LZMA_NUM_REPS];
\r
276 #define kNumOpts (1 << 11)
\r
277 #define kPackReserve (kNumOpts * 8)
\r
278 // #define kNumOpts (1 << 12)
\r
279 // #define kPackReserve (1 + kNumOpts * 2)
\r
281 #define kNumLenToPosStates 4
\r
282 #define kNumPosSlotBits 6
\r
283 // #define kDicLogSizeMin 0
\r
284 #define kDicLogSizeMax 32
\r
285 #define kDistTableSizeMax (kDicLogSizeMax * 2)
\r
287 #define kNumAlignBits 4
\r
288 #define kAlignTableSize (1 << kNumAlignBits)
\r
289 #define kAlignMask (kAlignTableSize - 1)
\r
291 #define kStartPosModelIndex 4
\r
292 #define kEndPosModelIndex 14
\r
293 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
\r
296 #ifdef _LZMA_PROB32
\r
303 #define LZMA_PB_MAX 4
\r
304 #define LZMA_LC_MAX 8
\r
305 #define LZMA_LP_MAX 4
\r
307 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
\r
309 #define kLenNumLowBits 3
\r
310 #define kLenNumLowSymbols (1 << kLenNumLowBits)
\r
311 #define kLenNumHighBits 8
\r
312 #define kLenNumHighSymbols (1 << kLenNumHighBits)
\r
313 #define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
\r
315 #define LZMA_MATCH_LEN_MIN 2
\r
316 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
\r
318 #define kNumStates 12
\r
323 CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
\r
324 CLzmaProb high[kLenNumHighSymbols];
\r
330 unsigned tableSize;
\r
331 UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
\r
332 // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
\r
333 // UInt32 prices2[kLenNumSymbolsTotal];
\r
336 #define GET_PRICE_LEN(p, posState, len) \
\r
337 ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
\r
340 #define GET_PRICE_LEN(p, posState, len) \
\r
341 ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
\r
353 ISeqOutStream *outStream;
\r
361 CLzmaProb *litProbs;
\r
364 UInt32 reps[LZMA_NUM_REPS];
\r
366 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
\r
367 CLzmaProb isRep[kNumStates];
\r
368 CLzmaProb isRepG0[kNumStates];
\r
369 CLzmaProb isRepG1[kNumStates];
\r
370 CLzmaProb isRepG2[kNumStates];
\r
371 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
\r
372 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
\r
374 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
\r
375 CLzmaProb posEncoders[kNumFullDistances];
\r
378 CLenEnc repLenProbs;
\r
383 typedef UInt32 CProbPrice;
\r
388 void *matchFinderObj;
\r
389 IMatchFinder2 matchFinder;
\r
394 unsigned longestMatchLen;
\r
399 unsigned numFastBytes;
\r
400 unsigned additionalOffset;
\r
401 UInt32 reps[LZMA_NUM_REPS];
\r
402 unsigned lpMask, pbMask;
\r
403 CLzmaProb *litProbs;
\r
408 unsigned lc, lp, pb;
\r
412 BoolInt writeEndMark;
\r
414 BoolInt multiThread;
\r
416 // BoolInt _maxMode;
\r
420 unsigned matchPriceCount;
\r
421 // unsigned alignPriceCount;
\r
422 int repLenEncCounter;
\r
424 unsigned distTableSize;
\r
431 // begin of CMatchFinderMt is used in LZ thread
\r
432 CMatchFinderMt matchFinderMt;
\r
433 // end of CMatchFinderMt is used in BT and HASH threads
\r
435 // CMatchFinder matchFinderBase;
\r
437 CMatchFinder matchFinderBase;
\r
440 // we suppose that we have 8-bytes alignment after CMatchFinder
\r
447 CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
\r
449 // we want {len , dist} pairs to be 8-bytes aligned in matches array
\r
450 UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2];
\r
452 // we want 8-bytes alignment here
\r
453 UInt32 alignPrices[kAlignTableSize];
\r
454 UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
\r
455 UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
\r
457 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
\r
458 CLzmaProb isRep[kNumStates];
\r
459 CLzmaProb isRepG0[kNumStates];
\r
460 CLzmaProb isRepG1[kNumStates];
\r
461 CLzmaProb isRepG2[kNumStates];
\r
462 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
\r
463 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
\r
464 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
\r
465 CLzmaProb posEncoders[kNumFullDistances];
\r
468 CLenEnc repLenProbs;
\r
470 #ifndef LZMA_LOG_BSR
\r
471 Byte g_FastPos[1 << kNumLogBits];
\r
474 CLenPriceEnc lenEnc;
\r
475 CLenPriceEnc repLenEnc;
\r
477 COptimal opt[kNumOpts];
\r
479 CSaveState saveState;
\r
481 // BoolInt mf_Failure;
\r
488 #define MFB (p->matchFinderBase)
\r
491 #define MFB (p->matchFinderMt.MatchFinder)
\r
495 #define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
\r
497 void LzmaEnc_SaveState(CLzmaEncHandle pp)
\r
499 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
500 CSaveState *dest = &p->saveState;
\r
502 dest->state = p->state;
\r
504 dest->lenProbs = p->lenProbs;
\r
505 dest->repLenProbs = p->repLenProbs;
\r
507 COPY_ARR(dest, p, reps);
\r
509 COPY_ARR(dest, p, posAlignEncoder);
\r
510 COPY_ARR(dest, p, isRep);
\r
511 COPY_ARR(dest, p, isRepG0);
\r
512 COPY_ARR(dest, p, isRepG1);
\r
513 COPY_ARR(dest, p, isRepG2);
\r
514 COPY_ARR(dest, p, isMatch);
\r
515 COPY_ARR(dest, p, isRep0Long);
\r
516 COPY_ARR(dest, p, posSlotEncoder);
\r
517 COPY_ARR(dest, p, posEncoders);
\r
519 memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
\r
523 void LzmaEnc_RestoreState(CLzmaEncHandle pp)
\r
525 CLzmaEnc *dest = (CLzmaEnc *)pp;
\r
526 const CSaveState *p = &dest->saveState;
\r
528 dest->state = p->state;
\r
530 dest->lenProbs = p->lenProbs;
\r
531 dest->repLenProbs = p->repLenProbs;
\r
533 COPY_ARR(dest, p, reps);
\r
535 COPY_ARR(dest, p, posAlignEncoder);
\r
536 COPY_ARR(dest, p, isRep);
\r
537 COPY_ARR(dest, p, isRepG0);
\r
538 COPY_ARR(dest, p, isRepG1);
\r
539 COPY_ARR(dest, p, isRepG2);
\r
540 COPY_ARR(dest, p, isMatch);
\r
541 COPY_ARR(dest, p, isRep0Long);
\r
542 COPY_ARR(dest, p, posSlotEncoder);
\r
543 COPY_ARR(dest, p, posEncoders);
\r
545 memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
\r
550 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
\r
552 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
553 CLzmaEncProps props = *props2;
\r
554 LzmaEncProps_Normalize(&props);
\r
556 if (props.lc > LZMA_LC_MAX
\r
557 || props.lp > LZMA_LP_MAX
\r
558 || props.pb > LZMA_PB_MAX)
\r
559 return SZ_ERROR_PARAM;
\r
562 if (props.dictSize > kLzmaMaxHistorySize)
\r
563 props.dictSize = kLzmaMaxHistorySize;
\r
565 #ifndef LZMA_LOG_BSR
\r
567 const UInt64 dict64 = props.dictSize;
\r
568 if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress))
\r
569 return SZ_ERROR_PARAM;
\r
573 p->dictSize = props.dictSize;
\r
575 unsigned fb = (unsigned)props.fb;
\r
578 if (fb > LZMA_MATCH_LEN_MAX)
\r
579 fb = LZMA_MATCH_LEN_MAX;
\r
580 p->numFastBytes = fb;
\r
582 p->lc = (unsigned)props.lc;
\r
583 p->lp = (unsigned)props.lp;
\r
584 p->pb = (unsigned)props.pb;
\r
585 p->fastMode = (props.algo == 0);
\r
586 // p->_maxMode = True;
\r
587 MFB.btMode = (Byte)(props.btMode ? 1 : 0);
\r
589 unsigned numHashBytes = 4;
\r
592 if (props.numHashBytes < 2) numHashBytes = 2;
\r
593 else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes;
\r
595 if (props.numHashBytes >= 5) numHashBytes = 5;
\r
597 MFB.numHashBytes = numHashBytes;
\r
600 MFB.cutValue = props.mc;
\r
602 p->writeEndMark = (BoolInt)props.writeEndMark;
\r
606 if (newMultiThread != _multiThread)
\r
608 ReleaseMatchFinder();
\r
609 _multiThread = newMultiThread;
\r
612 p->multiThread = (props.numThreads > 1);
\r
613 p->matchFinderMt.btSync.affinity =
\r
614 p->matchFinderMt.hashSync.affinity = props.affinity;
\r
621 void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
\r
623 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
624 MFB.expectedDataSize = expectedDataSiize;
\r
628 #define kState_Start 0
\r
629 #define kState_LitAfterMatch 4
\r
630 #define kState_LitAfterRep 5
\r
631 #define kState_MatchAfterLit 7
\r
632 #define kState_RepAfterLit 8
\r
634 static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
\r
635 static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
\r
636 static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
\r
637 static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
\r
639 #define IsLitState(s) ((s) < 7)
\r
640 #define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
\r
641 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
\r
643 #define kInfinityPrice (1 << 30)
\r
645 static void RangeEnc_Construct(CRangeEnc *p)
\r
647 p->outStream = NULL;
\r
651 #define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize)
\r
652 #define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
\r
654 #define RC_BUF_SIZE (1 << 16)
\r
656 static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
\r
660 p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
\r
663 p->bufLim = p->bufBase + RC_BUF_SIZE;
\r
668 static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
\r
670 ISzAlloc_Free(alloc, p->bufBase);
\r
674 static void RangeEnc_Init(CRangeEnc *p)
\r
676 p->range = 0xFFFFFFFF;
\r
681 p->buf = p->bufBase;
\r
687 MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
\r
689 const size_t num = (size_t)(p->buf - p->bufBase);
\r
690 if (p->res == SZ_OK)
\r
692 if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
\r
693 p->res = SZ_ERROR_WRITE;
\r
695 p->processed += num;
\r
696 p->buf = p->bufBase;
\r
699 MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
\r
701 UInt32 low = (UInt32)p->low;
\r
702 unsigned high = (unsigned)(p->low >> 32);
\r
703 p->low = (UInt32)(low << 8);
\r
704 if (low < (UInt32)0xFF000000 || high != 0)
\r
707 Byte *buf = p->buf;
\r
708 *buf++ = (Byte)(p->cache + high);
\r
709 p->cache = (unsigned)(low >> 24);
\r
711 if (buf == p->bufLim)
\r
712 RangeEnc_FlushStream(p);
\r
713 if (p->cacheSize == 0)
\r
719 Byte *buf = p->buf;
\r
720 *buf++ = (Byte)(high);
\r
722 if (buf == p->bufLim)
\r
723 RangeEnc_FlushStream(p);
\r
724 if (--p->cacheSize == 0)
\r
731 static void RangeEnc_FlushData(CRangeEnc *p)
\r
734 for (i = 0; i < 5; i++)
\r
735 RangeEnc_ShiftLow(p);
\r
738 #define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
\r
740 #define RC_BIT_PRE(p, prob) \
\r
742 newBound = (range >> kNumBitModelTotalBits) * ttt;
\r
744 // #define _LZMA_ENC_USE_BRANCH
\r
746 #ifdef _LZMA_ENC_USE_BRANCH
\r
748 #define RC_BIT(p, prob, bit) { \
\r
749 RC_BIT_PRE(p, prob) \
\r
750 if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
\r
751 else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
\r
752 *(prob) = (CLzmaProb)ttt; \
\r
758 #define RC_BIT(p, prob, bit) { \
\r
760 RC_BIT_PRE(p, prob) \
\r
761 mask = 0 - (UInt32)bit; \
\r
763 mask &= newBound; \
\r
765 (p)->low += mask; \
\r
766 mask = (UInt32)bit - 1; \
\r
767 range += newBound & mask; \
\r
768 mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
\r
769 mask += ((1 << kNumMoveBits) - 1); \
\r
770 ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \
\r
771 *(prob) = (CLzmaProb)ttt; \
\r
780 #define RC_BIT_0_BASE(p, prob) \
\r
781 range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
\r
783 #define RC_BIT_1_BASE(p, prob) \
\r
784 range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
\r
786 #define RC_BIT_0(p, prob) \
\r
787 RC_BIT_0_BASE(p, prob) \
\r
790 #define RC_BIT_1(p, prob) \
\r
791 RC_BIT_1_BASE(p, prob) \
\r
794 static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
\r
796 UInt32 range, ttt, newBound;
\r
798 RC_BIT_PRE(p, prob)
\r
803 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
\r
805 UInt32 range = p->range;
\r
809 UInt32 ttt, newBound;
\r
810 // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
\r
811 CLzmaProb *prob = probs + (sym >> 8);
\r
812 UInt32 bit = (sym >> 7) & 1;
\r
814 RC_BIT(p, prob, bit);
\r
816 while (sym < 0x10000);
\r
820 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)
\r
822 UInt32 range = p->range;
\r
823 UInt32 offs = 0x100;
\r
827 UInt32 ttt, newBound;
\r
831 // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);
\r
832 prob = probs + (offs + (matchByte & offs) + (sym >> 8));
\r
833 bit = (sym >> 7) & 1;
\r
835 offs &= ~(matchByte ^ sym);
\r
836 RC_BIT(p, prob, bit);
\r
838 while (sym < 0x10000);
\r
844 static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
\r
847 for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
\r
849 const unsigned kCyclesBits = kNumBitPriceShiftBits;
\r
850 UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
\r
851 unsigned bitCount = 0;
\r
853 for (j = 0; j < kCyclesBits; j++)
\r
857 while (w >= ((UInt32)1 << 16))
\r
863 ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
\r
864 // printf("\n%3d: %5d", i, ProbPrices[i]);
\r
869 #define GET_PRICE(prob, bit) \
\r
870 p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
\r
872 #define GET_PRICEa(prob, bit) \
\r
873 ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
\r
875 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
\r
876 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
\r
878 #define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
\r
879 #define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
\r
882 static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
\r
888 unsigned bit = sym & 1;
\r
890 price += GET_PRICEa(probs[sym], bit);
\r
897 static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
\r
900 UInt32 offs = 0x100;
\r
905 price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
\r
907 offs &= ~(matchByte ^ sym);
\r
909 while (sym < 0x10000);
\r
914 static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)
\r
916 UInt32 range = rc->range;
\r
920 UInt32 ttt, newBound;
\r
921 unsigned bit = sym & 1;
\r
922 // RangeEnc_EncodeBit(rc, probs + m, bit);
\r
924 RC_BIT(rc, probs + m, bit);
\r
925 m = (m << 1) | bit;
\r
933 static void LenEnc_Init(CLenEnc *p)
\r
936 for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
\r
937 p->low[i] = kProbInitValue;
\r
938 for (i = 0; i < kLenNumHighSymbols; i++)
\r
939 p->high[i] = kProbInitValue;
\r
942 static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
\r
944 UInt32 range, ttt, newBound;
\r
945 CLzmaProb *probs = p->low;
\r
947 RC_BIT_PRE(rc, probs);
\r
948 if (sym >= kLenNumLowSymbols)
\r
950 RC_BIT_1(rc, probs);
\r
951 probs += kLenNumLowSymbols;
\r
952 RC_BIT_PRE(rc, probs);
\r
953 if (sym >= kLenNumLowSymbols * 2)
\r
955 RC_BIT_1(rc, probs);
\r
957 // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
\r
958 LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
\r
961 sym -= kLenNumLowSymbols;
\r
964 // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
\r
968 RC_BIT_0(rc, probs);
\r
969 probs += (posState << (1 + kLenNumLowBits));
\r
970 bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
\r
971 bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
\r
972 bit = sym & 1; RC_BIT(rc, probs + m, bit);
\r
977 static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
\r
980 for (i = 0; i < 8; i += 2)
\r
982 UInt32 price = startPrice;
\r
984 price += GET_PRICEa(probs[1 ], (i >> 2));
\r
985 price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
\r
986 prob = probs[4 + (i >> 1)];
\r
987 prices[i ] = price + GET_PRICEa_0(prob);
\r
988 prices[i + 1] = price + GET_PRICEa_1(prob);
\r
993 MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
\r
995 unsigned numPosStates,
\r
996 const CLenEnc *enc,
\r
997 const CProbPrice *ProbPrices)
\r
1002 unsigned prob = enc->low[0];
\r
1004 unsigned posState;
\r
1005 b = GET_PRICEa_1(prob);
\r
1006 a = GET_PRICEa_0(prob);
\r
1007 c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
\r
1008 for (posState = 0; posState < numPosStates; posState++)
\r
1010 UInt32 *prices = p->prices[posState];
\r
1011 const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
\r
1012 SetPrices_3(probs, a, prices, ProbPrices);
\r
1013 SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
\r
1021 a = GET_PRICEa_0(enc->low[0]);
\r
1022 for (i = 0; i < kLenNumLowSymbols; i++)
\r
1023 p->prices2[i] = a;
\r
1024 a = GET_PRICEa_1(enc->low[0]);
\r
1025 b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
\r
1026 for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
\r
1027 p->prices2[i] = b;
\r
1028 a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
\r
1032 // p->counter = numSymbols;
\r
1033 // p->counter = 64;
\r
1036 unsigned i = p->tableSize;
\r
1038 if (i > kLenNumLowSymbols * 2)
\r
1040 const CLzmaProb *probs = enc->high;
\r
1041 UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
\r
1042 i -= kLenNumLowSymbols * 2 - 1;
\r
1044 b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
\r
1048 p->prices2[i] = a +
\r
1049 // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
\r
1050 LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
\r
1052 // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
\r
1053 unsigned sym = --i + (1 << (kLenNumHighBits - 1));
\r
1057 unsigned bit = sym & 1;
\r
1059 price += GET_PRICEa(probs[sym], bit);
\r
1064 unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
\r
1065 prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob);
\r
1066 prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
\r
1072 unsigned posState;
\r
1073 size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
\r
1074 for (posState = 1; posState < numPosStates; posState++)
\r
1075 memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
\r
1083 g_STAT_OFFSET += num;
\r
1084 printf("\n MovePos %u", num);
\r
1088 #define MOVE_POS(p, num) { \
\r
1089 p->additionalOffset += (num); \
\r
1090 p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
\r
1093 static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
\r
1095 unsigned numPairs;
\r
1097 p->additionalOffset++;
\r
1098 p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
\r
1100 const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
\r
1101 // if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; }
\r
1102 numPairs = (unsigned)(d - p->matches);
\r
1104 *numPairsRes = numPairs;
\r
1107 printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2);
\r
1111 for (i = 0; i < numPairs; i += 2)
\r
1112 printf("%2u %6u | ", p->matches[i], p->matches[i + 1]);
\r
1116 if (numPairs == 0)
\r
1119 const unsigned len = p->matches[(size_t)numPairs - 2];
\r
1120 if (len != p->numFastBytes)
\r
1123 UInt32 numAvail = p->numAvail;
\r
1124 if (numAvail > LZMA_MATCH_LEN_MAX)
\r
1125 numAvail = LZMA_MATCH_LEN_MAX;
\r
1127 const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
\r
1128 const Byte *p2 = p1 + len;
\r
1129 const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1];
\r
1130 const Byte *lim = p1 + numAvail;
\r
1131 for (; p2 != lim && *p2 == p2[dif]; p2++)
\r
1133 return (unsigned)(p2 - p1);
\r
1139 #define MARK_LIT ((UInt32)(Int32)-1)
\r
1141 #define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; }
\r
1142 #define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; }
\r
1143 #define IsShortRep(p) ((p)->dist == 0)
\r
1146 #define GetPrice_ShortRep(p, state, posState) \
\r
1147 ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
\r
1149 #define GetPrice_Rep_0(p, state, posState) ( \
\r
1150 GET_PRICE_1(p->isMatch[state][posState]) \
\r
1151 + GET_PRICE_1(p->isRep0Long[state][posState])) \
\r
1152 + GET_PRICE_1(p->isRep[state]) \
\r
1153 + GET_PRICE_0(p->isRepG0[state])
\r
1156 static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
\r
1159 UInt32 prob = p->isRepG0[state];
\r
1160 if (repIndex == 0)
\r
1162 price = GET_PRICE_0(prob);
\r
1163 price += GET_PRICE_1(p->isRep0Long[state][posState]);
\r
1167 price = GET_PRICE_1(prob);
\r
1168 prob = p->isRepG1[state];
\r
1169 if (repIndex == 1)
\r
1170 price += GET_PRICE_0(prob);
\r
1173 price += GET_PRICE_1(prob);
\r
1174 price += GET_PRICE(p->isRepG2[state], repIndex - 2);
\r
1181 static unsigned Backward(CLzmaEnc *p, unsigned cur)
\r
1183 unsigned wr = cur + 1;
\r
1188 UInt32 dist = p->opt[cur].dist;
\r
1189 unsigned len = (unsigned)p->opt[cur].len;
\r
1190 unsigned extra = (unsigned)p->opt[cur].extra;
\r
1196 p->opt[wr].len = (UInt32)len;
\r
1201 p->opt[wr].dist = dist;
\r
1206 p->opt[wr].dist = 0;
\r
1209 p->opt[wr].dist = MARK_LIT;
\r
1210 p->opt[wr].len = 1;
\r
1216 p->backRes = dist;
\r
1222 p->opt[wr].dist = dist;
\r
1223 p->opt[wr].len = (UInt32)len;
\r
1229 #define LIT_PROBS(pos, prevByte) \
\r
1230 (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
\r
1233 static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
\r
1235 unsigned last, cur;
\r
1236 UInt32 reps[LZMA_NUM_REPS];
\r
1237 unsigned repLens[LZMA_NUM_REPS];
\r
1242 unsigned numPairs, mainLen, repMaxIndex, i, posState;
\r
1243 UInt32 matchPrice, repMatchPrice;
\r
1245 Byte curByte, matchByte;
\r
1247 p->optCur = p->optEnd = 0;
\r
1249 if (p->additionalOffset == 0)
\r
1250 mainLen = ReadMatchDistances(p, &numPairs);
\r
1253 mainLen = p->longestMatchLen;
\r
1254 numPairs = p->numPairs;
\r
1257 numAvail = p->numAvail;
\r
1260 p->backRes = MARK_LIT;
\r
1263 if (numAvail > LZMA_MATCH_LEN_MAX)
\r
1264 numAvail = LZMA_MATCH_LEN_MAX;
\r
1266 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
\r
1269 for (i = 0; i < LZMA_NUM_REPS; i++)
\r
1272 const Byte *data2;
\r
1273 reps[i] = p->reps[i];
\r
1274 data2 = data - reps[i];
\r
1275 if (data[0] != data2[0] || data[1] != data2[1])
\r
1280 for (len = 2; len < numAvail && data[len] == data2[len]; len++)
\r
1283 if (len > repLens[repMaxIndex])
\r
1285 if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization
\r
1289 if (repLens[repMaxIndex] >= p->numFastBytes)
\r
1292 p->backRes = (UInt32)repMaxIndex;
\r
1293 len = repLens[repMaxIndex];
\r
1294 MOVE_POS(p, len - 1)
\r
1298 matches = p->matches;
\r
1299 #define MATCHES matches
\r
1300 // #define MATCHES p->matches
\r
1302 if (mainLen >= p->numFastBytes)
\r
1304 p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS;
\r
1305 MOVE_POS(p, mainLen - 1)
\r
1310 matchByte = *(data - reps[0]);
\r
1312 last = repLens[repMaxIndex];
\r
1313 if (last <= mainLen)
\r
1316 if (last < 2 && curByte != matchByte)
\r
1318 p->backRes = MARK_LIT;
\r
1322 p->opt[0].state = (CState)p->state;
\r
1324 posState = (position & p->pbMask);
\r
1327 const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
\r
1328 p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
\r
1329 (!IsLitState(p->state) ?
\r
1330 LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
\r
1331 LitEnc_GetPrice(probs, curByte, p->ProbPrices));
\r
1334 MakeAs_Lit(&p->opt[1]);
\r
1336 matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
\r
1337 repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
\r
1340 if (matchByte == curByte && repLens[0] == 0)
\r
1342 UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
\r
1343 if (shortRepPrice < p->opt[1].price)
\r
1345 p->opt[1].price = shortRepPrice;
\r
1346 MakeAs_ShortRep(&p->opt[1]);
\r
1350 p->backRes = p->opt[1].dist;
\r
1355 p->opt[1].len = 1;
\r
1357 p->opt[0].reps[0] = reps[0];
\r
1358 p->opt[0].reps[1] = reps[1];
\r
1359 p->opt[0].reps[2] = reps[2];
\r
1360 p->opt[0].reps[3] = reps[3];
\r
1362 // ---------- REP ----------
\r
1364 for (i = 0; i < LZMA_NUM_REPS; i++)
\r
1366 unsigned repLen = repLens[i];
\r
1370 price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
\r
1373 UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);
\r
1374 COptimal *opt = &p->opt[repLen];
\r
1375 if (price2 < opt->price)
\r
1377 opt->price = price2;
\r
1378 opt->len = (UInt32)repLen;
\r
1379 opt->dist = (UInt32)i;
\r
1383 while (--repLen >= 2);
\r
1387 // ---------- MATCH ----------
\r
1389 unsigned len = repLens[0] + 1;
\r
1390 if (len <= mainLen)
\r
1392 unsigned offs = 0;
\r
1393 UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
\r
1398 while (len > MATCHES[offs])
\r
1404 UInt32 dist = MATCHES[(size_t)offs + 1];
\r
1405 UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
\r
1406 unsigned lenToPosState = GetLenToPosState(len);
\r
1408 if (dist < kNumFullDistances)
\r
1409 price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
\r
1413 GetPosSlot2(dist, slot);
\r
1414 price += p->alignPrices[dist & kAlignMask];
\r
1415 price += p->posSlotPrices[lenToPosState][slot];
\r
1418 opt = &p->opt[len];
\r
1420 if (price < opt->price)
\r
1422 opt->price = price;
\r
1423 opt->len = (UInt32)len;
\r
1424 opt->dist = dist + LZMA_NUM_REPS;
\r
1428 if (len == MATCHES[offs])
\r
1431 if (offs == numPairs)
\r
1442 /* if (position >= 0) */
\r
1445 printf("\n pos = %4X", position);
\r
1446 for (i = cur; i <= last; i++)
\r
1447 printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
\r
1454 // ---------- Optimal Parsing ----------
\r
1458 unsigned numAvail;
\r
1459 UInt32 numAvailFull;
\r
1460 unsigned newLen, numPairs, prev, state, posState, startLen;
\r
1461 UInt32 litPrice, matchPrice, repMatchPrice;
\r
1462 BoolInt nextIsLit;
\r
1463 Byte curByte, matchByte;
\r
1465 COptimal *curOpt, *nextOpt;
\r
1467 if (++cur == last)
\r
1471 if (cur >= kNumOpts - 64)
\r
1474 UInt32 price = p->opt[cur].price;
\r
1476 for (j = cur + 1; j <= last; j++)
\r
1478 UInt32 price2 = p->opt[j].price;
\r
1479 if (price >= price2)
\r
1486 unsigned delta = best - cur;
\r
1489 MOVE_POS(p, delta);
\r
1496 newLen = ReadMatchDistances(p, &numPairs);
\r
1498 if (newLen >= p->numFastBytes)
\r
1500 p->numPairs = numPairs;
\r
1501 p->longestMatchLen = newLen;
\r
1505 curOpt = &p->opt[cur];
\r
1509 // we need that check here, if skip_items in p->opt are possible
\r
1511 if (curOpt->price >= kInfinityPrice)
\r
1515 prev = cur - curOpt->len;
\r
1517 if (curOpt->len == 1)
\r
1519 state = (unsigned)p->opt[prev].state;
\r
1520 if (IsShortRep(curOpt))
\r
1521 state = kShortRepNextStates[state];
\r
1523 state = kLiteralNextStates[state];
\r
1527 const COptimal *prevOpt;
\r
1529 UInt32 dist = curOpt->dist;
\r
1531 if (curOpt->extra)
\r
1533 prev -= (unsigned)curOpt->extra;
\r
1534 state = kState_RepAfterLit;
\r
1535 if (curOpt->extra == 1)
\r
1536 state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);
\r
1540 state = (unsigned)p->opt[prev].state;
\r
1541 if (dist < LZMA_NUM_REPS)
\r
1542 state = kRepNextStates[state];
\r
1544 state = kMatchNextStates[state];
\r
1547 prevOpt = &p->opt[prev];
\r
1548 b0 = prevOpt->reps[0];
\r
1550 if (dist < LZMA_NUM_REPS)
\r
1555 reps[1] = prevOpt->reps[1];
\r
1556 reps[2] = prevOpt->reps[2];
\r
1557 reps[3] = prevOpt->reps[3];
\r
1562 b0 = prevOpt->reps[1];
\r
1566 reps[2] = prevOpt->reps[2];
\r
1567 reps[3] = prevOpt->reps[3];
\r
1572 reps[0] = prevOpt->reps[dist];
\r
1573 reps[3] = prevOpt->reps[dist ^ 1];
\r
1579 reps[0] = (dist - LZMA_NUM_REPS + 1);
\r
1581 reps[2] = prevOpt->reps[1];
\r
1582 reps[3] = prevOpt->reps[2];
\r
1586 curOpt->state = (CState)state;
\r
1587 curOpt->reps[0] = reps[0];
\r
1588 curOpt->reps[1] = reps[1];
\r
1589 curOpt->reps[2] = reps[2];
\r
1590 curOpt->reps[3] = reps[3];
\r
1592 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
\r
1594 matchByte = *(data - reps[0]);
\r
1596 posState = (position & p->pbMask);
\r
1599 The order of Price checks:
\r
1603 < REP [ : LIT : REP_0 ]
\r
1604 < MATCH [ : LIT : REP_0 ]
\r
1608 UInt32 curPrice = curOpt->price;
\r
1609 unsigned prob = p->isMatch[state][posState];
\r
1610 matchPrice = curPrice + GET_PRICE_1(prob);
\r
1611 litPrice = curPrice + GET_PRICE_0(prob);
\r
1614 nextOpt = &p->opt[(size_t)cur + 1];
\r
1615 nextIsLit = False;
\r
1617 // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)
\r
1619 if ((nextOpt->price < kInfinityPrice
\r
1620 // && !IsLitState(state)
\r
1621 && matchByte == curByte)
\r
1622 || litPrice > nextOpt->price
\r
1627 const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
\r
1628 litPrice += (!IsLitState(state) ?
\r
1629 LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
\r
1630 LitEnc_GetPrice(probs, curByte, p->ProbPrices));
\r
1632 if (litPrice < nextOpt->price)
\r
1634 nextOpt->price = litPrice;
\r
1636 MakeAs_Lit(nextOpt);
\r
1641 repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
\r
1643 numAvailFull = p->numAvail;
\r
1645 unsigned temp = kNumOpts - 1 - cur;
\r
1646 if (numAvailFull > temp)
\r
1647 numAvailFull = (UInt32)temp;
\r
1651 // ---------- SHORT_REP ----------
\r
1652 if (IsLitState(state)) // 18.new
\r
1653 if (matchByte == curByte)
\r
1654 if (repMatchPrice < nextOpt->price) // 18.new
\r
1655 // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))
\r
1657 // nextOpt->price >= kInfinityPrice ||
\r
1658 nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt
\r
1659 || (nextOpt->dist != 0
\r
1660 // && nextOpt->extra <= 1 // 17.old
\r
1664 UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
\r
1665 // if (shortRepPrice <= nextOpt->price) // 17.old
\r
1666 if (shortRepPrice < nextOpt->price) // 18.new
\r
1668 nextOpt->price = shortRepPrice;
\r
1670 MakeAs_ShortRep(nextOpt);
\r
1671 nextIsLit = False;
\r
1675 if (numAvailFull < 2)
\r
1677 numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
\r
1679 // numAvail <= p->numFastBytes
\r
1681 // ---------- LIT : REP_0 ----------
\r
1684 && litPrice != 0 // 18.new
\r
1685 && matchByte != curByte
\r
1686 && numAvailFull > 2)
\r
1688 const Byte *data2 = data - reps[0];
\r
1689 if (data[1] == data2[1] && data[2] == data2[2])
\r
1692 unsigned limit = p->numFastBytes + 1;
\r
1693 if (limit > numAvailFull)
\r
1694 limit = numAvailFull;
\r
1695 for (len = 3; len < limit && data[len] == data2[len]; len++)
\r
1699 unsigned state2 = kLiteralNextStates[state];
\r
1700 unsigned posState2 = (position + 1) & p->pbMask;
\r
1701 UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
\r
1703 unsigned offset = cur + len;
\r
1705 if (last < offset)
\r
1713 // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
\r
1714 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);
\r
1716 opt = &p->opt[offset];
\r
1718 if (price2 < opt->price)
\r
1720 opt->price = price2;
\r
1721 opt->len = (UInt32)len;
\r
1726 // while (len >= 3);
\r
1732 startLen = 2; /* speed optimization */
\r
1735 // ---------- REP ----------
\r
1736 unsigned repIndex = 0; // 17.old
\r
1737 // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
\r
1738 for (; repIndex < LZMA_NUM_REPS; repIndex++)
\r
1742 const Byte *data2 = data - reps[repIndex];
\r
1743 if (data[0] != data2[0] || data[1] != data2[1])
\r
1746 for (len = 2; len < numAvail && data[len] == data2[len]; len++)
\r
1749 // if (len < startLen) continue; // 18.new: speed optimization
\r
1752 unsigned offset = cur + len;
\r
1753 if (last < offset)
\r
1757 unsigned len2 = len;
\r
1758 price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
\r
1761 UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);
\r
1762 COptimal *opt = &p->opt[cur + len2];
\r
1763 if (price2 < opt->price)
\r
1765 opt->price = price2;
\r
1766 opt->len = (UInt32)len2;
\r
1767 opt->dist = (UInt32)repIndex;
\r
1771 while (--len2 >= 2);
\r
1774 if (repIndex == 0) startLen = len + 1; // 17.old
\r
1775 // startLen = len + 1; // 18.new
\r
1777 /* if (_maxMode) */
\r
1779 // ---------- REP : LIT : REP_0 ----------
\r
1780 // numFastBytes + 1 + numFastBytes
\r
1782 unsigned len2 = len + 1;
\r
1783 unsigned limit = len2 + p->numFastBytes;
\r
1784 if (limit > numAvailFull)
\r
1785 limit = numAvailFull;
\r
1788 if (len2 <= limit)
\r
1789 if (data[len2 - 2] == data2[len2 - 2])
\r
1790 if (data[len2 - 1] == data2[len2 - 1])
\r
1792 unsigned state2 = kRepNextStates[state];
\r
1793 unsigned posState2 = (position + len) & p->pbMask;
\r
1794 price += GET_PRICE_LEN(&p->repLenEnc, posState, len)
\r
1795 + GET_PRICE_0(p->isMatch[state2][posState2])
\r
1796 + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
\r
1797 data[len], data2[len], p->ProbPrices);
\r
1799 // state2 = kLiteralNextStates[state2];
\r
1800 state2 = kState_LitAfterRep;
\r
1801 posState2 = (posState2 + 1) & p->pbMask;
\r
1804 price += GetPrice_Rep_0(p, state2, posState2);
\r
1806 for (; len2 < limit && data[len2] == data2[len2]; len2++)
\r
1813 unsigned offset = cur + len + len2;
\r
1815 if (last < offset)
\r
1822 // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
\r
1823 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
\r
1825 opt = &p->opt[offset];
\r
1827 if (price2 < opt->price)
\r
1829 opt->price = price2;
\r
1830 opt->len = (UInt32)len2;
\r
1831 opt->extra = (CExtra)(len + 1);
\r
1832 opt->dist = (UInt32)repIndex;
\r
1835 // while (len2 >= 3);
\r
1844 // ---------- MATCH ----------
\r
1845 /* for (unsigned len = 2; len <= newLen; len++) */
\r
1846 if (newLen > numAvail)
\r
1848 newLen = numAvail;
\r
1849 for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2);
\r
1850 MATCHES[numPairs] = (UInt32)newLen;
\r
1854 // startLen = 2; /* speed optimization */
\r
1856 if (newLen >= startLen)
\r
1858 UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
\r
1860 unsigned offs, posSlot, len;
\r
1863 unsigned offset = cur + newLen;
\r
1864 if (last < offset)
\r
1869 while (startLen > MATCHES[offs])
\r
1871 dist = MATCHES[(size_t)offs + 1];
\r
1873 // if (dist >= kNumFullDistances)
\r
1874 GetPosSlot2(dist, posSlot);
\r
1876 for (len = /*2*/ startLen; ; len++)
\r
1878 UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
\r
1881 unsigned lenNorm = len - 2;
\r
1882 lenNorm = GetLenToPosState2(lenNorm);
\r
1883 if (dist < kNumFullDistances)
\r
1884 price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];
\r
1886 price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];
\r
1888 opt = &p->opt[cur + len];
\r
1889 if (price < opt->price)
\r
1891 opt->price = price;
\r
1892 opt->len = (UInt32)len;
\r
1893 opt->dist = dist + LZMA_NUM_REPS;
\r
1898 if (len == MATCHES[offs])
\r
1900 // if (p->_maxMode) {
\r
1901 // MATCH : LIT : REP_0
\r
1903 const Byte *data2 = data - dist - 1;
\r
1904 unsigned len2 = len + 1;
\r
1905 unsigned limit = len2 + p->numFastBytes;
\r
1906 if (limit > numAvailFull)
\r
1907 limit = numAvailFull;
\r
1910 if (len2 <= limit)
\r
1911 if (data[len2 - 2] == data2[len2 - 2])
\r
1912 if (data[len2 - 1] == data2[len2 - 1])
\r
1914 for (; len2 < limit && data[len2] == data2[len2]; len2++)
\r
1921 unsigned state2 = kMatchNextStates[state];
\r
1922 unsigned posState2 = (position + len) & p->pbMask;
\r
1924 price += GET_PRICE_0(p->isMatch[state2][posState2]);
\r
1925 price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
\r
1926 data[len], data2[len], p->ProbPrices);
\r
1928 // state2 = kLiteralNextStates[state2];
\r
1929 state2 = kState_LitAfterMatch;
\r
1931 posState2 = (posState2 + 1) & p->pbMask;
\r
1932 price += GetPrice_Rep_0(p, state2, posState2);
\r
1934 offset = cur + len + len2;
\r
1936 if (last < offset)
\r
1943 // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
\r
1944 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
\r
1945 opt = &p->opt[offset];
\r
1947 if (price2 < opt->price)
\r
1949 opt->price = price2;
\r
1950 opt->len = (UInt32)len2;
\r
1951 opt->extra = (CExtra)(len + 1);
\r
1952 opt->dist = dist + LZMA_NUM_REPS;
\r
1955 // while (len2 >= 3);
\r
1961 if (offs == numPairs)
\r
1963 dist = MATCHES[(size_t)offs + 1];
\r
1964 // if (dist >= kNumFullDistances)
\r
1965 GetPosSlot2(dist, posSlot);
\r
1972 p->opt[last].price = kInfinityPrice;
\r
1975 return Backward(p, cur);
\r
1980 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
\r
1984 static unsigned GetOptimumFast(CLzmaEnc *p)
\r
1986 UInt32 numAvail, mainDist;
\r
1987 unsigned mainLen, numPairs, repIndex, repLen, i;
\r
1990 if (p->additionalOffset == 0)
\r
1991 mainLen = ReadMatchDistances(p, &numPairs);
\r
1994 mainLen = p->longestMatchLen;
\r
1995 numPairs = p->numPairs;
\r
1998 numAvail = p->numAvail;
\r
1999 p->backRes = MARK_LIT;
\r
2002 // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused
\r
2003 if (numAvail > LZMA_MATCH_LEN_MAX)
\r
2004 numAvail = LZMA_MATCH_LEN_MAX;
\r
2005 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
\r
2006 repLen = repIndex = 0;
\r
2008 for (i = 0; i < LZMA_NUM_REPS; i++)
\r
2011 const Byte *data2 = data - p->reps[i];
\r
2012 if (data[0] != data2[0] || data[1] != data2[1])
\r
2014 for (len = 2; len < numAvail && data[len] == data2[len]; len++)
\r
2016 if (len >= p->numFastBytes)
\r
2018 p->backRes = (UInt32)i;
\r
2019 MOVE_POS(p, len - 1)
\r
2029 if (mainLen >= p->numFastBytes)
\r
2031 p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
\r
2032 MOVE_POS(p, mainLen - 1)
\r
2036 mainDist = 0; /* for GCC */
\r
2040 mainDist = p->matches[(size_t)numPairs - 1];
\r
2041 while (numPairs > 2)
\r
2044 if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
\r
2046 dist2 = p->matches[(size_t)numPairs - 3];
\r
2047 if (!ChangePair(dist2, mainDist))
\r
2053 if (mainLen == 2 && mainDist >= 0x80)
\r
2058 if ( repLen + 1 >= mainLen
\r
2059 || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
\r
2060 || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
\r
2062 p->backRes = (UInt32)repIndex;
\r
2063 MOVE_POS(p, repLen - 1)
\r
2067 if (mainLen < 2 || numAvail <= 2)
\r
2071 unsigned len1 = ReadMatchDistances(p, &p->numPairs);
\r
2072 p->longestMatchLen = len1;
\r
2076 UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
\r
2077 if ( (len1 >= mainLen && newDist < mainDist)
\r
2078 || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
\r
2079 || (len1 > mainLen + 1)
\r
2080 || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
\r
2085 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
\r
2087 for (i = 0; i < LZMA_NUM_REPS; i++)
\r
2089 unsigned len, limit;
\r
2090 const Byte *data2 = data - p->reps[i];
\r
2091 if (data[0] != data2[0] || data[1] != data2[1])
\r
2093 limit = mainLen - 1;
\r
2094 for (len = 2;; len++)
\r
2098 if (data[len] != data2[len])
\r
2103 p->backRes = mainDist + LZMA_NUM_REPS;
\r
2106 MOVE_POS(p, mainLen - 2)
\r
2114 static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
\r
2117 range = p->rc.range;
\r
2119 UInt32 ttt, newBound;
\r
2120 CLzmaProb *prob = &p->isMatch[p->state][posState];
\r
2121 RC_BIT_PRE(&p->rc, prob)
\r
2122 RC_BIT_1(&p->rc, prob)
\r
2123 prob = &p->isRep[p->state];
\r
2124 RC_BIT_PRE(&p->rc, prob)
\r
2125 RC_BIT_0(&p->rc, prob)
\r
2127 p->state = kMatchNextStates[p->state];
\r
2129 p->rc.range = range;
\r
2130 LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
\r
2131 range = p->rc.range;
\r
2134 // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
\r
2135 CLzmaProb *probs = p->posSlotEncoder[0];
\r
2139 UInt32 ttt, newBound;
\r
2140 RC_BIT_PRE(p, probs + m)
\r
2141 RC_BIT_1(&p->rc, probs + m);
\r
2144 while (m < (1 << kNumPosSlotBits));
\r
2147 // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range;
\r
2148 unsigned numBits = 30 - kNumAlignBits;
\r
2152 p->rc.low += range;
\r
2155 while (--numBits);
\r
2159 // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
\r
2160 CLzmaProb *probs = p->posAlignEncoder;
\r
2164 UInt32 ttt, newBound;
\r
2165 RC_BIT_PRE(p, probs + m)
\r
2166 RC_BIT_1(&p->rc, probs + m);
\r
2169 while (m < kAlignTableSize);
\r
2171 p->rc.range = range;
\r
2175 static SRes CheckErrors(CLzmaEnc *p)
\r
2177 if (p->result != SZ_OK)
\r
2179 if (p->rc.res != SZ_OK)
\r
2180 p->result = SZ_ERROR_WRITE;
\r
2184 // p->mf_Failure ||
\r
2186 ( // p->matchFinderMt.failure_LZ_LZ ||
\r
2187 p->matchFinderMt.failure_LZ_BT))
\r
2190 p->result = MY_HRES_ERROR__INTERNAL_ERROR;
\r
2191 // printf("\nCheckErrors p->matchFinderMt.failureLZ\n");
\r
2195 if (MFB.result != SZ_OK)
\r
2196 p->result = SZ_ERROR_READ;
\r
2198 if (p->result != SZ_OK)
\r
2199 p->finished = True;
\r
2204 MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
\r
2206 /* ReleaseMFStream(); */
\r
2207 p->finished = True;
\r
2208 if (p->writeEndMark)
\r
2209 WriteEndMarker(p, nowPos & p->pbMask);
\r
2210 RangeEnc_FlushData(&p->rc);
\r
2211 RangeEnc_FlushStream(&p->rc);
\r
2212 return CheckErrors(p);
\r
2216 MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
\r
2219 const CProbPrice *ProbPrices = p->ProbPrices;
\r
2220 const CLzmaProb *probs = p->posAlignEncoder;
\r
2221 // p->alignPriceCount = 0;
\r
2222 for (i = 0; i < kAlignTableSize / 2; i++)
\r
2229 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
\r
2230 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
\r
2231 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
\r
2233 p->alignPrices[i ] = price + GET_PRICEa_0(prob);
\r
2234 p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
\r
2235 // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
\r
2240 MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
\r
2242 // int y; for (y = 0; y < 100; y++) {
\r
2244 UInt32 tempPrices[kNumFullDistances];
\r
2247 const CProbPrice *ProbPrices = p->ProbPrices;
\r
2248 p->matchPriceCount = 0;
\r
2250 for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
\r
2252 unsigned posSlot = GetPosSlot1(i);
\r
2253 unsigned footerBits = (posSlot >> 1) - 1;
\r
2254 unsigned base = ((2 | (posSlot & 1)) << footerBits);
\r
2255 const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;
\r
2256 // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
\r
2260 unsigned offset = (unsigned)1 << footerBits;
\r
2266 unsigned bit = sym & 1;
\r
2268 price += GET_PRICEa(probs[m], bit);
\r
2269 m = (m << 1) + bit;
\r
2271 while (--footerBits);
\r
2274 unsigned prob = probs[m];
\r
2275 tempPrices[base ] = price + GET_PRICEa_0(prob);
\r
2276 tempPrices[base + offset] = price + GET_PRICEa_1(prob);
\r
2280 for (lps = 0; lps < kNumLenToPosStates; lps++)
\r
2283 unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
\r
2284 UInt32 *posSlotPrices = p->posSlotPrices[lps];
\r
2285 const CLzmaProb *probs = p->posSlotEncoder[lps];
\r
2287 for (slot = 0; slot < distTableSize2; slot++)
\r
2289 // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
\r
2292 unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
\r
2294 bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit);
\r
2295 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
\r
2296 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
\r
2297 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
\r
2298 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
\r
2299 prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];
\r
2300 posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob);
\r
2301 posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);
\r
2305 UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
\r
2306 for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
\r
2308 posSlotPrices[(size_t)slot * 2 ] += delta;
\r
2309 posSlotPrices[(size_t)slot * 2 + 1] += delta;
\r
2310 delta += ((UInt32)1 << kNumBitPriceShiftBits);
\r
2315 UInt32 *dp = p->distancesPrices[lps];
\r
2317 dp[0] = posSlotPrices[0];
\r
2318 dp[1] = posSlotPrices[1];
\r
2319 dp[2] = posSlotPrices[2];
\r
2320 dp[3] = posSlotPrices[3];
\r
2322 for (i = 4; i < kNumFullDistances; i += 2)
\r
2324 UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
\r
2325 dp[i ] = slotPrice + tempPrices[i];
\r
2326 dp[i + 1] = slotPrice + tempPrices[i + 1];
\r
2335 static void LzmaEnc_Construct(CLzmaEnc *p)
\r
2337 RangeEnc_Construct(&p->rc);
\r
2338 MatchFinder_Construct(&MFB);
\r
2341 p->matchFinderMt.MatchFinder = &MFB;
\r
2342 MatchFinderMt_Construct(&p->matchFinderMt);
\r
2346 CLzmaEncProps props;
\r
2347 LzmaEncProps_Init(&props);
\r
2348 LzmaEnc_SetProps(p, &props);
\r
2351 #ifndef LZMA_LOG_BSR
\r
2352 LzmaEnc_FastPosInit(p->g_FastPos);
\r
2355 LzmaEnc_InitPriceTables(p->ProbPrices);
\r
2356 p->litProbs = NULL;
\r
2357 p->saveState.litProbs = NULL;
\r
2360 CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
\r
2363 p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
\r
2365 LzmaEnc_Construct((CLzmaEnc *)p);
\r
2369 static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
\r
2371 ISzAlloc_Free(alloc, p->litProbs);
\r
2372 ISzAlloc_Free(alloc, p->saveState.litProbs);
\r
2373 p->litProbs = NULL;
\r
2374 p->saveState.litProbs = NULL;
\r
2377 static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2380 MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
\r
2383 MatchFinder_Free(&MFB, allocBig);
\r
2384 LzmaEnc_FreeLits(p, alloc);
\r
2385 RangeEnc_Free(&p->rc, alloc);
\r
2388 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2390 LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
\r
2391 ISzAlloc_Free(alloc, p);
\r
2396 static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
\r
2398 UInt32 nowPos32, startPos32;
\r
2404 RINOK(MatchFinderMt_InitMt(&p->matchFinderMt));
\r
2407 p->matchFinder.Init(p->matchFinderObj);
\r
2413 RINOK(CheckErrors(p));
\r
2415 nowPos32 = (UInt32)p->nowPos64;
\r
2416 startPos32 = nowPos32;
\r
2418 if (p->nowPos64 == 0)
\r
2420 unsigned numPairs;
\r
2422 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
\r
2423 return Flush(p, nowPos32);
\r
2424 ReadMatchDistances(p, &numPairs);
\r
2425 RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
\r
2426 // p->state = kLiteralNextStates[p->state];
\r
2427 curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
\r
2428 LitEnc_Encode(&p->rc, p->litProbs, curByte);
\r
2429 p->additionalOffset--;
\r
2433 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
\r
2438 unsigned len, posState;
\r
2439 UInt32 range, ttt, newBound;
\r
2443 len = GetOptimumFast(p);
\r
2446 unsigned oci = p->optCur;
\r
2447 if (p->optEnd == oci)
\r
2448 len = GetOptimum(p, nowPos32);
\r
2451 const COptimal *opt = &p->opt[oci];
\r
2453 p->backRes = opt->dist;
\r
2454 p->optCur = oci + 1;
\r
2458 posState = (unsigned)nowPos32 & p->pbMask;
\r
2459 range = p->rc.range;
\r
2460 probs = &p->isMatch[p->state][posState];
\r
2462 RC_BIT_PRE(&p->rc, probs)
\r
2464 dist = p->backRes;
\r
2467 printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist);
\r
2470 if (dist == MARK_LIT)
\r
2476 RC_BIT_0(&p->rc, probs);
\r
2477 p->rc.range = range;
\r
2478 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
\r
2479 probs = LIT_PROBS(nowPos32, *(data - 1));
\r
2482 p->state = kLiteralNextStates[state];
\r
2483 if (IsLitState(state))
\r
2484 LitEnc_Encode(&p->rc, probs, curByte);
\r
2486 LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
\r
2490 RC_BIT_1(&p->rc, probs);
\r
2491 probs = &p->isRep[p->state];
\r
2492 RC_BIT_PRE(&p->rc, probs)
\r
2494 if (dist < LZMA_NUM_REPS)
\r
2496 RC_BIT_1(&p->rc, probs);
\r
2497 probs = &p->isRepG0[p->state];
\r
2498 RC_BIT_PRE(&p->rc, probs)
\r
2501 RC_BIT_0(&p->rc, probs);
\r
2502 probs = &p->isRep0Long[p->state][posState];
\r
2503 RC_BIT_PRE(&p->rc, probs)
\r
2506 RC_BIT_1_BASE(&p->rc, probs);
\r
2510 RC_BIT_0_BASE(&p->rc, probs);
\r
2511 p->state = kShortRepNextStates[p->state];
\r
2516 RC_BIT_1(&p->rc, probs);
\r
2517 probs = &p->isRepG1[p->state];
\r
2518 RC_BIT_PRE(&p->rc, probs)
\r
2521 RC_BIT_0_BASE(&p->rc, probs);
\r
2522 dist = p->reps[1];
\r
2526 RC_BIT_1(&p->rc, probs);
\r
2527 probs = &p->isRepG2[p->state];
\r
2528 RC_BIT_PRE(&p->rc, probs)
\r
2531 RC_BIT_0_BASE(&p->rc, probs);
\r
2532 dist = p->reps[2];
\r
2536 RC_BIT_1_BASE(&p->rc, probs);
\r
2537 dist = p->reps[3];
\r
2538 p->reps[3] = p->reps[2];
\r
2540 p->reps[2] = p->reps[1];
\r
2542 p->reps[1] = p->reps[0];
\r
2543 p->reps[0] = dist;
\r
2548 p->rc.range = range;
\r
2552 LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
\r
2553 --p->repLenEncCounter;
\r
2554 p->state = kRepNextStates[p->state];
\r
2560 RC_BIT_0(&p->rc, probs);
\r
2561 p->rc.range = range;
\r
2562 p->state = kMatchNextStates[p->state];
\r
2564 LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
\r
2565 // --p->lenEnc.counter;
\r
2567 dist -= LZMA_NUM_REPS;
\r
2568 p->reps[3] = p->reps[2];
\r
2569 p->reps[2] = p->reps[1];
\r
2570 p->reps[1] = p->reps[0];
\r
2571 p->reps[0] = dist + 1;
\r
2573 p->matchPriceCount++;
\r
2574 GetPosSlot(dist, posSlot);
\r
2575 // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
\r
2577 UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits);
\r
2578 range = p->rc.range;
\r
2579 probs = p->posSlotEncoder[GetLenToPosState(len)];
\r
2582 CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);
\r
2583 UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;
\r
2585 RC_BIT(&p->rc, prob, bit);
\r
2587 while (sym < (1 << kNumPosSlotBits * 2));
\r
2588 p->rc.range = range;
\r
2591 if (dist >= kStartPosModelIndex)
\r
2593 unsigned footerBits = ((posSlot >> 1) - 1);
\r
2595 if (dist < kNumFullDistances)
\r
2597 unsigned base = ((2 | (posSlot & 1)) << footerBits);
\r
2598 RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */));
\r
2602 UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
\r
2603 range = p->rc.range;
\r
2604 // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
\r
2609 p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
\r
2612 while (footerBits > kNumAlignBits);
\r
2617 p->rc.low += range & (0 - (pos2 >> 31));
\r
2621 while (pos2 != 0xF0000000);
\r
2624 // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
\r
2629 bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
\r
2630 bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
\r
2631 bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
\r
2632 bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
\r
2633 p->rc.range = range;
\r
2634 // p->alignPriceCount++;
\r
2641 nowPos32 += (UInt32)len;
\r
2642 p->additionalOffset -= len;
\r
2644 if (p->additionalOffset == 0)
\r
2651 if (p->alignPriceCount >= 16) // kAlignTableSize
\r
2652 FillAlignPrices(p);
\r
2653 if (p->matchPriceCount >= 128)
\r
2654 FillDistancesPrices(p);
\r
2655 if (p->lenEnc.counter <= 0)
\r
2656 LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
\r
2658 if (p->matchPriceCount >= 64)
\r
2660 FillAlignPrices(p);
\r
2661 // { int y; for (y = 0; y < 100; y++) {
\r
2662 FillDistancesPrices(p);
\r
2664 LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
\r
2666 if (p->repLenEncCounter <= 0)
\r
2668 p->repLenEncCounter = REP_LEN_COUNT;
\r
2669 LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
\r
2673 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
\r
2675 processed = nowPos32 - startPos32;
\r
2679 if (processed + kNumOpts + 300 >= maxUnpackSize
\r
2680 || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
\r
2683 else if (processed >= (1 << 17))
\r
2685 p->nowPos64 += nowPos32 - startPos32;
\r
2686 return CheckErrors(p);
\r
2691 p->nowPos64 += nowPos32 - startPos32;
\r
2692 return Flush(p, nowPos32);
\r
2697 #define kBigHashDicLimit ((UInt32)1 << 24)
\r
2699 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2701 UInt32 beforeSize = kNumOpts;
\r
2704 if (!RangeEnc_Alloc(&p->rc, alloc))
\r
2705 return SZ_ERROR_MEM;
\r
2708 p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0));
\r
2712 unsigned lclp = p->lc + p->lp;
\r
2713 if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
\r
2715 LzmaEnc_FreeLits(p, alloc);
\r
2716 p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
\r
2717 p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
\r
2718 if (!p->litProbs || !p->saveState.litProbs)
\r
2720 LzmaEnc_FreeLits(p, alloc);
\r
2721 return SZ_ERROR_MEM;
\r
2727 MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
\r
2730 dictSize = p->dictSize;
\r
2731 if (dictSize == ((UInt32)2 << 30) ||
\r
2732 dictSize == ((UInt32)3 << 30))
\r
2734 /* 21.03 : here we reduce the dictionary for 2 reasons:
\r
2735 1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary.
\r
2736 2) we want to elimate useless last MatchFinder_Normalize3() for corner cases,
\r
2737 where data size is aligned for 1 GB: 5/6/8 GB.
\r
2738 That reducing must be >= 1 for such corner cases. */
\r
2742 if (beforeSize + dictSize < keepWindowSize)
\r
2743 beforeSize = keepWindowSize - dictSize;
\r
2745 /* in worst case we can look ahead for
\r
2746 max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes.
\r
2747 we send larger value for (keepAfter) to MantchFinder_Create():
\r
2748 (numFastBytes + LZMA_MATCH_LEN_MAX + 1)
\r
2754 RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize,
\r
2755 p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */
\r
2757 p->matchFinderObj = &p->matchFinderMt;
\r
2758 MFB.bigHash = (Byte)(
\r
2759 (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0);
\r
2760 MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
\r
2765 if (!MatchFinder_Create(&MFB, dictSize, beforeSize,
\r
2766 p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */
\r
2768 return SZ_ERROR_MEM;
\r
2769 p->matchFinderObj = &MFB;
\r
2770 MatchFinder_CreateVTable(&MFB, &p->matchFinder);
\r
2776 static void LzmaEnc_Init(CLzmaEnc *p)
\r
2785 RangeEnc_Init(&p->rc);
\r
2787 for (i = 0; i < (1 << kNumAlignBits); i++)
\r
2788 p->posAlignEncoder[i] = kProbInitValue;
\r
2790 for (i = 0; i < kNumStates; i++)
\r
2793 for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
\r
2795 p->isMatch[i][j] = kProbInitValue;
\r
2796 p->isRep0Long[i][j] = kProbInitValue;
\r
2798 p->isRep[i] = kProbInitValue;
\r
2799 p->isRepG0[i] = kProbInitValue;
\r
2800 p->isRepG1[i] = kProbInitValue;
\r
2801 p->isRepG2[i] = kProbInitValue;
\r
2805 for (i = 0; i < kNumLenToPosStates; i++)
\r
2807 CLzmaProb *probs = p->posSlotEncoder[i];
\r
2809 for (j = 0; j < (1 << kNumPosSlotBits); j++)
\r
2810 probs[j] = kProbInitValue;
\r
2814 for (i = 0; i < kNumFullDistances; i++)
\r
2815 p->posEncoders[i] = kProbInitValue;
\r
2819 UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
\r
2821 CLzmaProb *probs = p->litProbs;
\r
2822 for (k = 0; k < num; k++)
\r
2823 probs[k] = kProbInitValue;
\r
2827 LenEnc_Init(&p->lenProbs);
\r
2828 LenEnc_Init(&p->repLenProbs);
\r
2834 for (i = 0; i < kNumOpts; i++)
\r
2835 p->opt[i].price = kInfinityPrice;
\r
2838 p->additionalOffset = 0;
\r
2840 p->pbMask = ((unsigned)1 << p->pb) - 1;
\r
2841 p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
\r
2843 // p->mf_Failure = False;
\r
2847 static void LzmaEnc_InitPrices(CLzmaEnc *p)
\r
2851 FillDistancesPrices(p);
\r
2852 FillAlignPrices(p);
\r
2855 p->lenEnc.tableSize =
\r
2856 p->repLenEnc.tableSize =
\r
2857 p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
\r
2859 p->repLenEncCounter = REP_LEN_COUNT;
\r
2861 LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
\r
2862 LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
\r
2865 static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2868 for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
\r
2869 if (p->dictSize <= ((UInt32)1 << i))
\r
2871 p->distTableSize = i * 2;
\r
2873 p->finished = False;
\r
2874 p->result = SZ_OK;
\r
2875 RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
\r
2877 LzmaEnc_InitPrices(p);
\r
2882 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
\r
2883 ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2885 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2886 MFB.stream = inStream;
\r
2888 p->rc.outStream = outStream;
\r
2889 return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
\r
2892 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
\r
2893 ISeqInStream *inStream, UInt32 keepWindowSize,
\r
2894 ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2896 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2897 MFB.stream = inStream;
\r
2899 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
\r
2902 static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
\r
2904 MFB.directInput = 1;
\r
2905 MFB.bufferBase = (Byte *)src;
\r
2906 MFB.directInputRem = srcLen;
\r
2909 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
\r
2910 UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
2912 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2913 LzmaEnc_SetInputBuf(p, src, srcLen);
\r
2916 LzmaEnc_SetDataSize(pp, srcLen);
\r
2917 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
\r
2920 void LzmaEnc_Finish(CLzmaEncHandle pp)
\r
2923 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2925 MatchFinderMt_ReleaseStream(&p->matchFinderMt);
\r
2938 } CLzmaEnc_SeqOutStreamBuf;
\r
2940 static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
\r
2942 CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
\r
2943 if (p->rem < size)
\r
2946 p->overflow = True;
\r
2950 memcpy(p->data, data, size);
\r
2959 UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
\r
2961 const CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2962 return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
\r
2966 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
\r
2968 const CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2969 return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
\r
2973 // (desiredPackSize == 0) is not allowed
\r
2974 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
\r
2975 Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
\r
2977 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
2980 CLzmaEnc_SeqOutStreamBuf outStream;
\r
2982 outStream.vt.Write = SeqOutStreamBuf_Write;
\r
2983 outStream.data = dest;
\r
2984 outStream.rem = *destLen;
\r
2985 outStream.overflow = False;
\r
2987 p->writeEndMark = False;
\r
2988 p->finished = False;
\r
2989 p->result = SZ_OK;
\r
2993 LzmaEnc_InitPrices(p);
\r
2994 RangeEnc_Init(&p->rc);
\r
2995 p->rc.outStream = &outStream.vt;
\r
2996 nowPos64 = p->nowPos64;
\r
2998 res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
\r
3000 *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
\r
3001 *destLen -= outStream.rem;
\r
3002 if (outStream.overflow)
\r
3003 return SZ_ERROR_OUTPUT_EOF;
\r
3010 static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
\r
3015 Byte allocaDummy[0x300];
\r
3016 allocaDummy[0] = 0;
\r
3017 allocaDummy[1] = allocaDummy[0];
\r
3022 res = LzmaEnc_CodeOneBlock(p, 0, 0);
\r
3023 if (res != SZ_OK || p->finished)
\r
3027 res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
\r
3030 res = SZ_ERROR_PROGRESS;
\r
3036 LzmaEnc_Finish(p);
\r
3039 if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB))
\r
3040 res = SZ_ERROR_FAIL;
\r
3048 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
\r
3049 ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
3051 RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
\r
3052 return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
\r
3056 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
\r
3058 if (*size < LZMA_PROPS_SIZE)
\r
3059 return SZ_ERROR_PARAM;
\r
3060 *size = LZMA_PROPS_SIZE;
\r
3062 const CLzmaEnc *p = (const CLzmaEnc *)pp;
\r
3063 const UInt32 dictSize = p->dictSize;
\r
3065 props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
\r
3067 // we write aligned dictionary value to properties for lzma decoder
\r
3068 if (dictSize >= ((UInt32)1 << 21))
\r
3070 const UInt32 kDictMask = ((UInt32)1 << 20) - 1;
\r
3071 v = (dictSize + kDictMask) & ~kDictMask;
\r
3077 unsigned i = 11 * 2;
\r
3080 v = (UInt32)(2 + (i & 1)) << (i >> 1);
\r
3083 while (v < dictSize);
\r
3086 SetUi32(props + 1, v);
\r
3092 unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
\r
3094 return (unsigned)((CLzmaEnc *)pp)->writeEndMark;
\r
3098 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
\r
3099 int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
3102 CLzmaEnc *p = (CLzmaEnc *)pp;
\r
3104 CLzmaEnc_SeqOutStreamBuf outStream;
\r
3106 outStream.vt.Write = SeqOutStreamBuf_Write;
\r
3107 outStream.data = dest;
\r
3108 outStream.rem = *destLen;
\r
3109 outStream.overflow = False;
\r
3111 p->writeEndMark = writeEndMark;
\r
3112 p->rc.outStream = &outStream.vt;
\r
3114 res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
\r
3118 res = LzmaEnc_Encode2(p, progress);
\r
3119 if (res == SZ_OK && p->nowPos64 != srcLen)
\r
3120 res = SZ_ERROR_FAIL;
\r
3123 *destLen -= outStream.rem;
\r
3124 if (outStream.overflow)
\r
3125 return SZ_ERROR_OUTPUT_EOF;
\r
3130 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
\r
3131 const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
\r
3132 ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
\r
3134 CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
\r
3137 return SZ_ERROR_MEM;
\r
3139 res = LzmaEnc_SetProps(p, props);
\r
3142 res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
\r
3144 res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
\r
3145 writeEndMark, progress, alloc, allocBig);
\r
3148 LzmaEnc_Destroy(p, alloc, allocBig);
\r
3155 void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2])
\r
3157 const CLzmaEnc *p = (CLzmaEnc *)pp;
\r
3158 lz_threads[0] = p->matchFinderMt.hashSync.thread;
\r
3159 lz_threads[1] = p->matchFinderMt.btSync.thread;
\r