private static ExpressionList GetAsExpressionList(Expression expression) { Assert.IsTrue(expression is SingleComponentExpression); var component = ((SingleComponentExpression)expression).Component; Assert.IsTrue(component is SingleFactorComponent); var factor = ((SingleFactorComponent)component).Factor; Assert.IsTrue(factor is ExpressionList); return (ExpressionList)factor; }
private Expression Evaluate(Expression parameter) { var operand = Factorizer.ToFactor(parameter.Evaluate()); if (operand is AlphabeticFactor) { // If operand is a constant (like pi), and the result is not an integer, don't evaluate var factor = (AlphabeticFactor)operand; if (Constants.IsNamedConstant(factor.Value)) { var result = _function(Constants.Get(factor.Value)); if (IsInteger(result)) { return Expressionizer.ToExpression(new NumericFactor(new Integer((int)result))); } return Expressionizer.ToExpression(new FunctionComponent(Name, new List<Expression> { parameter })); } } // See if our input is any of the basic trig identities var identityResult = TrigonometricIdentities.Get(Name, operand); if (identityResult != null) return Expressionizer.ToExpression(identityResult); if (operand is NumericFactor) { var factor = (NumericFactor)operand; if (factor.Number is Float) { var number = (Float)factor.Number; if (Name == "tan" && Math.Abs(number.Value - Math.PI / 2) < Constants.Tolerance) { return Expressionizer.ToExpression(new ExpressionFactor(new UndefinedExpression())); } return Expressionizer.ToExpression(new NumericFactor(new Float(_function(number.Value)))); } } return Expressionizer.ToExpression(new FunctionComponent(Name, new List<Expression> { Expressionizer.ToExpression(operand) })); }
internal ExpressionFactor(Expression expression) { Expression = expression; }
private static bool ReduceExponents(out Expression expression, Expression left, Expression right) { FunctionComponent leftFunction; FunctionComponent rightFunction; // If there is an exponent times another instance of that base, combine them // e.g. x^2 * x = x^3 if (Common.IsFunction(left, out leftFunction) && leftFunction.Function is Exponent) { var baseExpression = leftFunction.Operands[0]; var power = Factorizer.ToFactor(leftFunction.Operands[1]); if (power is NumericFactor && baseExpression.Equals(right)) { expression = Expressionizer.ToExpression(new FunctionComponent(new Exponent(), new List<Expression> { baseExpression, Expressionizer.ToExpression(new NumericFactor(((NumericFactor) power).Number + new Integer(1))) })); return true; } } if (Common.IsFunction(right, out rightFunction) && rightFunction.Function is Exponent) { var baseExpression = rightFunction.Operands[0]; var power = Factorizer.ToFactor(rightFunction.Operands[1]); if (power is NumericFactor && baseExpression.Equals(left)) { expression = Expressionizer.ToExpression(new FunctionComponent(new Exponent(), new List<Expression> { baseExpression, Expressionizer.ToExpression(new NumericFactor(((NumericFactor) power).Number + new Integer(1))) })); return true; } } expression = null; return false; }
private static bool ReduceFunctionsWithSameOperands(ComponentListFactor leftFactor, ComponentListFactor rightFactor, out Expression expression, Expression left, Expression right) { FunctionComponent leftFunction; FunctionComponent rightFunction; // If there are two functions with the same operands that should cancel out, cancel them out if (Common.IsFunction(left, out leftFunction) && Common.IsFunction(right, out rightFunction)) { if (leftFunction.Function.Name == rightFunction.Function.Name && leftFunction.Operands.Count == rightFunction.Operands.Count) { for (var i = 0; i < leftFunction.Operands.Count; i++) { var leftOperand = leftFunction.Operands[i]; var rightOperand = rightFunction.Operands[i]; if (!leftOperand.ToString().Equals(rightOperand.ToString())) { break; } if (leftFactor.IsInNumerator != rightFactor.IsInNumerator) { expression = Expressionizer.ToExpression(new NumericFactor(new Integer(1))); return true; } } } } expression = null; return false; }
private static bool ReduceMultipliedAlphabeticFactors(ComponentListFactor leftFactor, ComponentListFactor rightFactor, out Expression expression) { // If any alphabetic factors are identical, convert to exponent if (leftFactor.Factor is AlphabeticFactor && rightFactor.Factor is AlphabeticFactor) { var leftAlpha = (AlphabeticFactor) leftFactor.Factor; var rightAlpha = (AlphabeticFactor) rightFactor.Factor; if (leftAlpha.Value.Equals(rightAlpha.Value)) { var shouldPower = leftFactor.IsInNumerator && rightFactor.IsInNumerator; if (shouldPower) { expression = new SingleComponentExpression(new FunctionComponent("^", new List<Expression> { Expressionizer.ToExpression(leftAlpha), NumberToExpression(new Integer(2)) })); return true; } expression = NumberToExpression(new Integer(1)); return true; } } expression = null; return false; }
private static bool CanReduce(ComponentListFactor leftFactor, ComponentListFactor rightFactor, out Expression expression) { if (ReduceMultipliedAlphabeticFactors(leftFactor, rightFactor, out expression)) { return true; } var left = Expressionizer.ToExpression(leftFactor.Factor); var right = Expressionizer.ToExpression(rightFactor.Factor); Number leftNumber; Number rightNumber; if ((Common.IsConstant(left, out leftNumber) && Common.IsFloat(right, out rightNumber)) || (Common.IsFloat(left, out leftNumber) && Common.IsConstant(right, out rightNumber)) || (Common.IsNumber(left, out leftNumber) && Common.IsNumber(right, out rightNumber))) { expression = Evaluate(leftNumber, rightNumber, leftFactor.IsInNumerator, rightFactor.IsInNumerator); return true; } ExpressionList leftList; ExpressionList rightList; if (Common.IsList(left, out leftList)) { expression = Evaluate(leftList, right, leftFactor.IsInNumerator == rightFactor.IsInNumerator); return true; } if (Common.IsList(right, out rightList)) { expression = Evaluate(rightList, left, leftFactor.IsInNumerator == rightFactor.IsInNumerator); return true; } IntegerFraction leftFraction; IntegerFraction rightFraction; if (Common.IsNumber(left, out leftNumber) && Common.IsIntegerFraction(right, out rightFraction)) { expression = Expressionizer.ToExpression(Evaluate(leftNumber, rightFraction, leftFactor.IsInNumerator, rightFactor.IsInNumerator)); return true; } if (Common.IsIntegerFraction(left, out leftFraction) && Common.IsNumber(right, out rightNumber)) { expression = Expressionizer.ToExpression(Evaluate(leftFraction, rightNumber, leftFactor.IsInNumerator, rightFactor.IsInNumerator)); return true; } if (Common.IsIntegerFraction(left, out leftFraction) && Common.IsIntegerFraction(right, out rightFraction)) { expression = Expressionizer.ToExpression(Evaluate(leftFraction, rightFraction, leftFactor.IsInNumerator, rightFactor.IsInNumerator)); return true; } if (ReduceFunctionsWithSameOperands(leftFactor, rightFactor, out expression, left, right)) { return true; } if (ReduceExponents(out expression, left, right)) { return true; } expression = null; return false; }
private static Component ToComponent(Expression expression) { return expression is SingleComponentExpression ? ToComponent(((SingleComponentExpression)expression).Component) : new SingleFactorComponent(new ExpressionFactor(expression)); }
private static Expression ToExpression(Expression expression) { return expression is SingleComponentExpression ? ToExpression(((SingleComponentExpression)expression).Component) : expression; }
private static Factor ToFactor(Expression expression) { return expression is SingleComponentExpression ? ToFactor(((SingleComponentExpression)expression).Component) : new ExpressionFactor(expression); }