function(expr, context, subIntegral) {
      var MaxExponentExpanded = 10;

      if(expr.type === 'OperatorNode' && expr.op === '^') {
        var multipliedOut = tryMultiplyOut(expr);
        if(multipliedOut) {
          var int = subIntegral(multipliedOut, context, "reducing power");
          if(int) {
            return int;
          }
        }
      } else if(expr.type === 'OperatorNode' && expr.op === '*') {
        for(var i = 0; i < expr.args.length; i++) {
          var multipliedOutChild = tryMultiplyOut(expr.args[i]);
          if(multipliedOutChild) {
            var int = subIntegral(new OperatorNode('*', 'multiply', multipliedOutChild.args.concat(
              expr.args.slice(0, i),
              expr.args.slice(i+1)
            )), context, "reducing power");

            if(int) {
              return int;
            }
          }
        }
      }

      //
      function tryMultiplyOut(expr) {
        if(expr.type === 'OperatorNode' && expr.op === '^' && !context.isConstant(expr.args[0])) {
          var exponentValue = getNumericValue(expr.args[1]);
          if(Number.isInteger(exponentValue) && exponentValue > 1 && exponentValue <= MaxExponentExpanded) {
            return new OperatorNode('*', 'multiply', [
              expr.args[0],
              exponentValue === 2 ? expr.args[0] : new OperatorNode('^', 'pow', [
                expr.args[0],
                new ConstantNode(exponentValue-1)
              ])
            ]);
          }
        }

        return null;
      }
    }
function(expr, context, subIntegral) {
      var MaxExponentExpanded = 10;

      if(expr.type === 'OperatorNode' && expr.op === '^') {
        var multipliedOut = tryMultiplyOut(expr);
        if(multipliedOut) {
          var int = subIntegral(multipliedOut, context, "reducing power");
          if(int) {
            return int;
          }
        }
      } else if(expr.type === 'OperatorNode' && expr.op === '*') {
        for(var i = 0; i < expr.args.length; i++) {
          var multipliedOutChild = tryMultiplyOut(expr.args[i]);
          if(multipliedOutChild) {
            var int = subIntegral(new OperatorNode('*', 'multiply', multipliedOutChild.args.concat(
              expr.args.slice(0, i),
              expr.args.slice(i+1)
            )), context, "reducing power");

            if(int) {
              return int;
            }
          }
        }
      }

      
      function tryMultiplyOut(expr) {
        if(expr.type === 'OperatorNode' && expr.op === '^' && !context.isConstant(expr.args[0])) {
          var exponentValue = getNumericValue(expr.args[1]);
          if(Number.isInteger(exponentValue) && exponentValue > 1 && exponentValue <= MaxExponentExpanded) {
            return new OperatorNode('*', 'multiply', [
              expr.args[0],
              exponentValue === 2 ? expr.args[0] : new OperatorNode('^', 'pow', [
                expr.args[0],
                new ConstantNode(exponentValue-1)
              ])
            ]);
          }
        }

        return null;
      }
    }
function ( expr , context , subIntegral ) { var MaxExponentExpanded = 10 ; if ( expr . type === 'OperatorNode' && expr . op === '^' ) { var multipliedOut = tryMultiplyOut ( expr ) ; if ( multipliedOut ) { var int = subIntegral ( multipliedOut , context , "reducing power" ) ; if ( int ) { return int ; } } } else if ( expr . type === 'OperatorNode' && expr . op === '*' ) { for ( var i = 0 ; i < expr . args . length ; i ++ ) { var multipliedOutChild = tryMultiplyOut ( expr . args [ i ] ) ; if ( multipliedOutChild ) { var int = subIntegral ( new OperatorNode ( '*' , 'multiply' , multipliedOutChild . args . concat ( expr . args . slice ( 0 , i ) , expr . args . slice ( i + 1 ) ) ) , context , "reducing power" ) ; if ( int ) { return int ; } } } } // function tryMultiplyOut ( expr ) { if ( expr . type === 'OperatorNode' && expr . op === '^' && ! context . isConstant ( expr . args [ 0 ] ) ) { var exponentValue = getNumericValue ( expr . args [ 1 ] ) ; if ( Number . isInteger ( exponentValue ) && exponentValue > 1 && exponentValue <= MaxExponentExpanded ) { return new OperatorNode ( '*' , 'multiply' , [ expr . args [ 0 ] , exponentValue === 2 ? expr . args [ 0 ] : new OperatorNode ( '^' , 'pow' , [ expr . args [ 0 ] , new ConstantNode ( exponentValue - 1 ) ] ) ] ) ; } } return null ; } }
integral(f(x)^c [* g(x)], x) = integral(f(x) * f(x)^(c-1) [* g(x)], x) However, we only expand for c<=10 to save computational resources
integral ( f ( x ) ^c [ * g ( x ) ] x ) = integral ( f ( x ) * f ( x ) ^ ( c - 1 ) [ * g ( x ) ] x ) However we only expand for c< = 10 to save computational resources