LzmaEncoder.cs 65 KB

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