/// <summary> /// Updates the potentual blocks that could replace the current block /// </summary> /// <param name="value"></param> /// <param name="bitDiffDiff"></param> private void UpdateReplacingCalculations(ref OfcNumber value, int bitDiffDiff = 0) { // ReSharper disable once ForCanBeConvertedToForeach for (var j = _appendingCalculationSavingGrade + 1; j < _replacingCalculations.Length; j++) { if (!_replacingCalculations[j].IsValid) { continue; } var replacingCalculation = _replacingCalculations[j]; var savingGrade = replacingCalculation.VirtualBlock.GetSavingGrade(); if (!replacingCalculation.ProcessValue(value, _index)) { _replacingCalculations[j].IsValid = false; continue; } if ((replacingCalculation.SavedBits += bitDiffDiff) > 0) { _replacingCalculations[j].IsValid = false; _calculations.Clear(); //Todo: not jsut clear, but make a replacingCalc on this replacing calc ... _hasRunningPatternCalculation = false; if (!replacingCalculation.OldConcurrentBlock.IsValid) //Todo: check what this was { ReplaceNewestBlock(BlockCalculation.FromReplacingCalculation(replacingCalculation)); } else { _blocks[_blocks.Count - 1] = replacingCalculation.OldConcurrentBlock; // set last block to old, non-overlapping state AddNewBlock(BlockCalculation.FromReplacingCalculation(replacingCalculation)); } break; } var newSavingGrade = replacingCalculation.VirtualBlock.GetSavingGrade(); if (savingGrade != newSavingGrade) { _replacingCalculations[(int)savingGrade].IsValid = false; var overriddenCalc = _replacingCalculations[(int)newSavingGrade]; if (overriddenCalc.IsValid && overriddenCalc.SavedBits > replacingCalculation.SavedBits) { continue; } } if (newSavingGrade <= replacingCalculation.OldConcurrentSavingGrade) { replacingCalculation.IsValid = false; } // replacingCalculations[j].IsValid = false; _replacingCalculations[(int)newSavingGrade] = replacingCalculation; } }
/// <summary> /// Replaces the current block with a potentual block /// </summary> /// <param name="with"></param> private void ReplaceNewestBlock(BlockCalculation with) { _blocks[_blocks.Count - 1] = with.VirtualBlock; _lastStableBlock = with.VirtualBlock; _appendingCalculation = with; _appendingCalculation.SavedBits = 0; _appendingCalculationSavingGrade = (int)with.VirtualBlock.GetSavingGrade(); for (var i = 1; i < _replacingCalculations.Length; i++) { _replacingCalculations[i].IsValid = false; } }
/// <summary> /// Creates a block from a potentual block, and sets it as current block /// </summary> /// <param name="calc"></param> private void AddNewBlock(BlockCalculation calc) { _lastStableBlock = calc.VirtualBlock; _appendingCalculation = calc; _blocks.Add(calc.VirtualBlock); _isAppendingCalculationValid = true; _appendingCalculationSavingGrade = (int)calc.VirtualBlock.GetSavingGrade(); for (var i = 1; i < _replacingCalculations.Length; i++) { _replacingCalculations[i].IsValid = false; } }
/// <summary> /// Does one step. Will update everything /// </summary> /// <returns></returns> public bool ProcessNextValue() { var value = Values[_index]; var patternPred = _patternPredictor.PredictNext(value); #region adding value to last block and updating replacing calculations if (_isAppendingCalculationValid) { var lastBitDiff = _appendingCalculation.SavedBits; var lastAppendingBlock = _appendingCalculation.VirtualBlock; if (_appendingCalculation.ProcessValue(value, _index)) { var bifDiffDiff = lastBitDiff - _appendingCalculation.SavedBits; if (_appendingCalculation.SavedBits > 0) { if (_appendingCalculation.VirtualBlock.Length - _lastStableBlock.Length > 1) // we made a jump, maybe there were some calcs started in the meantime? { TransformCalcsToReplaceCalsOrDelete(lastAppendingBlock, _appendingCalculation.SavedBits); } ReplaceNewestBlock(_appendingCalculation); } _appendingCalculationSavingGrade = (int)_appendingCalculation.VirtualBlock.GetSavingGrade(); UpdateReplacingCalculations(ref value, bifDiffDiff); if (patternPred && _appendingCalculationSavingGrade < (int)Block.SavingGrade.Pattern && !_replacingCalculations[(int)Block.SavingGrade.Pattern].IsValid) { var block = new Block(_index, value.Exponent, value.NeededBitsNumber, value.IsNegative, value.Number, this, Methods.PatternSame, true); var calc = _replacingCalculations[(int)Block.SavingGrade.Pattern]; calc.Initialize(-Headers.StandardBlockPatternSame, block, lastAppendingBlock, (Block.SavingGrade)_appendingCalculationSavingGrade); if (calc.ProcessValue(value, _index)) { _replacingCalculations[(int)Block.SavingGrade.Pattern] = calc; } } } else { UpdateReplacingCalculations(ref value); _isAppendingCalculationValid = false; } } else { UpdateReplacingCalculations(ref value); } #endregion #region updating current calculations if nessecary var isLastBlockUp2Date = _lastStableBlock.Index + _lastStableBlock.Length - 1 == _index; for (var j = 0; j < _calculations.Count; j++) { var calc = _calculations[j]; // Todo: we shouldn't only remove calculations that are super far away, we should also remove calculations that have a very negative calc.SavedBits var hasPattern = calc.VirtualBlock.HasPattern; if (!calc.ProcessValue(value, _index)) { if (hasPattern) { _hasRunningPatternCalculation = false; } _calculations.RemoveAt(j--); // There was some error / the block is impossible, e.g. the exps are different and you can't even correct the values because of overflows ... continue; } if (hasPattern && !calc.VirtualBlock.HasPattern) { //throw new Exception("c#er is wrong"); _hasRunningPatternCalculation = false; } if (calc.SavedBits > 0) { if (calc.VirtualBlock.HasPattern) { _hasRunningPatternCalculation = false; } if (_lastStableBlock.Index + _lastStableBlock.Length - 1 >= calc.VirtualBlock.Index) { #if debug Console.WriteLine(_debugCounter); _debugSkip = 0; _debugEnabled = true; #endif _calculations.RemoveAt(j--); continue; throw new InvalidOperationException("Blocks sharing values! (ノ° ͜ʖ ͡°)ノ︵┻┻ "); } AddNewBlock(calc); isLastBlockUp2Date = true; for (var k = j + 1; k < _calculations.Count; k++) // we need to update the rest here or they jump one update tick if they get transformed to ReplaceCalcs ... { var calc2 = _calculations[k]; if (!calc2.ProcessValue(value, _index)) { _calculations.RemoveAt(k--); continue; } _calculations[k] = calc2; } TransformCalcsToReplaceCalsOrDelete(Block.InvalidBlock, calc.SavedBits, j); // we give an invalid block because the just created block and the already running calc could never co-exist. The just created block will get deleted if a replacing calc with an invalid oldConcurrentBLock gets founded break; // Bug: actually, breaking here is pretty bad. There could be multiple calculations that want to create a block, and maybe this is not the best one. Saves some performance though } _calculations[j] = calc; } #endregion #region starting new calculations if nessecary //if (isLastBlockUp2Date) //{ // if (patternPred && _appendingCalculationSavingGrade < (int)Block.SavingGrade.Pattern && !_replacingCalculations[(int)Block.SavingGrade.Pattern].IsValid) // { // var block = new Block(_index, value.Exponent, value.NeededBitsNumber, value.IsNegative, value.Number, this, Methods.PatternSame, true); // var calc = _replacingCalculations[(int)Block.SavingGrade.Pattern]; // calc.Initialize(-Headers.StandardBlockPatternSame, block, _lastStableBlock, (Block.SavingGrade)_appendingCalculationSavingGrade); // if (calc.ProcessValue(ref value, _index)) // _replacingCalculations[(int)Block.SavingGrade.Pattern] = calc; // } //} //else if (!_hasRunningPatternCalculation && !isLastBlockUp2Date) { if (patternPred) { var calc = new BlockCalculation(-Headers.StandardBlockPatternSame, new Block(_index, value.Exponent, 0, false, value.Number, this, Methods.PatternSame, true)); if (calc.ProcessValue(value, _index)) { _calculations.Add(calc); _hasRunningPatternCalculation = true; } } else { var hasExp = false; foreach (var runningCalculation in _calculations) //Todo: pre calculate that (bool array?) { if (runningCalculation.VirtualBlock.Exponent == value.Exponent) { hasExp = true; break; } } if (!hasExp) { BlockCalculation calc; // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression - You can't see **** if you do a ?: if (value.Exponent == 0) { calc = new BlockCalculation(-Headers.StandardBlockNumbersNoExp, new Block(_index, 0, value.NeededBitsNumber, value.IsNegative, value.Number, this, Methods.NumbersNoExp, false)); } else { calc = new BlockCalculation(-Headers.StandardBlockFloatSimmilar, new Block(_index, value.Exponent, value.NeededBitsNumber, value.IsNegative, value.Number, this, Methods.FloatSimmilar, false)); } if (calc.ProcessValue(value, _index)) { _calculations.Add(calc); } else { throw new Exception("Nice blockfinding Kappa"); } } } } #endregion return(++_index < ValueCount); }