xref: /third_party/lzma/C/LzmaEnc.c (revision 370b324c)
1370b324cSopenharmony_ci/* LzmaEnc.c -- LZMA Encoder
2370b324cSopenharmony_ci2023-04-13: Igor Pavlov : Public domain */
3370b324cSopenharmony_ci
4370b324cSopenharmony_ci#include "Precomp.h"
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include <string.h>
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci/* #define SHOW_STAT */
9370b324cSopenharmony_ci/* #define SHOW_STAT2 */
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#if defined(SHOW_STAT) || defined(SHOW_STAT2)
12370b324cSopenharmony_ci#include <stdio.h>
13370b324cSopenharmony_ci#endif
14370b324cSopenharmony_ci
15370b324cSopenharmony_ci#include "CpuArch.h"
16370b324cSopenharmony_ci#include "LzmaEnc.h"
17370b324cSopenharmony_ci
18370b324cSopenharmony_ci#include "LzFind.h"
19370b324cSopenharmony_ci#ifndef Z7_ST
20370b324cSopenharmony_ci#include "LzFindMt.h"
21370b324cSopenharmony_ci#endif
22370b324cSopenharmony_ci
23370b324cSopenharmony_ci/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */
24370b324cSopenharmony_ci
25370b324cSopenharmony_ciSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,
26370b324cSopenharmony_ci    ISzAllocPtr alloc, ISzAllocPtr allocBig);
27370b324cSopenharmony_ciSRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,
28370b324cSopenharmony_ci    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
29370b324cSopenharmony_ciSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,
30370b324cSopenharmony_ci    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
31370b324cSopenharmony_ciconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);
32370b324cSopenharmony_civoid LzmaEnc_Finish(CLzmaEncHandle p);
33370b324cSopenharmony_civoid LzmaEnc_SaveState(CLzmaEncHandle p);
34370b324cSopenharmony_civoid LzmaEnc_RestoreState(CLzmaEncHandle p);
35370b324cSopenharmony_ci
36370b324cSopenharmony_ci#ifdef SHOW_STAT
37370b324cSopenharmony_cistatic unsigned g_STAT_OFFSET = 0;
38370b324cSopenharmony_ci#endif
39370b324cSopenharmony_ci
40370b324cSopenharmony_ci/* for good normalization speed we still reserve 256 MB before 4 GB range */
41370b324cSopenharmony_ci#define kLzmaMaxHistorySize ((UInt32)15 << 28)
42370b324cSopenharmony_ci
43370b324cSopenharmony_ci// #define kNumTopBits 24
44370b324cSopenharmony_ci#define kTopValue ((UInt32)1 << 24)
45370b324cSopenharmony_ci
46370b324cSopenharmony_ci#define kNumBitModelTotalBits 11
47370b324cSopenharmony_ci#define kBitModelTotal (1 << kNumBitModelTotalBits)
48370b324cSopenharmony_ci#define kNumMoveBits 5
49370b324cSopenharmony_ci#define kProbInitValue (kBitModelTotal >> 1)
50370b324cSopenharmony_ci
51370b324cSopenharmony_ci#define kNumMoveReducingBits 4
52370b324cSopenharmony_ci#define kNumBitPriceShiftBits 4
53370b324cSopenharmony_ci// #define kBitPrice (1 << kNumBitPriceShiftBits)
54370b324cSopenharmony_ci
55370b324cSopenharmony_ci#define REP_LEN_COUNT 64
56370b324cSopenharmony_ci
57370b324cSopenharmony_civoid LzmaEncProps_Init(CLzmaEncProps *p)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci  p->level = 5;
60370b324cSopenharmony_ci  p->dictSize = p->mc = 0;
61370b324cSopenharmony_ci  p->reduceSize = (UInt64)(Int64)-1;
62370b324cSopenharmony_ci  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
63370b324cSopenharmony_ci  p->numHashOutBits = 0;
64370b324cSopenharmony_ci  p->writeEndMark = 0;
65370b324cSopenharmony_ci  p->affinity = 0;
66370b324cSopenharmony_ci}
67370b324cSopenharmony_ci
68370b324cSopenharmony_civoid LzmaEncProps_Normalize(CLzmaEncProps *p)
69370b324cSopenharmony_ci{
70370b324cSopenharmony_ci  int level = p->level;
71370b324cSopenharmony_ci  if (level < 0) level = 5;
72370b324cSopenharmony_ci  p->level = level;
73370b324cSopenharmony_ci
74370b324cSopenharmony_ci  if (p->dictSize == 0)
75370b324cSopenharmony_ci    p->dictSize =
76370b324cSopenharmony_ci      ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
77370b324cSopenharmony_ci      ( level <= 6 ? ((UInt32)1 << (level + 19)) :
78370b324cSopenharmony_ci      ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
79370b324cSopenharmony_ci      )));
80370b324cSopenharmony_ci
81370b324cSopenharmony_ci  if (p->dictSize > p->reduceSize)
82370b324cSopenharmony_ci  {
83370b324cSopenharmony_ci    UInt32 v = (UInt32)p->reduceSize;
84370b324cSopenharmony_ci    const UInt32 kReduceMin = ((UInt32)1 << 12);
85370b324cSopenharmony_ci    if (v < kReduceMin)
86370b324cSopenharmony_ci      v = kReduceMin;
87370b324cSopenharmony_ci    if (p->dictSize > v)
88370b324cSopenharmony_ci      p->dictSize = v;
89370b324cSopenharmony_ci  }
90370b324cSopenharmony_ci
91370b324cSopenharmony_ci  if (p->lc < 0) p->lc = 3;
92370b324cSopenharmony_ci  if (p->lp < 0) p->lp = 0;
93370b324cSopenharmony_ci  if (p->pb < 0) p->pb = 2;
94370b324cSopenharmony_ci
95370b324cSopenharmony_ci  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
96370b324cSopenharmony_ci  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
97370b324cSopenharmony_ci  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
98370b324cSopenharmony_ci  if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
99370b324cSopenharmony_ci  if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);
100370b324cSopenharmony_ci
101370b324cSopenharmony_ci  if (p->numThreads < 0)
102370b324cSopenharmony_ci    p->numThreads =
103370b324cSopenharmony_ci      #ifndef Z7_ST
104370b324cSopenharmony_ci      ((p->btMode && p->algo) ? 2 : 1);
105370b324cSopenharmony_ci      #else
106370b324cSopenharmony_ci      1;
107370b324cSopenharmony_ci      #endif
108370b324cSopenharmony_ci}
109370b324cSopenharmony_ci
110370b324cSopenharmony_ciUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
111370b324cSopenharmony_ci{
112370b324cSopenharmony_ci  CLzmaEncProps props = *props2;
113370b324cSopenharmony_ci  LzmaEncProps_Normalize(&props);
114370b324cSopenharmony_ci  return props.dictSize;
115370b324cSopenharmony_ci}
116370b324cSopenharmony_ci
117370b324cSopenharmony_ci
118370b324cSopenharmony_ci/*
119370b324cSopenharmony_cix86/x64:
120370b324cSopenharmony_ci
121370b324cSopenharmony_ciBSR:
122370b324cSopenharmony_ci  IF (SRC == 0) ZF = 1, DEST is undefined;
123370b324cSopenharmony_ci                  AMD : DEST is unchanged;
124370b324cSopenharmony_ci  IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit
125370b324cSopenharmony_ci  BSR is slow in some processors
126370b324cSopenharmony_ci
127370b324cSopenharmony_ciLZCNT:
128370b324cSopenharmony_ci  IF (SRC  == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64)
129370b324cSopenharmony_ci  IF (SRC  != 0) CF = 0, DEST = num_lead_zero_bits
130370b324cSopenharmony_ci  IF (DEST == 0) ZF = 1;
131370b324cSopenharmony_ci
132370b324cSopenharmony_ciLZCNT works only in new processors starting from Haswell.
133370b324cSopenharmony_ciif LZCNT is not supported by processor, then it's executed as BSR.
134370b324cSopenharmony_ciLZCNT can be faster than BSR, if supported.
135370b324cSopenharmony_ci*/
136370b324cSopenharmony_ci
137370b324cSopenharmony_ci// #define LZMA_LOG_BSR
138370b324cSopenharmony_ci
139370b324cSopenharmony_ci#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci  #if (defined(__clang__) && (__clang_major__ >= 6)) \
142370b324cSopenharmony_ci      || (defined(__GNUC__) && (__GNUC__ >= 6))
143370b324cSopenharmony_ci      #define LZMA_LOG_BSR
144370b324cSopenharmony_ci  #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
145370b324cSopenharmony_ci    // #if defined(MY_CPU_ARM_OR_ARM64)
146370b324cSopenharmony_ci      #define LZMA_LOG_BSR
147370b324cSopenharmony_ci    // #endif
148370b324cSopenharmony_ci  #endif
149370b324cSopenharmony_ci#endif
150370b324cSopenharmony_ci
151370b324cSopenharmony_ci// #include <intrin.h>
152370b324cSopenharmony_ci
153370b324cSopenharmony_ci#ifdef LZMA_LOG_BSR
154370b324cSopenharmony_ci
155370b324cSopenharmony_ci#if defined(__clang__) \
156370b324cSopenharmony_ci    || defined(__GNUC__)
157370b324cSopenharmony_ci
158370b324cSopenharmony_ci/*
159370b324cSopenharmony_ci  C code:                  : (30 - __builtin_clz(x))
160370b324cSopenharmony_ci    gcc9/gcc10 for x64 /x86  : 30 - (bsr(x) xor 31)
161370b324cSopenharmony_ci    clang10 for x64          : 31 + (bsr(x) xor -32)
162370b324cSopenharmony_ci*/
163370b324cSopenharmony_ci
164370b324cSopenharmony_ci  #define MY_clz(x)  ((unsigned)__builtin_clz(x))
165370b324cSopenharmony_ci  // __lzcnt32
166370b324cSopenharmony_ci  // __builtin_ia32_lzcnt_u32
167370b324cSopenharmony_ci
168370b324cSopenharmony_ci#else  // #if defined(_MSC_VER)
169370b324cSopenharmony_ci
170370b324cSopenharmony_ci  #ifdef MY_CPU_ARM_OR_ARM64
171370b324cSopenharmony_ci
172370b324cSopenharmony_ci    #define MY_clz  _CountLeadingZeros
173370b324cSopenharmony_ci
174370b324cSopenharmony_ci  #else // if defined(MY_CPU_X86_OR_AMD64)
175370b324cSopenharmony_ci
176370b324cSopenharmony_ci    // #define MY_clz  __lzcnt  // we can use lzcnt (unsupported by old CPU)
177370b324cSopenharmony_ci    // _BitScanReverse code is not optimal for some MSVC compilers
178370b324cSopenharmony_ci    #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \
179370b324cSopenharmony_ci      res = (zz + zz) + (pos >> zz); }
180370b324cSopenharmony_ci
181370b324cSopenharmony_ci  #endif // MY_CPU_X86_OR_AMD64
182370b324cSopenharmony_ci
183370b324cSopenharmony_ci#endif // _MSC_VER
184370b324cSopenharmony_ci
185370b324cSopenharmony_ci
186370b324cSopenharmony_ci#ifndef BSR2_RET
187370b324cSopenharmony_ci
188370b324cSopenharmony_ci    #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \
189370b324cSopenharmony_ci      res = (zz + zz) + (pos >> zz); }
190370b324cSopenharmony_ci
191370b324cSopenharmony_ci#endif
192370b324cSopenharmony_ci
193370b324cSopenharmony_ci
194370b324cSopenharmony_ciunsigned GetPosSlot1(UInt32 pos);
195370b324cSopenharmony_ciunsigned GetPosSlot1(UInt32 pos)
196370b324cSopenharmony_ci{
197370b324cSopenharmony_ci  unsigned res;
198370b324cSopenharmony_ci  BSR2_RET(pos, res);
199370b324cSopenharmony_ci  return res;
200370b324cSopenharmony_ci}
201370b324cSopenharmony_ci#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
202370b324cSopenharmony_ci#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
203370b324cSopenharmony_ci
204370b324cSopenharmony_ci
205370b324cSopenharmony_ci#else // ! LZMA_LOG_BSR
206370b324cSopenharmony_ci
207370b324cSopenharmony_ci#define kNumLogBits (11 + sizeof(size_t) / 8 * 3)
208370b324cSopenharmony_ci
209370b324cSopenharmony_ci#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
210370b324cSopenharmony_ci
211370b324cSopenharmony_cistatic void LzmaEnc_FastPosInit(Byte *g_FastPos)
212370b324cSopenharmony_ci{
213370b324cSopenharmony_ci  unsigned slot;
214370b324cSopenharmony_ci  g_FastPos[0] = 0;
215370b324cSopenharmony_ci  g_FastPos[1] = 1;
216370b324cSopenharmony_ci  g_FastPos += 2;
217370b324cSopenharmony_ci
218370b324cSopenharmony_ci  for (slot = 2; slot < kNumLogBits * 2; slot++)
219370b324cSopenharmony_ci  {
220370b324cSopenharmony_ci    size_t k = ((size_t)1 << ((slot >> 1) - 1));
221370b324cSopenharmony_ci    size_t j;
222370b324cSopenharmony_ci    for (j = 0; j < k; j++)
223370b324cSopenharmony_ci      g_FastPos[j] = (Byte)slot;
224370b324cSopenharmony_ci    g_FastPos += k;
225370b324cSopenharmony_ci  }
226370b324cSopenharmony_ci}
227370b324cSopenharmony_ci
228370b324cSopenharmony_ci/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
229370b324cSopenharmony_ci/*
230370b324cSopenharmony_ci#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
231370b324cSopenharmony_ci  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
232370b324cSopenharmony_ci  res = p->g_FastPos[pos >> zz] + (zz * 2); }
233370b324cSopenharmony_ci*/
234370b324cSopenharmony_ci
235370b324cSopenharmony_ci/*
236370b324cSopenharmony_ci#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
237370b324cSopenharmony_ci  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
238370b324cSopenharmony_ci  res = p->g_FastPos[pos >> zz] + (zz * 2); }
239370b324cSopenharmony_ci*/
240370b324cSopenharmony_ci
241370b324cSopenharmony_ci#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
242370b324cSopenharmony_ci  res = p->g_FastPos[pos >> zz] + (zz * 2); }
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci/*
245370b324cSopenharmony_ci#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
246370b324cSopenharmony_ci  p->g_FastPos[pos >> 6] + 12 : \
247370b324cSopenharmony_ci  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
248370b324cSopenharmony_ci*/
249370b324cSopenharmony_ci
250370b324cSopenharmony_ci#define GetPosSlot1(pos) p->g_FastPos[pos]
251370b324cSopenharmony_ci#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
252370b324cSopenharmony_ci#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
253370b324cSopenharmony_ci
254370b324cSopenharmony_ci#endif // LZMA_LOG_BSR
255370b324cSopenharmony_ci
256370b324cSopenharmony_ci
257370b324cSopenharmony_ci#define LZMA_NUM_REPS 4
258370b324cSopenharmony_ci
259370b324cSopenharmony_citypedef UInt16 CState;
260370b324cSopenharmony_citypedef UInt16 CExtra;
261370b324cSopenharmony_ci
262370b324cSopenharmony_citypedef struct
263370b324cSopenharmony_ci{
264370b324cSopenharmony_ci  UInt32 price;
265370b324cSopenharmony_ci  CState state;
266370b324cSopenharmony_ci  CExtra extra;
267370b324cSopenharmony_ci      // 0   : normal
268370b324cSopenharmony_ci      // 1   : LIT : MATCH
269370b324cSopenharmony_ci      // > 1 : MATCH (extra-1) : LIT : REP0 (len)
270370b324cSopenharmony_ci  UInt32 len;
271370b324cSopenharmony_ci  UInt32 dist;
272370b324cSopenharmony_ci  UInt32 reps[LZMA_NUM_REPS];
273370b324cSopenharmony_ci} COptimal;
274370b324cSopenharmony_ci
275370b324cSopenharmony_ci
276370b324cSopenharmony_ci// 18.06
277370b324cSopenharmony_ci#define kNumOpts (1 << 11)
278370b324cSopenharmony_ci#define kPackReserve (kNumOpts * 8)
279370b324cSopenharmony_ci// #define kNumOpts (1 << 12)
280370b324cSopenharmony_ci// #define kPackReserve (1 + kNumOpts * 2)
281370b324cSopenharmony_ci
282370b324cSopenharmony_ci#define kNumLenToPosStates 4
283370b324cSopenharmony_ci#define kNumPosSlotBits 6
284370b324cSopenharmony_ci// #define kDicLogSizeMin 0
285370b324cSopenharmony_ci#define kDicLogSizeMax 32
286370b324cSopenharmony_ci#define kDistTableSizeMax (kDicLogSizeMax * 2)
287370b324cSopenharmony_ci
288370b324cSopenharmony_ci#define kNumAlignBits 4
289370b324cSopenharmony_ci#define kAlignTableSize (1 << kNumAlignBits)
290370b324cSopenharmony_ci#define kAlignMask (kAlignTableSize - 1)
291370b324cSopenharmony_ci
292370b324cSopenharmony_ci#define kStartPosModelIndex 4
293370b324cSopenharmony_ci#define kEndPosModelIndex 14
294370b324cSopenharmony_ci#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
295370b324cSopenharmony_ci
296370b324cSopenharmony_citypedef
297370b324cSopenharmony_ci#ifdef Z7_LZMA_PROB32
298370b324cSopenharmony_ci  UInt32
299370b324cSopenharmony_ci#else
300370b324cSopenharmony_ci  UInt16
301370b324cSopenharmony_ci#endif
302370b324cSopenharmony_ci  CLzmaProb;
303370b324cSopenharmony_ci
304370b324cSopenharmony_ci#define LZMA_PB_MAX 4
305370b324cSopenharmony_ci#define LZMA_LC_MAX 8
306370b324cSopenharmony_ci#define LZMA_LP_MAX 4
307370b324cSopenharmony_ci
308370b324cSopenharmony_ci#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
309370b324cSopenharmony_ci
310370b324cSopenharmony_ci#define kLenNumLowBits 3
311370b324cSopenharmony_ci#define kLenNumLowSymbols (1 << kLenNumLowBits)
312370b324cSopenharmony_ci#define kLenNumHighBits 8
313370b324cSopenharmony_ci#define kLenNumHighSymbols (1 << kLenNumHighBits)
314370b324cSopenharmony_ci#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
315370b324cSopenharmony_ci
316370b324cSopenharmony_ci#define LZMA_MATCH_LEN_MIN 2
317370b324cSopenharmony_ci#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
318370b324cSopenharmony_ci
319370b324cSopenharmony_ci#define kNumStates 12
320370b324cSopenharmony_ci
321370b324cSopenharmony_ci
322370b324cSopenharmony_citypedef struct
323370b324cSopenharmony_ci{
324370b324cSopenharmony_ci  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
325370b324cSopenharmony_ci  CLzmaProb high[kLenNumHighSymbols];
326370b324cSopenharmony_ci} CLenEnc;
327370b324cSopenharmony_ci
328370b324cSopenharmony_ci
329370b324cSopenharmony_citypedef struct
330370b324cSopenharmony_ci{
331370b324cSopenharmony_ci  unsigned tableSize;
332370b324cSopenharmony_ci  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
333370b324cSopenharmony_ci  // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
334370b324cSopenharmony_ci  // UInt32 prices2[kLenNumSymbolsTotal];
335370b324cSopenharmony_ci} CLenPriceEnc;
336370b324cSopenharmony_ci
337370b324cSopenharmony_ci#define GET_PRICE_LEN(p, posState, len) \
338370b324cSopenharmony_ci    ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
339370b324cSopenharmony_ci
340370b324cSopenharmony_ci/*
341370b324cSopenharmony_ci#define GET_PRICE_LEN(p, posState, len) \
342370b324cSopenharmony_ci    ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
343370b324cSopenharmony_ci*/
344370b324cSopenharmony_ci
345370b324cSopenharmony_citypedef struct
346370b324cSopenharmony_ci{
347370b324cSopenharmony_ci  UInt32 range;
348370b324cSopenharmony_ci  unsigned cache;
349370b324cSopenharmony_ci  UInt64 low;
350370b324cSopenharmony_ci  UInt64 cacheSize;
351370b324cSopenharmony_ci  Byte *buf;
352370b324cSopenharmony_ci  Byte *bufLim;
353370b324cSopenharmony_ci  Byte *bufBase;
354370b324cSopenharmony_ci  ISeqOutStreamPtr outStream;
355370b324cSopenharmony_ci  UInt64 processed;
356370b324cSopenharmony_ci  SRes res;
357370b324cSopenharmony_ci} CRangeEnc;
358370b324cSopenharmony_ci
359370b324cSopenharmony_ci
360370b324cSopenharmony_citypedef struct
361370b324cSopenharmony_ci{
362370b324cSopenharmony_ci  CLzmaProb *litProbs;
363370b324cSopenharmony_ci
364370b324cSopenharmony_ci  unsigned state;
365370b324cSopenharmony_ci  UInt32 reps[LZMA_NUM_REPS];
366370b324cSopenharmony_ci
367370b324cSopenharmony_ci  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
368370b324cSopenharmony_ci  CLzmaProb isRep[kNumStates];
369370b324cSopenharmony_ci  CLzmaProb isRepG0[kNumStates];
370370b324cSopenharmony_ci  CLzmaProb isRepG1[kNumStates];
371370b324cSopenharmony_ci  CLzmaProb isRepG2[kNumStates];
372370b324cSopenharmony_ci  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
373370b324cSopenharmony_ci  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
374370b324cSopenharmony_ci
375370b324cSopenharmony_ci  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
376370b324cSopenharmony_ci  CLzmaProb posEncoders[kNumFullDistances];
377370b324cSopenharmony_ci
378370b324cSopenharmony_ci  CLenEnc lenProbs;
379370b324cSopenharmony_ci  CLenEnc repLenProbs;
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci} CSaveState;
382370b324cSopenharmony_ci
383370b324cSopenharmony_ci
384370b324cSopenharmony_citypedef UInt32 CProbPrice;
385370b324cSopenharmony_ci
386370b324cSopenharmony_ci
387370b324cSopenharmony_cistruct CLzmaEnc
388370b324cSopenharmony_ci{
389370b324cSopenharmony_ci  void *matchFinderObj;
390370b324cSopenharmony_ci  IMatchFinder2 matchFinder;
391370b324cSopenharmony_ci
392370b324cSopenharmony_ci  unsigned optCur;
393370b324cSopenharmony_ci  unsigned optEnd;
394370b324cSopenharmony_ci
395370b324cSopenharmony_ci  unsigned longestMatchLen;
396370b324cSopenharmony_ci  unsigned numPairs;
397370b324cSopenharmony_ci  UInt32 numAvail;
398370b324cSopenharmony_ci
399370b324cSopenharmony_ci  unsigned state;
400370b324cSopenharmony_ci  unsigned numFastBytes;
401370b324cSopenharmony_ci  unsigned additionalOffset;
402370b324cSopenharmony_ci  UInt32 reps[LZMA_NUM_REPS];
403370b324cSopenharmony_ci  unsigned lpMask, pbMask;
404370b324cSopenharmony_ci  CLzmaProb *litProbs;
405370b324cSopenharmony_ci  CRangeEnc rc;
406370b324cSopenharmony_ci
407370b324cSopenharmony_ci  UInt32 backRes;
408370b324cSopenharmony_ci
409370b324cSopenharmony_ci  unsigned lc, lp, pb;
410370b324cSopenharmony_ci  unsigned lclp;
411370b324cSopenharmony_ci
412370b324cSopenharmony_ci  BoolInt fastMode;
413370b324cSopenharmony_ci  BoolInt writeEndMark;
414370b324cSopenharmony_ci  BoolInt finished;
415370b324cSopenharmony_ci  BoolInt multiThread;
416370b324cSopenharmony_ci  BoolInt needInit;
417370b324cSopenharmony_ci  // BoolInt _maxMode;
418370b324cSopenharmony_ci
419370b324cSopenharmony_ci  UInt64 nowPos64;
420370b324cSopenharmony_ci
421370b324cSopenharmony_ci  unsigned matchPriceCount;
422370b324cSopenharmony_ci  // unsigned alignPriceCount;
423370b324cSopenharmony_ci  int repLenEncCounter;
424370b324cSopenharmony_ci
425370b324cSopenharmony_ci  unsigned distTableSize;
426370b324cSopenharmony_ci
427370b324cSopenharmony_ci  UInt32 dictSize;
428370b324cSopenharmony_ci  SRes result;
429370b324cSopenharmony_ci
430370b324cSopenharmony_ci  #ifndef Z7_ST
431370b324cSopenharmony_ci  BoolInt mtMode;
432370b324cSopenharmony_ci  // begin of CMatchFinderMt is used in LZ thread
433370b324cSopenharmony_ci  CMatchFinderMt matchFinderMt;
434370b324cSopenharmony_ci  // end of CMatchFinderMt is used in BT and HASH threads
435370b324cSopenharmony_ci  // #else
436370b324cSopenharmony_ci  // CMatchFinder matchFinderBase;
437370b324cSopenharmony_ci  #endif
438370b324cSopenharmony_ci  CMatchFinder matchFinderBase;
439370b324cSopenharmony_ci
440370b324cSopenharmony_ci
441370b324cSopenharmony_ci  // we suppose that we have 8-bytes alignment after CMatchFinder
442370b324cSopenharmony_ci
443370b324cSopenharmony_ci  #ifndef Z7_ST
444370b324cSopenharmony_ci  Byte pad[128];
445370b324cSopenharmony_ci  #endif
446370b324cSopenharmony_ci
447370b324cSopenharmony_ci  // LZ thread
448370b324cSopenharmony_ci  CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
449370b324cSopenharmony_ci
450370b324cSopenharmony_ci  // we want {len , dist} pairs to be 8-bytes aligned in matches array
451370b324cSopenharmony_ci  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2];
452370b324cSopenharmony_ci
453370b324cSopenharmony_ci  // we want 8-bytes alignment here
454370b324cSopenharmony_ci  UInt32 alignPrices[kAlignTableSize];
455370b324cSopenharmony_ci  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
456370b324cSopenharmony_ci  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
457370b324cSopenharmony_ci
458370b324cSopenharmony_ci  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
459370b324cSopenharmony_ci  CLzmaProb isRep[kNumStates];
460370b324cSopenharmony_ci  CLzmaProb isRepG0[kNumStates];
461370b324cSopenharmony_ci  CLzmaProb isRepG1[kNumStates];
462370b324cSopenharmony_ci  CLzmaProb isRepG2[kNumStates];
463370b324cSopenharmony_ci  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
464370b324cSopenharmony_ci  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
465370b324cSopenharmony_ci  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
466370b324cSopenharmony_ci  CLzmaProb posEncoders[kNumFullDistances];
467370b324cSopenharmony_ci
468370b324cSopenharmony_ci  CLenEnc lenProbs;
469370b324cSopenharmony_ci  CLenEnc repLenProbs;
470370b324cSopenharmony_ci
471370b324cSopenharmony_ci  #ifndef LZMA_LOG_BSR
472370b324cSopenharmony_ci  Byte g_FastPos[1 << kNumLogBits];
473370b324cSopenharmony_ci  #endif
474370b324cSopenharmony_ci
475370b324cSopenharmony_ci  CLenPriceEnc lenEnc;
476370b324cSopenharmony_ci  CLenPriceEnc repLenEnc;
477370b324cSopenharmony_ci
478370b324cSopenharmony_ci  COptimal opt[kNumOpts];
479370b324cSopenharmony_ci
480370b324cSopenharmony_ci  CSaveState saveState;
481370b324cSopenharmony_ci
482370b324cSopenharmony_ci  // BoolInt mf_Failure;
483370b324cSopenharmony_ci  #ifndef Z7_ST
484370b324cSopenharmony_ci  Byte pad2[128];
485370b324cSopenharmony_ci  #endif
486370b324cSopenharmony_ci};
487370b324cSopenharmony_ci
488370b324cSopenharmony_ci
489370b324cSopenharmony_ci#define MFB (p->matchFinderBase)
490370b324cSopenharmony_ci/*
491370b324cSopenharmony_ci#ifndef Z7_ST
492370b324cSopenharmony_ci#define MFB (p->matchFinderMt.MatchFinder)
493370b324cSopenharmony_ci#endif
494370b324cSopenharmony_ci*/
495370b324cSopenharmony_ci
496370b324cSopenharmony_ci// #define GET_CLzmaEnc_p  CLzmaEnc *p = (CLzmaEnc*)(void *)p;
497370b324cSopenharmony_ci// #define GET_const_CLzmaEnc_p  const CLzmaEnc *p = (const CLzmaEnc*)(const void *)p;
498370b324cSopenharmony_ci
499370b324cSopenharmony_ci#define COPY_ARR(dest, src, arr)  memcpy((dest)->arr, (src)->arr, sizeof((src)->arr));
500370b324cSopenharmony_ci
501370b324cSopenharmony_ci#define COPY_LZMA_ENC_STATE(d, s, p)  \
502370b324cSopenharmony_ci  (d)->state = (s)->state;  \
503370b324cSopenharmony_ci  COPY_ARR(d, s, reps)  \
504370b324cSopenharmony_ci  COPY_ARR(d, s, posAlignEncoder)  \
505370b324cSopenharmony_ci  COPY_ARR(d, s, isRep)  \
506370b324cSopenharmony_ci  COPY_ARR(d, s, isRepG0)  \
507370b324cSopenharmony_ci  COPY_ARR(d, s, isRepG1)  \
508370b324cSopenharmony_ci  COPY_ARR(d, s, isRepG2)  \
509370b324cSopenharmony_ci  COPY_ARR(d, s, isMatch)  \
510370b324cSopenharmony_ci  COPY_ARR(d, s, isRep0Long)  \
511370b324cSopenharmony_ci  COPY_ARR(d, s, posSlotEncoder)  \
512370b324cSopenharmony_ci  COPY_ARR(d, s, posEncoders)  \
513370b324cSopenharmony_ci  (d)->lenProbs = (s)->lenProbs;  \
514370b324cSopenharmony_ci  (d)->repLenProbs = (s)->repLenProbs;  \
515370b324cSopenharmony_ci  memcpy((d)->litProbs, (s)->litProbs, ((UInt32)0x300 << (p)->lclp) * sizeof(CLzmaProb));
516370b324cSopenharmony_ci
517370b324cSopenharmony_civoid LzmaEnc_SaveState(CLzmaEncHandle p)
518370b324cSopenharmony_ci{
519370b324cSopenharmony_ci  // GET_CLzmaEnc_p
520370b324cSopenharmony_ci  CSaveState *v = &p->saveState;
521370b324cSopenharmony_ci  COPY_LZMA_ENC_STATE(v, p, p)
522370b324cSopenharmony_ci}
523370b324cSopenharmony_ci
524370b324cSopenharmony_civoid LzmaEnc_RestoreState(CLzmaEncHandle p)
525370b324cSopenharmony_ci{
526370b324cSopenharmony_ci  // GET_CLzmaEnc_p
527370b324cSopenharmony_ci  const CSaveState *v = &p->saveState;
528370b324cSopenharmony_ci  COPY_LZMA_ENC_STATE(p, v, p)
529370b324cSopenharmony_ci}
530370b324cSopenharmony_ci
531370b324cSopenharmony_ci
532370b324cSopenharmony_ciZ7_NO_INLINE
533370b324cSopenharmony_ciSRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2)
534370b324cSopenharmony_ci{
535370b324cSopenharmony_ci  // GET_CLzmaEnc_p
536370b324cSopenharmony_ci  CLzmaEncProps props = *props2;
537370b324cSopenharmony_ci  LzmaEncProps_Normalize(&props);
538370b324cSopenharmony_ci
539370b324cSopenharmony_ci  if (props.lc > LZMA_LC_MAX
540370b324cSopenharmony_ci      || props.lp > LZMA_LP_MAX
541370b324cSopenharmony_ci      || props.pb > LZMA_PB_MAX)
542370b324cSopenharmony_ci    return SZ_ERROR_PARAM;
543370b324cSopenharmony_ci
544370b324cSopenharmony_ci
545370b324cSopenharmony_ci  if (props.dictSize > kLzmaMaxHistorySize)
546370b324cSopenharmony_ci    props.dictSize = kLzmaMaxHistorySize;
547370b324cSopenharmony_ci
548370b324cSopenharmony_ci  #ifndef LZMA_LOG_BSR
549370b324cSopenharmony_ci  {
550370b324cSopenharmony_ci    const UInt64 dict64 = props.dictSize;
551370b324cSopenharmony_ci    if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress))
552370b324cSopenharmony_ci      return SZ_ERROR_PARAM;
553370b324cSopenharmony_ci  }
554370b324cSopenharmony_ci  #endif
555370b324cSopenharmony_ci
556370b324cSopenharmony_ci  p->dictSize = props.dictSize;
557370b324cSopenharmony_ci  {
558370b324cSopenharmony_ci    unsigned fb = (unsigned)props.fb;
559370b324cSopenharmony_ci    if (fb < 5)
560370b324cSopenharmony_ci      fb = 5;
561370b324cSopenharmony_ci    if (fb > LZMA_MATCH_LEN_MAX)
562370b324cSopenharmony_ci      fb = LZMA_MATCH_LEN_MAX;
563370b324cSopenharmony_ci    p->numFastBytes = fb;
564370b324cSopenharmony_ci  }
565370b324cSopenharmony_ci  p->lc = (unsigned)props.lc;
566370b324cSopenharmony_ci  p->lp = (unsigned)props.lp;
567370b324cSopenharmony_ci  p->pb = (unsigned)props.pb;
568370b324cSopenharmony_ci  p->fastMode = (props.algo == 0);
569370b324cSopenharmony_ci  // p->_maxMode = True;
570370b324cSopenharmony_ci  MFB.btMode = (Byte)(props.btMode ? 1 : 0);
571370b324cSopenharmony_ci  // MFB.btMode = (Byte)(props.btMode);
572370b324cSopenharmony_ci  {
573370b324cSopenharmony_ci    unsigned numHashBytes = 4;
574370b324cSopenharmony_ci    if (props.btMode)
575370b324cSopenharmony_ci    {
576370b324cSopenharmony_ci           if (props.numHashBytes <  2) numHashBytes = 2;
577370b324cSopenharmony_ci      else if (props.numHashBytes <  4) numHashBytes = (unsigned)props.numHashBytes;
578370b324cSopenharmony_ci    }
579370b324cSopenharmony_ci    if (props.numHashBytes >= 5) numHashBytes = 5;
580370b324cSopenharmony_ci
581370b324cSopenharmony_ci    MFB.numHashBytes = numHashBytes;
582370b324cSopenharmony_ci    // MFB.numHashBytes_Min = 2;
583370b324cSopenharmony_ci    MFB.numHashOutBits = (Byte)props.numHashOutBits;
584370b324cSopenharmony_ci  }
585370b324cSopenharmony_ci
586370b324cSopenharmony_ci  MFB.cutValue = props.mc;
587370b324cSopenharmony_ci
588370b324cSopenharmony_ci  p->writeEndMark = (BoolInt)props.writeEndMark;
589370b324cSopenharmony_ci
590370b324cSopenharmony_ci  #ifndef Z7_ST
591370b324cSopenharmony_ci  /*
592370b324cSopenharmony_ci  if (newMultiThread != _multiThread)
593370b324cSopenharmony_ci  {
594370b324cSopenharmony_ci    ReleaseMatchFinder();
595370b324cSopenharmony_ci    _multiThread = newMultiThread;
596370b324cSopenharmony_ci  }
597370b324cSopenharmony_ci  */
598370b324cSopenharmony_ci  p->multiThread = (props.numThreads > 1);
599370b324cSopenharmony_ci  p->matchFinderMt.btSync.affinity =
600370b324cSopenharmony_ci  p->matchFinderMt.hashSync.affinity = props.affinity;
601370b324cSopenharmony_ci  #endif
602370b324cSopenharmony_ci
603370b324cSopenharmony_ci  return SZ_OK;
604370b324cSopenharmony_ci}
605370b324cSopenharmony_ci
606370b324cSopenharmony_ci
607370b324cSopenharmony_civoid LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize)
608370b324cSopenharmony_ci{
609370b324cSopenharmony_ci  // GET_CLzmaEnc_p
610370b324cSopenharmony_ci  MFB.expectedDataSize = expectedDataSiize;
611370b324cSopenharmony_ci}
612370b324cSopenharmony_ci
613370b324cSopenharmony_ci
614370b324cSopenharmony_ci#define kState_Start 0
615370b324cSopenharmony_ci#define kState_LitAfterMatch 4
616370b324cSopenharmony_ci#define kState_LitAfterRep   5
617370b324cSopenharmony_ci#define kState_MatchAfterLit 7
618370b324cSopenharmony_ci#define kState_RepAfterLit   8
619370b324cSopenharmony_ci
620370b324cSopenharmony_cistatic const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
621370b324cSopenharmony_cistatic const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
622370b324cSopenharmony_cistatic const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
623370b324cSopenharmony_cistatic const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
624370b324cSopenharmony_ci
625370b324cSopenharmony_ci#define IsLitState(s) ((s) < 7)
626370b324cSopenharmony_ci#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
627370b324cSopenharmony_ci#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
628370b324cSopenharmony_ci
629370b324cSopenharmony_ci#define kInfinityPrice (1 << 30)
630370b324cSopenharmony_ci
631370b324cSopenharmony_cistatic void RangeEnc_Construct(CRangeEnc *p)
632370b324cSopenharmony_ci{
633370b324cSopenharmony_ci  p->outStream = NULL;
634370b324cSopenharmony_ci  p->bufBase = NULL;
635370b324cSopenharmony_ci}
636370b324cSopenharmony_ci
637370b324cSopenharmony_ci#define RangeEnc_GetProcessed(p)       (        (p)->processed + (size_t)((p)->buf - (p)->bufBase) +         (p)->cacheSize)
638370b324cSopenharmony_ci#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
639370b324cSopenharmony_ci
640370b324cSopenharmony_ci#define RC_BUF_SIZE (1 << 16)
641370b324cSopenharmony_ci
642370b324cSopenharmony_cistatic int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
643370b324cSopenharmony_ci{
644370b324cSopenharmony_ci  if (!p->bufBase)
645370b324cSopenharmony_ci  {
646370b324cSopenharmony_ci    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
647370b324cSopenharmony_ci    if (!p->bufBase)
648370b324cSopenharmony_ci      return 0;
649370b324cSopenharmony_ci    p->bufLim = p->bufBase + RC_BUF_SIZE;
650370b324cSopenharmony_ci  }
651370b324cSopenharmony_ci  return 1;
652370b324cSopenharmony_ci}
653370b324cSopenharmony_ci
654370b324cSopenharmony_cistatic void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
655370b324cSopenharmony_ci{
656370b324cSopenharmony_ci  ISzAlloc_Free(alloc, p->bufBase);
657370b324cSopenharmony_ci  p->bufBase = NULL;
658370b324cSopenharmony_ci}
659370b324cSopenharmony_ci
660370b324cSopenharmony_cistatic void RangeEnc_Init(CRangeEnc *p)
661370b324cSopenharmony_ci{
662370b324cSopenharmony_ci  p->range = 0xFFFFFFFF;
663370b324cSopenharmony_ci  p->cache = 0;
664370b324cSopenharmony_ci  p->low = 0;
665370b324cSopenharmony_ci  p->cacheSize = 0;
666370b324cSopenharmony_ci
667370b324cSopenharmony_ci  p->buf = p->bufBase;
668370b324cSopenharmony_ci
669370b324cSopenharmony_ci  p->processed = 0;
670370b324cSopenharmony_ci  p->res = SZ_OK;
671370b324cSopenharmony_ci}
672370b324cSopenharmony_ci
673370b324cSopenharmony_ciZ7_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
674370b324cSopenharmony_ci{
675370b324cSopenharmony_ci  const size_t num = (size_t)(p->buf - p->bufBase);
676370b324cSopenharmony_ci  if (p->res == SZ_OK)
677370b324cSopenharmony_ci  {
678370b324cSopenharmony_ci    if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
679370b324cSopenharmony_ci      p->res = SZ_ERROR_WRITE;
680370b324cSopenharmony_ci  }
681370b324cSopenharmony_ci  p->processed += num;
682370b324cSopenharmony_ci  p->buf = p->bufBase;
683370b324cSopenharmony_ci}
684370b324cSopenharmony_ci
685370b324cSopenharmony_ciZ7_NO_INLINE static void Z7_FASTCALL RangeEnc_ShiftLow(CRangeEnc *p)
686370b324cSopenharmony_ci{
687370b324cSopenharmony_ci  UInt32 low = (UInt32)p->low;
688370b324cSopenharmony_ci  unsigned high = (unsigned)(p->low >> 32);
689370b324cSopenharmony_ci  p->low = (UInt32)(low << 8);
690370b324cSopenharmony_ci  if (low < (UInt32)0xFF000000 || high != 0)
691370b324cSopenharmony_ci  {
692370b324cSopenharmony_ci    {
693370b324cSopenharmony_ci      Byte *buf = p->buf;
694370b324cSopenharmony_ci      *buf++ = (Byte)(p->cache + high);
695370b324cSopenharmony_ci      p->cache = (unsigned)(low >> 24);
696370b324cSopenharmony_ci      p->buf = buf;
697370b324cSopenharmony_ci      if (buf == p->bufLim)
698370b324cSopenharmony_ci        RangeEnc_FlushStream(p);
699370b324cSopenharmony_ci      if (p->cacheSize == 0)
700370b324cSopenharmony_ci        return;
701370b324cSopenharmony_ci    }
702370b324cSopenharmony_ci    high += 0xFF;
703370b324cSopenharmony_ci    for (;;)
704370b324cSopenharmony_ci    {
705370b324cSopenharmony_ci      Byte *buf = p->buf;
706370b324cSopenharmony_ci      *buf++ = (Byte)(high);
707370b324cSopenharmony_ci      p->buf = buf;
708370b324cSopenharmony_ci      if (buf == p->bufLim)
709370b324cSopenharmony_ci        RangeEnc_FlushStream(p);
710370b324cSopenharmony_ci      if (--p->cacheSize == 0)
711370b324cSopenharmony_ci        return;
712370b324cSopenharmony_ci    }
713370b324cSopenharmony_ci  }
714370b324cSopenharmony_ci  p->cacheSize++;
715370b324cSopenharmony_ci}
716370b324cSopenharmony_ci
717370b324cSopenharmony_cistatic void RangeEnc_FlushData(CRangeEnc *p)
718370b324cSopenharmony_ci{
719370b324cSopenharmony_ci  int i;
720370b324cSopenharmony_ci  for (i = 0; i < 5; i++)
721370b324cSopenharmony_ci    RangeEnc_ShiftLow(p);
722370b324cSopenharmony_ci}
723370b324cSopenharmony_ci
724370b324cSopenharmony_ci#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
725370b324cSopenharmony_ci
726370b324cSopenharmony_ci#define RC_BIT_PRE(p, prob) \
727370b324cSopenharmony_ci  ttt = *(prob); \
728370b324cSopenharmony_ci  newBound = (range >> kNumBitModelTotalBits) * ttt;
729370b324cSopenharmony_ci
730370b324cSopenharmony_ci// #define Z7_LZMA_ENC_USE_BRANCH
731370b324cSopenharmony_ci
732370b324cSopenharmony_ci#ifdef Z7_LZMA_ENC_USE_BRANCH
733370b324cSopenharmony_ci
734370b324cSopenharmony_ci#define RC_BIT(p, prob, bit) { \
735370b324cSopenharmony_ci  RC_BIT_PRE(p, prob) \
736370b324cSopenharmony_ci  if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
737370b324cSopenharmony_ci  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
738370b324cSopenharmony_ci  *(prob) = (CLzmaProb)ttt; \
739370b324cSopenharmony_ci  RC_NORM(p) \
740370b324cSopenharmony_ci  }
741370b324cSopenharmony_ci
742370b324cSopenharmony_ci#else
743370b324cSopenharmony_ci
744370b324cSopenharmony_ci#define RC_BIT(p, prob, bit) { \
745370b324cSopenharmony_ci  UInt32 mask; \
746370b324cSopenharmony_ci  RC_BIT_PRE(p, prob) \
747370b324cSopenharmony_ci  mask = 0 - (UInt32)bit; \
748370b324cSopenharmony_ci  range &= mask; \
749370b324cSopenharmony_ci  mask &= newBound; \
750370b324cSopenharmony_ci  range -= mask; \
751370b324cSopenharmony_ci  (p)->low += mask; \
752370b324cSopenharmony_ci  mask = (UInt32)bit - 1; \
753370b324cSopenharmony_ci  range += newBound & mask; \
754370b324cSopenharmony_ci  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
755370b324cSopenharmony_ci  mask += ((1 << kNumMoveBits) - 1); \
756370b324cSopenharmony_ci  ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \
757370b324cSopenharmony_ci  *(prob) = (CLzmaProb)ttt; \
758370b324cSopenharmony_ci  RC_NORM(p) \
759370b324cSopenharmony_ci  }
760370b324cSopenharmony_ci
761370b324cSopenharmony_ci#endif
762370b324cSopenharmony_ci
763370b324cSopenharmony_ci
764370b324cSopenharmony_ci
765370b324cSopenharmony_ci
766370b324cSopenharmony_ci#define RC_BIT_0_BASE(p, prob) \
767370b324cSopenharmony_ci  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
768370b324cSopenharmony_ci
769370b324cSopenharmony_ci#define RC_BIT_1_BASE(p, prob) \
770370b324cSopenharmony_ci  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
771370b324cSopenharmony_ci
772370b324cSopenharmony_ci#define RC_BIT_0(p, prob) \
773370b324cSopenharmony_ci  RC_BIT_0_BASE(p, prob) \
774370b324cSopenharmony_ci  RC_NORM(p)
775370b324cSopenharmony_ci
776370b324cSopenharmony_ci#define RC_BIT_1(p, prob) \
777370b324cSopenharmony_ci  RC_BIT_1_BASE(p, prob) \
778370b324cSopenharmony_ci  RC_NORM(p)
779370b324cSopenharmony_ci
780370b324cSopenharmony_cistatic void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
781370b324cSopenharmony_ci{
782370b324cSopenharmony_ci  UInt32 range, ttt, newBound;
783370b324cSopenharmony_ci  range = p->range;
784370b324cSopenharmony_ci  RC_BIT_PRE(p, prob)
785370b324cSopenharmony_ci  RC_BIT_0(p, prob)
786370b324cSopenharmony_ci  p->range = range;
787370b324cSopenharmony_ci}
788370b324cSopenharmony_ci
789370b324cSopenharmony_cistatic void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
790370b324cSopenharmony_ci{
791370b324cSopenharmony_ci  UInt32 range = p->range;
792370b324cSopenharmony_ci  sym |= 0x100;
793370b324cSopenharmony_ci  do
794370b324cSopenharmony_ci  {
795370b324cSopenharmony_ci    UInt32 ttt, newBound;
796370b324cSopenharmony_ci    // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
797370b324cSopenharmony_ci    CLzmaProb *prob = probs + (sym >> 8);
798370b324cSopenharmony_ci    UInt32 bit = (sym >> 7) & 1;
799370b324cSopenharmony_ci    sym <<= 1;
800370b324cSopenharmony_ci    RC_BIT(p, prob, bit)
801370b324cSopenharmony_ci  }
802370b324cSopenharmony_ci  while (sym < 0x10000);
803370b324cSopenharmony_ci  p->range = range;
804370b324cSopenharmony_ci}
805370b324cSopenharmony_ci
806370b324cSopenharmony_cistatic void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)
807370b324cSopenharmony_ci{
808370b324cSopenharmony_ci  UInt32 range = p->range;
809370b324cSopenharmony_ci  UInt32 offs = 0x100;
810370b324cSopenharmony_ci  sym |= 0x100;
811370b324cSopenharmony_ci  do
812370b324cSopenharmony_ci  {
813370b324cSopenharmony_ci    UInt32 ttt, newBound;
814370b324cSopenharmony_ci    CLzmaProb *prob;
815370b324cSopenharmony_ci    UInt32 bit;
816370b324cSopenharmony_ci    matchByte <<= 1;
817370b324cSopenharmony_ci    // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);
818370b324cSopenharmony_ci    prob = probs + (offs + (matchByte & offs) + (sym >> 8));
819370b324cSopenharmony_ci    bit = (sym >> 7) & 1;
820370b324cSopenharmony_ci    sym <<= 1;
821370b324cSopenharmony_ci    offs &= ~(matchByte ^ sym);
822370b324cSopenharmony_ci    RC_BIT(p, prob, bit)
823370b324cSopenharmony_ci  }
824370b324cSopenharmony_ci  while (sym < 0x10000);
825370b324cSopenharmony_ci  p->range = range;
826370b324cSopenharmony_ci}
827370b324cSopenharmony_ci
828370b324cSopenharmony_ci
829370b324cSopenharmony_ci
830370b324cSopenharmony_cistatic void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
831370b324cSopenharmony_ci{
832370b324cSopenharmony_ci  UInt32 i;
833370b324cSopenharmony_ci  for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
834370b324cSopenharmony_ci  {
835370b324cSopenharmony_ci    const unsigned kCyclesBits = kNumBitPriceShiftBits;
836370b324cSopenharmony_ci    UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
837370b324cSopenharmony_ci    unsigned bitCount = 0;
838370b324cSopenharmony_ci    unsigned j;
839370b324cSopenharmony_ci    for (j = 0; j < kCyclesBits; j++)
840370b324cSopenharmony_ci    {
841370b324cSopenharmony_ci      w = w * w;
842370b324cSopenharmony_ci      bitCount <<= 1;
843370b324cSopenharmony_ci      while (w >= ((UInt32)1 << 16))
844370b324cSopenharmony_ci      {
845370b324cSopenharmony_ci        w >>= 1;
846370b324cSopenharmony_ci        bitCount++;
847370b324cSopenharmony_ci      }
848370b324cSopenharmony_ci    }
849370b324cSopenharmony_ci    ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
850370b324cSopenharmony_ci    // printf("\n%3d: %5d", i, ProbPrices[i]);
851370b324cSopenharmony_ci  }
852370b324cSopenharmony_ci}
853370b324cSopenharmony_ci
854370b324cSopenharmony_ci
855370b324cSopenharmony_ci#define GET_PRICE(prob, bit) \
856370b324cSopenharmony_ci  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]
857370b324cSopenharmony_ci
858370b324cSopenharmony_ci#define GET_PRICEa(prob, bit) \
859370b324cSopenharmony_ci     ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]
860370b324cSopenharmony_ci
861370b324cSopenharmony_ci#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
862370b324cSopenharmony_ci#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
863370b324cSopenharmony_ci
864370b324cSopenharmony_ci#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
865370b324cSopenharmony_ci#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
866370b324cSopenharmony_ci
867370b324cSopenharmony_ci
868370b324cSopenharmony_cistatic UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
869370b324cSopenharmony_ci{
870370b324cSopenharmony_ci  UInt32 price = 0;
871370b324cSopenharmony_ci  sym |= 0x100;
872370b324cSopenharmony_ci  do
873370b324cSopenharmony_ci  {
874370b324cSopenharmony_ci    unsigned bit = sym & 1;
875370b324cSopenharmony_ci    sym >>= 1;
876370b324cSopenharmony_ci    price += GET_PRICEa(probs[sym], bit);
877370b324cSopenharmony_ci  }
878370b324cSopenharmony_ci  while (sym >= 2);
879370b324cSopenharmony_ci  return price;
880370b324cSopenharmony_ci}
881370b324cSopenharmony_ci
882370b324cSopenharmony_ci
883370b324cSopenharmony_cistatic UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
884370b324cSopenharmony_ci{
885370b324cSopenharmony_ci  UInt32 price = 0;
886370b324cSopenharmony_ci  UInt32 offs = 0x100;
887370b324cSopenharmony_ci  sym |= 0x100;
888370b324cSopenharmony_ci  do
889370b324cSopenharmony_ci  {
890370b324cSopenharmony_ci    matchByte <<= 1;
891370b324cSopenharmony_ci    price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
892370b324cSopenharmony_ci    sym <<= 1;
893370b324cSopenharmony_ci    offs &= ~(matchByte ^ sym);
894370b324cSopenharmony_ci  }
895370b324cSopenharmony_ci  while (sym < 0x10000);
896370b324cSopenharmony_ci  return price;
897370b324cSopenharmony_ci}
898370b324cSopenharmony_ci
899370b324cSopenharmony_ci
900370b324cSopenharmony_cistatic void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)
901370b324cSopenharmony_ci{
902370b324cSopenharmony_ci  UInt32 range = rc->range;
903370b324cSopenharmony_ci  unsigned m = 1;
904370b324cSopenharmony_ci  do
905370b324cSopenharmony_ci  {
906370b324cSopenharmony_ci    UInt32 ttt, newBound;
907370b324cSopenharmony_ci    unsigned bit = sym & 1;
908370b324cSopenharmony_ci    // RangeEnc_EncodeBit(rc, probs + m, bit);
909370b324cSopenharmony_ci    sym >>= 1;
910370b324cSopenharmony_ci    RC_BIT(rc, probs + m, bit)
911370b324cSopenharmony_ci    m = (m << 1) | bit;
912370b324cSopenharmony_ci  }
913370b324cSopenharmony_ci  while (--numBits);
914370b324cSopenharmony_ci  rc->range = range;
915370b324cSopenharmony_ci}
916370b324cSopenharmony_ci
917370b324cSopenharmony_ci
918370b324cSopenharmony_ci
919370b324cSopenharmony_cistatic void LenEnc_Init(CLenEnc *p)
920370b324cSopenharmony_ci{
921370b324cSopenharmony_ci  unsigned i;
922370b324cSopenharmony_ci  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
923370b324cSopenharmony_ci    p->low[i] = kProbInitValue;
924370b324cSopenharmony_ci  for (i = 0; i < kLenNumHighSymbols; i++)
925370b324cSopenharmony_ci    p->high[i] = kProbInitValue;
926370b324cSopenharmony_ci}
927370b324cSopenharmony_ci
928370b324cSopenharmony_cistatic void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
929370b324cSopenharmony_ci{
930370b324cSopenharmony_ci  UInt32 range, ttt, newBound;
931370b324cSopenharmony_ci  CLzmaProb *probs = p->low;
932370b324cSopenharmony_ci  range = rc->range;
933370b324cSopenharmony_ci  RC_BIT_PRE(rc, probs)
934370b324cSopenharmony_ci  if (sym >= kLenNumLowSymbols)
935370b324cSopenharmony_ci  {
936370b324cSopenharmony_ci    RC_BIT_1(rc, probs)
937370b324cSopenharmony_ci    probs += kLenNumLowSymbols;
938370b324cSopenharmony_ci    RC_BIT_PRE(rc, probs)
939370b324cSopenharmony_ci    if (sym >= kLenNumLowSymbols * 2)
940370b324cSopenharmony_ci    {
941370b324cSopenharmony_ci      RC_BIT_1(rc, probs)
942370b324cSopenharmony_ci      rc->range = range;
943370b324cSopenharmony_ci      // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
944370b324cSopenharmony_ci      LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
945370b324cSopenharmony_ci      return;
946370b324cSopenharmony_ci    }
947370b324cSopenharmony_ci    sym -= kLenNumLowSymbols;
948370b324cSopenharmony_ci  }
949370b324cSopenharmony_ci
950370b324cSopenharmony_ci  // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
951370b324cSopenharmony_ci  {
952370b324cSopenharmony_ci    unsigned m;
953370b324cSopenharmony_ci    unsigned bit;
954370b324cSopenharmony_ci    RC_BIT_0(rc, probs)
955370b324cSopenharmony_ci    probs += (posState << (1 + kLenNumLowBits));
956370b324cSopenharmony_ci    bit = (sym >> 2)    ; RC_BIT(rc, probs + 1, bit)  m = (1 << 1) + bit;
957370b324cSopenharmony_ci    bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit)  m = (m << 1) + bit;
958370b324cSopenharmony_ci    bit =  sym       & 1; RC_BIT(rc, probs + m, bit)
959370b324cSopenharmony_ci    rc->range = range;
960370b324cSopenharmony_ci  }
961370b324cSopenharmony_ci}
962370b324cSopenharmony_ci
963370b324cSopenharmony_cistatic void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
964370b324cSopenharmony_ci{
965370b324cSopenharmony_ci  unsigned i;
966370b324cSopenharmony_ci  for (i = 0; i < 8; i += 2)
967370b324cSopenharmony_ci  {
968370b324cSopenharmony_ci    UInt32 price = startPrice;
969370b324cSopenharmony_ci    UInt32 prob;
970370b324cSopenharmony_ci    price += GET_PRICEa(probs[1           ], (i >> 2));
971370b324cSopenharmony_ci    price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
972370b324cSopenharmony_ci    prob = probs[4 + (i >> 1)];
973370b324cSopenharmony_ci    prices[i    ] = price + GET_PRICEa_0(prob);
974370b324cSopenharmony_ci    prices[i + 1] = price + GET_PRICEa_1(prob);
975370b324cSopenharmony_ci  }
976370b324cSopenharmony_ci}
977370b324cSopenharmony_ci
978370b324cSopenharmony_ci
979370b324cSopenharmony_ciZ7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(
980370b324cSopenharmony_ci    CLenPriceEnc *p,
981370b324cSopenharmony_ci    unsigned numPosStates,
982370b324cSopenharmony_ci    const CLenEnc *enc,
983370b324cSopenharmony_ci    const CProbPrice *ProbPrices)
984370b324cSopenharmony_ci{
985370b324cSopenharmony_ci  UInt32 b;
986370b324cSopenharmony_ci
987370b324cSopenharmony_ci  {
988370b324cSopenharmony_ci    unsigned prob = enc->low[0];
989370b324cSopenharmony_ci    UInt32 a, c;
990370b324cSopenharmony_ci    unsigned posState;
991370b324cSopenharmony_ci    b = GET_PRICEa_1(prob);
992370b324cSopenharmony_ci    a = GET_PRICEa_0(prob);
993370b324cSopenharmony_ci    c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
994370b324cSopenharmony_ci    for (posState = 0; posState < numPosStates; posState++)
995370b324cSopenharmony_ci    {
996370b324cSopenharmony_ci      UInt32 *prices = p->prices[posState];
997370b324cSopenharmony_ci      const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
998370b324cSopenharmony_ci      SetPrices_3(probs, a, prices, ProbPrices);
999370b324cSopenharmony_ci      SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
1000370b324cSopenharmony_ci    }
1001370b324cSopenharmony_ci  }
1002370b324cSopenharmony_ci
1003370b324cSopenharmony_ci  /*
1004370b324cSopenharmony_ci  {
1005370b324cSopenharmony_ci    unsigned i;
1006370b324cSopenharmony_ci    UInt32 b;
1007370b324cSopenharmony_ci    a = GET_PRICEa_0(enc->low[0]);
1008370b324cSopenharmony_ci    for (i = 0; i < kLenNumLowSymbols; i++)
1009370b324cSopenharmony_ci      p->prices2[i] = a;
1010370b324cSopenharmony_ci    a = GET_PRICEa_1(enc->low[0]);
1011370b324cSopenharmony_ci    b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
1012370b324cSopenharmony_ci    for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
1013370b324cSopenharmony_ci      p->prices2[i] = b;
1014370b324cSopenharmony_ci    a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
1015370b324cSopenharmony_ci  }
1016370b324cSopenharmony_ci  */
1017370b324cSopenharmony_ci
1018370b324cSopenharmony_ci  // p->counter = numSymbols;
1019370b324cSopenharmony_ci  // p->counter = 64;
1020370b324cSopenharmony_ci
1021370b324cSopenharmony_ci  {
1022370b324cSopenharmony_ci    unsigned i = p->tableSize;
1023370b324cSopenharmony_ci
1024370b324cSopenharmony_ci    if (i > kLenNumLowSymbols * 2)
1025370b324cSopenharmony_ci    {
1026370b324cSopenharmony_ci      const CLzmaProb *probs = enc->high;
1027370b324cSopenharmony_ci      UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
1028370b324cSopenharmony_ci      i -= kLenNumLowSymbols * 2 - 1;
1029370b324cSopenharmony_ci      i >>= 1;
1030370b324cSopenharmony_ci      b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
1031370b324cSopenharmony_ci      do
1032370b324cSopenharmony_ci      {
1033370b324cSopenharmony_ci        /*
1034370b324cSopenharmony_ci        p->prices2[i] = a +
1035370b324cSopenharmony_ci        // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
1036370b324cSopenharmony_ci        LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
1037370b324cSopenharmony_ci        */
1038370b324cSopenharmony_ci        // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
1039370b324cSopenharmony_ci        unsigned sym = --i + (1 << (kLenNumHighBits - 1));
1040370b324cSopenharmony_ci        UInt32 price = b;
1041370b324cSopenharmony_ci        do
1042370b324cSopenharmony_ci        {
1043370b324cSopenharmony_ci          unsigned bit = sym & 1;
1044370b324cSopenharmony_ci          sym >>= 1;
1045370b324cSopenharmony_ci          price += GET_PRICEa(probs[sym], bit);
1046370b324cSopenharmony_ci        }
1047370b324cSopenharmony_ci        while (sym >= 2);
1048370b324cSopenharmony_ci
1049370b324cSopenharmony_ci        {
1050370b324cSopenharmony_ci          unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
1051370b324cSopenharmony_ci          prices[(size_t)i * 2    ] = price + GET_PRICEa_0(prob);
1052370b324cSopenharmony_ci          prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
1053370b324cSopenharmony_ci        }
1054370b324cSopenharmony_ci      }
1055370b324cSopenharmony_ci      while (i);
1056370b324cSopenharmony_ci
1057370b324cSopenharmony_ci      {
1058370b324cSopenharmony_ci        unsigned posState;
1059370b324cSopenharmony_ci        size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
1060370b324cSopenharmony_ci        for (posState = 1; posState < numPosStates; posState++)
1061370b324cSopenharmony_ci          memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
1062370b324cSopenharmony_ci      }
1063370b324cSopenharmony_ci    }
1064370b324cSopenharmony_ci  }
1065370b324cSopenharmony_ci}
1066370b324cSopenharmony_ci
1067370b324cSopenharmony_ci/*
1068370b324cSopenharmony_ci  #ifdef SHOW_STAT
1069370b324cSopenharmony_ci  g_STAT_OFFSET += num;
1070370b324cSopenharmony_ci  printf("\n MovePos %u", num);
1071370b324cSopenharmony_ci  #endif
1072370b324cSopenharmony_ci*/
1073370b324cSopenharmony_ci
1074370b324cSopenharmony_ci#define MOVE_POS(p, num) { \
1075370b324cSopenharmony_ci    p->additionalOffset += (num); \
1076370b324cSopenharmony_ci    p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
1077370b324cSopenharmony_ci
1078370b324cSopenharmony_ci
1079370b324cSopenharmony_cistatic unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
1080370b324cSopenharmony_ci{
1081370b324cSopenharmony_ci  unsigned numPairs;
1082370b324cSopenharmony_ci
1083370b324cSopenharmony_ci  p->additionalOffset++;
1084370b324cSopenharmony_ci  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
1085370b324cSopenharmony_ci  {
1086370b324cSopenharmony_ci    const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
1087370b324cSopenharmony_ci    // if (!d) { p->mf_Failure = True; *numPairsRes = 0;  return 0; }
1088370b324cSopenharmony_ci    numPairs = (unsigned)(d - p->matches);
1089370b324cSopenharmony_ci  }
1090370b324cSopenharmony_ci  *numPairsRes = numPairs;
1091370b324cSopenharmony_ci
1092370b324cSopenharmony_ci  #ifdef SHOW_STAT
1093370b324cSopenharmony_ci  printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);
1094370b324cSopenharmony_ci  g_STAT_OFFSET++;
1095370b324cSopenharmony_ci  {
1096370b324cSopenharmony_ci    unsigned i;
1097370b324cSopenharmony_ci    for (i = 0; i < numPairs; i += 2)
1098370b324cSopenharmony_ci      printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);
1099370b324cSopenharmony_ci  }
1100370b324cSopenharmony_ci  #endif
1101370b324cSopenharmony_ci
1102370b324cSopenharmony_ci  if (numPairs == 0)
1103370b324cSopenharmony_ci    return 0;
1104370b324cSopenharmony_ci  {
1105370b324cSopenharmony_ci    const unsigned len = p->matches[(size_t)numPairs - 2];
1106370b324cSopenharmony_ci    if (len != p->numFastBytes)
1107370b324cSopenharmony_ci      return len;
1108370b324cSopenharmony_ci    {
1109370b324cSopenharmony_ci      UInt32 numAvail = p->numAvail;
1110370b324cSopenharmony_ci      if (numAvail > LZMA_MATCH_LEN_MAX)
1111370b324cSopenharmony_ci        numAvail = LZMA_MATCH_LEN_MAX;
1112370b324cSopenharmony_ci      {
1113370b324cSopenharmony_ci        const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1114370b324cSopenharmony_ci        const Byte *p2 = p1 + len;
1115370b324cSopenharmony_ci        const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1];
1116370b324cSopenharmony_ci        const Byte *lim = p1 + numAvail;
1117370b324cSopenharmony_ci        for (; p2 != lim && *p2 == p2[dif]; p2++)
1118370b324cSopenharmony_ci        {}
1119370b324cSopenharmony_ci        return (unsigned)(p2 - p1);
1120370b324cSopenharmony_ci      }
1121370b324cSopenharmony_ci    }
1122370b324cSopenharmony_ci  }
1123370b324cSopenharmony_ci}
1124370b324cSopenharmony_ci
1125370b324cSopenharmony_ci#define MARK_LIT ((UInt32)(Int32)-1)
1126370b324cSopenharmony_ci
1127370b324cSopenharmony_ci#define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }
1128370b324cSopenharmony_ci#define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }
1129370b324cSopenharmony_ci#define IsShortRep(p)       ((p)->dist == 0)
1130370b324cSopenharmony_ci
1131370b324cSopenharmony_ci
1132370b324cSopenharmony_ci#define GetPrice_ShortRep(p, state, posState) \
1133370b324cSopenharmony_ci  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
1134370b324cSopenharmony_ci
1135370b324cSopenharmony_ci#define GetPrice_Rep_0(p, state, posState) ( \
1136370b324cSopenharmony_ci    GET_PRICE_1(p->isMatch[state][posState]) \
1137370b324cSopenharmony_ci  + GET_PRICE_1(p->isRep0Long[state][posState])) \
1138370b324cSopenharmony_ci  + GET_PRICE_1(p->isRep[state]) \
1139370b324cSopenharmony_ci  + GET_PRICE_0(p->isRepG0[state])
1140370b324cSopenharmony_ci
1141370b324cSopenharmony_ciZ7_FORCE_INLINE
1142370b324cSopenharmony_cistatic UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
1143370b324cSopenharmony_ci{
1144370b324cSopenharmony_ci  UInt32 price;
1145370b324cSopenharmony_ci  UInt32 prob = p->isRepG0[state];
1146370b324cSopenharmony_ci  if (repIndex == 0)
1147370b324cSopenharmony_ci  {
1148370b324cSopenharmony_ci    price = GET_PRICE_0(prob);
1149370b324cSopenharmony_ci    price += GET_PRICE_1(p->isRep0Long[state][posState]);
1150370b324cSopenharmony_ci  }
1151370b324cSopenharmony_ci  else
1152370b324cSopenharmony_ci  {
1153370b324cSopenharmony_ci    price = GET_PRICE_1(prob);
1154370b324cSopenharmony_ci    prob = p->isRepG1[state];
1155370b324cSopenharmony_ci    if (repIndex == 1)
1156370b324cSopenharmony_ci      price += GET_PRICE_0(prob);
1157370b324cSopenharmony_ci    else
1158370b324cSopenharmony_ci    {
1159370b324cSopenharmony_ci      price += GET_PRICE_1(prob);
1160370b324cSopenharmony_ci      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
1161370b324cSopenharmony_ci    }
1162370b324cSopenharmony_ci  }
1163370b324cSopenharmony_ci  return price;
1164370b324cSopenharmony_ci}
1165370b324cSopenharmony_ci
1166370b324cSopenharmony_ci
1167370b324cSopenharmony_cistatic unsigned Backward(CLzmaEnc *p, unsigned cur)
1168370b324cSopenharmony_ci{
1169370b324cSopenharmony_ci  unsigned wr = cur + 1;
1170370b324cSopenharmony_ci  p->optEnd = wr;
1171370b324cSopenharmony_ci
1172370b324cSopenharmony_ci  for (;;)
1173370b324cSopenharmony_ci  {
1174370b324cSopenharmony_ci    UInt32 dist = p->opt[cur].dist;
1175370b324cSopenharmony_ci    unsigned len = (unsigned)p->opt[cur].len;
1176370b324cSopenharmony_ci    unsigned extra = (unsigned)p->opt[cur].extra;
1177370b324cSopenharmony_ci    cur -= len;
1178370b324cSopenharmony_ci
1179370b324cSopenharmony_ci    if (extra)
1180370b324cSopenharmony_ci    {
1181370b324cSopenharmony_ci      wr--;
1182370b324cSopenharmony_ci      p->opt[wr].len = (UInt32)len;
1183370b324cSopenharmony_ci      cur -= extra;
1184370b324cSopenharmony_ci      len = extra;
1185370b324cSopenharmony_ci      if (extra == 1)
1186370b324cSopenharmony_ci      {
1187370b324cSopenharmony_ci        p->opt[wr].dist = dist;
1188370b324cSopenharmony_ci        dist = MARK_LIT;
1189370b324cSopenharmony_ci      }
1190370b324cSopenharmony_ci      else
1191370b324cSopenharmony_ci      {
1192370b324cSopenharmony_ci        p->opt[wr].dist = 0;
1193370b324cSopenharmony_ci        len--;
1194370b324cSopenharmony_ci        wr--;
1195370b324cSopenharmony_ci        p->opt[wr].dist = MARK_LIT;
1196370b324cSopenharmony_ci        p->opt[wr].len = 1;
1197370b324cSopenharmony_ci      }
1198370b324cSopenharmony_ci    }
1199370b324cSopenharmony_ci
1200370b324cSopenharmony_ci    if (cur == 0)
1201370b324cSopenharmony_ci    {
1202370b324cSopenharmony_ci      p->backRes = dist;
1203370b324cSopenharmony_ci      p->optCur = wr;
1204370b324cSopenharmony_ci      return len;
1205370b324cSopenharmony_ci    }
1206370b324cSopenharmony_ci
1207370b324cSopenharmony_ci    wr--;
1208370b324cSopenharmony_ci    p->opt[wr].dist = dist;
1209370b324cSopenharmony_ci    p->opt[wr].len = (UInt32)len;
1210370b324cSopenharmony_ci  }
1211370b324cSopenharmony_ci}
1212370b324cSopenharmony_ci
1213370b324cSopenharmony_ci
1214370b324cSopenharmony_ci
1215370b324cSopenharmony_ci#define LIT_PROBS(pos, prevByte) \
1216370b324cSopenharmony_ci  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
1217370b324cSopenharmony_ci
1218370b324cSopenharmony_ci
1219370b324cSopenharmony_cistatic unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
1220370b324cSopenharmony_ci{
1221370b324cSopenharmony_ci  unsigned last, cur;
1222370b324cSopenharmony_ci  UInt32 reps[LZMA_NUM_REPS];
1223370b324cSopenharmony_ci  unsigned repLens[LZMA_NUM_REPS];
1224370b324cSopenharmony_ci  UInt32 *matches;
1225370b324cSopenharmony_ci
1226370b324cSopenharmony_ci  {
1227370b324cSopenharmony_ci    UInt32 numAvail;
1228370b324cSopenharmony_ci    unsigned numPairs, mainLen, repMaxIndex, i, posState;
1229370b324cSopenharmony_ci    UInt32 matchPrice, repMatchPrice;
1230370b324cSopenharmony_ci    const Byte *data;
1231370b324cSopenharmony_ci    Byte curByte, matchByte;
1232370b324cSopenharmony_ci
1233370b324cSopenharmony_ci    p->optCur = p->optEnd = 0;
1234370b324cSopenharmony_ci
1235370b324cSopenharmony_ci    if (p->additionalOffset == 0)
1236370b324cSopenharmony_ci      mainLen = ReadMatchDistances(p, &numPairs);
1237370b324cSopenharmony_ci    else
1238370b324cSopenharmony_ci    {
1239370b324cSopenharmony_ci      mainLen = p->longestMatchLen;
1240370b324cSopenharmony_ci      numPairs = p->numPairs;
1241370b324cSopenharmony_ci    }
1242370b324cSopenharmony_ci
1243370b324cSopenharmony_ci    numAvail = p->numAvail;
1244370b324cSopenharmony_ci    if (numAvail < 2)
1245370b324cSopenharmony_ci    {
1246370b324cSopenharmony_ci      p->backRes = MARK_LIT;
1247370b324cSopenharmony_ci      return 1;
1248370b324cSopenharmony_ci    }
1249370b324cSopenharmony_ci    if (numAvail > LZMA_MATCH_LEN_MAX)
1250370b324cSopenharmony_ci      numAvail = LZMA_MATCH_LEN_MAX;
1251370b324cSopenharmony_ci
1252370b324cSopenharmony_ci    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1253370b324cSopenharmony_ci    repMaxIndex = 0;
1254370b324cSopenharmony_ci
1255370b324cSopenharmony_ci    for (i = 0; i < LZMA_NUM_REPS; i++)
1256370b324cSopenharmony_ci    {
1257370b324cSopenharmony_ci      unsigned len;
1258370b324cSopenharmony_ci      const Byte *data2;
1259370b324cSopenharmony_ci      reps[i] = p->reps[i];
1260370b324cSopenharmony_ci      data2 = data - reps[i];
1261370b324cSopenharmony_ci      if (data[0] != data2[0] || data[1] != data2[1])
1262370b324cSopenharmony_ci      {
1263370b324cSopenharmony_ci        repLens[i] = 0;
1264370b324cSopenharmony_ci        continue;
1265370b324cSopenharmony_ci      }
1266370b324cSopenharmony_ci      for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1267370b324cSopenharmony_ci      {}
1268370b324cSopenharmony_ci      repLens[i] = len;
1269370b324cSopenharmony_ci      if (len > repLens[repMaxIndex])
1270370b324cSopenharmony_ci        repMaxIndex = i;
1271370b324cSopenharmony_ci      if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization
1272370b324cSopenharmony_ci        break;
1273370b324cSopenharmony_ci    }
1274370b324cSopenharmony_ci
1275370b324cSopenharmony_ci    if (repLens[repMaxIndex] >= p->numFastBytes)
1276370b324cSopenharmony_ci    {
1277370b324cSopenharmony_ci      unsigned len;
1278370b324cSopenharmony_ci      p->backRes = (UInt32)repMaxIndex;
1279370b324cSopenharmony_ci      len = repLens[repMaxIndex];
1280370b324cSopenharmony_ci      MOVE_POS(p, len - 1)
1281370b324cSopenharmony_ci      return len;
1282370b324cSopenharmony_ci    }
1283370b324cSopenharmony_ci
1284370b324cSopenharmony_ci    matches = p->matches;
1285370b324cSopenharmony_ci    #define MATCHES  matches
1286370b324cSopenharmony_ci    // #define MATCHES  p->matches
1287370b324cSopenharmony_ci
1288370b324cSopenharmony_ci    if (mainLen >= p->numFastBytes)
1289370b324cSopenharmony_ci    {
1290370b324cSopenharmony_ci      p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS;
1291370b324cSopenharmony_ci      MOVE_POS(p, mainLen - 1)
1292370b324cSopenharmony_ci      return mainLen;
1293370b324cSopenharmony_ci    }
1294370b324cSopenharmony_ci
1295370b324cSopenharmony_ci    curByte = *data;
1296370b324cSopenharmony_ci    matchByte = *(data - reps[0]);
1297370b324cSopenharmony_ci
1298370b324cSopenharmony_ci    last = repLens[repMaxIndex];
1299370b324cSopenharmony_ci    if (last <= mainLen)
1300370b324cSopenharmony_ci      last = mainLen;
1301370b324cSopenharmony_ci
1302370b324cSopenharmony_ci    if (last < 2 && curByte != matchByte)
1303370b324cSopenharmony_ci    {
1304370b324cSopenharmony_ci      p->backRes = MARK_LIT;
1305370b324cSopenharmony_ci      return 1;
1306370b324cSopenharmony_ci    }
1307370b324cSopenharmony_ci
1308370b324cSopenharmony_ci    p->opt[0].state = (CState)p->state;
1309370b324cSopenharmony_ci
1310370b324cSopenharmony_ci    posState = (position & p->pbMask);
1311370b324cSopenharmony_ci
1312370b324cSopenharmony_ci    {
1313370b324cSopenharmony_ci      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1314370b324cSopenharmony_ci      p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
1315370b324cSopenharmony_ci        (!IsLitState(p->state) ?
1316370b324cSopenharmony_ci          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1317370b324cSopenharmony_ci          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1318370b324cSopenharmony_ci    }
1319370b324cSopenharmony_ci
1320370b324cSopenharmony_ci    MakeAs_Lit(&p->opt[1])
1321370b324cSopenharmony_ci
1322370b324cSopenharmony_ci    matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
1323370b324cSopenharmony_ci    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
1324370b324cSopenharmony_ci
1325370b324cSopenharmony_ci    // 18.06
1326370b324cSopenharmony_ci    if (matchByte == curByte && repLens[0] == 0)
1327370b324cSopenharmony_ci    {
1328370b324cSopenharmony_ci      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
1329370b324cSopenharmony_ci      if (shortRepPrice < p->opt[1].price)
1330370b324cSopenharmony_ci      {
1331370b324cSopenharmony_ci        p->opt[1].price = shortRepPrice;
1332370b324cSopenharmony_ci        MakeAs_ShortRep(&p->opt[1])
1333370b324cSopenharmony_ci      }
1334370b324cSopenharmony_ci      if (last < 2)
1335370b324cSopenharmony_ci      {
1336370b324cSopenharmony_ci        p->backRes = p->opt[1].dist;
1337370b324cSopenharmony_ci        return 1;
1338370b324cSopenharmony_ci      }
1339370b324cSopenharmony_ci    }
1340370b324cSopenharmony_ci
1341370b324cSopenharmony_ci    p->opt[1].len = 1;
1342370b324cSopenharmony_ci
1343370b324cSopenharmony_ci    p->opt[0].reps[0] = reps[0];
1344370b324cSopenharmony_ci    p->opt[0].reps[1] = reps[1];
1345370b324cSopenharmony_ci    p->opt[0].reps[2] = reps[2];
1346370b324cSopenharmony_ci    p->opt[0].reps[3] = reps[3];
1347370b324cSopenharmony_ci
1348370b324cSopenharmony_ci    // ---------- REP ----------
1349370b324cSopenharmony_ci
1350370b324cSopenharmony_ci    for (i = 0; i < LZMA_NUM_REPS; i++)
1351370b324cSopenharmony_ci    {
1352370b324cSopenharmony_ci      unsigned repLen = repLens[i];
1353370b324cSopenharmony_ci      UInt32 price;
1354370b324cSopenharmony_ci      if (repLen < 2)
1355370b324cSopenharmony_ci        continue;
1356370b324cSopenharmony_ci      price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
1357370b324cSopenharmony_ci      do
1358370b324cSopenharmony_ci      {
1359370b324cSopenharmony_ci        UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);
1360370b324cSopenharmony_ci        COptimal *opt = &p->opt[repLen];
1361370b324cSopenharmony_ci        if (price2 < opt->price)
1362370b324cSopenharmony_ci        {
1363370b324cSopenharmony_ci          opt->price = price2;
1364370b324cSopenharmony_ci          opt->len = (UInt32)repLen;
1365370b324cSopenharmony_ci          opt->dist = (UInt32)i;
1366370b324cSopenharmony_ci          opt->extra = 0;
1367370b324cSopenharmony_ci        }
1368370b324cSopenharmony_ci      }
1369370b324cSopenharmony_ci      while (--repLen >= 2);
1370370b324cSopenharmony_ci    }
1371370b324cSopenharmony_ci
1372370b324cSopenharmony_ci
1373370b324cSopenharmony_ci    // ---------- MATCH ----------
1374370b324cSopenharmony_ci    {
1375370b324cSopenharmony_ci      unsigned len = repLens[0] + 1;
1376370b324cSopenharmony_ci      if (len <= mainLen)
1377370b324cSopenharmony_ci      {
1378370b324cSopenharmony_ci        unsigned offs = 0;
1379370b324cSopenharmony_ci        UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
1380370b324cSopenharmony_ci
1381370b324cSopenharmony_ci        if (len < 2)
1382370b324cSopenharmony_ci          len = 2;
1383370b324cSopenharmony_ci        else
1384370b324cSopenharmony_ci          while (len > MATCHES[offs])
1385370b324cSopenharmony_ci            offs += 2;
1386370b324cSopenharmony_ci
1387370b324cSopenharmony_ci        for (; ; len++)
1388370b324cSopenharmony_ci        {
1389370b324cSopenharmony_ci          COptimal *opt;
1390370b324cSopenharmony_ci          UInt32 dist = MATCHES[(size_t)offs + 1];
1391370b324cSopenharmony_ci          UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
1392370b324cSopenharmony_ci          unsigned lenToPosState = GetLenToPosState(len);
1393370b324cSopenharmony_ci
1394370b324cSopenharmony_ci          if (dist < kNumFullDistances)
1395370b324cSopenharmony_ci            price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
1396370b324cSopenharmony_ci          else
1397370b324cSopenharmony_ci          {
1398370b324cSopenharmony_ci            unsigned slot;
1399370b324cSopenharmony_ci            GetPosSlot2(dist, slot)
1400370b324cSopenharmony_ci            price += p->alignPrices[dist & kAlignMask];
1401370b324cSopenharmony_ci            price += p->posSlotPrices[lenToPosState][slot];
1402370b324cSopenharmony_ci          }
1403370b324cSopenharmony_ci
1404370b324cSopenharmony_ci          opt = &p->opt[len];
1405370b324cSopenharmony_ci
1406370b324cSopenharmony_ci          if (price < opt->price)
1407370b324cSopenharmony_ci          {
1408370b324cSopenharmony_ci            opt->price = price;
1409370b324cSopenharmony_ci            opt->len = (UInt32)len;
1410370b324cSopenharmony_ci            opt->dist = dist + LZMA_NUM_REPS;
1411370b324cSopenharmony_ci            opt->extra = 0;
1412370b324cSopenharmony_ci          }
1413370b324cSopenharmony_ci
1414370b324cSopenharmony_ci          if (len == MATCHES[offs])
1415370b324cSopenharmony_ci          {
1416370b324cSopenharmony_ci            offs += 2;
1417370b324cSopenharmony_ci            if (offs == numPairs)
1418370b324cSopenharmony_ci              break;
1419370b324cSopenharmony_ci          }
1420370b324cSopenharmony_ci        }
1421370b324cSopenharmony_ci      }
1422370b324cSopenharmony_ci    }
1423370b324cSopenharmony_ci
1424370b324cSopenharmony_ci
1425370b324cSopenharmony_ci    cur = 0;
1426370b324cSopenharmony_ci
1427370b324cSopenharmony_ci    #ifdef SHOW_STAT2
1428370b324cSopenharmony_ci    /* if (position >= 0) */
1429370b324cSopenharmony_ci    {
1430370b324cSopenharmony_ci      unsigned i;
1431370b324cSopenharmony_ci      printf("\n pos = %4X", position);
1432370b324cSopenharmony_ci      for (i = cur; i <= last; i++)
1433370b324cSopenharmony_ci      printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
1434370b324cSopenharmony_ci    }
1435370b324cSopenharmony_ci    #endif
1436370b324cSopenharmony_ci  }
1437370b324cSopenharmony_ci
1438370b324cSopenharmony_ci
1439370b324cSopenharmony_ci
1440370b324cSopenharmony_ci  // ---------- Optimal Parsing ----------
1441370b324cSopenharmony_ci
1442370b324cSopenharmony_ci  for (;;)
1443370b324cSopenharmony_ci  {
1444370b324cSopenharmony_ci    unsigned numAvail;
1445370b324cSopenharmony_ci    UInt32 numAvailFull;
1446370b324cSopenharmony_ci    unsigned newLen, numPairs, prev, state, posState, startLen;
1447370b324cSopenharmony_ci    UInt32 litPrice, matchPrice, repMatchPrice;
1448370b324cSopenharmony_ci    BoolInt nextIsLit;
1449370b324cSopenharmony_ci    Byte curByte, matchByte;
1450370b324cSopenharmony_ci    const Byte *data;
1451370b324cSopenharmony_ci    COptimal *curOpt, *nextOpt;
1452370b324cSopenharmony_ci
1453370b324cSopenharmony_ci    if (++cur == last)
1454370b324cSopenharmony_ci      break;
1455370b324cSopenharmony_ci
1456370b324cSopenharmony_ci    // 18.06
1457370b324cSopenharmony_ci    if (cur >= kNumOpts - 64)
1458370b324cSopenharmony_ci    {
1459370b324cSopenharmony_ci      unsigned j, best;
1460370b324cSopenharmony_ci      UInt32 price = p->opt[cur].price;
1461370b324cSopenharmony_ci      best = cur;
1462370b324cSopenharmony_ci      for (j = cur + 1; j <= last; j++)
1463370b324cSopenharmony_ci      {
1464370b324cSopenharmony_ci        UInt32 price2 = p->opt[j].price;
1465370b324cSopenharmony_ci        if (price >= price2)
1466370b324cSopenharmony_ci        {
1467370b324cSopenharmony_ci          price = price2;
1468370b324cSopenharmony_ci          best = j;
1469370b324cSopenharmony_ci        }
1470370b324cSopenharmony_ci      }
1471370b324cSopenharmony_ci      {
1472370b324cSopenharmony_ci        unsigned delta = best - cur;
1473370b324cSopenharmony_ci        if (delta != 0)
1474370b324cSopenharmony_ci        {
1475370b324cSopenharmony_ci          MOVE_POS(p, delta)
1476370b324cSopenharmony_ci        }
1477370b324cSopenharmony_ci      }
1478370b324cSopenharmony_ci      cur = best;
1479370b324cSopenharmony_ci      break;
1480370b324cSopenharmony_ci    }
1481370b324cSopenharmony_ci
1482370b324cSopenharmony_ci    newLen = ReadMatchDistances(p, &numPairs);
1483370b324cSopenharmony_ci
1484370b324cSopenharmony_ci    if (newLen >= p->numFastBytes)
1485370b324cSopenharmony_ci    {
1486370b324cSopenharmony_ci      p->numPairs = numPairs;
1487370b324cSopenharmony_ci      p->longestMatchLen = newLen;
1488370b324cSopenharmony_ci      break;
1489370b324cSopenharmony_ci    }
1490370b324cSopenharmony_ci
1491370b324cSopenharmony_ci    curOpt = &p->opt[cur];
1492370b324cSopenharmony_ci
1493370b324cSopenharmony_ci    position++;
1494370b324cSopenharmony_ci
1495370b324cSopenharmony_ci    // we need that check here, if skip_items in p->opt are possible
1496370b324cSopenharmony_ci    /*
1497370b324cSopenharmony_ci    if (curOpt->price >= kInfinityPrice)
1498370b324cSopenharmony_ci      continue;
1499370b324cSopenharmony_ci    */
1500370b324cSopenharmony_ci
1501370b324cSopenharmony_ci    prev = cur - curOpt->len;
1502370b324cSopenharmony_ci
1503370b324cSopenharmony_ci    if (curOpt->len == 1)
1504370b324cSopenharmony_ci    {
1505370b324cSopenharmony_ci      state = (unsigned)p->opt[prev].state;
1506370b324cSopenharmony_ci      if (IsShortRep(curOpt))
1507370b324cSopenharmony_ci        state = kShortRepNextStates[state];
1508370b324cSopenharmony_ci      else
1509370b324cSopenharmony_ci        state = kLiteralNextStates[state];
1510370b324cSopenharmony_ci    }
1511370b324cSopenharmony_ci    else
1512370b324cSopenharmony_ci    {
1513370b324cSopenharmony_ci      const COptimal *prevOpt;
1514370b324cSopenharmony_ci      UInt32 b0;
1515370b324cSopenharmony_ci      UInt32 dist = curOpt->dist;
1516370b324cSopenharmony_ci
1517370b324cSopenharmony_ci      if (curOpt->extra)
1518370b324cSopenharmony_ci      {
1519370b324cSopenharmony_ci        prev -= (unsigned)curOpt->extra;
1520370b324cSopenharmony_ci        state = kState_RepAfterLit;
1521370b324cSopenharmony_ci        if (curOpt->extra == 1)
1522370b324cSopenharmony_ci          state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);
1523370b324cSopenharmony_ci      }
1524370b324cSopenharmony_ci      else
1525370b324cSopenharmony_ci      {
1526370b324cSopenharmony_ci        state = (unsigned)p->opt[prev].state;
1527370b324cSopenharmony_ci        if (dist < LZMA_NUM_REPS)
1528370b324cSopenharmony_ci          state = kRepNextStates[state];
1529370b324cSopenharmony_ci        else
1530370b324cSopenharmony_ci          state = kMatchNextStates[state];
1531370b324cSopenharmony_ci      }
1532370b324cSopenharmony_ci
1533370b324cSopenharmony_ci      prevOpt = &p->opt[prev];
1534370b324cSopenharmony_ci      b0 = prevOpt->reps[0];
1535370b324cSopenharmony_ci
1536370b324cSopenharmony_ci      if (dist < LZMA_NUM_REPS)
1537370b324cSopenharmony_ci      {
1538370b324cSopenharmony_ci        if (dist == 0)
1539370b324cSopenharmony_ci        {
1540370b324cSopenharmony_ci          reps[0] = b0;
1541370b324cSopenharmony_ci          reps[1] = prevOpt->reps[1];
1542370b324cSopenharmony_ci          reps[2] = prevOpt->reps[2];
1543370b324cSopenharmony_ci          reps[3] = prevOpt->reps[3];
1544370b324cSopenharmony_ci        }
1545370b324cSopenharmony_ci        else
1546370b324cSopenharmony_ci        {
1547370b324cSopenharmony_ci          reps[1] = b0;
1548370b324cSopenharmony_ci          b0 = prevOpt->reps[1];
1549370b324cSopenharmony_ci          if (dist == 1)
1550370b324cSopenharmony_ci          {
1551370b324cSopenharmony_ci            reps[0] = b0;
1552370b324cSopenharmony_ci            reps[2] = prevOpt->reps[2];
1553370b324cSopenharmony_ci            reps[3] = prevOpt->reps[3];
1554370b324cSopenharmony_ci          }
1555370b324cSopenharmony_ci          else
1556370b324cSopenharmony_ci          {
1557370b324cSopenharmony_ci            reps[2] = b0;
1558370b324cSopenharmony_ci            reps[0] = prevOpt->reps[dist];
1559370b324cSopenharmony_ci            reps[3] = prevOpt->reps[dist ^ 1];
1560370b324cSopenharmony_ci          }
1561370b324cSopenharmony_ci        }
1562370b324cSopenharmony_ci      }
1563370b324cSopenharmony_ci      else
1564370b324cSopenharmony_ci      {
1565370b324cSopenharmony_ci        reps[0] = (dist - LZMA_NUM_REPS + 1);
1566370b324cSopenharmony_ci        reps[1] = b0;
1567370b324cSopenharmony_ci        reps[2] = prevOpt->reps[1];
1568370b324cSopenharmony_ci        reps[3] = prevOpt->reps[2];
1569370b324cSopenharmony_ci      }
1570370b324cSopenharmony_ci    }
1571370b324cSopenharmony_ci
1572370b324cSopenharmony_ci    curOpt->state = (CState)state;
1573370b324cSopenharmony_ci    curOpt->reps[0] = reps[0];
1574370b324cSopenharmony_ci    curOpt->reps[1] = reps[1];
1575370b324cSopenharmony_ci    curOpt->reps[2] = reps[2];
1576370b324cSopenharmony_ci    curOpt->reps[3] = reps[3];
1577370b324cSopenharmony_ci
1578370b324cSopenharmony_ci    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1579370b324cSopenharmony_ci    curByte = *data;
1580370b324cSopenharmony_ci    matchByte = *(data - reps[0]);
1581370b324cSopenharmony_ci
1582370b324cSopenharmony_ci    posState = (position & p->pbMask);
1583370b324cSopenharmony_ci
1584370b324cSopenharmony_ci    /*
1585370b324cSopenharmony_ci    The order of Price checks:
1586370b324cSopenharmony_ci       <  LIT
1587370b324cSopenharmony_ci       <= SHORT_REP
1588370b324cSopenharmony_ci       <  LIT : REP_0
1589370b324cSopenharmony_ci       <  REP    [ : LIT : REP_0 ]
1590370b324cSopenharmony_ci       <  MATCH  [ : LIT : REP_0 ]
1591370b324cSopenharmony_ci    */
1592370b324cSopenharmony_ci
1593370b324cSopenharmony_ci    {
1594370b324cSopenharmony_ci      UInt32 curPrice = curOpt->price;
1595370b324cSopenharmony_ci      unsigned prob = p->isMatch[state][posState];
1596370b324cSopenharmony_ci      matchPrice = curPrice + GET_PRICE_1(prob);
1597370b324cSopenharmony_ci      litPrice = curPrice + GET_PRICE_0(prob);
1598370b324cSopenharmony_ci    }
1599370b324cSopenharmony_ci
1600370b324cSopenharmony_ci    nextOpt = &p->opt[(size_t)cur + 1];
1601370b324cSopenharmony_ci    nextIsLit = False;
1602370b324cSopenharmony_ci
1603370b324cSopenharmony_ci    // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)
1604370b324cSopenharmony_ci    // 18.new.06
1605370b324cSopenharmony_ci    if ((nextOpt->price < kInfinityPrice
1606370b324cSopenharmony_ci        // && !IsLitState(state)
1607370b324cSopenharmony_ci        && matchByte == curByte)
1608370b324cSopenharmony_ci        || litPrice > nextOpt->price
1609370b324cSopenharmony_ci        )
1610370b324cSopenharmony_ci      litPrice = 0;
1611370b324cSopenharmony_ci    else
1612370b324cSopenharmony_ci    {
1613370b324cSopenharmony_ci      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1614370b324cSopenharmony_ci      litPrice += (!IsLitState(state) ?
1615370b324cSopenharmony_ci          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1616370b324cSopenharmony_ci          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1617370b324cSopenharmony_ci
1618370b324cSopenharmony_ci      if (litPrice < nextOpt->price)
1619370b324cSopenharmony_ci      {
1620370b324cSopenharmony_ci        nextOpt->price = litPrice;
1621370b324cSopenharmony_ci        nextOpt->len = 1;
1622370b324cSopenharmony_ci        MakeAs_Lit(nextOpt)
1623370b324cSopenharmony_ci        nextIsLit = True;
1624370b324cSopenharmony_ci      }
1625370b324cSopenharmony_ci    }
1626370b324cSopenharmony_ci
1627370b324cSopenharmony_ci    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
1628370b324cSopenharmony_ci
1629370b324cSopenharmony_ci    numAvailFull = p->numAvail;
1630370b324cSopenharmony_ci    {
1631370b324cSopenharmony_ci      unsigned temp = kNumOpts - 1 - cur;
1632370b324cSopenharmony_ci      if (numAvailFull > temp)
1633370b324cSopenharmony_ci        numAvailFull = (UInt32)temp;
1634370b324cSopenharmony_ci    }
1635370b324cSopenharmony_ci
1636370b324cSopenharmony_ci    // 18.06
1637370b324cSopenharmony_ci    // ---------- SHORT_REP ----------
1638370b324cSopenharmony_ci    if (IsLitState(state)) // 18.new
1639370b324cSopenharmony_ci    if (matchByte == curByte)
1640370b324cSopenharmony_ci    if (repMatchPrice < nextOpt->price) // 18.new
1641370b324cSopenharmony_ci    // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))
1642370b324cSopenharmony_ci    if (
1643370b324cSopenharmony_ci        // nextOpt->price >= kInfinityPrice ||
1644370b324cSopenharmony_ci        nextOpt->len < 2   // we can check nextOpt->len, if skip items are not allowed in p->opt
1645370b324cSopenharmony_ci        || (nextOpt->dist != 0
1646370b324cSopenharmony_ci            // && nextOpt->extra <= 1 // 17.old
1647370b324cSopenharmony_ci            )
1648370b324cSopenharmony_ci        )
1649370b324cSopenharmony_ci    {
1650370b324cSopenharmony_ci      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
1651370b324cSopenharmony_ci      // if (shortRepPrice <= nextOpt->price) // 17.old
1652370b324cSopenharmony_ci      if (shortRepPrice < nextOpt->price)  // 18.new
1653370b324cSopenharmony_ci      {
1654370b324cSopenharmony_ci        nextOpt->price = shortRepPrice;
1655370b324cSopenharmony_ci        nextOpt->len = 1;
1656370b324cSopenharmony_ci        MakeAs_ShortRep(nextOpt)
1657370b324cSopenharmony_ci        nextIsLit = False;
1658370b324cSopenharmony_ci      }
1659370b324cSopenharmony_ci    }
1660370b324cSopenharmony_ci
1661370b324cSopenharmony_ci    if (numAvailFull < 2)
1662370b324cSopenharmony_ci      continue;
1663370b324cSopenharmony_ci    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
1664370b324cSopenharmony_ci
1665370b324cSopenharmony_ci    // numAvail <= p->numFastBytes
1666370b324cSopenharmony_ci
1667370b324cSopenharmony_ci    // ---------- LIT : REP_0 ----------
1668370b324cSopenharmony_ci
1669370b324cSopenharmony_ci    if (!nextIsLit
1670370b324cSopenharmony_ci        && litPrice != 0 // 18.new
1671370b324cSopenharmony_ci        && matchByte != curByte
1672370b324cSopenharmony_ci        && numAvailFull > 2)
1673370b324cSopenharmony_ci    {
1674370b324cSopenharmony_ci      const Byte *data2 = data - reps[0];
1675370b324cSopenharmony_ci      if (data[1] == data2[1] && data[2] == data2[2])
1676370b324cSopenharmony_ci      {
1677370b324cSopenharmony_ci        unsigned len;
1678370b324cSopenharmony_ci        unsigned limit = p->numFastBytes + 1;
1679370b324cSopenharmony_ci        if (limit > numAvailFull)
1680370b324cSopenharmony_ci          limit = numAvailFull;
1681370b324cSopenharmony_ci        for (len = 3; len < limit && data[len] == data2[len]; len++)
1682370b324cSopenharmony_ci        {}
1683370b324cSopenharmony_ci
1684370b324cSopenharmony_ci        {
1685370b324cSopenharmony_ci          unsigned state2 = kLiteralNextStates[state];
1686370b324cSopenharmony_ci          unsigned posState2 = (position + 1) & p->pbMask;
1687370b324cSopenharmony_ci          UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
1688370b324cSopenharmony_ci          {
1689370b324cSopenharmony_ci            unsigned offset = cur + len;
1690370b324cSopenharmony_ci
1691370b324cSopenharmony_ci            if (last < offset)
1692370b324cSopenharmony_ci              last = offset;
1693370b324cSopenharmony_ci
1694370b324cSopenharmony_ci            // do
1695370b324cSopenharmony_ci            {
1696370b324cSopenharmony_ci              UInt32 price2;
1697370b324cSopenharmony_ci              COptimal *opt;
1698370b324cSopenharmony_ci              len--;
1699370b324cSopenharmony_ci              // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
1700370b324cSopenharmony_ci              price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);
1701370b324cSopenharmony_ci
1702370b324cSopenharmony_ci              opt = &p->opt[offset];
1703370b324cSopenharmony_ci              // offset--;
1704370b324cSopenharmony_ci              if (price2 < opt->price)
1705370b324cSopenharmony_ci              {
1706370b324cSopenharmony_ci                opt->price = price2;
1707370b324cSopenharmony_ci                opt->len = (UInt32)len;
1708370b324cSopenharmony_ci                opt->dist = 0;
1709370b324cSopenharmony_ci                opt->extra = 1;
1710370b324cSopenharmony_ci              }
1711370b324cSopenharmony_ci            }
1712370b324cSopenharmony_ci            // while (len >= 3);
1713370b324cSopenharmony_ci          }
1714370b324cSopenharmony_ci        }
1715370b324cSopenharmony_ci      }
1716370b324cSopenharmony_ci    }
1717370b324cSopenharmony_ci
1718370b324cSopenharmony_ci    startLen = 2; /* speed optimization */
1719370b324cSopenharmony_ci
1720370b324cSopenharmony_ci    {
1721370b324cSopenharmony_ci      // ---------- REP ----------
1722370b324cSopenharmony_ci      unsigned repIndex = 0; // 17.old
1723370b324cSopenharmony_ci      // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
1724370b324cSopenharmony_ci      for (; repIndex < LZMA_NUM_REPS; repIndex++)
1725370b324cSopenharmony_ci      {
1726370b324cSopenharmony_ci        unsigned len;
1727370b324cSopenharmony_ci        UInt32 price;
1728370b324cSopenharmony_ci        const Byte *data2 = data - reps[repIndex];
1729370b324cSopenharmony_ci        if (data[0] != data2[0] || data[1] != data2[1])
1730370b324cSopenharmony_ci          continue;
1731370b324cSopenharmony_ci
1732370b324cSopenharmony_ci        for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1733370b324cSopenharmony_ci        {}
1734370b324cSopenharmony_ci
1735370b324cSopenharmony_ci        // if (len < startLen) continue; // 18.new: speed optimization
1736370b324cSopenharmony_ci
1737370b324cSopenharmony_ci        {
1738370b324cSopenharmony_ci          unsigned offset = cur + len;
1739370b324cSopenharmony_ci          if (last < offset)
1740370b324cSopenharmony_ci            last = offset;
1741370b324cSopenharmony_ci        }
1742370b324cSopenharmony_ci        {
1743370b324cSopenharmony_ci          unsigned len2 = len;
1744370b324cSopenharmony_ci          price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
1745370b324cSopenharmony_ci          do
1746370b324cSopenharmony_ci          {
1747370b324cSopenharmony_ci            UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);
1748370b324cSopenharmony_ci            COptimal *opt = &p->opt[cur + len2];
1749370b324cSopenharmony_ci            if (price2 < opt->price)
1750370b324cSopenharmony_ci            {
1751370b324cSopenharmony_ci              opt->price = price2;
1752370b324cSopenharmony_ci              opt->len = (UInt32)len2;
1753370b324cSopenharmony_ci              opt->dist = (UInt32)repIndex;
1754370b324cSopenharmony_ci              opt->extra = 0;
1755370b324cSopenharmony_ci            }
1756370b324cSopenharmony_ci          }
1757370b324cSopenharmony_ci          while (--len2 >= 2);
1758370b324cSopenharmony_ci        }
1759370b324cSopenharmony_ci
1760370b324cSopenharmony_ci        if (repIndex == 0) startLen = len + 1;  // 17.old
1761370b324cSopenharmony_ci        // startLen = len + 1; // 18.new
1762370b324cSopenharmony_ci
1763370b324cSopenharmony_ci        /* if (_maxMode) */
1764370b324cSopenharmony_ci        {
1765370b324cSopenharmony_ci          // ---------- REP : LIT : REP_0 ----------
1766370b324cSopenharmony_ci          // numFastBytes + 1 + numFastBytes
1767370b324cSopenharmony_ci
1768370b324cSopenharmony_ci          unsigned len2 = len + 1;
1769370b324cSopenharmony_ci          unsigned limit = len2 + p->numFastBytes;
1770370b324cSopenharmony_ci          if (limit > numAvailFull)
1771370b324cSopenharmony_ci            limit = numAvailFull;
1772370b324cSopenharmony_ci
1773370b324cSopenharmony_ci          len2 += 2;
1774370b324cSopenharmony_ci          if (len2 <= limit)
1775370b324cSopenharmony_ci          if (data[len2 - 2] == data2[len2 - 2])
1776370b324cSopenharmony_ci          if (data[len2 - 1] == data2[len2 - 1])
1777370b324cSopenharmony_ci          {
1778370b324cSopenharmony_ci            unsigned state2 = kRepNextStates[state];
1779370b324cSopenharmony_ci            unsigned posState2 = (position + len) & p->pbMask;
1780370b324cSopenharmony_ci            price += GET_PRICE_LEN(&p->repLenEnc, posState, len)
1781370b324cSopenharmony_ci                + GET_PRICE_0(p->isMatch[state2][posState2])
1782370b324cSopenharmony_ci                + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1783370b324cSopenharmony_ci                    data[len], data2[len], p->ProbPrices);
1784370b324cSopenharmony_ci
1785370b324cSopenharmony_ci            // state2 = kLiteralNextStates[state2];
1786370b324cSopenharmony_ci            state2 = kState_LitAfterRep;
1787370b324cSopenharmony_ci            posState2 = (posState2 + 1) & p->pbMask;
1788370b324cSopenharmony_ci
1789370b324cSopenharmony_ci
1790370b324cSopenharmony_ci            price += GetPrice_Rep_0(p, state2, posState2);
1791370b324cSopenharmony_ci
1792370b324cSopenharmony_ci          for (; len2 < limit && data[len2] == data2[len2]; len2++)
1793370b324cSopenharmony_ci          {}
1794370b324cSopenharmony_ci
1795370b324cSopenharmony_ci          len2 -= len;
1796370b324cSopenharmony_ci          // if (len2 >= 3)
1797370b324cSopenharmony_ci          {
1798370b324cSopenharmony_ci            {
1799370b324cSopenharmony_ci              unsigned offset = cur + len + len2;
1800370b324cSopenharmony_ci
1801370b324cSopenharmony_ci              if (last < offset)
1802370b324cSopenharmony_ci                last = offset;
1803370b324cSopenharmony_ci              // do
1804370b324cSopenharmony_ci              {
1805370b324cSopenharmony_ci                UInt32 price2;
1806370b324cSopenharmony_ci                COptimal *opt;
1807370b324cSopenharmony_ci                len2--;
1808370b324cSopenharmony_ci                // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1809370b324cSopenharmony_ci                price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
1810370b324cSopenharmony_ci
1811370b324cSopenharmony_ci                opt = &p->opt[offset];
1812370b324cSopenharmony_ci                // offset--;
1813370b324cSopenharmony_ci                if (price2 < opt->price)
1814370b324cSopenharmony_ci                {
1815370b324cSopenharmony_ci                  opt->price = price2;
1816370b324cSopenharmony_ci                  opt->len = (UInt32)len2;
1817370b324cSopenharmony_ci                  opt->extra = (CExtra)(len + 1);
1818370b324cSopenharmony_ci                  opt->dist = (UInt32)repIndex;
1819370b324cSopenharmony_ci                }
1820370b324cSopenharmony_ci              }
1821370b324cSopenharmony_ci              // while (len2 >= 3);
1822370b324cSopenharmony_ci            }
1823370b324cSopenharmony_ci          }
1824370b324cSopenharmony_ci          }
1825370b324cSopenharmony_ci        }
1826370b324cSopenharmony_ci      }
1827370b324cSopenharmony_ci    }
1828370b324cSopenharmony_ci
1829370b324cSopenharmony_ci
1830370b324cSopenharmony_ci    // ---------- MATCH ----------
1831370b324cSopenharmony_ci    /* for (unsigned len = 2; len <= newLen; len++) */
1832370b324cSopenharmony_ci    if (newLen > numAvail)
1833370b324cSopenharmony_ci    {
1834370b324cSopenharmony_ci      newLen = numAvail;
1835370b324cSopenharmony_ci      for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2);
1836370b324cSopenharmony_ci      MATCHES[numPairs] = (UInt32)newLen;
1837370b324cSopenharmony_ci      numPairs += 2;
1838370b324cSopenharmony_ci    }
1839370b324cSopenharmony_ci
1840370b324cSopenharmony_ci    // startLen = 2; /* speed optimization */
1841370b324cSopenharmony_ci
1842370b324cSopenharmony_ci    if (newLen >= startLen)
1843370b324cSopenharmony_ci    {
1844370b324cSopenharmony_ci      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
1845370b324cSopenharmony_ci      UInt32 dist;
1846370b324cSopenharmony_ci      unsigned offs, posSlot, len;
1847370b324cSopenharmony_ci
1848370b324cSopenharmony_ci      {
1849370b324cSopenharmony_ci        unsigned offset = cur + newLen;
1850370b324cSopenharmony_ci        if (last < offset)
1851370b324cSopenharmony_ci          last = offset;
1852370b324cSopenharmony_ci      }
1853370b324cSopenharmony_ci
1854370b324cSopenharmony_ci      offs = 0;
1855370b324cSopenharmony_ci      while (startLen > MATCHES[offs])
1856370b324cSopenharmony_ci        offs += 2;
1857370b324cSopenharmony_ci      dist = MATCHES[(size_t)offs + 1];
1858370b324cSopenharmony_ci
1859370b324cSopenharmony_ci      // if (dist >= kNumFullDistances)
1860370b324cSopenharmony_ci      GetPosSlot2(dist, posSlot)
1861370b324cSopenharmony_ci
1862370b324cSopenharmony_ci      for (len = /*2*/ startLen; ; len++)
1863370b324cSopenharmony_ci      {
1864370b324cSopenharmony_ci        UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
1865370b324cSopenharmony_ci        {
1866370b324cSopenharmony_ci          COptimal *opt;
1867370b324cSopenharmony_ci          unsigned lenNorm = len - 2;
1868370b324cSopenharmony_ci          lenNorm = GetLenToPosState2(lenNorm);
1869370b324cSopenharmony_ci          if (dist < kNumFullDistances)
1870370b324cSopenharmony_ci            price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];
1871370b324cSopenharmony_ci          else
1872370b324cSopenharmony_ci            price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];
1873370b324cSopenharmony_ci
1874370b324cSopenharmony_ci          opt = &p->opt[cur + len];
1875370b324cSopenharmony_ci          if (price < opt->price)
1876370b324cSopenharmony_ci          {
1877370b324cSopenharmony_ci            opt->price = price;
1878370b324cSopenharmony_ci            opt->len = (UInt32)len;
1879370b324cSopenharmony_ci            opt->dist = dist + LZMA_NUM_REPS;
1880370b324cSopenharmony_ci            opt->extra = 0;
1881370b324cSopenharmony_ci          }
1882370b324cSopenharmony_ci        }
1883370b324cSopenharmony_ci
1884370b324cSopenharmony_ci        if (len == MATCHES[offs])
1885370b324cSopenharmony_ci        {
1886370b324cSopenharmony_ci          // if (p->_maxMode) {
1887370b324cSopenharmony_ci          // MATCH : LIT : REP_0
1888370b324cSopenharmony_ci
1889370b324cSopenharmony_ci          const Byte *data2 = data - dist - 1;
1890370b324cSopenharmony_ci          unsigned len2 = len + 1;
1891370b324cSopenharmony_ci          unsigned limit = len2 + p->numFastBytes;
1892370b324cSopenharmony_ci          if (limit > numAvailFull)
1893370b324cSopenharmony_ci            limit = numAvailFull;
1894370b324cSopenharmony_ci
1895370b324cSopenharmony_ci          len2 += 2;
1896370b324cSopenharmony_ci          if (len2 <= limit)
1897370b324cSopenharmony_ci          if (data[len2 - 2] == data2[len2 - 2])
1898370b324cSopenharmony_ci          if (data[len2 - 1] == data2[len2 - 1])
1899370b324cSopenharmony_ci          {
1900370b324cSopenharmony_ci          for (; len2 < limit && data[len2] == data2[len2]; len2++)
1901370b324cSopenharmony_ci          {}
1902370b324cSopenharmony_ci
1903370b324cSopenharmony_ci          len2 -= len;
1904370b324cSopenharmony_ci
1905370b324cSopenharmony_ci          // if (len2 >= 3)
1906370b324cSopenharmony_ci          {
1907370b324cSopenharmony_ci            unsigned state2 = kMatchNextStates[state];
1908370b324cSopenharmony_ci            unsigned posState2 = (position + len) & p->pbMask;
1909370b324cSopenharmony_ci            unsigned offset;
1910370b324cSopenharmony_ci            price += GET_PRICE_0(p->isMatch[state2][posState2]);
1911370b324cSopenharmony_ci            price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1912370b324cSopenharmony_ci                    data[len], data2[len], p->ProbPrices);
1913370b324cSopenharmony_ci
1914370b324cSopenharmony_ci            // state2 = kLiteralNextStates[state2];
1915370b324cSopenharmony_ci            state2 = kState_LitAfterMatch;
1916370b324cSopenharmony_ci
1917370b324cSopenharmony_ci            posState2 = (posState2 + 1) & p->pbMask;
1918370b324cSopenharmony_ci            price += GetPrice_Rep_0(p, state2, posState2);
1919370b324cSopenharmony_ci
1920370b324cSopenharmony_ci            offset = cur + len + len2;
1921370b324cSopenharmony_ci
1922370b324cSopenharmony_ci            if (last < offset)
1923370b324cSopenharmony_ci              last = offset;
1924370b324cSopenharmony_ci            // do
1925370b324cSopenharmony_ci            {
1926370b324cSopenharmony_ci              UInt32 price2;
1927370b324cSopenharmony_ci              COptimal *opt;
1928370b324cSopenharmony_ci              len2--;
1929370b324cSopenharmony_ci              // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1930370b324cSopenharmony_ci              price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
1931370b324cSopenharmony_ci              opt = &p->opt[offset];
1932370b324cSopenharmony_ci              // offset--;
1933370b324cSopenharmony_ci              if (price2 < opt->price)
1934370b324cSopenharmony_ci              {
1935370b324cSopenharmony_ci                opt->price = price2;
1936370b324cSopenharmony_ci                opt->len = (UInt32)len2;
1937370b324cSopenharmony_ci                opt->extra = (CExtra)(len + 1);
1938370b324cSopenharmony_ci                opt->dist = dist + LZMA_NUM_REPS;
1939370b324cSopenharmony_ci              }
1940370b324cSopenharmony_ci            }
1941370b324cSopenharmony_ci            // while (len2 >= 3);
1942370b324cSopenharmony_ci          }
1943370b324cSopenharmony_ci
1944370b324cSopenharmony_ci          }
1945370b324cSopenharmony_ci
1946370b324cSopenharmony_ci          offs += 2;
1947370b324cSopenharmony_ci          if (offs == numPairs)
1948370b324cSopenharmony_ci            break;
1949370b324cSopenharmony_ci          dist = MATCHES[(size_t)offs + 1];
1950370b324cSopenharmony_ci          // if (dist >= kNumFullDistances)
1951370b324cSopenharmony_ci            GetPosSlot2(dist, posSlot)
1952370b324cSopenharmony_ci        }
1953370b324cSopenharmony_ci      }
1954370b324cSopenharmony_ci    }
1955370b324cSopenharmony_ci  }
1956370b324cSopenharmony_ci
1957370b324cSopenharmony_ci  do
1958370b324cSopenharmony_ci    p->opt[last].price = kInfinityPrice;
1959370b324cSopenharmony_ci  while (--last);
1960370b324cSopenharmony_ci
1961370b324cSopenharmony_ci  return Backward(p, cur);
1962370b324cSopenharmony_ci}
1963370b324cSopenharmony_ci
1964370b324cSopenharmony_ci
1965370b324cSopenharmony_ci
1966370b324cSopenharmony_ci#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1967370b324cSopenharmony_ci
1968370b324cSopenharmony_ci
1969370b324cSopenharmony_ci
1970370b324cSopenharmony_cistatic unsigned GetOptimumFast(CLzmaEnc *p)
1971370b324cSopenharmony_ci{
1972370b324cSopenharmony_ci  UInt32 numAvail, mainDist;
1973370b324cSopenharmony_ci  unsigned mainLen, numPairs, repIndex, repLen, i;
1974370b324cSopenharmony_ci  const Byte *data;
1975370b324cSopenharmony_ci
1976370b324cSopenharmony_ci  if (p->additionalOffset == 0)
1977370b324cSopenharmony_ci    mainLen = ReadMatchDistances(p, &numPairs);
1978370b324cSopenharmony_ci  else
1979370b324cSopenharmony_ci  {
1980370b324cSopenharmony_ci    mainLen = p->longestMatchLen;
1981370b324cSopenharmony_ci    numPairs = p->numPairs;
1982370b324cSopenharmony_ci  }
1983370b324cSopenharmony_ci
1984370b324cSopenharmony_ci  numAvail = p->numAvail;
1985370b324cSopenharmony_ci  p->backRes = MARK_LIT;
1986370b324cSopenharmony_ci  if (numAvail < 2)
1987370b324cSopenharmony_ci    return 1;
1988370b324cSopenharmony_ci  // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused
1989370b324cSopenharmony_ci  if (numAvail > LZMA_MATCH_LEN_MAX)
1990370b324cSopenharmony_ci    numAvail = LZMA_MATCH_LEN_MAX;
1991370b324cSopenharmony_ci  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1992370b324cSopenharmony_ci  repLen = repIndex = 0;
1993370b324cSopenharmony_ci
1994370b324cSopenharmony_ci  for (i = 0; i < LZMA_NUM_REPS; i++)
1995370b324cSopenharmony_ci  {
1996370b324cSopenharmony_ci    unsigned len;
1997370b324cSopenharmony_ci    const Byte *data2 = data - p->reps[i];
1998370b324cSopenharmony_ci    if (data[0] != data2[0] || data[1] != data2[1])
1999370b324cSopenharmony_ci      continue;
2000370b324cSopenharmony_ci    for (len = 2; len < numAvail && data[len] == data2[len]; len++)
2001370b324cSopenharmony_ci    {}
2002370b324cSopenharmony_ci    if (len >= p->numFastBytes)
2003370b324cSopenharmony_ci    {
2004370b324cSopenharmony_ci      p->backRes = (UInt32)i;
2005370b324cSopenharmony_ci      MOVE_POS(p, len - 1)
2006370b324cSopenharmony_ci      return len;
2007370b324cSopenharmony_ci    }
2008370b324cSopenharmony_ci    if (len > repLen)
2009370b324cSopenharmony_ci    {
2010370b324cSopenharmony_ci      repIndex = i;
2011370b324cSopenharmony_ci      repLen = len;
2012370b324cSopenharmony_ci    }
2013370b324cSopenharmony_ci  }
2014370b324cSopenharmony_ci
2015370b324cSopenharmony_ci  if (mainLen >= p->numFastBytes)
2016370b324cSopenharmony_ci  {
2017370b324cSopenharmony_ci    p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
2018370b324cSopenharmony_ci    MOVE_POS(p, mainLen - 1)
2019370b324cSopenharmony_ci    return mainLen;
2020370b324cSopenharmony_ci  }
2021370b324cSopenharmony_ci
2022370b324cSopenharmony_ci  mainDist = 0; /* for GCC */
2023370b324cSopenharmony_ci
2024370b324cSopenharmony_ci  if (mainLen >= 2)
2025370b324cSopenharmony_ci  {
2026370b324cSopenharmony_ci    mainDist = p->matches[(size_t)numPairs - 1];
2027370b324cSopenharmony_ci    while (numPairs > 2)
2028370b324cSopenharmony_ci    {
2029370b324cSopenharmony_ci      UInt32 dist2;
2030370b324cSopenharmony_ci      if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
2031370b324cSopenharmony_ci        break;
2032370b324cSopenharmony_ci      dist2 = p->matches[(size_t)numPairs - 3];
2033370b324cSopenharmony_ci      if (!ChangePair(dist2, mainDist))
2034370b324cSopenharmony_ci        break;
2035370b324cSopenharmony_ci      numPairs -= 2;
2036370b324cSopenharmony_ci      mainLen--;
2037370b324cSopenharmony_ci      mainDist = dist2;
2038370b324cSopenharmony_ci    }
2039370b324cSopenharmony_ci    if (mainLen == 2 && mainDist >= 0x80)
2040370b324cSopenharmony_ci      mainLen = 1;
2041370b324cSopenharmony_ci  }
2042370b324cSopenharmony_ci
2043370b324cSopenharmony_ci  if (repLen >= 2)
2044370b324cSopenharmony_ci    if (    repLen + 1 >= mainLen
2045370b324cSopenharmony_ci        || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
2046370b324cSopenharmony_ci        || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
2047370b324cSopenharmony_ci  {
2048370b324cSopenharmony_ci    p->backRes = (UInt32)repIndex;
2049370b324cSopenharmony_ci    MOVE_POS(p, repLen - 1)
2050370b324cSopenharmony_ci    return repLen;
2051370b324cSopenharmony_ci  }
2052370b324cSopenharmony_ci
2053370b324cSopenharmony_ci  if (mainLen < 2 || numAvail <= 2)
2054370b324cSopenharmony_ci    return 1;
2055370b324cSopenharmony_ci
2056370b324cSopenharmony_ci  {
2057370b324cSopenharmony_ci    unsigned len1 = ReadMatchDistances(p, &p->numPairs);
2058370b324cSopenharmony_ci    p->longestMatchLen = len1;
2059370b324cSopenharmony_ci
2060370b324cSopenharmony_ci    if (len1 >= 2)
2061370b324cSopenharmony_ci    {
2062370b324cSopenharmony_ci      UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
2063370b324cSopenharmony_ci      if (   (len1 >= mainLen && newDist < mainDist)
2064370b324cSopenharmony_ci          || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
2065370b324cSopenharmony_ci          || (len1 >  mainLen + 1)
2066370b324cSopenharmony_ci          || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
2067370b324cSopenharmony_ci        return 1;
2068370b324cSopenharmony_ci    }
2069370b324cSopenharmony_ci  }
2070370b324cSopenharmony_ci
2071370b324cSopenharmony_ci  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
2072370b324cSopenharmony_ci
2073370b324cSopenharmony_ci  for (i = 0; i < LZMA_NUM_REPS; i++)
2074370b324cSopenharmony_ci  {
2075370b324cSopenharmony_ci    unsigned len, limit;
2076370b324cSopenharmony_ci    const Byte *data2 = data - p->reps[i];
2077370b324cSopenharmony_ci    if (data[0] != data2[0] || data[1] != data2[1])
2078370b324cSopenharmony_ci      continue;
2079370b324cSopenharmony_ci    limit = mainLen - 1;
2080370b324cSopenharmony_ci    for (len = 2;; len++)
2081370b324cSopenharmony_ci    {
2082370b324cSopenharmony_ci      if (len >= limit)
2083370b324cSopenharmony_ci        return 1;
2084370b324cSopenharmony_ci      if (data[len] != data2[len])
2085370b324cSopenharmony_ci        break;
2086370b324cSopenharmony_ci    }
2087370b324cSopenharmony_ci  }
2088370b324cSopenharmony_ci
2089370b324cSopenharmony_ci  p->backRes = mainDist + LZMA_NUM_REPS;
2090370b324cSopenharmony_ci  if (mainLen != 2)
2091370b324cSopenharmony_ci  {
2092370b324cSopenharmony_ci    MOVE_POS(p, mainLen - 2)
2093370b324cSopenharmony_ci  }
2094370b324cSopenharmony_ci  return mainLen;
2095370b324cSopenharmony_ci}
2096370b324cSopenharmony_ci
2097370b324cSopenharmony_ci
2098370b324cSopenharmony_ci
2099370b324cSopenharmony_ci
2100370b324cSopenharmony_cistatic void WriteEndMarker(CLzmaEnc *p, unsigned posState)
2101370b324cSopenharmony_ci{
2102370b324cSopenharmony_ci  UInt32 range;
2103370b324cSopenharmony_ci  range = p->rc.range;
2104370b324cSopenharmony_ci  {
2105370b324cSopenharmony_ci    UInt32 ttt, newBound;
2106370b324cSopenharmony_ci    CLzmaProb *prob = &p->isMatch[p->state][posState];
2107370b324cSopenharmony_ci    RC_BIT_PRE(&p->rc, prob)
2108370b324cSopenharmony_ci    RC_BIT_1(&p->rc, prob)
2109370b324cSopenharmony_ci    prob = &p->isRep[p->state];
2110370b324cSopenharmony_ci    RC_BIT_PRE(&p->rc, prob)
2111370b324cSopenharmony_ci    RC_BIT_0(&p->rc, prob)
2112370b324cSopenharmony_ci  }
2113370b324cSopenharmony_ci  p->state = kMatchNextStates[p->state];
2114370b324cSopenharmony_ci
2115370b324cSopenharmony_ci  p->rc.range = range;
2116370b324cSopenharmony_ci  LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
2117370b324cSopenharmony_ci  range = p->rc.range;
2118370b324cSopenharmony_ci
2119370b324cSopenharmony_ci  {
2120370b324cSopenharmony_ci    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
2121370b324cSopenharmony_ci    CLzmaProb *probs = p->posSlotEncoder[0];
2122370b324cSopenharmony_ci    unsigned m = 1;
2123370b324cSopenharmony_ci    do
2124370b324cSopenharmony_ci    {
2125370b324cSopenharmony_ci      UInt32 ttt, newBound;
2126370b324cSopenharmony_ci      RC_BIT_PRE(p, probs + m)
2127370b324cSopenharmony_ci      RC_BIT_1(&p->rc, probs + m)
2128370b324cSopenharmony_ci      m = (m << 1) + 1;
2129370b324cSopenharmony_ci    }
2130370b324cSopenharmony_ci    while (m < (1 << kNumPosSlotBits));
2131370b324cSopenharmony_ci  }
2132370b324cSopenharmony_ci  {
2133370b324cSopenharmony_ci    // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;
2134370b324cSopenharmony_ci    unsigned numBits = 30 - kNumAlignBits;
2135370b324cSopenharmony_ci    do
2136370b324cSopenharmony_ci    {
2137370b324cSopenharmony_ci      range >>= 1;
2138370b324cSopenharmony_ci      p->rc.low += range;
2139370b324cSopenharmony_ci      RC_NORM(&p->rc)
2140370b324cSopenharmony_ci    }
2141370b324cSopenharmony_ci    while (--numBits);
2142370b324cSopenharmony_ci  }
2143370b324cSopenharmony_ci
2144370b324cSopenharmony_ci  {
2145370b324cSopenharmony_ci    // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
2146370b324cSopenharmony_ci    CLzmaProb *probs = p->posAlignEncoder;
2147370b324cSopenharmony_ci    unsigned m = 1;
2148370b324cSopenharmony_ci    do
2149370b324cSopenharmony_ci    {
2150370b324cSopenharmony_ci      UInt32 ttt, newBound;
2151370b324cSopenharmony_ci      RC_BIT_PRE(p, probs + m)
2152370b324cSopenharmony_ci      RC_BIT_1(&p->rc, probs + m)
2153370b324cSopenharmony_ci      m = (m << 1) + 1;
2154370b324cSopenharmony_ci    }
2155370b324cSopenharmony_ci    while (m < kAlignTableSize);
2156370b324cSopenharmony_ci  }
2157370b324cSopenharmony_ci  p->rc.range = range;
2158370b324cSopenharmony_ci}
2159370b324cSopenharmony_ci
2160370b324cSopenharmony_ci
2161370b324cSopenharmony_cistatic SRes CheckErrors(CLzmaEnc *p)
2162370b324cSopenharmony_ci{
2163370b324cSopenharmony_ci  if (p->result != SZ_OK)
2164370b324cSopenharmony_ci    return p->result;
2165370b324cSopenharmony_ci  if (p->rc.res != SZ_OK)
2166370b324cSopenharmony_ci    p->result = SZ_ERROR_WRITE;
2167370b324cSopenharmony_ci
2168370b324cSopenharmony_ci  #ifndef Z7_ST
2169370b324cSopenharmony_ci  if (
2170370b324cSopenharmony_ci      // p->mf_Failure ||
2171370b324cSopenharmony_ci        (p->mtMode &&
2172370b324cSopenharmony_ci          ( // p->matchFinderMt.failure_LZ_LZ ||
2173370b324cSopenharmony_ci            p->matchFinderMt.failure_LZ_BT))
2174370b324cSopenharmony_ci     )
2175370b324cSopenharmony_ci  {
2176370b324cSopenharmony_ci    p->result = MY_HRES_ERROR_INTERNAL_ERROR;
2177370b324cSopenharmony_ci    // printf("\nCheckErrors p->matchFinderMt.failureLZ\n");
2178370b324cSopenharmony_ci  }
2179370b324cSopenharmony_ci  #endif
2180370b324cSopenharmony_ci
2181370b324cSopenharmony_ci  if (MFB.result != SZ_OK)
2182370b324cSopenharmony_ci    p->result = SZ_ERROR_READ;
2183370b324cSopenharmony_ci
2184370b324cSopenharmony_ci  if (p->result != SZ_OK)
2185370b324cSopenharmony_ci    p->finished = True;
2186370b324cSopenharmony_ci  return p->result;
2187370b324cSopenharmony_ci}
2188370b324cSopenharmony_ci
2189370b324cSopenharmony_ci
2190370b324cSopenharmony_ciZ7_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
2191370b324cSopenharmony_ci{
2192370b324cSopenharmony_ci  /* ReleaseMFStream(); */
2193370b324cSopenharmony_ci  p->finished = True;
2194370b324cSopenharmony_ci  if (p->writeEndMark)
2195370b324cSopenharmony_ci    WriteEndMarker(p, nowPos & p->pbMask);
2196370b324cSopenharmony_ci  RangeEnc_FlushData(&p->rc);
2197370b324cSopenharmony_ci  RangeEnc_FlushStream(&p->rc);
2198370b324cSopenharmony_ci  return CheckErrors(p);
2199370b324cSopenharmony_ci}
2200370b324cSopenharmony_ci
2201370b324cSopenharmony_ci
2202370b324cSopenharmony_ciZ7_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
2203370b324cSopenharmony_ci{
2204370b324cSopenharmony_ci  unsigned i;
2205370b324cSopenharmony_ci  const CProbPrice *ProbPrices = p->ProbPrices;
2206370b324cSopenharmony_ci  const CLzmaProb *probs = p->posAlignEncoder;
2207370b324cSopenharmony_ci  // p->alignPriceCount = 0;
2208370b324cSopenharmony_ci  for (i = 0; i < kAlignTableSize / 2; i++)
2209370b324cSopenharmony_ci  {
2210370b324cSopenharmony_ci    UInt32 price = 0;
2211370b324cSopenharmony_ci    unsigned sym = i;
2212370b324cSopenharmony_ci    unsigned m = 1;
2213370b324cSopenharmony_ci    unsigned bit;
2214370b324cSopenharmony_ci    UInt32 prob;
2215370b324cSopenharmony_ci    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2216370b324cSopenharmony_ci    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2217370b324cSopenharmony_ci    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2218370b324cSopenharmony_ci    prob = probs[m];
2219370b324cSopenharmony_ci    p->alignPrices[i    ] = price + GET_PRICEa_0(prob);
2220370b324cSopenharmony_ci    p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
2221370b324cSopenharmony_ci    // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
2222370b324cSopenharmony_ci  }
2223370b324cSopenharmony_ci}
2224370b324cSopenharmony_ci
2225370b324cSopenharmony_ci
2226370b324cSopenharmony_ciZ7_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
2227370b324cSopenharmony_ci{
2228370b324cSopenharmony_ci  // int y; for (y = 0; y < 100; y++) {
2229370b324cSopenharmony_ci
2230370b324cSopenharmony_ci  UInt32 tempPrices[kNumFullDistances];
2231370b324cSopenharmony_ci  unsigned i, lps;
2232370b324cSopenharmony_ci
2233370b324cSopenharmony_ci  const CProbPrice *ProbPrices = p->ProbPrices;
2234370b324cSopenharmony_ci  p->matchPriceCount = 0;
2235370b324cSopenharmony_ci
2236370b324cSopenharmony_ci  for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
2237370b324cSopenharmony_ci  {
2238370b324cSopenharmony_ci    unsigned posSlot = GetPosSlot1(i);
2239370b324cSopenharmony_ci    unsigned footerBits = (posSlot >> 1) - 1;
2240370b324cSopenharmony_ci    unsigned base = ((2 | (posSlot & 1)) << footerBits);
2241370b324cSopenharmony_ci    const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;
2242370b324cSopenharmony_ci    // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
2243370b324cSopenharmony_ci    UInt32 price = 0;
2244370b324cSopenharmony_ci    unsigned m = 1;
2245370b324cSopenharmony_ci    unsigned sym = i;
2246370b324cSopenharmony_ci    unsigned offset = (unsigned)1 << footerBits;
2247370b324cSopenharmony_ci    base += i;
2248370b324cSopenharmony_ci
2249370b324cSopenharmony_ci    if (footerBits)
2250370b324cSopenharmony_ci    do
2251370b324cSopenharmony_ci    {
2252370b324cSopenharmony_ci      unsigned bit = sym & 1;
2253370b324cSopenharmony_ci      sym >>= 1;
2254370b324cSopenharmony_ci      price += GET_PRICEa(probs[m], bit);
2255370b324cSopenharmony_ci      m = (m << 1) + bit;
2256370b324cSopenharmony_ci    }
2257370b324cSopenharmony_ci    while (--footerBits);
2258370b324cSopenharmony_ci
2259370b324cSopenharmony_ci    {
2260370b324cSopenharmony_ci      unsigned prob = probs[m];
2261370b324cSopenharmony_ci      tempPrices[base         ] = price + GET_PRICEa_0(prob);
2262370b324cSopenharmony_ci      tempPrices[base + offset] = price + GET_PRICEa_1(prob);
2263370b324cSopenharmony_ci    }
2264370b324cSopenharmony_ci  }
2265370b324cSopenharmony_ci
2266370b324cSopenharmony_ci  for (lps = 0; lps < kNumLenToPosStates; lps++)
2267370b324cSopenharmony_ci  {
2268370b324cSopenharmony_ci    unsigned slot;
2269370b324cSopenharmony_ci    unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
2270370b324cSopenharmony_ci    UInt32 *posSlotPrices = p->posSlotPrices[lps];
2271370b324cSopenharmony_ci    const CLzmaProb *probs = p->posSlotEncoder[lps];
2272370b324cSopenharmony_ci
2273370b324cSopenharmony_ci    for (slot = 0; slot < distTableSize2; slot++)
2274370b324cSopenharmony_ci    {
2275370b324cSopenharmony_ci      // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
2276370b324cSopenharmony_ci      UInt32 price;
2277370b324cSopenharmony_ci      unsigned bit;
2278370b324cSopenharmony_ci      unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
2279370b324cSopenharmony_ci      unsigned prob;
2280370b324cSopenharmony_ci      bit = sym & 1; sym >>= 1; price  = GET_PRICEa(probs[sym], bit);
2281370b324cSopenharmony_ci      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2282370b324cSopenharmony_ci      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2283370b324cSopenharmony_ci      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2284370b324cSopenharmony_ci      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2285370b324cSopenharmony_ci      prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];
2286370b324cSopenharmony_ci      posSlotPrices[(size_t)slot * 2    ] = price + GET_PRICEa_0(prob);
2287370b324cSopenharmony_ci      posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);
2288370b324cSopenharmony_ci    }
2289370b324cSopenharmony_ci
2290370b324cSopenharmony_ci    {
2291370b324cSopenharmony_ci      UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
2292370b324cSopenharmony_ci      for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
2293370b324cSopenharmony_ci      {
2294370b324cSopenharmony_ci        posSlotPrices[(size_t)slot * 2    ] += delta;
2295370b324cSopenharmony_ci        posSlotPrices[(size_t)slot * 2 + 1] += delta;
2296370b324cSopenharmony_ci        delta += ((UInt32)1 << kNumBitPriceShiftBits);
2297370b324cSopenharmony_ci      }
2298370b324cSopenharmony_ci    }
2299370b324cSopenharmony_ci
2300370b324cSopenharmony_ci    {
2301370b324cSopenharmony_ci      UInt32 *dp = p->distancesPrices[lps];
2302370b324cSopenharmony_ci
2303370b324cSopenharmony_ci      dp[0] = posSlotPrices[0];
2304370b324cSopenharmony_ci      dp[1] = posSlotPrices[1];
2305370b324cSopenharmony_ci      dp[2] = posSlotPrices[2];
2306370b324cSopenharmony_ci      dp[3] = posSlotPrices[3];
2307370b324cSopenharmony_ci
2308370b324cSopenharmony_ci      for (i = 4; i < kNumFullDistances; i += 2)
2309370b324cSopenharmony_ci      {
2310370b324cSopenharmony_ci        UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
2311370b324cSopenharmony_ci        dp[i    ] = slotPrice + tempPrices[i];
2312370b324cSopenharmony_ci        dp[i + 1] = slotPrice + tempPrices[i + 1];
2313370b324cSopenharmony_ci      }
2314370b324cSopenharmony_ci    }
2315370b324cSopenharmony_ci  }
2316370b324cSopenharmony_ci  // }
2317370b324cSopenharmony_ci}
2318370b324cSopenharmony_ci
2319370b324cSopenharmony_ci
2320370b324cSopenharmony_ci
2321370b324cSopenharmony_cistatic void LzmaEnc_Construct(CLzmaEnc *p)
2322370b324cSopenharmony_ci{
2323370b324cSopenharmony_ci  RangeEnc_Construct(&p->rc);
2324370b324cSopenharmony_ci  MatchFinder_Construct(&MFB);
2325370b324cSopenharmony_ci
2326370b324cSopenharmony_ci  #ifndef Z7_ST
2327370b324cSopenharmony_ci  p->matchFinderMt.MatchFinder = &MFB;
2328370b324cSopenharmony_ci  MatchFinderMt_Construct(&p->matchFinderMt);
2329370b324cSopenharmony_ci  #endif
2330370b324cSopenharmony_ci
2331370b324cSopenharmony_ci  {
2332370b324cSopenharmony_ci    CLzmaEncProps props;
2333370b324cSopenharmony_ci    LzmaEncProps_Init(&props);
2334370b324cSopenharmony_ci    LzmaEnc_SetProps((CLzmaEncHandle)(void *)p, &props);
2335370b324cSopenharmony_ci  }
2336370b324cSopenharmony_ci
2337370b324cSopenharmony_ci  #ifndef LZMA_LOG_BSR
2338370b324cSopenharmony_ci  LzmaEnc_FastPosInit(p->g_FastPos);
2339370b324cSopenharmony_ci  #endif
2340370b324cSopenharmony_ci
2341370b324cSopenharmony_ci  LzmaEnc_InitPriceTables(p->ProbPrices);
2342370b324cSopenharmony_ci  p->litProbs = NULL;
2343370b324cSopenharmony_ci  p->saveState.litProbs = NULL;
2344370b324cSopenharmony_ci}
2345370b324cSopenharmony_ci
2346370b324cSopenharmony_ciCLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
2347370b324cSopenharmony_ci{
2348370b324cSopenharmony_ci  void *p;
2349370b324cSopenharmony_ci  p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
2350370b324cSopenharmony_ci  if (p)
2351370b324cSopenharmony_ci    LzmaEnc_Construct((CLzmaEnc *)p);
2352370b324cSopenharmony_ci  return p;
2353370b324cSopenharmony_ci}
2354370b324cSopenharmony_ci
2355370b324cSopenharmony_cistatic void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
2356370b324cSopenharmony_ci{
2357370b324cSopenharmony_ci  ISzAlloc_Free(alloc, p->litProbs);
2358370b324cSopenharmony_ci  ISzAlloc_Free(alloc, p->saveState.litProbs);
2359370b324cSopenharmony_ci  p->litProbs = NULL;
2360370b324cSopenharmony_ci  p->saveState.litProbs = NULL;
2361370b324cSopenharmony_ci}
2362370b324cSopenharmony_ci
2363370b324cSopenharmony_cistatic void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2364370b324cSopenharmony_ci{
2365370b324cSopenharmony_ci  #ifndef Z7_ST
2366370b324cSopenharmony_ci  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
2367370b324cSopenharmony_ci  #endif
2368370b324cSopenharmony_ci
2369370b324cSopenharmony_ci  MatchFinder_Free(&MFB, allocBig);
2370370b324cSopenharmony_ci  LzmaEnc_FreeLits(p, alloc);
2371370b324cSopenharmony_ci  RangeEnc_Free(&p->rc, alloc);
2372370b324cSopenharmony_ci}
2373370b324cSopenharmony_ci
2374370b324cSopenharmony_civoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2375370b324cSopenharmony_ci{
2376370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2377370b324cSopenharmony_ci  LzmaEnc_Destruct(p, alloc, allocBig);
2378370b324cSopenharmony_ci  ISzAlloc_Free(alloc, p);
2379370b324cSopenharmony_ci}
2380370b324cSopenharmony_ci
2381370b324cSopenharmony_ci
2382370b324cSopenharmony_ciZ7_NO_INLINE
2383370b324cSopenharmony_cistatic SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
2384370b324cSopenharmony_ci{
2385370b324cSopenharmony_ci  UInt32 nowPos32, startPos32;
2386370b324cSopenharmony_ci  if (p->needInit)
2387370b324cSopenharmony_ci  {
2388370b324cSopenharmony_ci    #ifndef Z7_ST
2389370b324cSopenharmony_ci    if (p->mtMode)
2390370b324cSopenharmony_ci    {
2391370b324cSopenharmony_ci      RINOK(MatchFinderMt_InitMt(&p->matchFinderMt))
2392370b324cSopenharmony_ci    }
2393370b324cSopenharmony_ci    #endif
2394370b324cSopenharmony_ci    p->matchFinder.Init(p->matchFinderObj);
2395370b324cSopenharmony_ci    p->needInit = 0;
2396370b324cSopenharmony_ci  }
2397370b324cSopenharmony_ci
2398370b324cSopenharmony_ci  if (p->finished)
2399370b324cSopenharmony_ci    return p->result;
2400370b324cSopenharmony_ci  RINOK(CheckErrors(p))
2401370b324cSopenharmony_ci
2402370b324cSopenharmony_ci  nowPos32 = (UInt32)p->nowPos64;
2403370b324cSopenharmony_ci  startPos32 = nowPos32;
2404370b324cSopenharmony_ci
2405370b324cSopenharmony_ci  if (p->nowPos64 == 0)
2406370b324cSopenharmony_ci  {
2407370b324cSopenharmony_ci    unsigned numPairs;
2408370b324cSopenharmony_ci    Byte curByte;
2409370b324cSopenharmony_ci    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2410370b324cSopenharmony_ci      return Flush(p, nowPos32);
2411370b324cSopenharmony_ci    ReadMatchDistances(p, &numPairs);
2412370b324cSopenharmony_ci    RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
2413370b324cSopenharmony_ci    // p->state = kLiteralNextStates[p->state];
2414370b324cSopenharmony_ci    curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
2415370b324cSopenharmony_ci    LitEnc_Encode(&p->rc, p->litProbs, curByte);
2416370b324cSopenharmony_ci    p->additionalOffset--;
2417370b324cSopenharmony_ci    nowPos32++;
2418370b324cSopenharmony_ci  }
2419370b324cSopenharmony_ci
2420370b324cSopenharmony_ci  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
2421370b324cSopenharmony_ci
2422370b324cSopenharmony_ci  for (;;)
2423370b324cSopenharmony_ci  {
2424370b324cSopenharmony_ci    UInt32 dist;
2425370b324cSopenharmony_ci    unsigned len, posState;
2426370b324cSopenharmony_ci    UInt32 range, ttt, newBound;
2427370b324cSopenharmony_ci    CLzmaProb *probs;
2428370b324cSopenharmony_ci
2429370b324cSopenharmony_ci    if (p->fastMode)
2430370b324cSopenharmony_ci      len = GetOptimumFast(p);
2431370b324cSopenharmony_ci    else
2432370b324cSopenharmony_ci    {
2433370b324cSopenharmony_ci      unsigned oci = p->optCur;
2434370b324cSopenharmony_ci      if (p->optEnd == oci)
2435370b324cSopenharmony_ci        len = GetOptimum(p, nowPos32);
2436370b324cSopenharmony_ci      else
2437370b324cSopenharmony_ci      {
2438370b324cSopenharmony_ci        const COptimal *opt = &p->opt[oci];
2439370b324cSopenharmony_ci        len = opt->len;
2440370b324cSopenharmony_ci        p->backRes = opt->dist;
2441370b324cSopenharmony_ci        p->optCur = oci + 1;
2442370b324cSopenharmony_ci      }
2443370b324cSopenharmony_ci    }
2444370b324cSopenharmony_ci
2445370b324cSopenharmony_ci    posState = (unsigned)nowPos32 & p->pbMask;
2446370b324cSopenharmony_ci    range = p->rc.range;
2447370b324cSopenharmony_ci    probs = &p->isMatch[p->state][posState];
2448370b324cSopenharmony_ci
2449370b324cSopenharmony_ci    RC_BIT_PRE(&p->rc, probs)
2450370b324cSopenharmony_ci
2451370b324cSopenharmony_ci    dist = p->backRes;
2452370b324cSopenharmony_ci
2453370b324cSopenharmony_ci    #ifdef SHOW_STAT2
2454370b324cSopenharmony_ci    printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);
2455370b324cSopenharmony_ci    #endif
2456370b324cSopenharmony_ci
2457370b324cSopenharmony_ci    if (dist == MARK_LIT)
2458370b324cSopenharmony_ci    {
2459370b324cSopenharmony_ci      Byte curByte;
2460370b324cSopenharmony_ci      const Byte *data;
2461370b324cSopenharmony_ci      unsigned state;
2462370b324cSopenharmony_ci
2463370b324cSopenharmony_ci      RC_BIT_0(&p->rc, probs)
2464370b324cSopenharmony_ci      p->rc.range = range;
2465370b324cSopenharmony_ci      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2466370b324cSopenharmony_ci      probs = LIT_PROBS(nowPos32, *(data - 1));
2467370b324cSopenharmony_ci      curByte = *data;
2468370b324cSopenharmony_ci      state = p->state;
2469370b324cSopenharmony_ci      p->state = kLiteralNextStates[state];
2470370b324cSopenharmony_ci      if (IsLitState(state))
2471370b324cSopenharmony_ci        LitEnc_Encode(&p->rc, probs, curByte);
2472370b324cSopenharmony_ci      else
2473370b324cSopenharmony_ci        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
2474370b324cSopenharmony_ci    }
2475370b324cSopenharmony_ci    else
2476370b324cSopenharmony_ci    {
2477370b324cSopenharmony_ci      RC_BIT_1(&p->rc, probs)
2478370b324cSopenharmony_ci      probs = &p->isRep[p->state];
2479370b324cSopenharmony_ci      RC_BIT_PRE(&p->rc, probs)
2480370b324cSopenharmony_ci
2481370b324cSopenharmony_ci      if (dist < LZMA_NUM_REPS)
2482370b324cSopenharmony_ci      {
2483370b324cSopenharmony_ci        RC_BIT_1(&p->rc, probs)
2484370b324cSopenharmony_ci        probs = &p->isRepG0[p->state];
2485370b324cSopenharmony_ci        RC_BIT_PRE(&p->rc, probs)
2486370b324cSopenharmony_ci        if (dist == 0)
2487370b324cSopenharmony_ci        {
2488370b324cSopenharmony_ci          RC_BIT_0(&p->rc, probs)
2489370b324cSopenharmony_ci          probs = &p->isRep0Long[p->state][posState];
2490370b324cSopenharmony_ci          RC_BIT_PRE(&p->rc, probs)
2491370b324cSopenharmony_ci          if (len != 1)
2492370b324cSopenharmony_ci          {
2493370b324cSopenharmony_ci            RC_BIT_1_BASE(&p->rc, probs)
2494370b324cSopenharmony_ci          }
2495370b324cSopenharmony_ci          else
2496370b324cSopenharmony_ci          {
2497370b324cSopenharmony_ci            RC_BIT_0_BASE(&p->rc, probs)
2498370b324cSopenharmony_ci            p->state = kShortRepNextStates[p->state];
2499370b324cSopenharmony_ci          }
2500370b324cSopenharmony_ci        }
2501370b324cSopenharmony_ci        else
2502370b324cSopenharmony_ci        {
2503370b324cSopenharmony_ci          RC_BIT_1(&p->rc, probs)
2504370b324cSopenharmony_ci          probs = &p->isRepG1[p->state];
2505370b324cSopenharmony_ci          RC_BIT_PRE(&p->rc, probs)
2506370b324cSopenharmony_ci          if (dist == 1)
2507370b324cSopenharmony_ci          {
2508370b324cSopenharmony_ci            RC_BIT_0_BASE(&p->rc, probs)
2509370b324cSopenharmony_ci            dist = p->reps[1];
2510370b324cSopenharmony_ci          }
2511370b324cSopenharmony_ci          else
2512370b324cSopenharmony_ci          {
2513370b324cSopenharmony_ci            RC_BIT_1(&p->rc, probs)
2514370b324cSopenharmony_ci            probs = &p->isRepG2[p->state];
2515370b324cSopenharmony_ci            RC_BIT_PRE(&p->rc, probs)
2516370b324cSopenharmony_ci            if (dist == 2)
2517370b324cSopenharmony_ci            {
2518370b324cSopenharmony_ci              RC_BIT_0_BASE(&p->rc, probs)
2519370b324cSopenharmony_ci              dist = p->reps[2];
2520370b324cSopenharmony_ci            }
2521370b324cSopenharmony_ci            else
2522370b324cSopenharmony_ci            {
2523370b324cSopenharmony_ci              RC_BIT_1_BASE(&p->rc, probs)
2524370b324cSopenharmony_ci              dist = p->reps[3];
2525370b324cSopenharmony_ci              p->reps[3] = p->reps[2];
2526370b324cSopenharmony_ci            }
2527370b324cSopenharmony_ci            p->reps[2] = p->reps[1];
2528370b324cSopenharmony_ci          }
2529370b324cSopenharmony_ci          p->reps[1] = p->reps[0];
2530370b324cSopenharmony_ci          p->reps[0] = dist;
2531370b324cSopenharmony_ci        }
2532370b324cSopenharmony_ci
2533370b324cSopenharmony_ci        RC_NORM(&p->rc)
2534370b324cSopenharmony_ci
2535370b324cSopenharmony_ci        p->rc.range = range;
2536370b324cSopenharmony_ci
2537370b324cSopenharmony_ci        if (len != 1)
2538370b324cSopenharmony_ci        {
2539370b324cSopenharmony_ci          LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2540370b324cSopenharmony_ci          --p->repLenEncCounter;
2541370b324cSopenharmony_ci          p->state = kRepNextStates[p->state];
2542370b324cSopenharmony_ci        }
2543370b324cSopenharmony_ci      }
2544370b324cSopenharmony_ci      else
2545370b324cSopenharmony_ci      {
2546370b324cSopenharmony_ci        unsigned posSlot;
2547370b324cSopenharmony_ci        RC_BIT_0(&p->rc, probs)
2548370b324cSopenharmony_ci        p->rc.range = range;
2549370b324cSopenharmony_ci        p->state = kMatchNextStates[p->state];
2550370b324cSopenharmony_ci
2551370b324cSopenharmony_ci        LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2552370b324cSopenharmony_ci        // --p->lenEnc.counter;
2553370b324cSopenharmony_ci
2554370b324cSopenharmony_ci        dist -= LZMA_NUM_REPS;
2555370b324cSopenharmony_ci        p->reps[3] = p->reps[2];
2556370b324cSopenharmony_ci        p->reps[2] = p->reps[1];
2557370b324cSopenharmony_ci        p->reps[1] = p->reps[0];
2558370b324cSopenharmony_ci        p->reps[0] = dist + 1;
2559370b324cSopenharmony_ci
2560370b324cSopenharmony_ci        p->matchPriceCount++;
2561370b324cSopenharmony_ci        GetPosSlot(dist, posSlot)
2562370b324cSopenharmony_ci        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
2563370b324cSopenharmony_ci        {
2564370b324cSopenharmony_ci          UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits);
2565370b324cSopenharmony_ci          range = p->rc.range;
2566370b324cSopenharmony_ci          probs = p->posSlotEncoder[GetLenToPosState(len)];
2567370b324cSopenharmony_ci          do
2568370b324cSopenharmony_ci          {
2569370b324cSopenharmony_ci            CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);
2570370b324cSopenharmony_ci            UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;
2571370b324cSopenharmony_ci            sym <<= 1;
2572370b324cSopenharmony_ci            RC_BIT(&p->rc, prob, bit)
2573370b324cSopenharmony_ci          }
2574370b324cSopenharmony_ci          while (sym < (1 << kNumPosSlotBits * 2));
2575370b324cSopenharmony_ci          p->rc.range = range;
2576370b324cSopenharmony_ci        }
2577370b324cSopenharmony_ci
2578370b324cSopenharmony_ci        if (dist >= kStartPosModelIndex)
2579370b324cSopenharmony_ci        {
2580370b324cSopenharmony_ci          unsigned footerBits = ((posSlot >> 1) - 1);
2581370b324cSopenharmony_ci
2582370b324cSopenharmony_ci          if (dist < kNumFullDistances)
2583370b324cSopenharmony_ci          {
2584370b324cSopenharmony_ci            unsigned base = ((2 | (posSlot & 1)) << footerBits);
2585370b324cSopenharmony_ci            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */));
2586370b324cSopenharmony_ci          }
2587370b324cSopenharmony_ci          else
2588370b324cSopenharmony_ci          {
2589370b324cSopenharmony_ci            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
2590370b324cSopenharmony_ci            range = p->rc.range;
2591370b324cSopenharmony_ci            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
2592370b324cSopenharmony_ci            /*
2593370b324cSopenharmony_ci            do
2594370b324cSopenharmony_ci            {
2595370b324cSopenharmony_ci              range >>= 1;
2596370b324cSopenharmony_ci              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
2597370b324cSopenharmony_ci              RC_NORM(&p->rc)
2598370b324cSopenharmony_ci            }
2599370b324cSopenharmony_ci            while (footerBits > kNumAlignBits);
2600370b324cSopenharmony_ci            */
2601370b324cSopenharmony_ci            do
2602370b324cSopenharmony_ci            {
2603370b324cSopenharmony_ci              range >>= 1;
2604370b324cSopenharmony_ci              p->rc.low += range & (0 - (pos2 >> 31));
2605370b324cSopenharmony_ci              pos2 += pos2;
2606370b324cSopenharmony_ci              RC_NORM(&p->rc)
2607370b324cSopenharmony_ci            }
2608370b324cSopenharmony_ci            while (pos2 != 0xF0000000);
2609370b324cSopenharmony_ci
2610370b324cSopenharmony_ci
2611370b324cSopenharmony_ci            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
2612370b324cSopenharmony_ci
2613370b324cSopenharmony_ci            {
2614370b324cSopenharmony_ci              unsigned m = 1;
2615370b324cSopenharmony_ci              unsigned bit;
2616370b324cSopenharmony_ci              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;
2617370b324cSopenharmony_ci              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;
2618370b324cSopenharmony_ci              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;
2619370b324cSopenharmony_ci              bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit)
2620370b324cSopenharmony_ci              p->rc.range = range;
2621370b324cSopenharmony_ci              // p->alignPriceCount++;
2622370b324cSopenharmony_ci            }
2623370b324cSopenharmony_ci          }
2624370b324cSopenharmony_ci        }
2625370b324cSopenharmony_ci      }
2626370b324cSopenharmony_ci    }
2627370b324cSopenharmony_ci
2628370b324cSopenharmony_ci    nowPos32 += (UInt32)len;
2629370b324cSopenharmony_ci    p->additionalOffset -= len;
2630370b324cSopenharmony_ci
2631370b324cSopenharmony_ci    if (p->additionalOffset == 0)
2632370b324cSopenharmony_ci    {
2633370b324cSopenharmony_ci      UInt32 processed;
2634370b324cSopenharmony_ci
2635370b324cSopenharmony_ci      if (!p->fastMode)
2636370b324cSopenharmony_ci      {
2637370b324cSopenharmony_ci        /*
2638370b324cSopenharmony_ci        if (p->alignPriceCount >= 16) // kAlignTableSize
2639370b324cSopenharmony_ci          FillAlignPrices(p);
2640370b324cSopenharmony_ci        if (p->matchPriceCount >= 128)
2641370b324cSopenharmony_ci          FillDistancesPrices(p);
2642370b324cSopenharmony_ci        if (p->lenEnc.counter <= 0)
2643370b324cSopenharmony_ci          LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
2644370b324cSopenharmony_ci        */
2645370b324cSopenharmony_ci        if (p->matchPriceCount >= 64)
2646370b324cSopenharmony_ci        {
2647370b324cSopenharmony_ci          FillAlignPrices(p);
2648370b324cSopenharmony_ci          // { int y; for (y = 0; y < 100; y++) {
2649370b324cSopenharmony_ci          FillDistancesPrices(p);
2650370b324cSopenharmony_ci          // }}
2651370b324cSopenharmony_ci          LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
2652370b324cSopenharmony_ci        }
2653370b324cSopenharmony_ci        if (p->repLenEncCounter <= 0)
2654370b324cSopenharmony_ci        {
2655370b324cSopenharmony_ci          p->repLenEncCounter = REP_LEN_COUNT;
2656370b324cSopenharmony_ci          LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
2657370b324cSopenharmony_ci        }
2658370b324cSopenharmony_ci      }
2659370b324cSopenharmony_ci
2660370b324cSopenharmony_ci      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2661370b324cSopenharmony_ci        break;
2662370b324cSopenharmony_ci      processed = nowPos32 - startPos32;
2663370b324cSopenharmony_ci
2664370b324cSopenharmony_ci      if (maxPackSize)
2665370b324cSopenharmony_ci      {
2666370b324cSopenharmony_ci        if (processed + kNumOpts + 300 >= maxUnpackSize
2667370b324cSopenharmony_ci            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
2668370b324cSopenharmony_ci          break;
2669370b324cSopenharmony_ci      }
2670370b324cSopenharmony_ci      else if (processed >= (1 << 17))
2671370b324cSopenharmony_ci      {
2672370b324cSopenharmony_ci        p->nowPos64 += nowPos32 - startPos32;
2673370b324cSopenharmony_ci        return CheckErrors(p);
2674370b324cSopenharmony_ci      }
2675370b324cSopenharmony_ci    }
2676370b324cSopenharmony_ci  }
2677370b324cSopenharmony_ci
2678370b324cSopenharmony_ci  p->nowPos64 += nowPos32 - startPos32;
2679370b324cSopenharmony_ci  return Flush(p, nowPos32);
2680370b324cSopenharmony_ci}
2681370b324cSopenharmony_ci
2682370b324cSopenharmony_ci
2683370b324cSopenharmony_ci
2684370b324cSopenharmony_ci#define kBigHashDicLimit ((UInt32)1 << 24)
2685370b324cSopenharmony_ci
2686370b324cSopenharmony_cistatic SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2687370b324cSopenharmony_ci{
2688370b324cSopenharmony_ci  UInt32 beforeSize = kNumOpts;
2689370b324cSopenharmony_ci  UInt32 dictSize;
2690370b324cSopenharmony_ci
2691370b324cSopenharmony_ci  if (!RangeEnc_Alloc(&p->rc, alloc))
2692370b324cSopenharmony_ci    return SZ_ERROR_MEM;
2693370b324cSopenharmony_ci
2694370b324cSopenharmony_ci  #ifndef Z7_ST
2695370b324cSopenharmony_ci  p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0));
2696370b324cSopenharmony_ci  #endif
2697370b324cSopenharmony_ci
2698370b324cSopenharmony_ci  {
2699370b324cSopenharmony_ci    unsigned lclp = p->lc + p->lp;
2700370b324cSopenharmony_ci    if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
2701370b324cSopenharmony_ci    {
2702370b324cSopenharmony_ci      LzmaEnc_FreeLits(p, alloc);
2703370b324cSopenharmony_ci      p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2704370b324cSopenharmony_ci      p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2705370b324cSopenharmony_ci      if (!p->litProbs || !p->saveState.litProbs)
2706370b324cSopenharmony_ci      {
2707370b324cSopenharmony_ci        LzmaEnc_FreeLits(p, alloc);
2708370b324cSopenharmony_ci        return SZ_ERROR_MEM;
2709370b324cSopenharmony_ci      }
2710370b324cSopenharmony_ci      p->lclp = lclp;
2711370b324cSopenharmony_ci    }
2712370b324cSopenharmony_ci  }
2713370b324cSopenharmony_ci
2714370b324cSopenharmony_ci  MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
2715370b324cSopenharmony_ci
2716370b324cSopenharmony_ci
2717370b324cSopenharmony_ci  dictSize = p->dictSize;
2718370b324cSopenharmony_ci  if (dictSize == ((UInt32)2 << 30) ||
2719370b324cSopenharmony_ci      dictSize == ((UInt32)3 << 30))
2720370b324cSopenharmony_ci  {
2721370b324cSopenharmony_ci    /* 21.03 : here we reduce the dictionary for 2 reasons:
2722370b324cSopenharmony_ci       1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary.
2723370b324cSopenharmony_ci       2) we want to elimate useless last MatchFinder_Normalize3() for corner cases,
2724370b324cSopenharmony_ci          where data size is aligned for 1 GB: 5/6/8 GB.
2725370b324cSopenharmony_ci          That reducing must be >= 1 for such corner cases. */
2726370b324cSopenharmony_ci    dictSize -= 1;
2727370b324cSopenharmony_ci  }
2728370b324cSopenharmony_ci
2729370b324cSopenharmony_ci  if (beforeSize + dictSize < keepWindowSize)
2730370b324cSopenharmony_ci    beforeSize = keepWindowSize - dictSize;
2731370b324cSopenharmony_ci
2732370b324cSopenharmony_ci  /* in worst case we can look ahead for
2733370b324cSopenharmony_ci        max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes.
2734370b324cSopenharmony_ci     we send larger value for (keepAfter) to MantchFinder_Create():
2735370b324cSopenharmony_ci        (numFastBytes + LZMA_MATCH_LEN_MAX + 1)
2736370b324cSopenharmony_ci  */
2737370b324cSopenharmony_ci
2738370b324cSopenharmony_ci  #ifndef Z7_ST
2739370b324cSopenharmony_ci  if (p->mtMode)
2740370b324cSopenharmony_ci  {
2741370b324cSopenharmony_ci    RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize,
2742370b324cSopenharmony_ci        p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */
2743370b324cSopenharmony_ci        , allocBig))
2744370b324cSopenharmony_ci    p->matchFinderObj = &p->matchFinderMt;
2745370b324cSopenharmony_ci    MFB.bigHash = (Byte)(MFB.hashMask >= 0xFFFFFF ? 1 : 0);
2746370b324cSopenharmony_ci    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
2747370b324cSopenharmony_ci  }
2748370b324cSopenharmony_ci  else
2749370b324cSopenharmony_ci  #endif
2750370b324cSopenharmony_ci  {
2751370b324cSopenharmony_ci    if (!MatchFinder_Create(&MFB, dictSize, beforeSize,
2752370b324cSopenharmony_ci        p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */
2753370b324cSopenharmony_ci        , allocBig))
2754370b324cSopenharmony_ci      return SZ_ERROR_MEM;
2755370b324cSopenharmony_ci    p->matchFinderObj = &MFB;
2756370b324cSopenharmony_ci    MatchFinder_CreateVTable(&MFB, &p->matchFinder);
2757370b324cSopenharmony_ci  }
2758370b324cSopenharmony_ci
2759370b324cSopenharmony_ci  return SZ_OK;
2760370b324cSopenharmony_ci}
2761370b324cSopenharmony_ci
2762370b324cSopenharmony_cistatic void LzmaEnc_Init(CLzmaEnc *p)
2763370b324cSopenharmony_ci{
2764370b324cSopenharmony_ci  unsigned i;
2765370b324cSopenharmony_ci  p->state = 0;
2766370b324cSopenharmony_ci  p->reps[0] =
2767370b324cSopenharmony_ci  p->reps[1] =
2768370b324cSopenharmony_ci  p->reps[2] =
2769370b324cSopenharmony_ci  p->reps[3] = 1;
2770370b324cSopenharmony_ci
2771370b324cSopenharmony_ci  RangeEnc_Init(&p->rc);
2772370b324cSopenharmony_ci
2773370b324cSopenharmony_ci  for (i = 0; i < (1 << kNumAlignBits); i++)
2774370b324cSopenharmony_ci    p->posAlignEncoder[i] = kProbInitValue;
2775370b324cSopenharmony_ci
2776370b324cSopenharmony_ci  for (i = 0; i < kNumStates; i++)
2777370b324cSopenharmony_ci  {
2778370b324cSopenharmony_ci    unsigned j;
2779370b324cSopenharmony_ci    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
2780370b324cSopenharmony_ci    {
2781370b324cSopenharmony_ci      p->isMatch[i][j] = kProbInitValue;
2782370b324cSopenharmony_ci      p->isRep0Long[i][j] = kProbInitValue;
2783370b324cSopenharmony_ci    }
2784370b324cSopenharmony_ci    p->isRep[i] = kProbInitValue;
2785370b324cSopenharmony_ci    p->isRepG0[i] = kProbInitValue;
2786370b324cSopenharmony_ci    p->isRepG1[i] = kProbInitValue;
2787370b324cSopenharmony_ci    p->isRepG2[i] = kProbInitValue;
2788370b324cSopenharmony_ci  }
2789370b324cSopenharmony_ci
2790370b324cSopenharmony_ci  {
2791370b324cSopenharmony_ci    for (i = 0; i < kNumLenToPosStates; i++)
2792370b324cSopenharmony_ci    {
2793370b324cSopenharmony_ci      CLzmaProb *probs = p->posSlotEncoder[i];
2794370b324cSopenharmony_ci      unsigned j;
2795370b324cSopenharmony_ci      for (j = 0; j < (1 << kNumPosSlotBits); j++)
2796370b324cSopenharmony_ci        probs[j] = kProbInitValue;
2797370b324cSopenharmony_ci    }
2798370b324cSopenharmony_ci  }
2799370b324cSopenharmony_ci  {
2800370b324cSopenharmony_ci    for (i = 0; i < kNumFullDistances; i++)
2801370b324cSopenharmony_ci      p->posEncoders[i] = kProbInitValue;
2802370b324cSopenharmony_ci  }
2803370b324cSopenharmony_ci
2804370b324cSopenharmony_ci  {
2805370b324cSopenharmony_ci    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
2806370b324cSopenharmony_ci    UInt32 k;
2807370b324cSopenharmony_ci    CLzmaProb *probs = p->litProbs;
2808370b324cSopenharmony_ci    for (k = 0; k < num; k++)
2809370b324cSopenharmony_ci      probs[k] = kProbInitValue;
2810370b324cSopenharmony_ci  }
2811370b324cSopenharmony_ci
2812370b324cSopenharmony_ci
2813370b324cSopenharmony_ci  LenEnc_Init(&p->lenProbs);
2814370b324cSopenharmony_ci  LenEnc_Init(&p->repLenProbs);
2815370b324cSopenharmony_ci
2816370b324cSopenharmony_ci  p->optEnd = 0;
2817370b324cSopenharmony_ci  p->optCur = 0;
2818370b324cSopenharmony_ci
2819370b324cSopenharmony_ci  {
2820370b324cSopenharmony_ci    for (i = 0; i < kNumOpts; i++)
2821370b324cSopenharmony_ci      p->opt[i].price = kInfinityPrice;
2822370b324cSopenharmony_ci  }
2823370b324cSopenharmony_ci
2824370b324cSopenharmony_ci  p->additionalOffset = 0;
2825370b324cSopenharmony_ci
2826370b324cSopenharmony_ci  p->pbMask = ((unsigned)1 << p->pb) - 1;
2827370b324cSopenharmony_ci  p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
2828370b324cSopenharmony_ci
2829370b324cSopenharmony_ci  // p->mf_Failure = False;
2830370b324cSopenharmony_ci}
2831370b324cSopenharmony_ci
2832370b324cSopenharmony_ci
2833370b324cSopenharmony_cistatic void LzmaEnc_InitPrices(CLzmaEnc *p)
2834370b324cSopenharmony_ci{
2835370b324cSopenharmony_ci  if (!p->fastMode)
2836370b324cSopenharmony_ci  {
2837370b324cSopenharmony_ci    FillDistancesPrices(p);
2838370b324cSopenharmony_ci    FillAlignPrices(p);
2839370b324cSopenharmony_ci  }
2840370b324cSopenharmony_ci
2841370b324cSopenharmony_ci  p->lenEnc.tableSize =
2842370b324cSopenharmony_ci  p->repLenEnc.tableSize =
2843370b324cSopenharmony_ci      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
2844370b324cSopenharmony_ci
2845370b324cSopenharmony_ci  p->repLenEncCounter = REP_LEN_COUNT;
2846370b324cSopenharmony_ci
2847370b324cSopenharmony_ci  LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
2848370b324cSopenharmony_ci  LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
2849370b324cSopenharmony_ci}
2850370b324cSopenharmony_ci
2851370b324cSopenharmony_cistatic SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2852370b324cSopenharmony_ci{
2853370b324cSopenharmony_ci  unsigned i;
2854370b324cSopenharmony_ci  for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
2855370b324cSopenharmony_ci    if (p->dictSize <= ((UInt32)1 << i))
2856370b324cSopenharmony_ci      break;
2857370b324cSopenharmony_ci  p->distTableSize = i * 2;
2858370b324cSopenharmony_ci
2859370b324cSopenharmony_ci  p->finished = False;
2860370b324cSopenharmony_ci  p->result = SZ_OK;
2861370b324cSopenharmony_ci  p->nowPos64 = 0;
2862370b324cSopenharmony_ci  p->needInit = 1;
2863370b324cSopenharmony_ci  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig))
2864370b324cSopenharmony_ci  LzmaEnc_Init(p);
2865370b324cSopenharmony_ci  LzmaEnc_InitPrices(p);
2866370b324cSopenharmony_ci  return SZ_OK;
2867370b324cSopenharmony_ci}
2868370b324cSopenharmony_ci
2869370b324cSopenharmony_cistatic SRes LzmaEnc_Prepare(CLzmaEncHandle p,
2870370b324cSopenharmony_ci    ISeqOutStreamPtr outStream,
2871370b324cSopenharmony_ci    ISeqInStreamPtr inStream,
2872370b324cSopenharmony_ci    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2873370b324cSopenharmony_ci{
2874370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2875370b324cSopenharmony_ci  MatchFinder_SET_STREAM(&MFB, inStream)
2876370b324cSopenharmony_ci  p->rc.outStream = outStream;
2877370b324cSopenharmony_ci  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
2878370b324cSopenharmony_ci}
2879370b324cSopenharmony_ci
2880370b324cSopenharmony_ciSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p,
2881370b324cSopenharmony_ci    ISeqInStreamPtr inStream, UInt32 keepWindowSize,
2882370b324cSopenharmony_ci    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2883370b324cSopenharmony_ci{
2884370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2885370b324cSopenharmony_ci  MatchFinder_SET_STREAM(&MFB, inStream)
2886370b324cSopenharmony_ci  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2887370b324cSopenharmony_ci}
2888370b324cSopenharmony_ci
2889370b324cSopenharmony_ciSRes LzmaEnc_MemPrepare(CLzmaEncHandle p,
2890370b324cSopenharmony_ci    const Byte *src, SizeT srcLen,
2891370b324cSopenharmony_ci    UInt32 keepWindowSize,
2892370b324cSopenharmony_ci    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2893370b324cSopenharmony_ci{
2894370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2895370b324cSopenharmony_ci  MatchFinder_SET_DIRECT_INPUT_BUF(&MFB, src, srcLen)
2896370b324cSopenharmony_ci  LzmaEnc_SetDataSize(p, srcLen);
2897370b324cSopenharmony_ci  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2898370b324cSopenharmony_ci}
2899370b324cSopenharmony_ci
2900370b324cSopenharmony_civoid LzmaEnc_Finish(CLzmaEncHandle p)
2901370b324cSopenharmony_ci{
2902370b324cSopenharmony_ci  #ifndef Z7_ST
2903370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2904370b324cSopenharmony_ci  if (p->mtMode)
2905370b324cSopenharmony_ci    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
2906370b324cSopenharmony_ci  #else
2907370b324cSopenharmony_ci  UNUSED_VAR(p)
2908370b324cSopenharmony_ci  #endif
2909370b324cSopenharmony_ci}
2910370b324cSopenharmony_ci
2911370b324cSopenharmony_ci
2912370b324cSopenharmony_citypedef struct
2913370b324cSopenharmony_ci{
2914370b324cSopenharmony_ci  ISeqOutStream vt;
2915370b324cSopenharmony_ci  Byte *data;
2916370b324cSopenharmony_ci  size_t rem;
2917370b324cSopenharmony_ci  BoolInt overflow;
2918370b324cSopenharmony_ci} CLzmaEnc_SeqOutStreamBuf;
2919370b324cSopenharmony_ci
2920370b324cSopenharmony_cistatic size_t SeqOutStreamBuf_Write(ISeqOutStreamPtr pp, const void *data, size_t size)
2921370b324cSopenharmony_ci{
2922370b324cSopenharmony_ci  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLzmaEnc_SeqOutStreamBuf)
2923370b324cSopenharmony_ci  if (p->rem < size)
2924370b324cSopenharmony_ci  {
2925370b324cSopenharmony_ci    size = p->rem;
2926370b324cSopenharmony_ci    p->overflow = True;
2927370b324cSopenharmony_ci  }
2928370b324cSopenharmony_ci  if (size != 0)
2929370b324cSopenharmony_ci  {
2930370b324cSopenharmony_ci    memcpy(p->data, data, size);
2931370b324cSopenharmony_ci    p->rem -= size;
2932370b324cSopenharmony_ci    p->data += size;
2933370b324cSopenharmony_ci  }
2934370b324cSopenharmony_ci  return size;
2935370b324cSopenharmony_ci}
2936370b324cSopenharmony_ci
2937370b324cSopenharmony_ci
2938370b324cSopenharmony_ci/*
2939370b324cSopenharmony_ciUInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p)
2940370b324cSopenharmony_ci{
2941370b324cSopenharmony_ci  GET_const_CLzmaEnc_p
2942370b324cSopenharmony_ci  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
2943370b324cSopenharmony_ci}
2944370b324cSopenharmony_ci*/
2945370b324cSopenharmony_ci
2946370b324cSopenharmony_ciconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p)
2947370b324cSopenharmony_ci{
2948370b324cSopenharmony_ci  // GET_const_CLzmaEnc_p
2949370b324cSopenharmony_ci  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2950370b324cSopenharmony_ci}
2951370b324cSopenharmony_ci
2952370b324cSopenharmony_ci
2953370b324cSopenharmony_ci// (desiredPackSize == 0) is not allowed
2954370b324cSopenharmony_ciSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,
2955370b324cSopenharmony_ci    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
2956370b324cSopenharmony_ci{
2957370b324cSopenharmony_ci  // GET_CLzmaEnc_p
2958370b324cSopenharmony_ci  UInt64 nowPos64;
2959370b324cSopenharmony_ci  SRes res;
2960370b324cSopenharmony_ci  CLzmaEnc_SeqOutStreamBuf outStream;
2961370b324cSopenharmony_ci
2962370b324cSopenharmony_ci  outStream.vt.Write = SeqOutStreamBuf_Write;
2963370b324cSopenharmony_ci  outStream.data = dest;
2964370b324cSopenharmony_ci  outStream.rem = *destLen;
2965370b324cSopenharmony_ci  outStream.overflow = False;
2966370b324cSopenharmony_ci
2967370b324cSopenharmony_ci  p->writeEndMark = False;
2968370b324cSopenharmony_ci  p->finished = False;
2969370b324cSopenharmony_ci  p->result = SZ_OK;
2970370b324cSopenharmony_ci
2971370b324cSopenharmony_ci  if (reInit)
2972370b324cSopenharmony_ci    LzmaEnc_Init(p);
2973370b324cSopenharmony_ci  LzmaEnc_InitPrices(p);
2974370b324cSopenharmony_ci  RangeEnc_Init(&p->rc);
2975370b324cSopenharmony_ci  p->rc.outStream = &outStream.vt;
2976370b324cSopenharmony_ci  nowPos64 = p->nowPos64;
2977370b324cSopenharmony_ci
2978370b324cSopenharmony_ci  res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
2979370b324cSopenharmony_ci
2980370b324cSopenharmony_ci  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
2981370b324cSopenharmony_ci  *destLen -= outStream.rem;
2982370b324cSopenharmony_ci  if (outStream.overflow)
2983370b324cSopenharmony_ci    return SZ_ERROR_OUTPUT_EOF;
2984370b324cSopenharmony_ci
2985370b324cSopenharmony_ci  return res;
2986370b324cSopenharmony_ci}
2987370b324cSopenharmony_ci
2988370b324cSopenharmony_ci
2989370b324cSopenharmony_ciZ7_NO_INLINE
2990370b324cSopenharmony_cistatic SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgressPtr progress)
2991370b324cSopenharmony_ci{
2992370b324cSopenharmony_ci  SRes res = SZ_OK;
2993370b324cSopenharmony_ci
2994370b324cSopenharmony_ci  #ifndef Z7_ST
2995370b324cSopenharmony_ci  Byte allocaDummy[0x300];
2996370b324cSopenharmony_ci  allocaDummy[0] = 0;
2997370b324cSopenharmony_ci  allocaDummy[1] = allocaDummy[0];
2998370b324cSopenharmony_ci  #endif
2999370b324cSopenharmony_ci
3000370b324cSopenharmony_ci  for (;;)
3001370b324cSopenharmony_ci  {
3002370b324cSopenharmony_ci    res = LzmaEnc_CodeOneBlock(p, 0, 0);
3003370b324cSopenharmony_ci    if (res != SZ_OK || p->finished)
3004370b324cSopenharmony_ci      break;
3005370b324cSopenharmony_ci    if (progress)
3006370b324cSopenharmony_ci    {
3007370b324cSopenharmony_ci      res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
3008370b324cSopenharmony_ci      if (res != SZ_OK)
3009370b324cSopenharmony_ci      {
3010370b324cSopenharmony_ci        res = SZ_ERROR_PROGRESS;
3011370b324cSopenharmony_ci        break;
3012370b324cSopenharmony_ci      }
3013370b324cSopenharmony_ci    }
3014370b324cSopenharmony_ci  }
3015370b324cSopenharmony_ci
3016370b324cSopenharmony_ci  LzmaEnc_Finish((CLzmaEncHandle)(void *)p);
3017370b324cSopenharmony_ci
3018370b324cSopenharmony_ci  /*
3019370b324cSopenharmony_ci  if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB))
3020370b324cSopenharmony_ci    res = SZ_ERROR_FAIL;
3021370b324cSopenharmony_ci  }
3022370b324cSopenharmony_ci  */
3023370b324cSopenharmony_ci
3024370b324cSopenharmony_ci  return res;
3025370b324cSopenharmony_ci}
3026370b324cSopenharmony_ci
3027370b324cSopenharmony_ci
3028370b324cSopenharmony_ciSRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress,
3029370b324cSopenharmony_ci    ISzAllocPtr alloc, ISzAllocPtr allocBig)
3030370b324cSopenharmony_ci{
3031370b324cSopenharmony_ci  // GET_CLzmaEnc_p
3032370b324cSopenharmony_ci  RINOK(LzmaEnc_Prepare(p, outStream, inStream, alloc, allocBig))
3033370b324cSopenharmony_ci  return LzmaEnc_Encode2(p, progress);
3034370b324cSopenharmony_ci}
3035370b324cSopenharmony_ci
3036370b324cSopenharmony_ci
3037370b324cSopenharmony_ciSRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *props, SizeT *size)
3038370b324cSopenharmony_ci{
3039370b324cSopenharmony_ci  if (*size < LZMA_PROPS_SIZE)
3040370b324cSopenharmony_ci    return SZ_ERROR_PARAM;
3041370b324cSopenharmony_ci  *size = LZMA_PROPS_SIZE;
3042370b324cSopenharmony_ci  {
3043370b324cSopenharmony_ci    // GET_CLzmaEnc_p
3044370b324cSopenharmony_ci    const UInt32 dictSize = p->dictSize;
3045370b324cSopenharmony_ci    UInt32 v;
3046370b324cSopenharmony_ci    props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
3047370b324cSopenharmony_ci
3048370b324cSopenharmony_ci    // we write aligned dictionary value to properties for lzma decoder
3049370b324cSopenharmony_ci    if (dictSize >= ((UInt32)1 << 21))
3050370b324cSopenharmony_ci    {
3051370b324cSopenharmony_ci      const UInt32 kDictMask = ((UInt32)1 << 20) - 1;
3052370b324cSopenharmony_ci      v = (dictSize + kDictMask) & ~kDictMask;
3053370b324cSopenharmony_ci      if (v < dictSize)
3054370b324cSopenharmony_ci        v = dictSize;
3055370b324cSopenharmony_ci    }
3056370b324cSopenharmony_ci    else
3057370b324cSopenharmony_ci    {
3058370b324cSopenharmony_ci      unsigned i = 11 * 2;
3059370b324cSopenharmony_ci      do
3060370b324cSopenharmony_ci      {
3061370b324cSopenharmony_ci        v = (UInt32)(2 + (i & 1)) << (i >> 1);
3062370b324cSopenharmony_ci        i++;
3063370b324cSopenharmony_ci      }
3064370b324cSopenharmony_ci      while (v < dictSize);
3065370b324cSopenharmony_ci    }
3066370b324cSopenharmony_ci
3067370b324cSopenharmony_ci    SetUi32(props + 1, v)
3068370b324cSopenharmony_ci    return SZ_OK;
3069370b324cSopenharmony_ci  }
3070370b324cSopenharmony_ci}
3071370b324cSopenharmony_ci
3072370b324cSopenharmony_ci
3073370b324cSopenharmony_ciunsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p)
3074370b324cSopenharmony_ci{
3075370b324cSopenharmony_ci  // GET_CLzmaEnc_p
3076370b324cSopenharmony_ci  return (unsigned)p->writeEndMark;
3077370b324cSopenharmony_ci}
3078370b324cSopenharmony_ci
3079370b324cSopenharmony_ci
3080370b324cSopenharmony_ciSRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
3081370b324cSopenharmony_ci    int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
3082370b324cSopenharmony_ci{
3083370b324cSopenharmony_ci  SRes res;
3084370b324cSopenharmony_ci  // GET_CLzmaEnc_p
3085370b324cSopenharmony_ci
3086370b324cSopenharmony_ci  CLzmaEnc_SeqOutStreamBuf outStream;
3087370b324cSopenharmony_ci
3088370b324cSopenharmony_ci  outStream.vt.Write = SeqOutStreamBuf_Write;
3089370b324cSopenharmony_ci  outStream.data = dest;
3090370b324cSopenharmony_ci  outStream.rem = *destLen;
3091370b324cSopenharmony_ci  outStream.overflow = False;
3092370b324cSopenharmony_ci
3093370b324cSopenharmony_ci  p->writeEndMark = writeEndMark;
3094370b324cSopenharmony_ci  p->rc.outStream = &outStream.vt;
3095370b324cSopenharmony_ci
3096370b324cSopenharmony_ci  res = LzmaEnc_MemPrepare(p, src, srcLen, 0, alloc, allocBig);
3097370b324cSopenharmony_ci
3098370b324cSopenharmony_ci  if (res == SZ_OK)
3099370b324cSopenharmony_ci  {
3100370b324cSopenharmony_ci    res = LzmaEnc_Encode2(p, progress);
3101370b324cSopenharmony_ci    if (res == SZ_OK && p->nowPos64 != srcLen)
3102370b324cSopenharmony_ci      res = SZ_ERROR_FAIL;
3103370b324cSopenharmony_ci  }
3104370b324cSopenharmony_ci
3105370b324cSopenharmony_ci  *destLen -= (SizeT)outStream.rem;
3106370b324cSopenharmony_ci  if (outStream.overflow)
3107370b324cSopenharmony_ci    return SZ_ERROR_OUTPUT_EOF;
3108370b324cSopenharmony_ci  return res;
3109370b324cSopenharmony_ci}
3110370b324cSopenharmony_ci
3111370b324cSopenharmony_ci
3112370b324cSopenharmony_ciSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
3113370b324cSopenharmony_ci    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
3114370b324cSopenharmony_ci    ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
3115370b324cSopenharmony_ci{
3116370b324cSopenharmony_ci  CLzmaEncHandle p = LzmaEnc_Create(alloc);
3117370b324cSopenharmony_ci  SRes res;
3118370b324cSopenharmony_ci  if (!p)
3119370b324cSopenharmony_ci    return SZ_ERROR_MEM;
3120370b324cSopenharmony_ci
3121370b324cSopenharmony_ci  res = LzmaEnc_SetProps(p, props);
3122370b324cSopenharmony_ci  if (res == SZ_OK)
3123370b324cSopenharmony_ci  {
3124370b324cSopenharmony_ci    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
3125370b324cSopenharmony_ci    if (res == SZ_OK)
3126370b324cSopenharmony_ci      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
3127370b324cSopenharmony_ci          writeEndMark, progress, alloc, allocBig);
3128370b324cSopenharmony_ci  }
3129370b324cSopenharmony_ci
3130370b324cSopenharmony_ci  LzmaEnc_Destroy(p, alloc, allocBig);
3131370b324cSopenharmony_ci  return res;
3132370b324cSopenharmony_ci}
3133370b324cSopenharmony_ci
3134370b324cSopenharmony_ci
3135370b324cSopenharmony_ci/*
3136370b324cSopenharmony_ci#ifndef Z7_ST
3137370b324cSopenharmony_civoid LzmaEnc_GetLzThreads(CLzmaEncHandle p, HANDLE lz_threads[2])
3138370b324cSopenharmony_ci{
3139370b324cSopenharmony_ci  GET_const_CLzmaEnc_p
3140370b324cSopenharmony_ci  lz_threads[0] = p->matchFinderMt.hashSync.thread;
3141370b324cSopenharmony_ci  lz_threads[1] = p->matchFinderMt.btSync.thread;
3142370b324cSopenharmony_ci}
3143370b324cSopenharmony_ci#endif
3144370b324cSopenharmony_ci*/
3145