Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5098 clevermous 1
#include "LZMAEncoder.h"
2
#include "MatchFinder.h"
3
 
4
const byte kLiteralNextStates[kNumStates] = {0,0,0,0,1,2,3,4,5,6,4,5};
5
const byte kMatchNextStates[kNumStates] = {7,7,7,7,7,7,7,10,10,10,10,10};
6
const byte kRepNextStates[kNumStates] = {8,8,8,8,8,8,8,11,11,11,11,11};
7
const byte kShortRepNextStates[kNumStates] = {9,9,9,9,9,9,9,11,11,11,11,11};
8
 
9
static CState _state;
10
static byte _previousByte;
11
static unsigned _repDistances[kNumRepDistances];
12
 
13
static COptimal _optimum[kNumOpts];
14
static CMyBitEncoder _isMatch[kNumStates][kNumPosStatesEncodingMax];
15
static CMyBitEncoder _isRep[kNumStates];
16
static CMyBitEncoder _isRepG0[kNumStates];
17
static CMyBitEncoder _isRepG1[kNumStates];
18
static CMyBitEncoder _isRepG2[kNumStates];
19
static CMyBitEncoder _isRep0Long[kNumStates][kNumPosStatesEncodingMax];
20
static NRangeCoder_CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates];
21
static CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
22
static NRangeCoder_CBitTreeEncoder _posAlignEncoder;
23
static NLength_CPriceTableEncoder _lenEncoder;
24
static NLength_CPriceTableEncoder _repMatchLenEncoder;
25
static CLiteralEncoder _literalEncoder;
26
static unsigned _matchDistances[kMatchMaxLen+1];
27
static unsigned _numFastBytes;
28
static unsigned _longestMatchLength;
29
static unsigned _additionalOffset;
30
static unsigned _optimumEndIndex;
31
static unsigned _optimumCurrentIndex;
32
static bool _longestMatchWasFound;
33
static unsigned _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
34
static unsigned _distancesPrices[kNumLenToPosStates][kNumFullDistances];
35
static unsigned _alignPrices[kAlignTableSize];
36
static unsigned _alignPriceCount;
37
static unsigned _distTableSize;
38
static unsigned _posStateBits;
39
static unsigned _posStateMask;
40
static unsigned _numLiteralPosStateBits;
41
static unsigned _numLiteralContextBits;
42
static unsigned _dictionarySize;
43
static uint64 lastPosSlotFillingPos;
44
static uint64 nowPos64;
45
static bool _finished;
46
static bool _writeEndMark;
47
 
48
static byte g_FastPos[1024];
49
 
