whole_func_string: function(expr, context, subIntegral) {
        if(expr.type === "OperatorNode" && expr.op === '*') {
          var wasChange = false;
          var isTotalPositive = true;
          var processedArgs = [];
          expr.args.forEach(function(expr) {
            if(expr.type === "OperatorNode" && expr.args.length === 1 && (expr.op === '+' || expr.op === '-')) {
              wasChange = true;
              isTotalPositive = isTotalPositive ^ (expr.op === '-');
              processedArgs.push(expr.args[0]);
            } else {
              processedArgs.push(expr);
            }
          });
  
          if(wasChange) {
            var int = subIntegral(new OperatorNode('*', 'multiply', processedArgs), context, "removing unary +/- from factors");
            if(int) {
              return isTotalPositive ? int : new OperatorNode('-', 'unaryMinus', [int]);
            }
          }
        }
      }
func_code_string: function(expr, context, subIntegral) {
        if(expr.type === "OperatorNode" && expr.op === '*') {
          var wasChange = false;
          var isTotalPositive = true;
          var processedArgs = [];
          expr.args.forEach(function(expr) {
            if(expr.type === "OperatorNode" && expr.args.length === 1 && (expr.op === '+' || expr.op === '-')) {
              wasChange = true;
              isTotalPositive = isTotalPositive ^ (expr.op === '-');
              processedArgs.push(expr.args[0]);
            } else {
              processedArgs.push(expr);
            }
          });
  
          if(wasChange) {
            var int = subIntegral(new OperatorNode('*', 'multiply', processedArgs), context, "removing unary +/- from factors");
            if(int) {
              return isTotalPositive ? int : new OperatorNode('-', 'unaryMinus', [int]);
            }
          }
        }
      }
func_documentation_string: integral(f(x) * +/-g(x), x) = +/-integral(f(x) * g(x), x)