LzmaEncoder.cs 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. // LzmaEncoder.cs
  2. using System;
  3. namespace SevenZip.Compression.LZMA
  4. {
  5. using RangeCoder;
  6. public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
  7. {
  8. enum EMatchFinderType
  9. {
  10. BT2,
  11. BT4,
  12. };
  13. const UInt32 kIfinityPrice = 0xFFFFFFF;
  14. static Byte[] g_FastPos = new Byte[1 << 11];
  15. static Encoder()
  16. {
  17. const Byte kFastSlots = 22;
  18. int c = 2;
  19. g_FastPos[0] = 0;
  20. g_FastPos[1] = 1;
  21. for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
  22. {
  23. UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));
  24. for (UInt32 j = 0; j < k; j++, c++)
  25. g_FastPos[c] = slotFast;
  26. }
  27. }
  28. static UInt32 GetPosSlot(UInt32 pos)
  29. {
  30. if (pos < (1 << 11))
  31. return g_FastPos[pos];
  32. if (pos < (1 << 21))
  33. return (UInt32)(g_FastPos[pos >> 10] + 20);
  34. return (UInt32)(g_FastPos[pos >> 20] + 40);
  35. }
  36. static UInt32 GetPosSlot2(UInt32 pos)
  37. {
  38. if (pos < (1 << 17))
  39. return (UInt32)(g_FastPos[pos >> 6] + 12);
  40. if (pos < (1 << 27))
  41. return (UInt32)(g_FastPos[pos >> 16] + 32);
  42. return (UInt32)(g_FastPos[pos >> 26] + 52);
  43. }
  44. Base.State _state = new Base.State();
  45. Byte _previousByte;
  46. UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
  47. void BaseInit()
  48. {
  49. _state.Init();
  50. _previousByte = 0;
  51. for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
  52. _repDistances[i] = 0;
  53. }
  54. const int kDefaultDictionaryLogSize = 22;
  55. const UInt32 kNumFastBytesDefault = 0x20;
  56. class LiteralEncoder
  57. {
  58. public struct Encoder2
  59. {
  60. BitEncoder[] m_Encoders;
  61. public void Create() { m_Encoders = new BitEncoder[0x300]; }
  62. public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }
  63. public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
  64. {
  65. uint context = 1;
  66. for (int i = 7; i >= 0; i--)
  67. {
  68. uint bit = (uint)((symbol >> i) & 1);
  69. m_Encoders[context].Encode(rangeEncoder, bit);
  70. context = (context << 1) | bit;
  71. }
  72. }
  73. public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
  74. {
  75. uint context = 1;
  76. bool same = true;
  77. for (int i = 7; i >= 0; i--)
  78. {
  79. uint bit = (uint)((symbol >> i) & 1);
  80. uint state = context;
  81. if (same)
  82. {
  83. uint matchBit = (uint)((matchByte >> i) & 1);
  84. state += ((1 + matchBit) << 8);
  85. same = (matchBit == bit);
  86. }
  87. m_Encoders[state].Encode(rangeEncoder, bit);
  88. context = (context << 1) | bit;
  89. }
  90. }
  91. public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
  92. {
  93. uint price = 0;
  94. uint context = 1;
  95. int i = 7;
  96. if (matchMode)
  97. {
  98. for (; i >= 0; i--)
  99. {
  100. uint matchBit = (uint)(matchByte >> i) & 1;
  101. uint bit = (uint)(symbol >> i) & 1;
  102. price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
  103. context = (context << 1) | bit;
  104. if (matchBit != bit)
  105. {
  106. i--;
  107. break;
  108. }
  109. }
  110. }
  111. for (; i >= 0; i--)
  112. {
  113. uint bit = (uint)(symbol >> i) & 1;
  114. price += m_Encoders[context].GetPrice(bit);
  115. context = (context << 1) | bit;
  116. }
  117. return price;
  118. }
  119. }
  120. Encoder2[] m_Coders;
  121. int m_NumPrevBits;
  122. int m_NumPosBits;
  123. uint m_PosMask;
  124. public void Create(int numPosBits, int numPrevBits)
  125. {
  126. if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
  127. return;
  128. m_NumPosBits = numPosBits;
  129. m_PosMask = ((uint)1 << numPosBits) - 1;
  130. m_NumPrevBits = numPrevBits;
  131. uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
  132. m_Coders = new Encoder2[numStates];
  133. for (uint i = 0; i < numStates; i++)
  134. m_Coders[i].Create();
  135. }
  136. public void Init()
  137. {
  138. uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
  139. for (uint i = 0; i < numStates; i++)
  140. m_Coders[i].Init();
  141. }
  142. public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
  143. { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }
  144. }
  145. class LenEncoder
  146. {
  147. RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();
  148. RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();
  149. RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
  150. RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
  151. RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);
  152. public LenEncoder()
  153. {
  154. for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
  155. {
  156. _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);
  157. _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);
  158. }
  159. }
  160. public void Init(UInt32 numPosStates)
  161. {
  162. _choice.Init();
  163. _choice2.Init();
  164. for (UInt32 posState = 0; posState < numPosStates; posState++)
  165. {
  166. _lowCoder[posState].Init();
  167. _midCoder[posState].Init();
  168. }
  169. _highCoder.Init();
  170. }
  171. public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
  172. {
  173. if (symbol < Base.kNumLowLenSymbols)
  174. {
  175. _choice.Encode(rangeEncoder, 0);
  176. _lowCoder[posState].Encode(rangeEncoder, symbol);
  177. }
  178. else
  179. {
  180. symbol -= Base.kNumLowLenSymbols;
  181. _choice.Encode(rangeEncoder, 1);
  182. if (symbol < Base.kNumMidLenSymbols)
  183. {
  184. _choice2.Encode(rangeEncoder, 0);
  185. _midCoder[posState].Encode(rangeEncoder, symbol);
  186. }
  187. else
  188. {
  189. _choice2.Encode(rangeEncoder, 1);
  190. _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
  191. }
  192. }
  193. }
  194. public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
  195. {
  196. UInt32 a0 = _choice.GetPrice0();
  197. UInt32 a1 = _choice.GetPrice1();
  198. UInt32 b0 = a1 + _choice2.GetPrice0();
  199. UInt32 b1 = a1 + _choice2.GetPrice1();
  200. UInt32 i = 0;
  201. for (i = 0; i < Base.kNumLowLenSymbols; i++)
  202. {
  203. if (i >= numSymbols)
  204. return;
  205. prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
  206. }
  207. for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
  208. {
  209. if (i >= numSymbols)
  210. return;
  211. prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
  212. }
  213. for (; i < numSymbols; i++)
  214. prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
  215. }
  216. };
  217. const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
  218. class LenPriceTableEncoder : LenEncoder
  219. {
  220. UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
  221. UInt32 _tableSize;
  222. UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
  223. public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
  224. public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
  225. {
  226. return _prices[posState * Base.kNumLenSymbols + symbol];
  227. }
  228. void UpdateTable(UInt32 posState)
  229. {
  230. SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
  231. _counters[posState] = _tableSize;
  232. }
  233. public void UpdateTables(UInt32 numPosStates)
  234. {
  235. for (UInt32 posState = 0; posState < numPosStates; posState++)
  236. UpdateTable(posState);
  237. }
  238. public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
  239. {
  240. base.Encode(rangeEncoder, symbol, posState);
  241. if (--_counters[posState] == 0)
  242. UpdateTable(posState);
  243. }
  244. }
  245. const UInt32 kNumOpts = 1 << 12;
  246. class Optimal
  247. {
  248. public Base.State State;
  249. public bool Prev1IsChar;
  250. public bool Prev2;
  251. public UInt32 PosPrev2;
  252. public UInt32 BackPrev2;
  253. public UInt32 Price;
  254. public UInt32 PosPrev;
  255. public UInt32 BackPrev;
  256. public UInt32 Backs0;
  257. public UInt32 Backs1;
  258. public UInt32 Backs2;
  259. public UInt32 Backs3;
  260. public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
  261. public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
  262. public bool IsShortRep() { return (BackPrev == 0); }
  263. };
  264. Optimal[] _optimum = new Optimal[kNumOpts];
  265. LZ.IMatchFinder _matchFinder = null;
  266. RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
  267. RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
  268. RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];
  269. RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];
  270. RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];
  271. RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];
  272. RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
  273. RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates];
  274. RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
  275. RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);
  276. LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
  277. LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
  278. LiteralEncoder _literalEncoder = new LiteralEncoder();
  279. UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2];
  280. UInt32 _numFastBytes = kNumFastBytesDefault;
  281. UInt32 _longestMatchLength;
  282. UInt32 _numDistancePairs;
  283. UInt32 _additionalOffset;
  284. UInt32 _optimumEndIndex;
  285. UInt32 _optimumCurrentIndex;
  286. bool _longestMatchWasFound;
  287. UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
  288. UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
  289. UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
  290. UInt32 _alignPriceCount;
  291. UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);
  292. int _posStateBits = 2;
  293. UInt32 _posStateMask = (4 - 1);
  294. int _numLiteralPosStateBits = 0;
  295. int _numLiteralContextBits = 3;
  296. UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);
  297. UInt32 _dictionarySizePrev = 0xFFFFFFFF;
  298. UInt32 _numFastBytesPrev = 0xFFFFFFFF;
  299. Int64 nowPos64;
  300. bool _finished;
  301. System.IO.Stream _inStream;
  302. EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
  303. bool _writeEndMark = false;
  304. bool _needReleaseMFStream;
  305. void Create()
  306. {
  307. if (_matchFinder == null)
  308. {
  309. LZ.BinTree bt = new LZ.BinTree();
  310. int numHashBytes = 4;
  311. if (_matchFinderType == EMatchFinderType.BT2)
  312. numHashBytes = 2;
  313. bt.SetType(numHashBytes);
  314. _matchFinder = bt;
  315. }
  316. _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
  317. if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
  318. return;
  319. _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
  320. _dictionarySizePrev = _dictionarySize;
  321. _numFastBytesPrev = _numFastBytes;
  322. }
  323. public Encoder()
  324. {
  325. for (int i = 0; i < kNumOpts; i++)
  326. _optimum[i] = new Optimal();
  327. for (int i = 0; i < Base.kNumLenToPosStates; i++)
  328. _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);
  329. }
  330. void SetWriteEndMarkerMode(bool writeEndMarker)
  331. {
  332. _writeEndMark = writeEndMarker;
  333. }
  334. void Init()
  335. {
  336. BaseInit();
  337. _rangeEncoder.Init();
  338. uint i;
  339. for (i = 0; i < Base.kNumStates; i++)
  340. {
  341. for (uint j = 0; j <= _posStateMask; j++)
  342. {
  343. uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
  344. _isMatch[complexState].Init();
  345. _isRep0Long[complexState].Init();
  346. }
  347. _isRep[i].Init();
  348. _isRepG0[i].Init();
  349. _isRepG1[i].Init();
  350. _isRepG2[i].Init();
  351. }
  352. _literalEncoder.Init();
  353. for (i = 0; i < Base.kNumLenToPosStates; i++)
  354. _posSlotEncoder[i].Init();
  355. for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
  356. _posEncoders[i].Init();
  357. _lenEncoder.Init((UInt32)1 << _posStateBits);
  358. _repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
  359. _posAlignEncoder.Init();
  360. _longestMatchWasFound = false;
  361. _optimumEndIndex = 0;
  362. _optimumCurrentIndex = 0;
  363. _additionalOffset = 0;
  364. }
  365. void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
  366. {
  367. lenRes = 0;
  368. numDistancePairs = _matchFinder.GetMatches(_matchDistances);
  369. if (numDistancePairs > 0)
  370. {
  371. lenRes = _matchDistances[numDistancePairs - 2];
  372. if (lenRes == _numFastBytes)
  373. lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
  374. Base.kMatchMaxLen - lenRes);
  375. }
  376. _additionalOffset++;
  377. }
  378. void MovePos(UInt32 num)
  379. {
  380. if (num > 0)
  381. {
  382. _matchFinder.Skip(num);
  383. _additionalOffset += num;
  384. }
  385. }
  386. UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
  387. {
  388. return _isRepG0[state.Index].GetPrice0() +
  389. _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
  390. }
  391. UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
  392. {
  393. UInt32 price;
  394. if (repIndex == 0)
  395. {
  396. price = _isRepG0[state.Index].GetPrice0();
  397. price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
  398. }
  399. else
  400. {
  401. price = _isRepG0[state.Index].GetPrice1();
  402. if (repIndex == 1)
  403. price += _isRepG1[state.Index].GetPrice0();
  404. else
  405. {
  406. price += _isRepG1[state.Index].GetPrice1();
  407. price += _isRepG2[state.Index].GetPrice(repIndex - 2);
  408. }
  409. }
  410. return price;
  411. }
  412. UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
  413. {
  414. UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
  415. return price + GetPureRepPrice(repIndex, state, posState);
  416. }
  417. UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
  418. {
  419. UInt32 price;
  420. UInt32 lenToPosState = Base.GetLenToPosState(len);
  421. if (pos < Base.kNumFullDistances)
  422. price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
  423. else
  424. price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
  425. _alignPrices[pos & Base.kAlignMask];
  426. return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
  427. }
  428. UInt32 Backward(out UInt32 backRes, UInt32 cur)
  429. {
  430. _optimumEndIndex = cur;
  431. UInt32 posMem = _optimum[cur].PosPrev;
  432. UInt32 backMem = _optimum[cur].BackPrev;
  433. do
  434. {
  435. if (_optimum[cur].Prev1IsChar)
  436. {
  437. _optimum[posMem].MakeAsChar();
  438. _optimum[posMem].PosPrev = posMem - 1;
  439. if (_optimum[cur].Prev2)
  440. {
  441. _optimum[posMem - 1].Prev1IsChar = false;
  442. _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
  443. _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
  444. }
  445. }
  446. UInt32 posPrev = posMem;
  447. UInt32 backCur = backMem;
  448. backMem = _optimum[posPrev].BackPrev;
  449. posMem = _optimum[posPrev].PosPrev;
  450. _optimum[posPrev].BackPrev = backCur;
  451. _optimum[posPrev].PosPrev = cur;
  452. cur = posPrev;
  453. }
  454. while (cur > 0);
  455. backRes = _optimum[0].BackPrev;
  456. _optimumCurrentIndex = _optimum[0].PosPrev;
  457. return _optimumCurrentIndex;
  458. }
  459. UInt32[] reps = new UInt32[Base.kNumRepDistances];
  460. UInt32[] repLens = new UInt32[Base.kNumRepDistances];
  461. UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
  462. {
  463. if (_optimumEndIndex != _optimumCurrentIndex)
  464. {
  465. UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
  466. backRes = _optimum[_optimumCurrentIndex].BackPrev;
  467. _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
  468. return lenRes;
  469. }
  470. _optimumCurrentIndex = _optimumEndIndex = 0;
  471. UInt32 lenMain, numDistancePairs;
  472. if (!_longestMatchWasFound)
  473. {
  474. ReadMatchDistances(out lenMain, out numDistancePairs);
  475. }
  476. else
  477. {
  478. lenMain = _longestMatchLength;
  479. numDistancePairs = _numDistancePairs;
  480. _longestMatchWasFound = false;
  481. }
  482. UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
  483. if (numAvailableBytes < 2)
  484. {
  485. backRes = 0xFFFFFFFF;
  486. return 1;
  487. }
  488. if (numAvailableBytes > Base.kMatchMaxLen)
  489. numAvailableBytes = Base.kMatchMaxLen;
  490. UInt32 repMaxIndex = 0;
  491. UInt32 i;
  492. for (i = 0; i < Base.kNumRepDistances; i++)
  493. {
  494. reps[i] = _repDistances[i];
  495. repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
  496. if (repLens[i] > repLens[repMaxIndex])
  497. repMaxIndex = i;
  498. }
  499. if (repLens[repMaxIndex] >= _numFastBytes)
  500. {
  501. backRes = repMaxIndex;
  502. UInt32 lenRes = repLens[repMaxIndex];
  503. MovePos(lenRes - 1);
  504. return lenRes;
  505. }
  506. if (lenMain >= _numFastBytes)
  507. {
  508. backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
  509. MovePos(lenMain - 1);
  510. return lenMain;
  511. }
  512. Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
  513. Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
  514. if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
  515. {
  516. backRes = (UInt32)0xFFFFFFFF;
  517. return 1;
  518. }
  519. _optimum[0].State = _state;
  520. UInt32 posState = (position & _posStateMask);
  521. _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
  522. _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
  523. _optimum[1].MakeAsChar();
  524. UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
  525. UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
  526. if (matchByte == currentByte)
  527. {
  528. UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
  529. if (shortRepPrice < _optimum[1].Price)
  530. {
  531. _optimum[1].Price = shortRepPrice;
  532. _optimum[1].MakeAsShortRep();
  533. }
  534. }
  535. UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
  536. if(lenEnd < 2)
  537. {
  538. backRes = _optimum[1].BackPrev;
  539. return 1;
  540. }
  541. _optimum[1].PosPrev = 0;
  542. _optimum[0].Backs0 = reps[0];
  543. _optimum[0].Backs1 = reps[1];
  544. _optimum[0].Backs2 = reps[2];
  545. _optimum[0].Backs3 = reps[3];
  546. UInt32 len = lenEnd;
  547. do
  548. _optimum[len--].Price = kIfinityPrice;
  549. while (len >= 2);
  550. for (i = 0; i < Base.kNumRepDistances; i++)
  551. {
  552. UInt32 repLen = repLens[i];
  553. if (repLen < 2)
  554. continue;
  555. UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
  556. do
  557. {
  558. UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
  559. Optimal optimum = _optimum[repLen];
  560. if (curAndLenPrice < optimum.Price)
  561. {
  562. optimum.Price = curAndLenPrice;
  563. optimum.PosPrev = 0;
  564. optimum.BackPrev = i;
  565. optimum.Prev1IsChar = false;
  566. }
  567. }
  568. while (--repLen >= 2);
  569. }
  570. UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
  571. len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
  572. if (len <= lenMain)
  573. {
  574. UInt32 offs = 0;
  575. while (len > _matchDistances[offs])
  576. offs += 2;
  577. for (; ; len++)
  578. {
  579. UInt32 distance = _matchDistances[offs + 1];
  580. UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
  581. Optimal optimum = _optimum[len];
  582. if (curAndLenPrice < optimum.Price)
  583. {
  584. optimum.Price = curAndLenPrice;
  585. optimum.PosPrev = 0;
  586. optimum.BackPrev = distance + Base.kNumRepDistances;
  587. optimum.Prev1IsChar = false;
  588. }
  589. if (len == _matchDistances[offs])
  590. {
  591. offs += 2;
  592. if (offs == numDistancePairs)
  593. break;
  594. }
  595. }
  596. }
  597. UInt32 cur = 0;
  598. while (true)
  599. {
  600. cur++;
  601. if (cur == lenEnd)
  602. return Backward(out backRes, cur);
  603. UInt32 newLen;
  604. ReadMatchDistances(out newLen, out numDistancePairs);
  605. if (newLen >= _numFastBytes)
  606. {
  607. _numDistancePairs = numDistancePairs;
  608. _longestMatchLength = newLen;
  609. _longestMatchWasFound = true;
  610. return Backward(out backRes, cur);
  611. }
  612. position++;
  613. UInt32 posPrev = _optimum[cur].PosPrev;
  614. Base.State state;
  615. if (_optimum[cur].Prev1IsChar)
  616. {
  617. posPrev--;
  618. if (_optimum[cur].Prev2)
  619. {
  620. state = _optimum[_optimum[cur].PosPrev2].State;
  621. if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
  622. state.UpdateRep();
  623. else
  624. state.UpdateMatch();
  625. }
  626. else
  627. state = _optimum[posPrev].State;
  628. state.UpdateChar();
  629. }
  630. else
  631. state = _optimum[posPrev].State;
  632. if (posPrev == cur - 1)
  633. {
  634. if (_optimum[cur].IsShortRep())
  635. state.UpdateShortRep();
  636. else
  637. state.UpdateChar();
  638. }
  639. else
  640. {
  641. UInt32 pos;
  642. if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
  643. {
  644. posPrev = _optimum[cur].PosPrev2;
  645. pos = _optimum[cur].BackPrev2;
  646. state.UpdateRep();
  647. }
  648. else
  649. {
  650. pos = _optimum[cur].BackPrev;
  651. if (pos < Base.kNumRepDistances)
  652. state.UpdateRep();
  653. else
  654. state.UpdateMatch();
  655. }
  656. Optimal opt = _optimum[posPrev];
  657. if (pos < Base.kNumRepDistances)
  658. {
  659. if (pos == 0)
  660. {
  661. reps[0] = opt.Backs0;
  662. reps[1] = opt.Backs1;
  663. reps[2] = opt.Backs2;
  664. reps[3] = opt.Backs3;
  665. }
  666. else if (pos == 1)
  667. {
  668. reps[0] = opt.Backs1;
  669. reps[1] = opt.Backs0;
  670. reps[2] = opt.Backs2;
  671. reps[3] = opt.Backs3;
  672. }
  673. else if (pos == 2)
  674. {
  675. reps[0] = opt.Backs2;
  676. reps[1] = opt.Backs0;
  677. reps[2] = opt.Backs1;
  678. reps[3] = opt.Backs3;
  679. }
  680. else
  681. {
  682. reps[0] = opt.Backs3;
  683. reps[1] = opt.Backs0;
  684. reps[2] = opt.Backs1;
  685. reps[3] = opt.Backs2;
  686. }
  687. }
  688. else
  689. {
  690. reps[0] = (pos - Base.kNumRepDistances);
  691. reps[1] = opt.Backs0;
  692. reps[2] = opt.Backs1;
  693. reps[3] = opt.Backs2;
  694. }
  695. }
  696. _optimum[cur].State = state;
  697. _optimum[cur].Backs0 = reps[0];
  698. _optimum[cur].Backs1 = reps[1];
  699. _optimum[cur].Backs2 = reps[2];
  700. _optimum[cur].Backs3 = reps[3];
  701. UInt32 curPrice = _optimum[cur].Price;
  702. currentByte = _matchFinder.GetIndexByte(0 - 1);
  703. matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
  704. posState = (position & _posStateMask);
  705. UInt32 curAnd1Price = curPrice +
  706. _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
  707. _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
  708. GetPrice(!state.IsCharState(), matchByte, currentByte);
  709. Optimal nextOptimum = _optimum[cur + 1];
  710. bool nextIsChar = false;
  711. if (curAnd1Price < nextOptimum.Price)
  712. {
  713. nextOptimum.Price = curAnd1Price;
  714. nextOptimum.PosPrev = cur;
  715. nextOptimum.MakeAsChar();
  716. nextIsChar = true;
  717. }
  718. matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
  719. repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
  720. if (matchByte == currentByte &&
  721. !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
  722. {
  723. UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
  724. if (shortRepPrice <= nextOptimum.Price)
  725. {
  726. nextOptimum.Price = shortRepPrice;
  727. nextOptimum.PosPrev = cur;
  728. nextOptimum.MakeAsShortRep();
  729. nextIsChar = true;
  730. }
  731. }
  732. UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
  733. numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
  734. numAvailableBytes = numAvailableBytesFull;
  735. if (numAvailableBytes < 2)
  736. continue;
  737. if (numAvailableBytes > _numFastBytes)
  738. numAvailableBytes = _numFastBytes;
  739. if (!nextIsChar && matchByte != currentByte)
  740. {
  741. // try Literal + rep0
  742. UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
  743. UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
  744. if (lenTest2 >= 2)
  745. {
  746. Base.State state2 = state;
  747. state2.UpdateChar();
  748. UInt32 posStateNext = (position + 1) & _posStateMask;
  749. UInt32 nextRepMatchPrice = curAnd1Price +
  750. _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
  751. _isRep[state2.Index].GetPrice1();
  752. {
  753. UInt32 offset = cur + 1 + lenTest2;
  754. while (lenEnd < offset)
  755. _optimum[++lenEnd].Price = kIfinityPrice;
  756. UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
  757. 0, lenTest2, state2, posStateNext);
  758. Optimal optimum = _optimum[offset];
  759. if (curAndLenPrice < optimum.Price)
  760. {
  761. optimum.Price = curAndLenPrice;
  762. optimum.PosPrev = cur + 1;
  763. optimum.BackPrev = 0;
  764. optimum.Prev1IsChar = true;
  765. optimum.Prev2 = false;
  766. }
  767. }
  768. }
  769. }
  770. UInt32 startLen = 2; // speed optimization
  771. for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
  772. {
  773. UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
  774. if (lenTest < 2)
  775. continue;
  776. UInt32 lenTestTemp = lenTest;
  777. do
  778. {
  779. while (lenEnd < cur + lenTest)
  780. _optimum[++lenEnd].Price = kIfinityPrice;
  781. UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
  782. Optimal optimum = _optimum[cur + lenTest];
  783. if (curAndLenPrice < optimum.Price)
  784. {
  785. optimum.Price = curAndLenPrice;
  786. optimum.PosPrev = cur;
  787. optimum.BackPrev = repIndex;
  788. optimum.Prev1IsChar = false;
  789. }
  790. }
  791. while(--lenTest >= 2);
  792. lenTest = lenTestTemp;
  793. if (repIndex == 0)
  794. startLen = lenTest + 1;
  795. // if (_maxMode)
  796. if (lenTest < numAvailableBytesFull)
  797. {
  798. UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
  799. UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);
  800. if (lenTest2 >= 2)
  801. {
  802. Base.State state2 = state;
  803. state2.UpdateRep();
  804. UInt32 posStateNext = (position + lenTest) & _posStateMask;
  805. UInt32 curAndLenCharPrice =
  806. repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
  807. _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
  808. _literalEncoder.GetSubCoder(position + lenTest,
  809. _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
  810. _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))),
  811. _matchFinder.GetIndexByte((Int32)lenTest - 1));
  812. state2.UpdateChar();
  813. posStateNext = (position + lenTest + 1) & _posStateMask;
  814. UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
  815. UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
  816. // for(; lenTest2 >= 2; lenTest2--)
  817. {
  818. UInt32 offset = lenTest + 1 + lenTest2;
  819. while(lenEnd < cur + offset)
  820. _optimum[++lenEnd].Price = kIfinityPrice;
  821. UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
  822. Optimal optimum = _optimum[cur + offset];
  823. if (curAndLenPrice < optimum.Price)
  824. {
  825. optimum.Price = curAndLenPrice;
  826. optimum.PosPrev = cur + lenTest + 1;
  827. optimum.BackPrev = 0;
  828. optimum.Prev1IsChar = true;
  829. optimum.Prev2 = true;
  830. optimum.PosPrev2 = cur;
  831. optimum.BackPrev2 = repIndex;
  832. }
  833. }
  834. }
  835. }
  836. }
  837. if (newLen > numAvailableBytes)
  838. {
  839. newLen = numAvailableBytes;
  840. for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
  841. _matchDistances[numDistancePairs] = newLen;
  842. numDistancePairs += 2;
  843. }
  844. if (newLen >= startLen)
  845. {
  846. normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
  847. while (lenEnd < cur + newLen)
  848. _optimum[++lenEnd].Price = kIfinityPrice;
  849. UInt32 offs = 0;
  850. while (startLen > _matchDistances[offs])
  851. offs += 2;
  852. for (UInt32 lenTest = startLen; ; lenTest++)
  853. {
  854. UInt32 curBack = _matchDistances[offs + 1];
  855. UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
  856. Optimal optimum = _optimum[cur + lenTest];
  857. if (curAndLenPrice < optimum.Price)
  858. {
  859. optimum.Price = curAndLenPrice;
  860. optimum.PosPrev = cur;
  861. optimum.BackPrev = curBack + Base.kNumRepDistances;
  862. optimum.Prev1IsChar = false;
  863. }
  864. if (lenTest == _matchDistances[offs])
  865. {
  866. if (lenTest < numAvailableBytesFull)
  867. {
  868. UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
  869. UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
  870. if (lenTest2 >= 2)
  871. {
  872. Base.State state2 = state;
  873. state2.UpdateMatch();
  874. UInt32 posStateNext = (position + lenTest) & _posStateMask;
  875. UInt32 curAndLenCharPrice = curAndLenPrice +
  876. _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
  877. _literalEncoder.GetSubCoder(position + lenTest,
  878. _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
  879. GetPrice(true,
  880. _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),
  881. _matchFinder.GetIndexByte((Int32)lenTest - 1));
  882. state2.UpdateChar();
  883. posStateNext = (position + lenTest + 1) & _posStateMask;
  884. UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
  885. UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
  886. UInt32 offset = lenTest + 1 + lenTest2;
  887. while (lenEnd < cur + offset)
  888. _optimum[++lenEnd].Price = kIfinityPrice;
  889. curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
  890. optimum = _optimum[cur + offset];
  891. if (curAndLenPrice < optimum.Price)
  892. {
  893. optimum.Price = curAndLenPrice;
  894. optimum.PosPrev = cur + lenTest + 1;
  895. optimum.BackPrev = 0;
  896. optimum.Prev1IsChar = true;
  897. optimum.Prev2 = true;
  898. optimum.PosPrev2 = cur;
  899. optimum.BackPrev2 = curBack + Base.kNumRepDistances;
  900. }
  901. }
  902. }
  903. offs += 2;
  904. if (offs == numDistancePairs)
  905. break;
  906. }
  907. }
  908. }
  909. }
  910. }
  911. bool ChangePair(UInt32 smallDist, UInt32 bigDist)
  912. {
  913. const int kDif = 7;
  914. return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
  915. }
  916. void WriteEndMarker(UInt32 posState)
  917. {
  918. if (!_writeEndMark)
  919. return;
  920. _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
  921. _isRep[_state.Index].Encode(_rangeEncoder, 0);
  922. _state.UpdateMatch();
  923. UInt32 len = Base.kMatchMinLen;
  924. _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
  925. UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
  926. UInt32 lenToPosState = Base.GetLenToPosState(len);
  927. _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
  928. int footerBits = 30;
  929. UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
  930. _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
  931. _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
  932. }
  933. void Flush(UInt32 nowPos)
  934. {
  935. ReleaseMFStream();
  936. WriteEndMarker(nowPos & _posStateMask);
  937. _rangeEncoder.FlushData();
  938. _rangeEncoder.FlushStream();
  939. }
  940. public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
  941. {
  942. inSize = 0;
  943. outSize = 0;
  944. finished = true;
  945. if (_inStream != null)
  946. {
  947. _matchFinder.SetStream(_inStream);
  948. _matchFinder.Init();
  949. _needReleaseMFStream = true;
  950. _inStream = null;
  951. if (_trainSize > 0)
  952. _matchFinder.Skip(_trainSize);
  953. }
  954. if (_finished)
  955. return;
  956. _finished = true;
  957. Int64 progressPosValuePrev = nowPos64;
  958. if (nowPos64 == 0)
  959. {
  960. if (_matchFinder.GetNumAvailableBytes() == 0)
  961. {
  962. Flush((UInt32)nowPos64);
  963. return;
  964. }
  965. UInt32 len, numDistancePairs; // it's not used
  966. ReadMatchDistances(out len, out numDistancePairs);
  967. UInt32 posState = (UInt32)(nowPos64) & _posStateMask;
  968. _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
  969. _state.UpdateChar();
  970. Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
  971. _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
  972. _previousByte = curByte;
  973. _additionalOffset--;
  974. nowPos64++;
  975. }
  976. if (_matchFinder.GetNumAvailableBytes() == 0)
  977. {
  978. Flush((UInt32)nowPos64);
  979. return;
  980. }
  981. while (true)
  982. {
  983. UInt32 pos;
  984. UInt32 len = GetOptimum((UInt32)nowPos64, out pos);
  985. UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
  986. UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
  987. if (len == 1 && pos == 0xFFFFFFFF)
  988. {
  989. _isMatch[complexState].Encode(_rangeEncoder, 0);
  990. Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
  991. LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
  992. if (!_state.IsCharState())
  993. {
  994. Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
  995. subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
  996. }
  997. else
  998. subCoder.Encode(_rangeEncoder, curByte);
  999. _previousByte = curByte;
  1000. _state.UpdateChar();
  1001. }
  1002. else
  1003. {
  1004. _isMatch[complexState].Encode(_rangeEncoder, 1);
  1005. if (pos < Base.kNumRepDistances)
  1006. {
  1007. _isRep[_state.Index].Encode(_rangeEncoder, 1);
  1008. if (pos == 0)
  1009. {
  1010. _isRepG0[_state.Index].Encode(_rangeEncoder, 0);
  1011. if (len == 1)
  1012. _isRep0Long[complexState].Encode(_rangeEncoder, 0);
  1013. else
  1014. _isRep0Long[complexState].Encode(_rangeEncoder, 1);
  1015. }
  1016. else
  1017. {
  1018. _isRepG0[_state.Index].Encode(_rangeEncoder, 1);
  1019. if (pos == 1)
  1020. _isRepG1[_state.Index].Encode(_rangeEncoder, 0);
  1021. else
  1022. {
  1023. _isRepG1[_state.Index].Encode(_rangeEncoder, 1);
  1024. _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);
  1025. }
  1026. }
  1027. if (len == 1)
  1028. _state.UpdateShortRep();
  1029. else
  1030. {
  1031. _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
  1032. _state.UpdateRep();
  1033. }
  1034. UInt32 distance = _repDistances[pos];
  1035. if (pos != 0)
  1036. {
  1037. for (UInt32 i = pos; i >= 1; i--)
  1038. _repDistances[i] = _repDistances[i - 1];
  1039. _repDistances[0] = distance;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. _isRep[_state.Index].Encode(_rangeEncoder, 0);
  1045. _state.UpdateMatch();
  1046. _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
  1047. pos -= Base.kNumRepDistances;
  1048. UInt32 posSlot = GetPosSlot(pos);
  1049. UInt32 lenToPosState = Base.GetLenToPosState(len);
  1050. _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
  1051. if (posSlot >= Base.kStartPosModelIndex)
  1052. {
  1053. int footerBits = (int)((posSlot >> 1) - 1);
  1054. UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
  1055. UInt32 posReduced = pos - baseVal;
  1056. if (posSlot < Base.kEndPosModelIndex)
  1057. RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,
  1058. baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
  1059. else
  1060. {
  1061. _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
  1062. _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
  1063. _alignPriceCount++;
  1064. }
  1065. }
  1066. UInt32 distance = pos;
  1067. for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
  1068. _repDistances[i] = _repDistances[i - 1];
  1069. _repDistances[0] = distance;
  1070. _matchPriceCount++;
  1071. }
  1072. _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
  1073. }
  1074. _additionalOffset -= len;
  1075. nowPos64 += len;
  1076. if (_additionalOffset == 0)
  1077. {
  1078. // if (!_fastMode)
  1079. if (_matchPriceCount >= (1 << 7))
  1080. FillDistancesPrices();
  1081. if (_alignPriceCount >= Base.kAlignTableSize)
  1082. FillAlignPrices();
  1083. inSize = nowPos64;
  1084. outSize = _rangeEncoder.GetProcessedSizeAdd();
  1085. if (_matchFinder.GetNumAvailableBytes() == 0)
  1086. {
  1087. Flush((UInt32)nowPos64);
  1088. return;
  1089. }
  1090. if (nowPos64 - progressPosValuePrev >= (1 << 12))
  1091. {
  1092. _finished = false;
  1093. finished = false;
  1094. return;
  1095. }
  1096. }
  1097. }
  1098. }
  1099. void ReleaseMFStream()
  1100. {
  1101. if (_matchFinder != null && _needReleaseMFStream)
  1102. {
  1103. _matchFinder.ReleaseStream();
  1104. _needReleaseMFStream = false;
  1105. }
  1106. }
  1107. void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
  1108. void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
  1109. void ReleaseStreams()
  1110. {
  1111. ReleaseMFStream();
  1112. ReleaseOutStream();
  1113. }
  1114. void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
  1115. Int64 inSize, Int64 outSize)
  1116. {
  1117. _inStream = inStream;
  1118. _finished = false;
  1119. Create();
  1120. SetOutStream(outStream);
  1121. Init();
  1122. // if (!_fastMode)
  1123. {
  1124. FillDistancesPrices();
  1125. FillAlignPrices();
  1126. }
  1127. _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
  1128. _lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
  1129. _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
  1130. _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
  1131. nowPos64 = 0;
  1132. }
  1133. public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
  1134. Int64 inSize, Int64 outSize, ICodeProgress progress)
  1135. {
  1136. _needReleaseMFStream = false;
  1137. try
  1138. {
  1139. SetStreams(inStream, outStream, inSize, outSize);
  1140. while (true)
  1141. {
  1142. Int64 processedInSize;
  1143. Int64 processedOutSize;
  1144. bool finished;
  1145. CodeOneBlock(out processedInSize, out processedOutSize, out finished);
  1146. if (finished)
  1147. return;
  1148. if (progress != null)
  1149. {
  1150. progress.SetProgress(processedInSize, processedOutSize);
  1151. }
  1152. }
  1153. }
  1154. finally
  1155. {
  1156. ReleaseStreams();
  1157. }
  1158. }
  1159. const int kPropSize = 5;
  1160. Byte[] properties = new Byte[kPropSize];
  1161. public void WriteCoderProperties(System.IO.Stream outStream)
  1162. {
  1163. properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
  1164. for (int i = 0; i < 4; i++)
  1165. properties[1 + i] = (Byte)(_dictionarySize >> (8 * i));
  1166. outStream.Write(properties, 0, kPropSize);
  1167. }
  1168. UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
  1169. UInt32 _matchPriceCount;
  1170. void FillDistancesPrices()
  1171. {
  1172. for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
  1173. {
  1174. UInt32 posSlot = GetPosSlot(i);
  1175. int footerBits = (int)((posSlot >> 1) - 1);
  1176. UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
  1177. tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
  1178. baseVal - posSlot - 1, footerBits, i - baseVal);
  1179. }
  1180. for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
  1181. {
  1182. UInt32 posSlot;
  1183. RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
  1184. UInt32 st = (lenToPosState << Base.kNumPosSlotBits);
  1185. for (posSlot = 0; posSlot < _distTableSize; posSlot++)
  1186. _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
  1187. for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
  1188. _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);
  1189. UInt32 st2 = lenToPosState * Base.kNumFullDistances;
  1190. UInt32 i;
  1191. for (i = 0; i < Base.kStartPosModelIndex; i++)
  1192. _distancesPrices[st2 + i] = _posSlotPrices[st + i];
  1193. for (; i < Base.kNumFullDistances; i++)
  1194. _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
  1195. }
  1196. _matchPriceCount = 0;
  1197. }
  1198. void FillAlignPrices()
  1199. {
  1200. for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
  1201. _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
  1202. _alignPriceCount = 0;
  1203. }
  1204. static string[] kMatchFinderIDs =
  1205. {
  1206. "BT2",
  1207. "BT4",
  1208. };
  1209. static int FindMatchFinder(string s)
  1210. {
  1211. for (int m = 0; m < kMatchFinderIDs.Length; m++)
  1212. if (s == kMatchFinderIDs[m])
  1213. return m;
  1214. return -1;
  1215. }
  1216. public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
  1217. {
  1218. for (UInt32 i = 0; i < properties.Length; i++)
  1219. {
  1220. object prop = properties[i];
  1221. switch (propIDs[i])
  1222. {
  1223. case CoderPropID.NumFastBytes:
  1224. {
  1225. if (!(prop is Int32))
  1226. throw new InvalidParamException();
  1227. Int32 numFastBytes = (Int32)prop;
  1228. if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
  1229. throw new InvalidParamException();
  1230. _numFastBytes = (UInt32)numFastBytes;
  1231. break;
  1232. }
  1233. case CoderPropID.Algorithm:
  1234. {
  1235. /*
  1236. if (!(prop is Int32))
  1237. throw new InvalidParamException();
  1238. Int32 maximize = (Int32)prop;
  1239. _fastMode = (maximize == 0);
  1240. _maxMode = (maximize >= 2);
  1241. */
  1242. break;
  1243. }
  1244. case CoderPropID.MatchFinder:
  1245. {
  1246. if (!(prop is String))
  1247. throw new InvalidParamException();
  1248. EMatchFinderType matchFinderIndexPrev = _matchFinderType;
  1249. int m = FindMatchFinder(((string)prop).ToUpper());
  1250. if (m < 0)
  1251. throw new InvalidParamException();
  1252. _matchFinderType = (EMatchFinderType)m;
  1253. if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
  1254. {
  1255. _dictionarySizePrev = 0xFFFFFFFF;
  1256. _matchFinder = null;
  1257. }
  1258. break;
  1259. }
  1260. case CoderPropID.DictionarySize:
  1261. {
  1262. const int kDicLogSizeMaxCompress = 30;
  1263. if (!(prop is Int32))
  1264. throw new InvalidParamException(); ;
  1265. Int32 dictionarySize = (Int32)prop;
  1266. if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
  1267. dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
  1268. throw new InvalidParamException();
  1269. _dictionarySize = (UInt32)dictionarySize;
  1270. int dicLogSize;
  1271. for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
  1272. if (dictionarySize <= ((UInt32)(1) << dicLogSize))
  1273. break;
  1274. _distTableSize = (UInt32)dicLogSize * 2;
  1275. break;
  1276. }
  1277. case CoderPropID.PosStateBits:
  1278. {
  1279. if (!(prop is Int32))
  1280. throw new InvalidParamException();
  1281. Int32 v = (Int32)prop;
  1282. if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
  1283. throw new InvalidParamException();
  1284. _posStateBits = (int)v;
  1285. _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;
  1286. break;
  1287. }
  1288. case CoderPropID.LitPosBits:
  1289. {
  1290. if (!(prop is Int32))
  1291. throw new InvalidParamException();
  1292. Int32 v = (Int32)prop;
  1293. if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)
  1294. throw new InvalidParamException();
  1295. _numLiteralPosStateBits = (int)v;
  1296. break;
  1297. }
  1298. case CoderPropID.LitContextBits:
  1299. {
  1300. if (!(prop is Int32))
  1301. throw new InvalidParamException();
  1302. Int32 v = (Int32)prop;
  1303. if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)
  1304. throw new InvalidParamException(); ;
  1305. _numLiteralContextBits = (int)v;
  1306. break;
  1307. }
  1308. case CoderPropID.EndMarker:
  1309. {
  1310. if (!(prop is Boolean))
  1311. throw new InvalidParamException();
  1312. SetWriteEndMarkerMode((Boolean)prop);
  1313. break;
  1314. }
  1315. default:
  1316. throw new InvalidParamException();
  1317. }
  1318. }
  1319. }
  1320. uint _trainSize = 0;
  1321. public void SetTrainSize(uint trainSize)
  1322. {
  1323. _trainSize = trainSize;
  1324. }
  1325. }
  1326. }