public Characteristic(FormulaInfo formulaInfo, ReportDataProvider reportDataProvider)
        {
            if (formulaInfo == null)
            {
                throw new ArgumentNullException("formulaInfo");
            }
            if (reportDataProvider == null)
            {
                throw new ArgumentNullException("reportDataProvider");
            }

            _reportDataProvider = reportDataProvider;

            var formulaCore = formulaInfo.Coefficients
                                         .Aggregate(formulaInfo.Expression,
                                             (current, coeff) =>
                                                 current.Replace(coeff.Key,
                                                     coeff.Value.ToString(CultureInfo.InvariantCulture)));

            _arguments = formulaInfo.Arguments;

            var preparedExpression = ToolsHelper.Parser.Parse(formulaCore);
            _compiledExpression = ToolsHelper.Compiler.Compile(preparedExpression);
            _compiledExpression = ToolsHelper.Optimizer.Optimize(_compiledExpression);
        }
Example #2
0
 public double Calculate(CompiledExpression compiledExpression, List<VariableValue> variableValues) {
     if (compiledExpression == null)
         throw new ArgumentNullException("compiledExpression");
     if (variableValues == null)
         throw new ArgumentNullException("variableValues");
     //
     List<double> calculationsStack = new List<double>();
     //
     for (int i = 0; i < compiledExpression.CompiledExpressionItems.Count; i++) {
         CompiledExpressionItem item = compiledExpression.CompiledExpressionItems[i];
         //
         switch (item.Kind) {
             case CompiledExpressionItemKind.Constant: {
                 calculationsStack.Add(item.Constant);
                 break;
             }
             case CompiledExpressionItemKind.Variable: {
                 // TODO: Add dictionary optimizations.
                 bool variableValueFound = false;
                 foreach (VariableValue variableValue in variableValues) {
                     if (item.VariableName == variableValue.VariableName) {
                         variableValueFound = true;
                         calculationsStack.Add(variableValue.Value);
                         break;
                     }
                 }
                 if (!variableValueFound)
                     throw new MathProcessorException(String.Format("Variable {0} is not initialized.", item.VariableName));
                 break;
             }
             case CompiledExpressionItemKind.Operation: {
                 Operation operation = operationsRegistry.GetOperationByName(item.OperationName);
                 double[] parametersArray = new double[operation.OperandsCount];
                 //
                 if (calculationsStack.Count - operation.OperandsCount < 0)
                     throw new MathProcessorException("Stack is empty.");
                 for (int j = 0; j < operation.OperandsCount; j++) {
                     int index = calculationsStack.Count - operation.OperandsCount + j;
                     parametersArray[j] = calculationsStack[index];
                 }
                 //
                 calculationsStack.RemoveRange(calculationsStack.Count - operation.OperandsCount, operation.OperandsCount);
                 calculationsStack.Add(operation.Calculator.Calculate(parametersArray));
                 break;
             }
             default: {
                 throw new InvalidOperationException("Unknown item kind.");
             }
         }
     }
     //
     if (calculationsStack.Count != 1)
         throw new MathProcessorException("Stack disbalance. Expression has invalid syntax.");
     return calculationsStack[0];
 }
Example #3
0
 public CompiledExpression Optimize(CompiledExpression compiledExpression) {
     if (compiledExpression == null)
         throw new ArgumentNullException("compiledExpression");
     //
     List<CompiledExpressionItem> optimizedExpression = new List<CompiledExpressionItem>();
     //
     for (int i = 0; i < compiledExpression.CompiledExpressionItems.Count; i++) {
         CompiledExpressionItem item = compiledExpression.CompiledExpressionItems[i];
         //
         switch (item.Kind) {
             case CompiledExpressionItemKind.Constant: {
                 optimizedExpression.Add(item);
                 break;
             }
             case CompiledExpressionItemKind.Variable: {
                 optimizedExpression.Add(item);
                 break;
             }
             case CompiledExpressionItemKind.Operation: {
                 Operation operation = operationsRegistry.GetOperationByName(item.OperationName);
                 // If all arguments are constants, we can optimize this. Otherwise, we can't
                 bool noVariablesInArguments = true;
                 for (int j = 0; (j < operation.OperandsCount) && noVariablesInArguments; j++) {
                     int index = optimizedExpression.Count - operation.OperandsCount + j;
                     if (index < 0)
                         throw new MathProcessorException("Stack is empty.");
                     //
                     if (optimizedExpression[index].Kind != CompiledExpressionItemKind.Constant)
                         noVariablesInArguments = false;
                 }
                 if (noVariablesInArguments) {
                     double[] arguments = new double[operation.OperandsCount];
                     for (int j = optimizedExpression.Count - operation.OperandsCount, k = 0; j < optimizedExpression.Count; j++, k++) {
                         arguments[k] = optimizedExpression[j].Constant;
                     }
                     //
                     optimizedExpression.RemoveRange(optimizedExpression.Count - operation.OperandsCount, operation.OperandsCount);
                     optimizedExpression.Add(new CompiledExpressionItem(CompiledExpressionItemKind.Constant,
                                                                        operation.Calculator.Calculate(arguments)));
                 } else {
                     optimizedExpression.Add(item);
                 }
                 break;
             }
             default: {
                 throw new InvalidOperationException("Unknown item kind.");
             }
         }
     }
     return new CompiledExpression(optimizedExpression);
 }