50
// must be called before work
51
static void FastPosInit(void)
52
{
53
	int c = 2;
54
	int slotFast;
55
	unsigned j,k;
56
	g_FastPos[0] = 0;
57
	g_FastPos[1] = 1;
58
	for (slotFast = 2; slotFast < 20; slotFast++)
59
	{
60
		k = (1 << ((slotFast >> 1) - 1));
61
		for (j=0;j
62
	}
63
}
64
static unsigned GetPosSlot(unsigned pos)
65
{
66
	if (pos < (1<<10))
67
		return g_FastPos[pos];
68
	if (pos < (1<<19))
69
		return g_FastPos[pos>>9]+18;
70
	return g_FastPos[pos>>18]+36;
71
}
72
static unsigned GetPosSlot2(unsigned pos)
73
{
74
	if (pos < (1<<16))
75
		return g_FastPos[pos>>6]+12;
76
	if (pos < (1<<25))
77
		return g_FastPos[pos>>15]+30;
78
	return g_FastPos[pos>>24]+48;
79
}
80
 
81
unsigned pack_length;
82
unsigned pack_pos;
83
const byte* curin;
84
byte* curout;
85
 
86
static void NLength_CEncoder_Init(NLength_CEncoder*e, unsigned numPosStates)
87
{
88
	unsigned posState;
89
	CMyBitEncoder_Init(e->_choice);
90
	CMyBitEncoder_Init(e->_choice2);
91
	for (posState=0;posState
92
	{
93
		CBitTreeEncoder_Init(&e->_lowCoder[posState],kNumLowBits);
94
		CBitTreeEncoder_Init(&e->_midCoder[posState],kNumMidBits);
95
	}
96
	CBitTreeEncoder_Init(&e->_highCoder,kNumHighBits);
97
}
98
 
99
static void NLength_CEncoder_Encode(NLength_CEncoder*e, unsigned symbol, unsigned posState)
100
{
101
	if (symbol < kNumLowSymbols)
102
	{
103
		CMyBitEncoder_Encode(&e->_choice,0);
104
		CBitTreeEncoder_Encode(&e->_lowCoder[posState],symbol);
105
	}
106
	else
107
	{
108
		CMyBitEncoder_Encode(&e->_choice,1);
109
		if (symbol < kNumLowSymbols + kNumMidSymbols)
110
		{
111
			CMyBitEncoder_Encode(&e->_choice2,0);
112
			CBitTreeEncoder_Encode(&e->_midCoder[posState],symbol-kNumLowSymbols);
113
		}
114
		else
115
		{
116
			CMyBitEncoder_Encode(&e->_choice2,1);
117
			CBitTreeEncoder_Encode(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols);
118
		}
119
	}
120
}
121
 
122
static unsigned NLength_CEncoder_GetPrice(NLength_CEncoder*e, unsigned symbol, unsigned posState)
123
{
124
	unsigned price;
125
	if (symbol < kNumLowSymbols)
126
		return CMyBitEncoder_GetPrice0(&e->_choice) +
127
			CBitTreeEncoder_GetPrice(&e->_lowCoder[posState],symbol);
128
	price = CMyBitEncoder_GetPrice1(&e->_choice);
129
	if (symbol < kNumLowSymbols + kNumMidSymbols)
130
	{
131
		price += CMyBitEncoder_GetPrice0(&e->_choice2);
132
		price += CBitTreeEncoder_GetPrice(&e->_midCoder[posState],symbol-kNumLowSymbols);
133
	}
134
	else
135
	{
136
		price += CMyBitEncoder_GetPrice1(&e->_choice2);
137
		price += CBitTreeEncoder_GetPrice(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols);
138
	}
139
	return price;
140
}
141
 
142
static void CPriceTableEncoder_SetTableSize(NLength_CPriceTableEncoder*pte,unsigned tableSize)
143
{pte->_tableSize = tableSize;}
144
static unsigned CPriceTableEncoder_GetPrice(NLength_CPriceTableEncoder*pte,unsigned symbol,unsigned posState)
145
{return pte->_prices[symbol][posState];}
146
static void CPriceTableEncoder_UpdateTable(NLength_CPriceTableEncoder*pte,unsigned posState)
147
{
148
	unsigned len;
149
	for (len=0;len_tableSize;len++)
150
		pte->_prices[len][posState] = NLength_CEncoder_GetPrice(&pte->base,len,posState);
151
	pte->_counters[posState] = pte->_tableSize;
152
}
153
static void CPriceTableEncoder_UpdateTables(NLength_CPriceTableEncoder*pte,unsigned numPosStates)
154
{
155
	unsigned posState;
156
	for (posState=0;posState
157
		CPriceTableEncoder_UpdateTable(pte,posState);
158
}
159
static void CPriceTableEncoder_Encode(NLength_CPriceTableEncoder*pte, unsigned symbol, unsigned posState)
160
{
161
	NLength_CEncoder_Encode(&pte->base,symbol,posState);
162
	if (--pte->_counters[posState] == 0)
163
		CPriceTableEncoder_UpdateTable(pte,posState);
164
}
165
 
166
static void CBaseState_Init(void)
167
{
168
	unsigned i;
169
	CState_Init(_state);
170
	_previousByte = 0;
171
	for (i=0;i
172
		_repDistances[i] = 0;
173
}
174
 
175
static void CLiteralEncoder2_Init(CLiteralEncoder2 le)
176
{
177
	int i;
178
	for (i=0;i<0x300;i++)
179
		CMyBitEncoder_Init(le[i]);
180
}
181
 
182
static void CLiteralEncoder2_Encode(CLiteralEncoder2 le, byte symbol)
183
{
184
	unsigned context = 1;
185
	int i;
186
	unsigned bit;
187
	for (i=8;i--;)
188
	{
189
		bit = (symbol >> i) & 1;
190
		CMyBitEncoder_Encode(&le[context],bit);
191
		context = (context << 1) | bit;
192
	}
193
}
194
 
195
static void CLiteralEncoder2_EncodeMatched(CLiteralEncoder2 le, byte matchByte, byte symbol)
196
{
197
	unsigned context = 1;
198
	int i;
199
	unsigned bit,matchBit;
200
	for (i=8;i--;)
201
	{
202
		bit = (symbol >> i) & 1;
203
		matchBit = (matchByte >> i) & 1;
204
		CMyBitEncoder_Encode(&le[0x100 + (matchBit<<8) + context],bit);
205
		context = (context << 1) | bit;
206
		if (matchBit != bit)
207
		{
208
			while (i--)
209
			{
210
				bit = (symbol >> i) & 1;
211
				CMyBitEncoder_Encode(&le[context],bit);
212
				context = (context << 1) | bit;
213
			}
214
			break;
215
		}
216
	}
217
}
218
 
219
static unsigned CLiteralEncoder2_GetPrice(CLiteralEncoder2 le, bool matchMode, byte matchByte, byte symbol)
220
{
221
	unsigned price = 0;
222
	unsigned context = 1;
223
	unsigned bit,matchBit;
224
	int i = 8;
225
	if (matchMode)
226
	{
227
		do
228
		{
229
			i--;
230
			matchBit = (matchByte >> i) & 1;
231
			bit = (symbol >> i) & 1;
232
			price += CMyBitEncoder_GetPrice(&le[0x100 + (matchBit<<8) + context],bit);
233
			context = (context << 1) | bit;
234
			if (matchBit != bit)
235
				break;
236
		} while (i);
237
	}
238
	while (i--)
239
	{
240
		bit = (symbol >> i) & 1;
241
		price += CMyBitEncoder_GetPrice(&le[context],bit);
242
		context = (context << 1) | bit;
243
	}
244
	return price;
245
}
246
 
247
static void WriteEndMarker(unsigned posState)
248
{
249
	unsigned posSlot;
250
	if (!_writeEndMark)
251
		return;
252
	CMyBitEncoder_Encode(&_isMatch[_state][posState],1);
253
	CMyBitEncoder_Encode(&_isRep[_state],0);
254
	CState_UpdateMatch(_state);
255
	CPriceTableEncoder_Encode(&_lenEncoder,0,posState);
256
	posSlot = (1<
257
	CBitTreeEncoder_Encode(&_posSlotEncoder[GetLenToPosState(kMatchMinLen)],posSlot);
258
	RangeEncoder_EncodeDirectBits(((1<<30)-1)>>kNumAlignBits,30-kNumAlignBits);
259
	CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,((1<<30)-1) & kAlignMask);
260
}
261
 
262
static void CEncoder_Flush(void)
263
{
264
	WriteEndMarker((unsigned)nowPos64 & _posStateMask);
265
	RangeEncoder_FlushData();
266
}
267
 
268
static void CLiteralEncoder_Create(CLiteralEncoder*le, byte** memory, int numPosBits, int numPrevBits)
269
{
270
	unsigned numStates;
271
	le->_coders = (CLiteralEncoder2*)*memory;
272
	numStates = 1 << (numPosBits+numPrevBits);
273
	*memory = (byte*)(le->_coders + numStates);
274
	le->_numPosBits = numPosBits;
275
	le->_posMask = (1<
276
	le->_numPrevBits = numPrevBits;
277
}
278
 
279
static void CLiteralEncoder_Init(CLiteralEncoder*le)
280
{
281
	unsigned numStates,i;
282
	numStates = 1 << (le->_numPosBits + le->_numPrevBits);
283
	for (i=0;i
284
		CLiteralEncoder2_Init(le->_coders[i]);
285
}
286
 
287
static unsigned CLiteralEncoder_GetState(CLiteralEncoder*le,unsigned pos,byte prevByte)
288
{return ((pos&le->_posMask)<_numPrevBits)+(prevByte>>(8-le->_numPrevBits));}
289
static CLiteralEncoder2* CLiteralEncoder_GetSubCoder(CLiteralEncoder*le,unsigned pos,byte prevByte)
290
{return &le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)];}
291
 
292
static unsigned CLiteralEncoder_GetPrice(CLiteralEncoder*le,unsigned pos,byte prevByte,
293
	bool matchMode, byte matchByte, byte symbol)
294
{
295
	return CLiteralEncoder2_GetPrice(le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)],
296
		matchMode, matchByte, symbol);
297
}
298
 
299
static void CEncoder_Create(void*workmem)
300
{
301
	byte* workpos = (byte*)workmem;
302
	/* align on dword boundary */
303
	unsigned a;
304
	a = (unsigned)workpos & 3;
305
	if (a) workpos += 4-a;
306
	/* sizeof(CLiteralEncoder2) * (1<<(numPosBits+numPrevBits)) for literal encoders */
307
	/* = 0xC00 * 8 = 0x6000 with current settings */
308
	CLiteralEncoder_Create(&_literalEncoder,&workpos,_numLiteralPosStateBits,_numLiteralContextBits);
309
	/* (dictsize+0x1223)*1.5+256 for LZ input window */
310
	/* (0x140400 + (dictsize+1)*2) * 4 for match finder hash */
311
	MatchFinder_Create(_dictionarySize,kNumOpts,_numFastBytes,
312
		kMatchMaxLen*2+1-_numFastBytes,&workpos);
313
	/* total 0x508C3C + dictsize*9.5 */
314
	/* plus max 6 bytes for alignment */
315
}
316
 
317
static void CEncoder_Init(void)
318
{
319
	int i;
320
	unsigned j;
321
	CBaseState_Init();
322
	RangeEncoder_Init();
323
	for (i=0;i
324
	{
325
		for (j=0;j<=_posStateMask;j++)
326
		{
327
			CMyBitEncoder_Init(_isMatch[i][j]);
328
			CMyBitEncoder_Init(_isRep0Long[i][j]);
329
		}
330
		CMyBitEncoder_Init(_isRep[i]);
331
		CMyBitEncoder_Init(_isRepG0[i]);
332
		CMyBitEncoder_Init(_isRepG1[i]);
333
		CMyBitEncoder_Init(_isRepG2[i]);
334
	}
335
	CLiteralEncoder_Init(&_literalEncoder);
336
	for (i=0;i
337
		CBitTreeEncoder_Init(_posSlotEncoder+i,kNumPosSlotBits);
338
	for (i=0;i
339
		CMyBitEncoder_Init(_posEncoders[i]);
340
	CPriceTableEncoder_Init(_lenEncoder, 1<<_posStateBits);
341
	CPriceTableEncoder_Init(_repMatchLenEncoder,1<<_posStateBits);
342
	CBitTreeEncoder_Init(&_posAlignEncoder,kNumAlignBits);
343
	_longestMatchWasFound = false;
344
	_optimumEndIndex = 0;
345
	_optimumCurrentIndex = 0;
346
	_additionalOffset = 0;
347
}
348
 
349
static void MovePos(unsigned num)
350
{
351
	for (;num--;)
352
	{
353
		DummyLongestMatch();
354
		MatchFinder_MovePos();
355
		_additionalOffset++;
356
	}
357
}
358
 
359
static unsigned Backward(unsigned* backRes, unsigned cur)
360
{
361
	unsigned posMem,backMem;
362
	unsigned posPrev,backCur;
363
	_optimumEndIndex = cur;
364
	posMem = _optimum[cur].PosPrev;
365
	backMem = _optimum[cur].BackPrev;
366
	do
367
	{
368
		if (_optimum[cur].Prev1IsChar)
369
		{
370
			COptimal_MakeAsChar(&_optimum[posMem]);
371
			_optimum[posMem].PosPrev = posMem-1;
372
			if (_optimum[cur].Prev2)
373
			{
374
				_optimum[posMem-1].Prev1IsChar = false;
375
				_optimum[posMem-1].PosPrev = _optimum[cur].PosPrev2;
376
				_optimum[posMem-1].BackPrev = _optimum[cur].BackPrev2;
377
			}
378
		}
379
		posPrev = posMem;
380
		backCur = backMem;
381
		backMem = _optimum[posPrev].BackPrev;
382
		posMem = _optimum[posPrev].PosPrev;
383
		_optimum[posPrev].BackPrev = backCur;
384
		_optimum[posPrev].PosPrev = cur;
385
		cur = posPrev;
386
	} while (cur);
387
	*backRes = _optimum[0].BackPrev;
388
	_optimumCurrentIndex = _optimum[0].PosPrev;
389
	return _optimumCurrentIndex;
390
}
391
 
392
static unsigned ReadMatchDistances(void)
393
{
394
	unsigned res;
395
	res = GetLongestMatch(_matchDistances);
396
	if (res == _numFastBytes)
397
		res += GetMatchLen(res,_matchDistances[res],kMatchMaxLen-res);
398
	_additionalOffset++;
399
	MatchFinder_MovePos();
400
	return res;
401
}
402
 
403
static void FillPosSlotPrices(void)
404
{
405
	unsigned lenToPosState,posSlot;
406
	for (lenToPosState=0;lenToPosState
407
	{
408
		for (posSlot=0;posSlot
409
			_posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot);
410
		for (;posSlot<_distTableSize;posSlot++)
411
			_posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot) +
412
				(((posSlot>>1)-1-kNumAlignBits)<
413
	}
414
}
415
 
416
static void FillDistancesPrices(void)
417
{
418
	unsigned lenToPosState,i;
419
	unsigned posSlot,footerBits,base;
420
	for (lenToPosState=0;lenToPosState
421
	{
422
		for (i=0;i
423
			_distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
424
		for (;i
425
		{
426
			posSlot = GetPosSlot(i);
427
			footerBits = ((posSlot>>1)-1);
428
			base = (2|(posSlot&1))<
429
			_distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
430
				ReverseBitTreeGetPrice(_posEncoders+base-posSlot-1,footerBits,i-base);
431
		}
432
	}
433
}
434
 
435
static void FillAlignPrices(void)
436
{
437
	unsigned i;
438
	for (i=0;i
439
		_alignPrices[i] = CBitTreeEncoder_ReverseGetPrice(&_posAlignEncoder,i);
440
	_alignPriceCount = kAlignTableSize;
441
}
442
 
443
static unsigned GetRepLen1Price(CState state, unsigned posState)
444
{
445
	return CMyBitEncoder_GetPrice0(&_isRepG0[state]) +
446
		CMyBitEncoder_GetPrice0(&_isRep0Long[state][posState]);
447
}
448
static unsigned GetRepPrice(unsigned repIndex, unsigned len, CState state, unsigned posState)
449
{
450
	unsigned price;
451
	price = CPriceTableEncoder_GetPrice(&_repMatchLenEncoder,len-kMatchMinLen,posState);
452
	if (!repIndex)
453
	{
454
		price += CMyBitEncoder_GetPrice0(&_isRepG0[state]);
455
		price += CMyBitEncoder_GetPrice1(&_isRep0Long[state][posState]);
456
	}
457
	else
458
	{
459
		price += CMyBitEncoder_GetPrice1(&_isRepG0[state]);
460
		if (repIndex == 1)
461
			price += CMyBitEncoder_GetPrice0(&_isRepG1[state]);
462
		else
463
		{
464
			price += CMyBitEncoder_GetPrice1(&_isRepG1[state]);
465
			price += CMyBitEncoder_GetPrice(&_isRepG2[state],repIndex-2);
466
		}
467
	}
468
	return price;
469
}
470
static unsigned GetPosLenPrice(unsigned pos, unsigned len, unsigned posState)
471
{
472
	unsigned price,lenToPosState;
473
	if (len==2 && pos>=0x80)
474
		return kIfinityPrice;
475
	lenToPosState = GetLenToPosState(len);
476
	if (pos < kNumFullDistances)
477
		price = _distancesPrices[lenToPosState][pos];
478
	else
479
		price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
480
			_alignPrices[pos & kAlignMask];
481
	return price + CPriceTableEncoder_GetPrice(&_lenEncoder,len-kMatchMinLen,posState);
482
}
483
 
484
static void GetOptimum(unsigned position,unsigned*backRes,unsigned*lenRes)
485
{
486
	int lenMain,lenEnd;
487
	COptimal* opt,*prevOpt;
488
	int reps[kNumRepDistances];
489
	int repLens[kNumRepDistances];
490
	int repIndex,repMaxIndex;
491
	int i,len,repLen,lenTest,newLen,lenTestTemp,lenTest2;
492
	int posState,posStateNext;
493
	byte currentByte,matchByte;
494
	unsigned matchPrice,repMatchPrice,shortRepPrice,normalMatchPrice,curAndLenPrice,curPrice,curAnd1Price,curAndLenCharPrice;
495
	unsigned nextMatchPrice,nextRepMatchPrice;
496
	int cur,posPrev,pos;
497
	CState state,state2;
498
	const byte* data;
499
	bool nextIsChar;
500
	int numAvailableBytesFull,numAvailableBytes;
501
	int backOffset,offset;
502
	int limit;
503
	if (_optimumEndIndex != _optimumCurrentIndex)
504
	{
505
		opt = &_optimum[_optimumCurrentIndex];
506
		*lenRes = opt->PosPrev - _optimumCurrentIndex;
507
		*backRes = opt->BackPrev;
508
		_optimumCurrentIndex = opt->PosPrev;
509
		return;
510
	}
511
	_optimumCurrentIndex = _optimumEndIndex = 0;
512
	if (!_longestMatchWasFound)
513
		lenMain = ReadMatchDistances();
514
	else
515
	{
516
		lenMain = _longestMatchLength;
517
		_longestMatchWasFound = false;
518
	}
519
	for (i=0;i
520
	{
521
		reps[i] = _repDistances[i];
522
		repLens[i] = GetMatchLen(0-1,reps[i],kMatchMaxLen);
523
		if (i==0 || repLens[i] > repLens[repMaxIndex])
524
			repMaxIndex = i;
525
	}
526
	if (repLens[repMaxIndex] >= _numFastBytes)
527
	{
528
		*backRes = repMaxIndex;
529
		*lenRes = repLens[repMaxIndex];
530
		MovePos(*lenRes-1);
531
		return;
532
	}
533
	if (lenMain >= _numFastBytes)
534
	{
535
		*backRes = _matchDistances[_numFastBytes]+kNumRepDistances;
536
		*lenRes = lenMain;
537
		MovePos(lenMain-1);
538
		return;
539
	}
540
	currentByte = GetIndexByte(0-1);
541
	_optimum[0].State = _state;
542
	matchByte = GetIndexByte(0-_repDistances[0]-2);
543
	posState = position & _posStateMask;
544
	_optimum[1].Price = CMyBitEncoder_GetPrice0(&_isMatch[_state][posState]) +
545
		CLiteralEncoder_GetPrice(&_literalEncoder,position,_previousByte,
546
		(bool)!CState_IsCharState(_state),matchByte,currentByte);
547
	COptimal_MakeAsChar(&_optimum[1]);
548
	_optimum[1].PosPrev = 0;
549
	for (i=0;i
550
		_optimum[0].Backs[i] = reps[i];
551
	matchPrice = CMyBitEncoder_GetPrice1(&_isMatch[_state][posState]);
552
	repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[_state]);
553
	if (matchByte == currentByte)
554
	{
555
		shortRepPrice = repMatchPrice + GetRepLen1Price(_state,posState);
556
		if (shortRepPrice < _optimum[1].Price)
557
		{
558
			_optimum[1].Price = shortRepPrice;
559
			COptimal_MakeAsShortRep(&_optimum[1]);
560
		}
561
	}
562
	if (lenMain < 2)
563
	{
564
		*backRes = _optimum[1].BackPrev;
565
		*lenRes = 1;
566
		return;
567
	}
568
	normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[_state]);
569
	if (lenMain <= repLens[repMaxIndex])
570
		lenMain = 0;
571
	for (len=2;len<=lenMain;len++)
572
	{
573
		_optimum[len].PosPrev = 0;
574
		_optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
575
		_optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len],len,posState);
576
		_optimum[len].Prev1IsChar = false;
577
	}
578
	if (lenMain < repLens[repMaxIndex])
579
		lenMain = repLens[repMaxIndex];
580
	for (;len<=lenMain;len++)
581
		_optimum[len].Price = kIfinityPrice;
582
	for (i=0;i
583
	{
584
		repLen = repLens[i];
585
		for (lenTest=2;lenTest<=repLen;lenTest++)
586
		{
587
			curAndLenPrice = repMatchPrice + GetRepPrice(i,lenTest,_state,posState);
588
			opt = &_optimum[lenTest];
589
			if (curAndLenPrice < opt->Price)
590
			{
591
				opt->Price = curAndLenPrice;
592
				opt->PosPrev = 0;
593
				opt->BackPrev = i;
594
				opt->Prev1IsChar = false;
595
			}
596
		}
597
	}
598
	cur=0;
599
	lenEnd = lenMain;
600
	while (1)
601
	{
602
		cur++;
603
		if (cur==lenEnd)
604
		{
605
			*lenRes = Backward(backRes,cur);
606
			return;
607
		}
608
		position++;
609
		opt = &_optimum[cur];
610
		posPrev = opt->PosPrev;
611
		if (opt->Prev1IsChar)
612
		{
613
			posPrev--;
614
			if (opt->Prev2)
615
			{
616
				state = _optimum[opt->PosPrev2].State;
617
				if (opt->BackPrev2 < kNumRepDistances)
618
					CState_UpdateRep(state);
619
				else
620
					CState_UpdateMatch(state);
621
			}
622
			else
623
				state = _optimum[posPrev].State;
624
			CState_UpdateChar(state);
625
		}
626
		else
627
			state = _optimum[posPrev].State;
628
		if (posPrev == cur-1)
629
		{
630
			if (COptimal_IsShortRep(opt))
631
				CState_UpdateShortRep(state);
632
			else
633
				CState_UpdateChar(state);
634
		}
635
		else
636
		{
637
			if (opt->Prev1IsChar && opt->Prev2)
638
			{
639
				posPrev = opt->PosPrev2;
640
				pos = opt->BackPrev2;
641
				CState_UpdateRep(state);
642
			}
643
			else
644
			{
645
				pos = opt->BackPrev;
646
				if (pos < kNumRepDistances)
647
					CState_UpdateRep(state);
648
				else
649
					CState_UpdateMatch(state);
650
			}
651
			prevOpt = &_optimum[posPrev];
652
			if (pos < kNumRepDistances)
653
			{
654
				reps[0] = prevOpt->Backs[pos];
655
				for (i=1;i<=pos;i++)
656
					reps[i] = prevOpt->Backs[i-1];
657
				for (;i
658
					reps[i] = prevOpt->Backs[i];
659
			}
660
			else
661
			{
662
				reps[0] = pos-kNumRepDistances;
663
				for (i=1;i
664
					reps[i] = prevOpt->Backs[i-1];
665
			}
666
		}
667
		opt->State = state;
668
		for (i=0;i
669
			opt->Backs[i] = reps[i];
670
		newLen = ReadMatchDistances();
671
		if (newLen >= _numFastBytes)
672
		{
673
			_longestMatchLength = newLen;
674
			_longestMatchWasFound = true;
675
			*lenRes = Backward(backRes,cur);
676
			return;
677
		}
678
		curPrice = opt->Price;
679
		data = GetPointerToCurrentPos()-1;
680
		currentByte = *data;
681
		matchByte = data[-1-reps[0]];
682
		posState = position & _posStateMask;
683
		curAnd1Price = curPrice + CMyBitEncoder_GetPrice0(&_isMatch[state][posState]) +
684
			CLiteralEncoder_GetPrice(&_literalEncoder,position,data[-1],(bool)!CState_IsCharState(state),matchByte,currentByte);
685
		opt = &_optimum[cur+1];
686
		nextIsChar = false;
687
		if (curAnd1Price < opt->Price)
688
		{
689
			opt->Price = curAnd1Price;
690
			opt->PosPrev = cur;
691
			COptimal_MakeAsChar(opt);
692
			nextIsChar = true;
693
		}
694
		matchPrice = curPrice + CMyBitEncoder_GetPrice1(&_isMatch[state][posState]);
695
		repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[state]);
696
		if (matchByte == currentByte && !(opt->PosPrevBackPrev))
697
		{
698
			shortRepPrice = repMatchPrice + GetRepLen1Price(state,posState);
699
			if (shortRepPrice <= opt->Price)
700
			{
701
				opt->Price = shortRepPrice;
702
				opt->PosPrev = cur;
703
				COptimal_MakeAsShortRep(opt);
704
			}
705
		}
706
		numAvailableBytesFull = GetNumAvailableBytes()+1;
707
		if (numAvailableBytesFull > kNumOpts-1-cur)
708
			numAvailableBytesFull = kNumOpts-1-cur;
709
		numAvailableBytes = numAvailableBytesFull;
710
		if (numAvailableBytes < 2)
711
			continue;
712
		if (numAvailableBytes > _numFastBytes)
713
			numAvailableBytes = _numFastBytes;
714
		if (numAvailableBytes >= 3 && !nextIsChar)
715
		{
716
			// try Literal + rep0
717
			int temp;
718
			backOffset = reps[0]+1;
719
			for (temp=1;temp
720
				if (data[temp]!=data[temp-backOffset])
721
					break;
722
			lenTest = temp-1;
723
			if (lenTest>=2)
724
			{
725
				int posStateNext;
726
				unsigned nextRepMatchPrice;
727
				state2 = state;
728
				CState_UpdateChar(state2);
729
				posStateNext = (position+1) & _posStateMask;
730
				nextRepMatchPrice = curAnd1Price +
731
					CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]) +
732
					CMyBitEncoder_GetPrice1(&_isRep[state2]);
733
				while (lenEnd < cur+1+lenTest)
734
					_optimum[++lenEnd].Price = kIfinityPrice;
735
				curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest,state2,posStateNext);
736
				opt = &_optimum[cur+1+lenTest];
737
				if (curAndLenPrice < opt->Price)
738
				{
739
					opt->Price = curAndLenPrice;
740
					opt->PosPrev = cur+1;
741
					opt->BackPrev = 0;
742
					opt->Prev1IsChar = true;
743
					opt->Prev2 = false;
744
				}
745
			}
746
		}
747
		for (repIndex=0;repIndex
748
		{
749
			backOffset = reps[repIndex]+1;
750
			if (data[0] != data[0-backOffset] ||
751
				data[1] != data[1-backOffset])
752
				continue;
753
			for (lenTest=2;lenTest
754
				if (data[lenTest]!=data[lenTest-backOffset])
755
					break;
756
			lenTestTemp = lenTest;
757
			do
758
			{
759
				while (lenEnd < cur+lenTest)
760
					_optimum[++lenEnd].Price = kIfinityPrice;
761
				curAndLenPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState);
762
				opt = &_optimum[cur+lenTest];
763
				if (curAndLenPrice < opt->Price)
764
				{
765
					opt->Price = curAndLenPrice;
766
					opt->PosPrev = cur;
767
					opt->BackPrev = repIndex;
768
					opt->Prev1IsChar = false;
769
				}
770
			} while (--lenTest>=2);
771
			lenTest = lenTestTemp;
772
			lenTest2 = lenTest+1;
773
			limit = lenTest2 + _numFastBytes;
774
			if (limit > numAvailableBytesFull)
775
				limit = numAvailableBytesFull;
776
			for (;lenTest2
777
				if (data[lenTest2] != data[lenTest2-backOffset])
778
					break;
779
			lenTest2 -= lenTest+1;
780
			if (lenTest2 >= 2)
781
			{
782
				unsigned nextMatchPrice,nextRepMatchPrice;
783
				int offset;
784
				state2 = state;
785
				CState_UpdateRep(state2);
786
				posStateNext = (position+lenTest)&_posStateMask;
787
				curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState) +
788
					CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) +
789
					CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]);
790
				CState_UpdateChar(state2);
791
				posStateNext = (position+lenTest+1)&_posStateMask;
792
				nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]);
793
				nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]);
794
				offset = lenTest+1+lenTest2;
795
				while (lenEnd
796
					_optimum[++lenEnd].Price = kIfinityPrice;
797
				curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext);
798
				opt = &_optimum[cur+offset];
799
				if (curAndLenPrice < opt->Price)
800
				{
801
					opt->Price = curAndLenPrice;
802
					opt->PosPrev = cur+lenTest+1;
803
					opt->BackPrev = 0;
804
					opt->Prev1IsChar = true;
805
					opt->Prev2 = true;
806
					opt->PosPrev2 = cur;
807
					opt->BackPrev2 = repIndex;
808
				}
809
			}
810
		}
811
		if (newLen > numAvailableBytes)
812
			newLen = numAvailableBytes;
813
		if (newLen >= 2)
814
		{
815
			if (newLen==2 && _matchDistances[2] >= 0x80)
816
				continue;
817
			normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[state]);
818
			while (lenEnd < cur+newLen)
819
				_optimum[++lenEnd].Price = kIfinityPrice;
820
			for (lenTest=newLen;lenTest>=2;lenTest--)
821
			{
822
				backOffset = _matchDistances[lenTest];
823
				curAndLenPrice = normalMatchPrice + GetPosLenPrice(backOffset,lenTest,posState);
824
				opt = &_optimum[cur+lenTest];
825
				if (curAndLenPrice < opt->Price)
826
				{
827
					opt->Price = curAndLenPrice;
828
					opt->PosPrev = cur;
829
					opt->BackPrev = backOffset+kNumRepDistances;
830
					opt->Prev1IsChar = false;
831
				}
832
				if (lenTest==newLen || backOffset!=_matchDistances[lenTest+1])
833
				{
834
					// Try Match + Literal + Rep0
835
					backOffset++;
836
					lenTest2 = lenTest+1;
837
					limit = lenTest2+_numFastBytes;
838
					if (limit > numAvailableBytesFull)
839
						limit = numAvailableBytesFull;
840
					for (;lenTest2
841
						if (data[lenTest2]!=data[lenTest2-backOffset])
842
							break;
843
					lenTest2 -= lenTest+1;
844
					if (lenTest2 >= 2)
845
					{
846
						state2 = state;
847
						CState_UpdateMatch(state2);
848
						posStateNext = (position+lenTest)&_posStateMask;
849
						curAndLenCharPrice = curAndLenPrice + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) +
850
							CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]);
851
						CState_UpdateChar(state2);
852
						posStateNext = (position+lenTest+1)&_posStateMask;
853
						nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]);
854
						nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]);
855
						offset = lenTest+1+lenTest2;
856
						while (lenEnd
857
							_optimum[++lenEnd].Price = kIfinityPrice;
858
						curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext);
859
						opt = &_optimum[cur+offset];
860
						if (curAndLenPrice < opt->Price)
861
						{
862
							opt->Price = curAndLenPrice;
863
							opt->PosPrev = cur+lenTest+1;
864
							opt->BackPrev = 0;
865
							opt->Prev1IsChar = true;
866
							opt->Prev2 = true;
867
							opt->PosPrev2 = cur;
868
							opt->BackPrev2 = backOffset - 1 + kNumRepDistances;
869
						}
870
					}
871
				}
