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