lib/integral.js
function preprocessIntegrand(expr, context) {
    expr = removeParenthesis(expr);
    expr = reduceFunctions(expr);
    expr = removeDivision(expr);
    return expr;

    function removeParenthesis(node) {
      if(node.type === "ParenthesisNode") {
        return removeParenthesis(node.content);
      } else {
        return node.map(removeParenthesis);
      }
    }

    function reduceFunctions(expr) {
      return helper(expr);

      function helper(expr) {
        if(!context.isConstant(expr) && expr.type === "FunctionNode") {
          var funcName = typeof expr.fn === "string" ? expr.fn : expr.fn.name;

          switch(funcName) {
            case "add":
              return new OperatorNode('+', 'add', expr.args);
            case "subtract":
              return new OperatorNode('-', 'subtract', expr.args);
            case "multiply":
              return new OperatorNode('*', 'multiply', expr.args);
            case "divide":
              return new OperatorNode('/', 'divide', expr.args);
            case "sqrt":
              return new OperatorNode('^', 'pow', [
                expr.args[0].map(helper),
                new OperatorNode('/', 'divide', [
                  new ConstantNode(1),
                  new ConstantNode(2)
                ])
              ]);
            case "nthRoot":
              return new OperatorNode('^', 'pow', [
                expr.args[0].map(helper),
                new OperatorNode('/', 'divide', [
                  new ConstantNode(1),
                  expr.args[1].map(helper)
                ])
              ]);
            case "exp":
              return new OperatorNode('^', 'pow', [new SymbolNode('e'), expr.args[0]]);
            case "pow":
              return new OperatorNode('^', 'pow', expr.args);
            case "log":
              if(expr.args.length === 2) {
                return new OperatorNode('/', 'divide', [
                  new FunctionNode('log', [expr.args[0].map(helper)]),
                  new FunctionNode('log', [expr.args[1].map(helper)])
                ]);
              } else {
                break;
              }
            default:
              break;
          }
        }
        return expr.map(helper);
      }
    }

    function removeDivision(expr) {
      return expr.transform(function(node) {
        if(!context.isConstant(node) && node.type === 'OperatorNode' && node.op === '/') {
          return new OperatorNode('*', 'multiply', [
            node.args[0],
            new OperatorNode('^', 'pow', [
              node.args[1],
              new ConstantNode(-1)
            ])
          ]);
        } else {
          return node;
        }
      });
    }
  }
function preprocessIntegrand(expr, context) {
    expr = removeParenthesis(expr);
    expr = reduceFunctions(expr);
    expr = removeDivision(expr);
    return expr;

    function removeParenthesis(node) {
      if(node.type === "ParenthesisNode") {
        return removeParenthesis(node.content);
      } else {
        return node.map(removeParenthesis);
      }
    }

    function reduceFunctions(expr) {
      return helper(expr);

      function helper(expr) {
        if(!context.isConstant(expr) && expr.type === "FunctionNode") {
          var funcName = typeof expr.fn === "string" ? expr.fn : expr.fn.name;

          switch(funcName) {
            case "add":
              return new OperatorNode('+', 'add', expr.args);
            case "subtract":
              return new OperatorNode('-', 'subtract', expr.args);
            case "multiply":
              return new OperatorNode('*', 'multiply', expr.args);
            case "divide":
              return new OperatorNode('/', 'divide', expr.args);
            case "sqrt":
              return new OperatorNode('^', 'pow', [
                expr.args[0].map(helper),
                new OperatorNode('/', 'divide', [
                  new ConstantNode(1),
                  new ConstantNode(2)
                ])
              ]);
            case "nthRoot":
              return new OperatorNode('^', 'pow', [
                expr.args[0].map(helper),
                new OperatorNode('/', 'divide', [
                  new ConstantNode(1),
                  expr.args[1].map(helper)
                ])
              ]);
            case "exp":
              return new OperatorNode('^', 'pow', [new SymbolNode('e'), expr.args[0]]);
            case "pow":
              return new OperatorNode('^', 'pow', expr.args);
            case "log":
              if(expr.args.length === 2) {
                return new OperatorNode('/', 'divide', [
                  new FunctionNode('log', [expr.args[0].map(helper)]),
                  new FunctionNode('log', [expr.args[1].map(helper)])
                ]);
              } else {
                break;
              }
            default:
              break;
          }
        }
        return expr.map(helper);
      }
    }

    function removeDivision(expr) {
      return expr.transform(function(node) {
        if(!context.isConstant(node) && node.type === 'OperatorNode' && node.op === '/') {
          return new OperatorNode('*', 'multiply', [
            node.args[0],
            new OperatorNode('^', 'pow', [
              node.args[1],
              new ConstantNode(-1)
            ])
          ]);
        } else {
          return node;
        }
      });
    }
  }
