undistribute := proc( form)
#
# undistribute recursively simplifies an expression by
# pulling out of integrands, summands, or limit expressions
# any factors which are constant with respect to the variable
# of integration, summation, or of the limit process.
# e.g.  undistribute( int( a*f( x), x)) => a*int( f( x), x).
#
# Author: Vincent Broman, broman@nosc.mil
#
   local newform, oldigrand, newigrand, cof, var, fac;
   
   if type( form, {string, numeric}) then
      form
   else
      newform := map( procname, form);
      if type( newform, function) and
	 member( op( 0, newform), {int, Int, limit, Limit, sum, Sum})
      then
	 if type( [op( newform)], {[algebraic, {name, name=anything}],
	       	     	      	   [algebraic, {name, name=anything}, string]})
	 then
	    # this one we try to pull constant factors out of
	    oldigrand := factor( op( 1, newform));
	    if type( op( 2, newform), string) then
	       var := op( 2, newform);
	    else
	       var := op( 1, op( 2, newform));		# name=anything
	    fi;
      	    if not has( oldigrand, var) then
	       RETURN( oldigrand * subsop( 1=1, newform));
	    fi;
	    if type( oldigrand, `*`) then
      	       newigrand := 1;
	       cof := 1;
	       for fac in oldigrand do
	       	  if has( fac, var) then
		     newigrand := newigrand * fac;
		  else
		     cof := cof * fac;
		  fi;
	       od;
	       RETURN( cof * subsop( 1=newigrand, newform));
	    fi;
	 fi;
      fi;
      newform;		# otherwise no change
   fi;
end:

`help/text/undistribute` := TEXT(
`FUNCTION: undistribute - move constant factors out of sums, integrals, limits`,
`   `,
`CALLING SEQUENCE: undistribute( expr);`,
`   `,
`PARAMETERS: expr - an expression`,
`   `,
`SYNOPSIS:   `,
`- The call undistribute( expr) returns an expression which is`,
`  equivalent to the argument expr, differing only in that factors`,
`  of integrands, summands, and limit expressions which are`,
`  constant with respect to the variable of integration, summation,`,
`  or the limit are moved outside of the integral, sum, or limit.`,
`     `,
`EXAMPLES:   `,
`   `,
`> undistribute( Sum( a*sin(b*x), x=1..10));`,
`                                 /  10          \\`,
`                                 |-----         |`,
`                                 | \\            |`,
`                               a |  )   sin(b x)|`,
`                                 | /            |`,
`                                 |-----         |`,
`                                 \\x = 1         /`,
`   `,
`> undistribute( Int( Sum( f(x)*g(n), n=0..infinity), x=0..1));`,
`                          /infinity     \\   1`,
`                          | -----       |   /`,
`                          |  \\          |  |`,
`                          |   )     g(n)|  |  f(x) dx`,
`                          |  /          |  |`,
`                          | -----       | /`,
`                          \\ n = 0       / 0`,
`   `,
`SEE ALSO:  combine`,
`   `,
`AUTHOR: Vincent Broman, Naval Command Control and Ocean Surveillance Center`
):

#save `undist.m`;
#quit
