Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA/LZMAEncoder.h, revision 1.1.1.1
1.1 misho 1: // LZMA/Encoder.h
2:
3: #ifndef __LZMA_ENCODER_H
4: #define __LZMA_ENCODER_H
5:
6: #include "../../../Common/MyCom.h"
7: #include "../../../Common/Alloc.h"
8: #include "../../ICoder.h"
9: #include "../LZ/IMatchFinder.h"
10: #include "../RangeCoder/RangeCoderBitTree.h"
11:
12: #include "LZMA.h"
13:
14: namespace NCompress {
15: namespace NLZMA {
16:
17: typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;
18:
19: class CBaseState
20: {
21: protected:
22: CState _state;
23: Byte _previousByte;
24: UInt32 _repDistances[kNumRepDistances];
25: void Init()
26: {
27: _state.Init();
28: _previousByte = 0;
29: for(UInt32 i = 0 ; i < kNumRepDistances; i++)
30: _repDistances[i] = 0;
31: }
32: };
33:
34: struct COptimal
35: {
36: CState State;
37:
38: bool Prev1IsChar;
39: bool Prev2;
40:
41: UInt32 PosPrev2;
42: UInt32 BackPrev2;
43:
44: UInt32 Price;
45: UInt32 PosPrev; // posNext;
46: UInt32 BackPrev;
47: UInt32 Backs[kNumRepDistances];
48: void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }
49: void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
50: bool IsShortRep() { return (BackPrev == 0); }
51: };
52:
53:
54: extern Byte g_FastPos[1024];
55: inline UInt32 GetPosSlot(UInt32 pos)
56: {
57: if (pos < (1 << 10))
58: return g_FastPos[pos];
59: if (pos < (1 << 19))
60: return g_FastPos[pos >> 9] + 18;
61: return g_FastPos[pos >> 18] + 36;
62: }
63:
64: inline UInt32 GetPosSlot2(UInt32 pos)
65: {
66: if (pos < (1 << 16))
67: return g_FastPos[pos >> 6] + 12;
68: if (pos < (1 << 25))
69: return g_FastPos[pos >> 15] + 30;
70: return g_FastPos[pos >> 24] + 48;
71: }
72:
73: const UInt32 kIfinityPrice = 0xFFFFFFF;
74:
75: const UInt32 kNumOpts = 1 << 12;
76:
77:
78: class CLiteralEncoder2
79: {
80: CMyBitEncoder _encoders[0x300];
81: public:
82: void Init()
83: {
84: for (int i = 0; i < 0x300; i++)
85: _encoders[i].Init();
86: }
87: void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);
88: void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);
89: UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;
90: };
91:
92: class CLiteralEncoder
93: {
94: CLiteralEncoder2 *_coders;
95: int _numPrevBits;
96: int _numPosBits;
97: UInt32 _posMask;
98: public:
99: CLiteralEncoder(): _coders(0) {}
100: ~CLiteralEncoder() { Free(); }
101: void Free()
102: {
103: MyFree(_coders);
104: _coders = 0;
105: }
106: bool Create(int numPosBits, int numPrevBits)
107: {
108: if (_coders == 0 || (numPosBits + numPrevBits) !=
109: (_numPrevBits + _numPosBits) )
110: {
111: Free();
112: UInt32 numStates = 1 << (numPosBits + numPrevBits);
113: _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));
114: }
115: _numPosBits = numPosBits;
116: _posMask = (1 << numPosBits) - 1;
117: _numPrevBits = numPrevBits;
118: return (_coders != 0);
119: }
120: void Init()
121: {
122: UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
123: for (UInt32 i = 0; i < numStates; i++)
124: _coders[i].Init();
125: }
126: UInt32 GetState(UInt32 pos, Byte prevByte) const
127: { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
128: CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
129: { return &_coders[GetState(pos, prevByte)]; }
130: /*
131: void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
132: Byte symbol)
133: { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); }
134: void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte,
135: Byte matchByte, Byte symbol)
136: { _coders[GetState(pos, prevByte)].Encode(rangeEncoder,
137: matchByte, symbol); }
138: */
139: UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const
140: { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); }
141: };
142:
143: namespace NLength {
144:
145: class CEncoder
146: {
147: CMyBitEncoder _choice;
148: CMyBitEncoder _choice2;
149: NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
150: NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
151: NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
152: public:
153: void Init(UInt32 numPosStates);
154: void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
155: UInt32 GetPrice(UInt32 symbol, UInt32 posState) const;
156: };
157:
158: const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
159:
160: class CPriceTableEncoder: public CEncoder
161: {
162: UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax];
163: UInt32 _tableSize;
164: UInt32 _counters[kNumPosStatesEncodingMax];
165: public:
166: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
167: UInt32 GetPrice(UInt32 symbol, UInt32 posState) const
168: { return _prices[symbol][posState]; }
169: void UpdateTable(UInt32 posState)
170: {
171: for (UInt32 len = 0; len < _tableSize; len++)
172: _prices[len][posState] = CEncoder::GetPrice(len, posState);
173: _counters[posState] = _tableSize;
174: }
175: void UpdateTables(UInt32 numPosStates)
176: {
177: for (UInt32 posState = 0; posState < numPosStates; posState++)
178: UpdateTable(posState);
179: }
180: void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
181: {
182: CEncoder::Encode(rangeEncoder, symbol, posState);
183: if (--_counters[posState] == 0)
184: UpdateTable(posState);
185: }
186: };
187:
188: }
189:
190: class CEncoder :
191: public ICompressCoder,
192: public ICompressSetOutStream,
193: public ICompressSetCoderProperties,
194: public ICompressWriteCoderProperties,
195: public CBaseState,
196: public CMyUnknownImp
197: {
198: COptimal _optimum[kNumOpts];
199: CMyComPtr<IMatchFinder> _matchFinder; // test it
200: NRangeCoder::CEncoder _rangeEncoder;
201:
202: CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
203: CMyBitEncoder _isRep[kNumStates];
204: CMyBitEncoder _isRepG0[kNumStates];
205: CMyBitEncoder _isRepG1[kNumStates];
206: CMyBitEncoder _isRepG2[kNumStates];
207: CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];
208:
209: NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
210:
211: CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
212: NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;
213:
214: NLength::CPriceTableEncoder _lenEncoder;
215: NLength::CPriceTableEncoder _repMatchLenEncoder;
216:
217: CLiteralEncoder _literalEncoder;
218:
219: UInt32 _matchDistances[kMatchMaxLen + 1];
220:
221: bool _fastMode;
222: bool _maxMode;
223: UInt32 _numFastBytes;
224: UInt32 _longestMatchLength;
225:
226: UInt32 _additionalOffset;
227:
228: UInt32 _optimumEndIndex;
229: UInt32 _optimumCurrentIndex;
230:
231: bool _longestMatchWasFound;
232:
233: UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
234:
235: UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];
236:
237: UInt32 _alignPrices[kAlignTableSize];
238: UInt32 _alignPriceCount;
239:
240: UInt32 _distTableSize;
241:
242: UInt32 _posStateBits;
243: UInt32 _posStateMask;
244: UInt32 _numLiteralPosStateBits;
245: UInt32 _numLiteralContextBits;
246:
247: UInt32 _dictionarySize;
248:
249: UInt32 _dictionarySizePrev;
250: UInt32 _numFastBytesPrev;
251:
252: UInt64 lastPosSlotFillingPos;
253: UInt64 nowPos64;
254: bool _finished;
255: ISequentialInStream *_inStream;
256:
257: int _matchFinderIndex;
258: #ifdef COMPRESS_MF_MT
259: bool _multiThread;
260: #endif
261:
262: bool _writeEndMark;
263:
264: bool _needReleaseMFStream;
265:
266: HRESULT ReadMatchDistances(UInt32 &len);
267:
268: HRESULT MovePos(UInt32 num);
269: UInt32 GetRepLen1Price(CState state, UInt32 posState) const
270: {
271: return _isRepG0[state.Index].GetPrice0() +
272: _isRep0Long[state.Index][posState].GetPrice0();
273: }
274: UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
275: {
276: UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState);
277: if(repIndex == 0)
278: {
279: price += _isRepG0[state.Index].GetPrice0();
280: price += _isRep0Long[state.Index][posState].GetPrice1();
281: }
282: else
283: {
284: price += _isRepG0[state.Index].GetPrice1();
285: if (repIndex == 1)
286: price += _isRepG1[state.Index].GetPrice0();
287: else
288: {
289: price += _isRepG1[state.Index].GetPrice1();
290: price += _isRepG2[state.Index].GetPrice(repIndex - 2);
291: }
292: }
293: return price;
294: }
295: /*
296: UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
297: {
298: if (pos >= kNumFullDistances)
299: return kIfinityPrice;
300: return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);
301: }
302: UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const
303: {
304: UInt32 price;
305: UInt32 lenToPosState = GetLenToPosState(len);
306: if (pos < kNumFullDistances)
307: price = _distancesPrices[lenToPosState][pos];
308: else
309: price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
310: _alignPrices[pos & kAlignMask];
311: return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
312: }
313: */
314: UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
315: {
316: if (len == 2 && pos >= 0x80)
317: return kIfinityPrice;
318: UInt32 price;
319: UInt32 lenToPosState = GetLenToPosState(len);
320: if (pos < kNumFullDistances)
321: price = _distancesPrices[lenToPosState][pos];
322: else
323: price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
324: _alignPrices[pos & kAlignMask];
325: return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
326: }
327:
328: UInt32 Backward(UInt32 &backRes, UInt32 cur);
329: HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
330: HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
331:
332: void FillPosSlotPrices();
333: void FillDistancesPrices();
334: void FillAlignPrices();
335:
336: void ReleaseMFStream()
337: {
338: if (_matchFinder && _needReleaseMFStream)
339: {
340: _matchFinder->ReleaseStream();
341: _needReleaseMFStream = false;
342: }
343: }
344:
345: void ReleaseStreams()
346: {
347: ReleaseMFStream();
348: ReleaseOutStream();
349: }
350:
351: HRESULT Flush(UInt32 nowPos);
352: class CCoderReleaser
353: {
354: CEncoder *_coder;
355: public:
356: CCoderReleaser(CEncoder *coder): _coder(coder) {}
357: ~CCoderReleaser()
358: {
359: _coder->ReleaseStreams();
360: }
361: };
362: friend class CCoderReleaser;
363:
364: void WriteEndMarker(UInt32 posState);
365:
366: public:
367: CEncoder();
368: void SetWriteEndMarkerMode(bool writeEndMarker)
369: { _writeEndMark= writeEndMarker; }
370:
371: HRESULT Create();
372:
373: MY_UNKNOWN_IMP3(
374: ICompressSetOutStream,
375: ICompressSetCoderProperties,
376: ICompressWriteCoderProperties
377: )
378:
379: HRESULT Init();
380:
381: // ICompressCoder interface
382: HRESULT SetStreams(ISequentialInStream *inStream,
383: ISequentialOutStream *outStream,
384: const UInt64 *inSize, const UInt64 *outSize);
385: HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);
386:
387: HRESULT CodeReal(ISequentialInStream *inStream,
388: ISequentialOutStream *outStream,
389: const UInt64 *inSize, const UInt64 *outSize,
390: ICompressProgressInfo *progress);
391:
392: // ICompressCoder interface
393: STDMETHOD(Code)(ISequentialInStream *inStream,
394: ISequentialOutStream *outStream,
395: const UInt64 *inSize, const UInt64 *outSize,
396: ICompressProgressInfo *progress);
397:
398: // IInitMatchFinder interface
399: STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder);
400:
401: // ICompressSetCoderProperties2
402: STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
403: const PROPVARIANT *properties, UInt32 numProperties);
404:
405: // ICompressWriteCoderProperties
406: STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
407:
408: STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
409: STDMETHOD(ReleaseOutStream)();
410:
411: virtual ~CEncoder() {}
412: };
413:
414: }}
415:
416: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>