872
			}
873
		}
874
	}
875
}
876
 
877
static bool CodeOneBlock(void)
878
{
879
	unsigned posState;
880
	byte curByte,matchByte;
881
	unsigned pos,len,distance,i;
882
	unsigned posSlot,lenToPosState;
883
	CLiteralEncoder2* subCoder;
884
	uint64 progressPosValuePrev;
885
 
886
	if (_finished)
887
		return false;
888
	_finished = true;
889
	progressPosValuePrev = nowPos64;
890
	if (nowPos64 == 0)
891
	{
892
		if (GetNumAvailableBytes() == 0)
893
		{
894
			CEncoder_Flush();
895
			return false;
896
		}
897
		ReadMatchDistances();
898
		posState = (unsigned)nowPos64 & _posStateMask;
899
		CMyBitEncoder_Encode(&_isMatch[_state][posState],0);
900
		CState_UpdateChar(_state);
901
		curByte = GetIndexByte(0 - _additionalOffset);
902
		CLiteralEncoder2_Encode(
903
			*CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,_previousByte),
904
			curByte);
905
		_previousByte = curByte;
906
		_additionalOffset--;
907
		nowPos64++;
908
	}
909
	if (GetNumAvailableBytes() == 0)
910
	{
911
		CEncoder_Flush();
912
		return false;
913
	}
