private static Node DAtan(FunctionNode f, IReadOnlyList <Node> dargs) => dargs.Check(1)[0] / (Node.One + Node.Power(f.Arguments[0], Node.Two));
/// <summary> /// Derives the specified node to the variables. /// </summary> /// <param name="node">The nodes.</param> /// <returns>The derived nodes, or <c>null</c> if all derivatives are zero.</returns> public virtual Dictionary <VariableNode, Node> Derive(Node node) { if (Variables == null) { return(null); } // We can skip anything that is constant! if ((node.Properties & NodeProperties.Constant) != 0) { return(null); } Dictionary <VariableNode, Node> a = null, b = null; switch (node) { case UnaryOperatorNode un: if (un.NodeType == NodeTypes.Not) { return(null); } a = Derive(un.Argument); switch (un.NodeType) { case NodeTypes.Plus: return(Apply(a, n => Node.Plus(n))); case NodeTypes.Minus: return(Apply(a, n => Node.Minus(n))); } break; case BinaryOperatorNode bn: switch (bn.NodeType) { case NodeTypes.And: case NodeTypes.Or: case NodeTypes.Xor: case NodeTypes.GreaterThan: case NodeTypes.GreaterThanOrEqual: case NodeTypes.LessThan: case NodeTypes.LessThanOrEqual: case NodeTypes.Equals: case NodeTypes.NotEquals: return(null); } a = Derive(bn.Left); b = Derive(bn.Right); switch (bn.NodeType) { case NodeTypes.Add: return(Combine(a, b, n1 => n1, n2 => n2)); case NodeTypes.Subtract: return(Combine(a, b, n1 => n1, n2 => Node.Minus(n2), (n1, n2) => Node.Subtract(n1, n2))); case NodeTypes.Multiply: return(Combine(a, b, n1 => n1 * bn.Right, n2 => bn.Left * n2)); case NodeTypes.Divide: return(Combine(a, b, n1 => n1 / bn.Right, n2 => - (n2 / Node.Power(bn.Right, Node.Two)), (n1, n2) => (n1 * bn.Right - bn.Left * n2) / Node.Power(bn.Right, Node.Two))); case NodeTypes.Pow: return(Combine(a, b, n1 => n1 * bn.Right * Node.Power(bn.Left, bn.Right - Node.One), n2 => n2 * Node.Function("log", bn.Left) * bn)); case NodeTypes.Modulo: return(Combine(a, b, n1 => n1, n2 => n2 * -bn, (n1, n2) => n1 - n2 * bn)); } break; case TernaryOperatorNode tn: a = Derive(tn.IfTrue); b = Derive(tn.IfFalse); return(Combine(a, b, n1 => Node.Conditional(tn.Condition, n1, Node.Zero), n2 => Node.Conditional(tn.Condition, Node.Zero, n2), (n1, n2) => Node.Conditional(tn.Condition, n1, n2))); case FunctionNode fn: if (fn.Arguments.Count == 0) { return(null); } // Build the derived arguments var lst = new Dictionary <VariableNode, Node[]>(Variables.Comparer); for (var i = 0; i < fn.Arguments.Count; i++) { var darg = Derive(fn.Arguments[i]); if (darg != null) { foreach (var pair in darg) { if (!lst.TryGetValue(pair.Key, out var dargs)) { dargs = new Node[fn.Arguments.Count]; lst.Add(pair.Key, dargs); } dargs[i] = pair.Value; } } } // If there are no derivative, let's just stop here if (lst.Count == 0) { return(null); } // Give a chance to our function rules if (FunctionRules == null || !FunctionRules.TryGetValue(fn.Name, out var rule)) { rule = (fn, darg) => ChainRule(fn, darg, "d{0}({1})"); } a = new Dictionary <VariableNode, Node>(Variables.Comparer); foreach (var pair in lst) { var df = rule(fn, pair.Value); if (df != null) { a.Add(pair.Key, df); } } // If all derivatives are zero, return null return(a.Count > 0 ? a : null); case VariableNode vn: if (Variables.Contains(vn)) { a = new Dictionary <VariableNode, Node>(Variables.Comparer) { { vn, Node.One } }; return(a); } return(null); case PropertyNode _: case ConstantNode _: return(null); } throw new Exception("Could not derive expression node {0}".FormatString(node)); }
private static Node DAsin(FunctionNode f, IReadOnlyList <Node> dargs) => dargs.Check(1)[0] / Node.Function("sqrt", Node.One - Node.Power(f.Arguments[0], Node.Two));