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