protected override SyntaxToken VisitFunction(FunctionSyntaxToken token) { SyntaxToken arg = token.Arguments[0]; SyntaxToken diff = this.Visit(arg); SyntaxToken one = SyntaxToken.Constant(1); SyntaxToken two = SyntaxToken.Constant(2); SyntaxToken result; switch (token.Type) { case FunctionType.Sin: result = SyntaxToken.Cos(arg); break; case FunctionType.Cos: result = SyntaxToken.Negate(SyntaxToken.Sin(arg)); break; case FunctionType.Tan: result = SyntaxToken.Add(one, SyntaxToken.Pow(SyntaxToken.Tan(arg), two)); break; case FunctionType.Cot: result = SyntaxToken.Negate(SyntaxToken.Add(one, SyntaxToken.Pow(SyntaxToken.Cot(arg), two))); break; case FunctionType.Asin: result = SyntaxToken.Divide(one, SyntaxToken.Root(SyntaxToken.Subtract(one, SyntaxToken.Pow(arg, two)), two)); break; case FunctionType.Acos: result = -(one / SyntaxToken.Root(one - SyntaxToken.Pow(arg, two), two)); break; case FunctionType.Atan: result = one / (one + SyntaxToken.Pow(arg, two)); break; case FunctionType.Acot: result = -(one / (one + SyntaxToken.Pow(arg, two))); break; case FunctionType.Log: SyntaxToken b = token.Arguments[1]; result = one / (arg * SyntaxToken.Ln(b)); break; case FunctionType.Ln: result = one / arg; break; case FunctionType.Abs: result = arg / SyntaxToken.Abs(arg); break; case FunctionType.Unsupported: default: throw new NotSupportedException(); } return(result * diff); }
protected override SyntaxToken VisitBinary(BinarySyntaxToken token) { SyntaxToken leftDiff = this.Visit(token.Left); SyntaxToken rightDiff = this.Visit(token.Right); switch (token.Type) { case BinaryOperationType.Add: return(leftDiff + rightDiff); case BinaryOperationType.Subtract: return(leftDiff - rightDiff); case BinaryOperationType.Multiply: return(leftDiff * token.Right + token.Left * rightDiff); case BinaryOperationType.Divide: return((leftDiff * token.Right - token.Left * rightDiff) / SyntaxToken.Pow(token.Right, SyntaxToken.Constant(2))); // TODO: implement case BinaryOperationType.Modulus: return(token); case BinaryOperationType.Power: if (!this.VarDetector.HasVariable(token.Right)) { return(token.Right * SyntaxToken.Pow(token.Left, token.Right - SyntaxToken.Constant(1))); } return(token * (leftDiff * token.Right / token.Left + rightDiff * SyntaxToken.Ln(token.Left))); default: throw new NotSupportedException(); } }
private SyntaxToken EvalUnary(ConstantSyntaxToken value, UnaryOperationType type) { switch (type) { case UnaryOperationType.Factorial: return SyntaxToken.Constant(MathEx.Factorial(value.Value)); default: throw new NotSupportedException(); } }
protected override SyntaxToken VisitVariable(VariableSyntaxToken token) { if (SyntaxToken.Equals(this.Variable, token)) { return(SyntaxToken.Constant(1)); } return(SyntaxToken.Constant(0)); }
public EvaluationContext CreateEvaluationContext() { EvaluationContext context = new EvaluationContext(); foreach (var item in this.Constants) { context.SetVariable(item.Key, SyntaxToken.Constant(item.Value)); } return(context); }
private SyntaxToken EvalBinary(ConstantSyntaxToken left, ConstantSyntaxToken right, BinaryOperationType type) { double lval = left.Value; double rval = right.Value; switch (type) { case BinaryOperationType.Add: return SyntaxToken.Constant(lval + rval); case BinaryOperationType.Subtract: return SyntaxToken.Constant(lval - rval); case BinaryOperationType.Multiply: return SyntaxToken.Constant(lval * rval); case BinaryOperationType.Divide: return SyntaxToken.Constant(lval / rval); case BinaryOperationType.Modulus: return SyntaxToken.Constant(lval % rval); case BinaryOperationType.Power: return SyntaxToken.Constant(Math.Pow(lval, rval)); default: throw new NotSupportedException(); } }
private SyntaxToken EvalFunction(ConstantSyntaxToken[] values, FunctionType type) { switch (type) { case FunctionType.Sin: return SyntaxToken.Constant(Math.Sin(values[0].Value)); case FunctionType.Cos: return SyntaxToken.Constant(Math.Cos(values[0].Value)); case FunctionType.Tan: return SyntaxToken.Constant(Math.Tan(values[0].Value)); case FunctionType.Cot: return SyntaxToken.Constant(MathEx.Cot(values[0].Value)); case FunctionType.Asin: return SyntaxToken.Constant(Math.Asin(values[0].Value)); case FunctionType.Acos: return SyntaxToken.Constant(Math.Acos(values[0].Value)); case FunctionType.Atan: return SyntaxToken.Constant(Math.Atan(values[0].Value)); case FunctionType.Acot: return SyntaxToken.Constant(MathEx.Acot(values[0].Value)); case FunctionType.Log: return SyntaxToken.Constant(Math.Log(values[0].Value, values[1].Value)); case FunctionType.Ln: return SyntaxToken.Constant(Math.Log(values[0].Value)); case FunctionType.Abs: return SyntaxToken.Constant(Math.Abs(values[0].Value)); default: throw new NotSupportedException(); } }
protected override SyntaxToken VisitConstant(ConstantSyntaxToken token) { return(SyntaxToken.Constant(0)); }
protected override SyntaxToken VisitNamedConstant(NamedConstantSyntaxToken token) { return SyntaxToken.Constant(token.Value); }
protected override SyntaxToken VisitBinary(BinarySyntaxToken token) { SyntaxToken left = this.Visit(token.Left); SyntaxToken right = this.Visit(token.Right); BinaryOperationType type = token.Type; if (left.TokenType == SyntaxTokenType.Constant && right.TokenType == SyntaxTokenType.Constant) { return this.EvalBinary((ConstantSyntaxToken)left, (ConstantSyntaxToken)right, type); } // swap constant to the right if ((type == BinaryOperationType.Add || type == BinaryOperationType.Multiply) && (left.TokenType == SyntaxTokenType.Constant)) { SyntaxToken temp = right; right = left; left = temp; } // add if (type == BinaryOperationType.Add) { if (right.HasValue(0)) { return left; } } // subtract else if (type == BinaryOperationType.Subtract) { if (right.HasValue(0)) { return left; } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(0); } } // multiply else if (type == BinaryOperationType.Multiply) { if (right.HasValue(0)) { return SyntaxToken.Constant(0); } if (right.HasValue(1)) { return left; } if (left.TokenType == SyntaxTokenType.Binary && right.TokenType == SyntaxTokenType.Binary) { BinarySyntaxToken bl = (BinarySyntaxToken)left; BinarySyntaxToken br = (BinarySyntaxToken)right; if (bl.Type == BinaryOperationType.Power && br.Type == BinaryOperationType.Power && SyntaxToken.Equals(bl.Left, br.Left)) { return this.Visit(SyntaxToken.Pow(bl.Left, SyntaxToken.Add(bl.Right, br.Right))); } } } // divide else if (type == BinaryOperationType.Divide) { if (left.HasValue(0)) { return SyntaxToken.Constant(0); } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(1); } } // modulus else if (type == BinaryOperationType.Modulus) { if (left.HasValue(0)) { return SyntaxToken.Constant(0); } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(0); } } // pow else if (type == BinaryOperationType.Power) { if (right.HasValue(0)) { return SyntaxToken.Constant(1); } if (right.HasValue(1)) { return left; } if (left.HasValue(0)) { return SyntaxToken.Constant(1); } if (left.TokenType == SyntaxTokenType.Binary) { BinarySyntaxToken bl = (BinarySyntaxToken)left; if (bl.Type == BinaryOperationType.Power) { return this.Visit(SyntaxToken.Pow(bl.Left, SyntaxToken.Multiply(bl.Right, right))); } } } return SyntaxToken.Binary(left, right, type); }