914
	for (;;)
915
	{
916
		posState = (unsigned)nowPos64 & _posStateMask;
917
		GetOptimum((unsigned)nowPos64,&pos,&len);
918
		if (len==1 && pos==0xFFFFFFFF)
919
		{
920
			CMyBitEncoder_Encode(&_isMatch[_state][posState],0);
921
			curByte = GetIndexByte(0-_additionalOffset);
922
			subCoder = CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,
923
				_previousByte);
924
			if (!CState_IsCharState(_state))
925
			{
926
				matchByte = GetIndexByte(0-_repDistances[0]-1-_additionalOffset);
927
				CLiteralEncoder2_EncodeMatched(*subCoder,matchByte,curByte);
928
			}
929
			else
930
				CLiteralEncoder2_Encode(*subCoder,curByte);
931
			CState_UpdateChar(_state);
932
			_previousByte = curByte;
933
		}
934
		else
935
		{
936
			CMyBitEncoder_Encode(&_isMatch[_state][posState],1);
937
			if (pos < kNumRepDistances)
938
			{
939
				CMyBitEncoder_Encode(&_isRep[_state],1);
940
				if (pos==0)
941
				{
942
					CMyBitEncoder_Encode(&_isRepG0[_state],0);
943
					CMyBitEncoder_Encode(&_isRep0Long[_state][posState],
944
						(len==1) ? 0 : 1);
945
				}
946
				else
947
				{
948
					CMyBitEncoder_Encode(&_isRepG0[_state],1);
949
					if (pos==1)
950
						CMyBitEncoder_Encode(&_isRepG1[_state],0);
951
					else
952
					{
953
						CMyBitEncoder_Encode(&_isRepG1[_state],1);
954
						CMyBitEncoder_Encode(&_isRepG2[_state],pos-2);
955
					}
956
				}
957
				if (len==1)
958
					CState_UpdateShortRep(_state);
959
				else
960
				{
961
					CPriceTableEncoder_Encode(&_repMatchLenEncoder,len-kMatchMinLen,posState);
962
					CState_UpdateRep(_state);
963
				}
964
				distance = _repDistances[pos];
965
				if (pos)
966
				{
967
					for (i=pos;i;i--)
968
						_repDistances[i] = _repDistances[i-1];
969
					_repDistances[0] = distance;
970
				}
971
			}
972
			else
973
			{
974
				CMyBitEncoder_Encode(&_isRep[_state],0);
975
				CState_UpdateMatch(_state);
976
				CPriceTableEncoder_Encode(&_lenEncoder,len-kMatchMinLen,posState);
977
				pos -= kNumRepDistances;
978
				posSlot = GetPosSlot(pos);
979
				lenToPosState = GetLenToPosState(len);
980
				CBitTreeEncoder_Encode(&_posSlotEncoder[lenToPosState],posSlot);
981
				if (posSlot >= kStartPosModelIndex)
982
				{
983
					unsigned footerBits;
984
					unsigned base,posReduced;
985
					footerBits = (posSlot>>1)-1;
986
					base = (2 | (posSlot&1)) << footerBits;
987
					posReduced = pos-base;
988
					if (posSlot < kEndPosModelIndex)
989
						ReverseBitTreeEncode(_posEncoders+base-posSlot-1,
990
							footerBits,posReduced);
991
					else
992
					{
993
						RangeEncoder_EncodeDirectBits(posReduced>>kNumAlignBits,footerBits-kNumAlignBits);
994
						CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,posReduced&kAlignMask);
995
						if (--_alignPriceCount == 0)
996
							FillAlignPrices();
997
					}
998
				}
999
				distance = pos;
1000
				for (i=kNumRepDistances-1;i;i--)
1001
					_repDistances[i] = _repDistances[i-1];
1002
				_repDistances[0] = distance;
1003
			}
