/// <summary>
        /// Applies the chain rule on a function.
        /// </summary>
        /// <param name="function">The function definition.</param>
        /// <param name="dargs">The derivatives of the arguments.</param>
        /// <param name="format">The format of the new function. {0} denotes the old name, while {1} will hold the index to which the function should be derived.</param>
        /// <returns></returns>
        public static Node ChainRule(FunctionNode function, IReadOnlyList <Node> dargs, string format)
        {
            Node result = null;

            for (var i = 0; i < dargs.Count; i++)
            {
                if (dargs[i] == null)
                {
                    break;
                }
                var b = Node.Function(format.FormatString(function.Name, i), function.Arguments) * dargs[i];
                result = result == null ? b : Node.Add(result, b);
            }
            return(result);
        }
        private static Node DPwr(FunctionNode f, IReadOnlyList <Node> dargs)
        {
            dargs.Check(2);
            Node result = null;

            if (dargs[0] != null)
            {
                result = Node.Function("sgn", f.Arguments[0]) * f.Arguments[1] * dargs[0] * Node.Function(f.Name, f.Arguments[0], f.Arguments[1] - 1.0);
            }
            if (dargs[1] != null)
            {
                result += dargs[1] * Node.Function("log", f.Arguments[0]) * f;
            }
            return(result);
        }
        private static Node Limit(FunctionNode f, IReadOnlyList <Node> dargs)
        {
            dargs.Check(3);

            var x = f.Arguments[0];
            var y = f.Arguments[1];
            var z = f.Arguments[2];

            Node result = null;

            if (dargs[0] != null)
            {
                result = Node.Conditional(
                    Node.And(
                        Node.GreaterThan(x, Node.Function("min", y, z)),
                        Node.LessThan(x, Node.Function("max", y, z))),
                    dargs[0],
                    Node.Zero);
            }

            if (dargs[1] != null)
            {
                result += Node.Conditional(
                    Node.And(
                        Node.LessThanOrEqual(y, z),
                        Node.LessThanOrEqual(x, Node.Function("min", y, z))),
                    dargs[1],
                    Node.Zero);
            }

            if (dargs[2] != null)
            {
                result += Node.Conditional(
                    Node.And(
                        Node.LessThan(y, z),
                        Node.GreaterThanOrEqual(x, Node.Function("max", y, z))),
                    dargs[2],
                    Node.Zero);
            }

            return(result);
        }
 private static Node DHypot(FunctionNode f, IReadOnlyList <Node> dargs)
 {
     dargs.Check(2);
     if (dargs[1] == null)
     {
         if (dargs[0] == null)
         {
             return(null);
         }
         return(0.5 * f.Arguments[0] * dargs[0] / f);
     }
     else if (dargs[0] == null)
     {
         return(0.5 * f.Arguments[1] * dargs[1] / f);
     }
     else
     {
         return(0.5 * (f.Arguments[0] * dargs[0] + f.Arguments[1] * dargs[1]) / f);
     }
 }
 private static Node DAtan2(FunctionNode f, IReadOnlyList <Node> dargs)
 {
     dargs.Check(2);
     if (dargs[1] == null)
     {
         if (dargs[0] == null)
         {
             return(null);
         }
         return(f.Arguments[1] * dargs[0] / (Node.Function("square", f.Arguments[0]) + Node.Function("square", f.Arguments[1])));
     }
     else if (dargs[0] == null)
     {
         return(-f.Arguments[0] * dargs[1] / (Node.Function("square", f.Arguments[0]) + Node.Function("square", f.Arguments[1])));
     }
     else
     {
         return((f.Arguments[1] * dargs[0] - f.Arguments[0] * dargs[1]) / (Node.Function("square", f.Arguments[0]) + Node.Function("square", f.Arguments[1])));
     }
 }
 private static Node DAtan(FunctionNode f, IReadOnlyList <Node> dargs) => dargs.Check(1)[0] / (Node.One + Node.Power(f.Arguments[0], Node.Two));
 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));
 private static Node Zero(FunctionNode f, IReadOnlyList <Node> dargs) => null;
 private static Node DPassThrough(FunctionNode f, IReadOnlyList <Node> dargs) => Node.Function(f.Name, dargs);
 private static Node DAtanh(FunctionNode f, IReadOnlyList <Node> dargs) => dargs.Check(1)[0] / (1 - Node.Function("square", f.Arguments[0]));
 /// <include file='docs.xml' path='docs/members/Function/*'/>
 public static FunctionNode Function(string name, params Node[] arguments) => FunctionNode.Function(name, arguments);
 /// <include file='docs.xml' path='docs/members/Function/*'/>
 public static FunctionNode Function(string name, IReadOnlyList <Node> arguments) => FunctionNode.Function(name, arguments);