private static object CountIfs(List <Expression> p) { // get parameters var ce = new CalcEngine(); long count = 0; int numberOfCriteria = p.Count / 2; long totalCount = 0; // prepare criteria-parameters: var criteriaRanges = new Tuple <object, List <object> > [numberOfCriteria]; for (int criteriaPair = 0; criteriaPair < numberOfCriteria; criteriaPair++) { var criteriaRange = p[criteriaPair * 2] as XObjectExpression; var criterion = p[(criteriaPair * 2) + 1].Evaluate(); var criteriaRangeValues = new List <object>(); foreach (var value in criteriaRange) { criteriaRangeValues.Add(value); } criteriaRanges[criteriaPair] = new Tuple <object, List <object> >( criterion, criteriaRangeValues); if (totalCount == 0) { totalCount = CalcEngineHelpers.GetTotalCellsCount(criteriaRange); } } long processedCount = 0; for (var i = 0; i < criteriaRanges[0].Item2.Count; i++) { if (criteriaRanges.All(criteriaPair => CalcEngineHelpers.ValueSatisfiesCriteria( criteriaPair.Item2[i], criteriaPair.Item1, ce))) { count++; } processedCount++; } // Add count of empty cells outside the used range if they match criteria if (criteriaRanges.All(criteriaPair => CalcEngineHelpers.ValueSatisfiesCriteria( string.Empty, criteriaPair.Item1, ce))) { count += (totalCount - processedCount); } // done return(count); }
private static TransformManyBlock <DecodedBlockTx, Tuple <TxOutputKey, CompletionCount, DecodedBlockTx> > InitQueueUnspentTxLookup(CancellationToken cancelToken) { return(new TransformManyBlock <DecodedBlockTx, Tuple <TxOutputKey, CompletionCount, DecodedBlockTx> >( blockTx => { var tx = blockTx.Transaction; var outputCount = tx.Outputs.Length; var inputCount = !blockTx.IsCoinbase ? tx.Inputs.Length * 2 : 0; var txOutputKeys = new Tuple <TxOutputKey, CompletionCount, DecodedBlockTx> [1 + outputCount + inputCount]; var completionCount = new CompletionCount(txOutputKeys.Length); var keyIndex = 0; // warm-up the UnspentTx entry that will be added for the new tx txOutputKeys[keyIndex++] = Tuple.Create(new TxOutputKey(blockTx.Hash, uint.MaxValue), completionCount, blockTx); // warm-up the TxOutput entries that will be added for each of the tx's outputs for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var txOutputKey = new TxOutputKey(blockTx.Hash, (uint)outputIndex); txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); } // warm-up the previous UnspentTx and TxOutput entries that will be needed for each of the tx's inputs if (!blockTx.IsCoinbase) { for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; // input's previous tx's UnspentTx entry var txOutputKey = new TxOutputKey(input.PrevTxHash, uint.MaxValue); txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); // input's previous tx outputs's TxOutput entry txOutputKey = input.PrevTxOutputKey; txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); } } Debug.Assert(txOutputKeys.All(x => x != null)); return txOutputKeys; }, new ExecutionDataflowBlockOptions { CancellationToken = cancelToken })); }
private static TransformManyBlock<DecodedBlockTx, Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>> InitQueueUnspentTxLookup(CancellationToken cancelToken) { return new TransformManyBlock<DecodedBlockTx, Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>>( blockTx => { var tx = blockTx.Transaction; var outputCount = tx.Outputs.Length; var inputCount = !blockTx.IsCoinbase ? tx.Inputs.Length * 2 : 0; var txOutputKeys = new Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>[1 + outputCount + inputCount]; var completionCount = new CompletionCount(txOutputKeys.Length); var keyIndex = 0; // warm-up the UnspentTx entry that will be added for the new tx txOutputKeys[keyIndex++] = Tuple.Create(new TxOutputKey(blockTx.Hash, uint.MaxValue), completionCount, blockTx); // warm-up the TxOutput entries that will be added for each of the tx's outputs for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var txOutputKey = new TxOutputKey(blockTx.Hash, (uint)outputIndex); txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); } // warm-up the previous UnspentTx and TxOutput entries that will be needed for each of the tx's inputs if (!blockTx.IsCoinbase) { for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; // input's previous tx's UnspentTx entry var txOutputKey = new TxOutputKey(input.PrevTxHash, uint.MaxValue); txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); // input's previous tx outputs's TxOutput entry txOutputKey = input.PrevTxOutputKey; txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx); } } Debug.Assert(txOutputKeys.All(x => x != null)); return txOutputKeys; }, new ExecutionDataflowBlockOptions { CancellationToken = cancelToken }); }