function preprocessIntegrand ( expr , context ) { expr = removeParenthesis ( expr ) ; expr = reduceFunctions ( expr ) ; expr = removeDivision ( expr ) ; return expr ; function removeParenthesis ( node ) { if ( node . type === "ParenthesisNode" ) { return removeParenthesis ( node . content ) ; } else { return node . map ( removeParenthesis ) ; } } function reduceFunctions ( expr ) { return helper ( expr ) ; function helper ( expr ) { if ( ! context . isConstant ( expr ) && expr . type === "FunctionNode" ) { var funcName = typeof expr . fn === "string" ? expr . fn : expr . fn . name ; switch ( funcName ) { case "add" : return new OperatorNode ( '+' , 'add' , expr . args ) ; case "subtract" : return new OperatorNode ( '-' , 'subtract' , expr . args ) ; case "multiply" : return new OperatorNode ( '*' , 'multiply' , expr . args ) ; case "divide" : return new OperatorNode ( '/' , 'divide' , expr . args ) ; case "sqrt" : return new OperatorNode ( '^' , 'pow' , [ expr . args [ 0 ] . map ( helper ) , new OperatorNode ( '/' , 'divide' , [ new ConstantNode ( 1 ) , new ConstantNode ( 2 ) ] ) ] ) ; case "nthRoot" : return new OperatorNode ( '^' , 'pow' , [ expr . args [ 0 ] . map ( helper ) , new OperatorNode ( '/' , 'divide' , [ new ConstantNode ( 1 ) , expr . args [ 1 ] . map ( helper ) ] ) ] ) ; case "exp" : return new OperatorNode ( '^' , 'pow' , [ new SymbolNode ( 'e' ) , expr . args [ 0 ] ] ) ; case "pow" : return new OperatorNode ( '^' , 'pow' , expr . args ) ; case "log" : if ( expr . args . length === 2 ) { return new OperatorNode ( '/' , 'divide' , [ new FunctionNode ( 'log' , [ expr . args [ 0 ] . map ( helper ) ] ) , new FunctionNode ( 'log' , [ expr . args [ 1 ] . map ( helper ) ] ) ] ) ; } else { break ; } default : break ; } } return expr . map ( helper ) ; } } function removeDivision ( expr ) { return expr . transform ( function ( node ) { if ( ! context . isConstant ( node ) && node . type === 'OperatorNode' && node . op === '/' ) { return new OperatorNode ( '*' , 'multiply' , [ node . args [ 0 ] , new OperatorNode ( '^' , 'pow' , [ node . args [ 1 ] , new ConstantNode ( - 1 ) ] ) ] ) ; } else { return node ; } } ) ; } }
Prepare the given expression for integration by
- Remove parentheses
- Reduce standard functions into more generic structures:
- Convert 'add', 'subtract', 'multiply', and 'divide' into their operator counterparts
- Convert 'sqrt', 'nthRoot', 'exp', and 'pow' into '^' operator
- Convert 2-arg 'log' into quotient of natrual logarithms
- Convert division into multiplication to power of -1 (only in non-constant nodes)

@param {Node} expr  The expression tree representing the integrand to be processed
@param {Object} context  The integration context to interpret the integrand
@return {Node}  The processed integrand
Prepare the given expression for integration by - Remove parentheses - Reduce standard functions into more generic structures : - Convert add subtract multiply and divide into their operator counterparts - Convert sqrt nthRoot exp and pow into ^ operator - Convert 2 - arg log into quotient of natrual logarithms - Convert division into multiplication to power of - 1 ( only in non - constant nodes )