Example #4
0
 public PreparedExpression Decompile(CompiledExpression compiledExpression) {
     if (compiledExpression == null)
         throw new ArgumentNullException("compiledExpression");
     //
     List<DecompiledExpressionItem> decompilationStack = new List<DecompiledExpressionItem>();
     //
     for (int i = 0; i < compiledExpression.CompiledExpressionItems.Count; i++) {
         CompiledExpressionItem item = compiledExpression.CompiledExpressionItems[i];
         //
         switch (item.Kind) {
             case CompiledExpressionItemKind.Constant: {
                 List<PreparedExpressionItem> items = new List<PreparedExpressionItem>();
                 items.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Constant, item.Constant));
                 decompilationStack.Add(new DecompiledExpressionItem(false, new PreparedExpression(items)));
                 break;
             }
             case CompiledExpressionItemKind.Variable: {
                 List<PreparedExpressionItem> items = new List<PreparedExpressionItem>();
                 items.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Variable, item.VariableName));
                 decompilationStack.Add(new DecompiledExpressionItem(false, new PreparedExpression(items)));
                 break;
             }
             case CompiledExpressionItemKind.Operation: {
                 Operation operation = operationsRegistry.GetOperationByName(item.OperationName);
                 List<PreparedExpressionItem> resultExpression = new List<PreparedExpressionItem>();
                 // Begining to construct a new expression string
                 if (operation.Kind == OperationKind.Function) {
                     resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Signature, operation.Signature[0]));
                     resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, DelimiterKind.OpeningBrace));
                 } else if (operation.OperandsCount == 1) {
                     // Unary operator
                     resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Signature, operation.Signature[0]));
                 }
                 // For each argument we have to determine, need there are braces or not
                 for (int j = 0; j < operation.OperandsCount; j++) {
                     int index = decompilationStack.Count - operation.OperandsCount + j;
                     if (index < 0)
                         throw new MathProcessorException("Stack is empty.");
                     //
                     DecompiledExpressionItem decompiledItem = decompilationStack[index];
                     bool applyBraces = false;
                     if (operation.Kind != OperationKind.Function) {
                         // First argument
                         if (j == 0) {
                             if (decompiledItem.IsComplex)
                                 if (decompiledItem.LastOperation.Kind != OperationKind.Function) {
                                     if (decompiledItem.LastOperation.OperandsCount == 1)
                                         applyBraces = true;
                                     else {
                                         if (operation.Priority < decompiledItem.LastOperation.Priority)
                                             applyBraces = true;
                                         else if (operation.Priority == decompiledItem.LastOperation.Priority) {
                                             if (operationsRegistry.GetAssociationByPriority(operation.Priority) == PriorityAssociation.RightAssociated)
                                                 applyBraces = true;
                                         }
                                     }
                                 }
                         } else
                             // Last argument
                             if (j == operation.OperandsCount - 1)
                                 if (decompiledItem.IsComplex)
                                     if (decompiledItem.LastOperation.Kind != OperationKind.Function) {
                                         if (decompiledItem.LastOperation.OperandsCount == 1)
                                             applyBraces = true;
                                         else {
                                             if (operation.Priority < decompiledItem.LastOperation.Priority)
                                                 applyBraces = true;
                                             else if (operation.Priority == decompiledItem.LastOperation.Priority) {
                                                 if (operationsRegistry.GetAssociationByPriority(operation.Priority) == PriorityAssociation.LeftAssociated)
                                                     applyBraces = true;
                                             }
                                         }
                                     }
                     }
                     if (applyBraces)
                         resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, DelimiterKind.OpeningBrace));
                     resultExpression.AddRange(decompiledItem.Expression.PreparedExpressionItems);
                     if (applyBraces)
                         resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, DelimiterKind.ClosingBrace));
                     
                     
                     // Appending delimiters between arguments
                     if (j < operation.OperandsCount - 1) {
                         if (operation.Kind == OperationKind.Function) {
                             resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, DelimiterKind.Comma));
                         } else {
                             resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Signature, operation.Signature[j]));
                         }
                     }
                 }
                 decompilationStack.RemoveRange(decompilationStack.Count - operation.OperandsCount, operation.OperandsCount);
                 //
                 if (operation.Kind == OperationKind.Function)
                     resultExpression.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, DelimiterKind.ClosingBrace));
                 //
                 decompilationStack.Add(new DecompiledExpressionItem(true, new PreparedExpression(resultExpression), operation));
                 break;
             }
             default: {
                 throw new InvalidOperationException("Unknown item kind.");
             }
         }
     }
     //
     if (decompilationStack.Count != 1)
         throw new MathProcessorException("Stack disbalance. Expression has invalid syntax.");
     return (decompilationStack[0].Expression);
 }
Example #5
0
 /// <summary>
 /// Checks a compiled expression for stack balance.
 /// </summary>
 private bool isCompiledExpressionStackBalanced(CompiledExpression compiledExpression) {
     if (compiledExpression == null)
         throw new ArgumentNullException("compiledExpression");
     //
     int stackPointer = 0;
     //
     for (int i = 0; i < compiledExpression.CompiledExpressionItems.Count; i++) {
         CompiledExpressionItem item = compiledExpression.CompiledExpressionItems[i];
         //
         switch (item.Kind) {
             case CompiledExpressionItemKind.Constant: {
                 stackPointer++;
                 break;
             }
             case CompiledExpressionItemKind.Variable: {
                 stackPointer++;
                 break;
             }
             case CompiledExpressionItemKind.Operation: {
                 Operation operation = operationsRegistry.GetOperationByName(item.OperationName);
                 stackPointer -= operation.OperandsCount - 1;
                 break;
             }
             default: {
                 throw new InvalidOperationException("Unknown item kind.");
             }
         }
     }
     //
     if (stackPointer != 1)
         return (false);
     return (true);
 }