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