/**
   * Applies differentiation to a function. Used the rules specified by objects of type {@link
   * DiffRulesI}.
   *
   * @param node The node of the function.
   * @param data The variable to differentiate wrt.
   */
  public Object visit(ASTFunNode node, Object data) throws ParseException {
    String name = node.getName();

    // System.out.println("FUN: "+ node + " nchild "+nchild);
    Node children[] = TreeUtils.getChildrenAsArray(node);
    Node dchildren[] = acceptChildrenAsArray(node, data);

    if (node.getPFMC() instanceof DiffRulesI) {
      return ((DiffRulesI) node.getPFMC())
          .differentiate(node, (String) data, children, dchildren, localDJep);
    }
    DiffRulesI rules = (DiffRulesI) diffRules.get(name);
    if (rules != null)
      return rules.differentiate(node, (String) data, children, dchildren, localDJep);

    throw new ParseException("Sorry I don't know how to differentiate " + node + "\n");
  }
 /** Prints all the differentation rules for all functions on specified stream. */
 public void printDiffRules(PrintStream out) {
   out.println("Standard Functions and their derivatives");
   for (String key : globalDJep.getFunctionTable().functionNames()) {
     PostfixMathCommandI value = globalDJep.getFunctionTable().get(key);
     DiffRulesI rule = (DiffRulesI) diffRules.get(key);
     if (rule == null)
       out.print(
           key + " No diff rules specified (" + value.getNumberOfParameters() + " arguments).");
     else out.print(rule.toString());
     out.println();
   }
   for (Enumeration en = diffRules.keys(); en.hasMoreElements(); ) {
     String key = (String) en.nextElement();
     DiffRulesI rule = (DiffRulesI) diffRules.get(key);
     if (!globalDJep.getFunctionTable().contains(key)) {
       out.print(rule.toString());
       out.println("\tnot in JEP function list");
     }
   }
 }
 /** Adds the rules for a given function. */
 void addDiffRule(DiffRulesI rule) {
   diffRules.put(rule.getName(), rule);
   if (DEBUG) System.out.println("Adding rule for " + rule.getName());
 }