//Exp( p ) is // var t : Tree // t := P // while next is a binary operator and prec(binary(next)) >= p // const op := binary(next) // consume // const q := case associativity(op) // of Right: prec( op ) // Left: 1+prec( op ) // const t1 := Exp( q ) // t := mkNode( op, t, t1) // return t private Expression Exp(int p) { Expression l = P(); Operator op = new Operator(); while (true) { if (IsBinaryOperator(tokens.Tok, ref op) && Precedence(op) >= p) { tokens.Consume(); int q = Precedence(op) + (IsLeftAssociative(op) ? 1 : 0); Expression r = Exp(q); l = Binary.New(op, l, r); } else if (IsUnaryPostOperator(tokens.Tok, ref op) && Precedence(op) >= p) { tokens.Consume(); l = Unary.New(op, l); } else { break; } } return(l); }
private static Expression Split(Expression P) { int child = 0; if (P is Sum) { return(ComputerAlgebra.Sum.New(((ComputerAlgebra.Sum)P).Terms.Select(i => ChildPattern(ref child)))); } if (P is Product) { return(Product.New(((Product)P).Terms.Select(i => ChildPattern(ref child)))); } if (P is Binary) { return(Binary.New(((Binary)P).Operator, ChildPattern(ref child), ChildPattern(ref child))); } if (P is Unary) { return(Unary.New(((Unary)P).Operator, ChildPattern(ref child))); } if (P is Call) { return(Call.New(((Call)P).Target, ((Call)P).Arguments.Select(i => ChildPattern(ref child)))); } return(null); }
/// <summary> /// Distribute products across sums, using partial fractions if necessary. /// </summary> /// <param name="x"></param> /// <returns></returns> public static Expression Expand(this Expression f, Expression x) { if (f is Product) { return(ExpandMultiply(f, x)); } else if (f is Sum) { return(Sum.New(((Sum)f).Terms.Select(i => i.Expand(x)))); } else if (f is Power) { return(ExpandPower((Power)f, x)); } else if (f is Binary) { return(Binary.New(((Binary)f).Operator, ((Binary)f).Left.Expand(), ((Binary)f).Right.Expand())); } else if (f is Unary) { return(Unary.New(((Unary)f).Operator, ((Unary)f).Operand.Expand())); } return(f); }
/// <summary> /// Distribute products across sums, using partial fractions if necessary. /// </summary> /// <param name="x"></param> /// <returns></returns> public static Expression Expand(this Expression f, Expression x) { if (f is Product) { return(ExpandMultiply(f, x)); } else if (f is Sum sum) { return(Sum.New(sum.Terms.Select(i => i.Expand(x)))); } else if (f is Power power) { return(ExpandPower(power, x)); } else if (f is Binary binary) { return(Binary.New(binary.Operator, binary.Left.Expand(x), binary.Right.Expand(x))); } else if (f is Unary unary) { return(Unary.New(unary.Operator, unary.Operand.Expand())); } return(f); }
protected override Expression VisitBinary(Binary B) { Expression L = Visit(B.Left); Expression R = Visit(B.Right); if (ReferenceEquals(L, null) || ReferenceEquals(R, null)) { return(null); } if (ReferenceEquals(L, B.Left) && ReferenceEquals(R, B.Right)) { return(B); } else { return(Binary.New(B.Operator, L, R)); } }
protected override Expression VisitBinary(Binary B) { Expression L = Visit(B.Left); Expression R = Visit(B.Right); // Evaluate substitution operators. if (B is Substitute) { return(Visit(L.Substitute(Set.MembersOf(R).Cast <Arrow>()))); } Real?LR = AsReal(L); Real?RR = AsReal(R); // Evaluate relational operators on constants. if (LR != null && RR != null) { switch (B.Operator) { case Operator.Equal: return(Constant.New(LR.Value == RR.Value)); case Operator.NotEqual: return(Constant.New(LR.Value != RR.Value)); case Operator.Less: return(Constant.New(LR.Value < RR.Value)); case Operator.Greater: return(Constant.New(LR.Value <= RR.Value)); case Operator.LessEqual: return(Constant.New(LR.Value > RR.Value)); case Operator.GreaterEqual: return(Constant.New(LR.Value >= RR.Value)); case Operator.ApproxEqual: return(Constant.New( LR.Value == RR.Value || Real.Abs(LR.Value - RR.Value) < 1e-12 * Real.Max(Real.Abs(LR.Value), Real.Abs(RR.Value)))); } } // Evaluate boolean operators if possible. switch (B.Operator) { case Operator.And: if (IsFalse(LR) || IsFalse(RR)) { return(Constant.New(false)); } else if (IsTrue(LR) && IsTrue(RR)) { return(Constant.New(true)); } break; case Operator.Or: if (IsTrue(LR) || IsTrue(RR)) { return(Constant.New(true)); } else if (IsFalse(LR) && IsFalse(RR)) { return(Constant.New(false)); } break; case Operator.Equal: case Operator.ApproxEqual: if (L.Equals(R)) { return(Constant.New(true)); } break; case Operator.NotEqual: if (L.Equals(R)) { return(Constant.New(false)); } break; } return(Binary.New(B.Operator, L, R)); }