1004
			_previousByte = GetIndexByte(len-1-_additionalOffset);
1005
		}
1006
		_additionalOffset -= len;
1007
		nowPos64 += len;
1008
		if (nowPos64 - lastPosSlotFillingPos >= (1<<9))
1009
		{
1010
			FillPosSlotPrices();
1011
			FillDistancesPrices();
1012
			lastPosSlotFillingPos = nowPos64;
1013
		}
1014
		if (!_additionalOffset)
1015
		{
1016
			if (GetNumAvailableBytes() == 0)
1017
			{
1018
				CEncoder_Flush();
1019
				return false;
1020
			}
1021
			if (nowPos64 - progressPosValuePrev >= (1<<12))
1022
			{
1023
				_finished = false;
1024
				return true;
1025
			}
1026
		}
1027
	}
1028
}
1029
 
1030
extern void __stdcall lzma_set_dict_size(
1031
	unsigned logdictsize)
1032
{
1033
	_dictionarySize = 1 << logdictsize;
1034
	_distTableSize = logdictsize*2;
1035
}
1036
 
1037
extern unsigned __stdcall lzma_compress(
1038
	const void* source,
1039
	void* destination,
1040
	unsigned length,
1041
	void* workmem)
1042
{
1043
	FastPosInit();
1044
	//memset(&encoder,0,sizeof(encoder));
1045
	//memset(&rangeEncoder,0,sizeof(rangeEncoder));
1046
	// CEncoder::CEncoder, CEncoder::SetCoderProperties
1047
	_numFastBytes = 128;
1048
#ifdef FOR_KERPACK
1049
        _posStateBits = 0;
1050
        _posStateMask = 0;
1051
#else
1052
	_posStateBits = 2;
1053
        _posStateMask = 3;
1054
#endif
1055
	_numLiteralContextBits = 3;
1056
	_numLiteralPosStateBits = 0;
1057
	_writeEndMark = false;
1058
	// CEncoder::Code - поехали!
1059
	_finished = false;
1060
	CEncoder_Create(workmem);
1061
	CEncoder_Init();
1062
	FillPosSlotPrices();
1063
	FillDistancesPrices();
1064
	FillAlignPrices();
1065
	CPriceTableEncoder_SetTableSize(&_lenEncoder,_numFastBytes+1-kMatchMinLen);
1066
	CPriceTableEncoder_UpdateTables(&_lenEncoder,1<<_posStateBits);
1067
	CPriceTableEncoder_SetTableSize(&_repMatchLenEncoder,_numFastBytes+1-kMatchMinLen);
1068
	CPriceTableEncoder_UpdateTables(&_repMatchLenEncoder,1<<_posStateBits);
1069
	lastPosSlotFillingPos = 0;
1070
	nowPos64 = 0;
1071
	pack_length = length;
1072
	pack_pos = 0;
1073
	curin = (const byte*)source;
1074
	curout = (byte*)destination;
1075
	MatchFinder_Init();
1076
	while (CodeOneBlock()) ;
1077
	return curout - (byte*)destination;
1078
}