private void BackwardPass(byte[] input, int startPosition) { var matches = GetAllMatches(input, startPosition); var dataLength = input.Length - startPosition; var unitSize = _finders.Min(x => (int)x.DataType); for (var i = dataLength - unitSize; i >= 0; i -= unitSize) { // First get the compression length when the next byte is not compressed _history[i] = new PriceHistoryElement { IsLiteral = true, Length = unitSize, Price = _priceCalculator.CalculateLiteralPrice(input[i + startPosition]) }; if (i + unitSize < dataLength) { _history[i].Price += _history[i + unitSize].Price; } // Then go through all longest matches at position i var matchIndex = 0; foreach (var match in matches[i]) { // Get the longest match at position i if (match != null) { var matchLength = match.Length; for (var j = _finders[matchIndex].MinMatchSize; j <= matchLength; j += unitSize) { match.Length = j; var matchPrice = _priceCalculator.CalculateMatchPrice(match); long newCompLen = matchPrice; if (i + j < dataLength) { newCompLen += _history[i + j].Price; } if (newCompLen < _history[i].Price) { _history[i].IsLiteral = false; _history[i].Displacement = match.Displacement; _history[i].Length = j; _history[i].Price = newCompLen; } } } matchIndex++; } } }
private void ForwardPass(byte[] input, int startPosition) { var state = new ParserState(_history, FindOptions); var unitSize = (int)FindOptions.UnitSize; var dataPosition = 0; var dataLength = input.Length - startPosition; foreach (var matches in GetAllMatches(input, startPosition)) { // Calculate literal place at position var literalPrice = _priceCalculator.CalculateLiteralPrice(state, dataPosition, input[dataPosition]); literalPrice += _history[dataPosition].Price; if (dataPosition + unitSize < _history.Length && literalPrice < _history[dataPosition + unitSize].Price) { _history[dataPosition + unitSize].IsLiteral = true; _history[dataPosition + unitSize].Price = literalPrice; _history[dataPosition + unitSize].Length = unitSize; _history[dataPosition + unitSize].Displacement = 0; } // Then go through all longest matches at current position for (int finderIndex = 0; finderIndex < _finders.Length; finderIndex++) { var finderMatches = matches[finderIndex]; if (finderMatches == null || !finderMatches.Any()) { continue; } var longestMatch = finderMatches.MaxBy(x => x.Position); for (var j = _finders[finderIndex].FindLimitations.MinLength; j <= longestMatch.Length; j += unitSize) { var matchPrice = _priceCalculator.CalculateMatchPrice(state, dataPosition, longestMatch.Displacement, j); matchPrice += _history[dataPosition].Price; if (dataPosition + j < _history.Length && matchPrice < _history[dataPosition + j].Price) { _history[dataPosition + j].IsLiteral = false; _history[dataPosition + j].Displacement = longestMatch.Displacement; //finderMatches.TakeWhile(x => x.Length >= j).OrderBy(x => x.Displacement).First().Displacement; _history[dataPosition + j].Length = j; _history[dataPosition + j].Price = matchPrice; } } } dataPosition += unitSize; } }
private void ForwardPass(byte[] input, int startPosition, PositionElement[] history) { var matches = GetAllMatches(input, startPosition); var unitSize = (int)FindOptions.UnitSize; for (var dataPosition = 0; dataPosition < input.Length - startPosition; dataPosition += unitSize) { // Calculate literal place at position var element = history[dataPosition]; var newRunLength = element.IsMatchRun ? unitSize : element.CurrentRunLength + unitSize; var isFirstLiteralRun = IsFirstLiteralRun(dataPosition, unitSize, history); var literalPrice = _priceCalculator.CalculateLiteralPrice(input[dataPosition], newRunLength, isFirstLiteralRun); literalPrice += element.Price; if (dataPosition + unitSize < history.Length && literalPrice <= history[dataPosition + unitSize].Price) { var nextElement = history[dataPosition + unitSize]; nextElement.Parent = element; nextElement.Price = literalPrice; nextElement.CurrentRunLength = newRunLength; nextElement.IsMatchRun = false; nextElement.Match = null; } // Then go through all longest matches at current position for (var finderIndex = 0; finderIndex < _finders.Length; finderIndex++) { var finderMatch = matches[finderIndex][dataPosition]; if (finderMatch == null || !finderMatch.HasMatches) { continue; } for (var j = _finders[finderIndex].FindLimitations.MinLength; j <= finderMatch.MaxLength; j += unitSize) { var displacement = finderMatch.GetDisplacement(j); if (displacement < 0) { continue; } newRunLength = element.IsMatchRun ? element.CurrentRunLength + 1 : 1; var matchPrice = _priceCalculator.CalculateMatchPrice(displacement, j, newRunLength, input[dataPosition]); matchPrice += element.Price; if (dataPosition + j < history.Length && matchPrice < history[dataPosition + j].Price) { var nextElement = history[dataPosition + j]; nextElement.Parent = element; nextElement.Price = matchPrice; nextElement.CurrentRunLength = newRunLength; nextElement.IsMatchRun = true; nextElement.Match = new Match(dataPosition, displacement, j); } } } } }