protected override Expression VisitPower(Power P) { Expression f = P.Left; Expression g = P.Right; if (g.DependsOn(x)) { // f(x)^g(x) return(Product.New(P, Sum.New( Product.New(Visit(f), Binary.Divide(g, f)), Product.New(Visit(g), Call.Ln(f)))).Evaluate()); } else { // f(x)^g return(Product.New( g, Power.New(f, Binary.Subtract(g, 1)), Visit(f)).Evaluate()); } }
public override bool Matches(Expression E, MatchContext Matched) { // Move the constants in this pattern to E. IEnumerable <Expression> PTerms = Terms; IEnumerable <Expression> Constants = PTerms.OfType <Constant>(); if (Constants.Any()) { E = Binary.Subtract(E, New(Constants)).Evaluate(); PTerms = PTerms.Except(Constants, RefComparer); } IEnumerable <Expression> ETerms = TermsOf(E); // Try starting the match at each term of the pattern. foreach (Expression p in PTerms) { // Remaining terms of the pattern. Expression P = New(PTerms.ExceptUnique(p, RefComparer)); // If p is a variable, we have to handle the possibility that more than one term of E might match this term. if (p is Variable) { // Check if p has already been matched. If it has, treat it as a constant and match the rest of the terms. Expression matched; if (Matched.TryGetValue(p, out matched)) { // p has already been matched. Remove it out of E and match the remainder of the pattern. if (P.Matches(Binary.Subtract(E, matched).Evaluate(), Matched)) { return(true); } } else { // Try matching p to the various combinations of the terms of E. for (int i = 1; i <= ETerms.Count(); ++i) { foreach (IEnumerable <Expression> e in ETerms.Combinations(i)) { if (Matched.TryMatch(() => p.Matches(New(e), Matched) && P.Matches(New(ETerms.ExceptUnique(e, RefComparer)), Matched))) { return(true); } } } // Try matching p to identity. if (Matched.TryMatch(() => p.Matches(0, Matched) && P.Matches(E, Matched))) { return(true); } } } else { // If p is not a variable, try matching it to any of the terms of E. foreach (Expression e in ETerms) { if (Matched.TryMatch(() => p.Matches(e, Matched) && P.Matches(New(ETerms.ExceptUnique(e, RefComparer)), Matched))) { return(true); } } } } return(false); }