		/** Simplification of rational expressions **/

/*K: simplify, rational, factor */
/*A: John Gottschalk */
/*S: University of Western Australia */
/*D: December 1986 */

Sepf_:Collect_:Simp_:Findelem_:Dterms_:Tier

Loadonce[XEex]

/*: Simp[$term,$fac,$expr]
	will simplify $expr (where $expr is a sum of terms) according to 
	the following steps:
		a) All the subexpressions in $expr with $term in the 
		denominator are collected and put over a common denominator,
		b) If possible $fac is factored out of the numerator 
		(the procedure Sepf is used here,
		c) The simplified $expr is returned.
	To use Simp, $fac should be a subexpression of $term, for example
	$term : (r1+r2)^3, $fac : r1+r2. Thus subexpressions of $expr with 
	(r1+r2)^3 in the denominator are, if possible, written as 
	subexpressions with (r1+r2)^2 in the denominator. */

Simp[$term,$fac,$expr_=~P[$expr[0]='Plus]] :: \
	(Pr[" $expr must me a sum of terms"];$expr)

Simp[$term,$fac,$expr_=$expr[0]='Plus] :: (Lcl[%elem,%exp,%exprlist,%den,%i]; \
	%exprlist : S[$expr,'Plus->'List]; \
	%den : Map[Den,%exprlist]; \
	%elem : Findelem[$term,%den]; \
	If[P[Len[%elem] > 0], \
		(%exp : Ap['Plus,Map[%exprlist,%elem]]; \
		 %exp : Rat[%exp]; \
		 %exp : Eex[Num[%exp]]/Den[%exp]; \
		 If[Len[%exp] > 0, %exp[1] : Sepf[%exp[1],$fac]];  \
		 %exprlist[%elem[1]] : %exp; \
		 Do[%i,2,Len[%exprlist],,%exprlist[%elem[%i]] : 0]; \
		 Ap['Plus,%exprlist]), \
		(Pr[];Pr["Simp: I Can't find",$term]; $expr)])

Sepf[$expr,$fac_=~Listp[$fac]] :: (Lcl[%e,%exp]; \
	%e : Inter[Cont[$expr],Cont[$fac]]; \
	If[P[%e = {}], $expr, (%exp : Pqr[$expr,$fac,Rel[%e[1]]]; \
		If[P[Eex[%exp[2]=0]], $fac Eex[%exp[1]], \
			Pr["Sepf: separation unsuccessful"];$expr])])

Sepf[$expr,{$fac}] :: Sepf[$expr,$fac] 

Sepf[$expr,{$fac1,$$fac2}] :: (Lcl[%e,%exp]; \
	%e : Inter[Cont[$expr],Cont[$fac1]]; \
	If[P[%e = {}], Sepf[$expr,{$$fac2}], \
		(%exp : Pqr[$expr,$fac1,Rel[%e[1]]]; \
		If[P[Eex[%exp[2]=0]], $fac1 Sepf[Eex[%exp[1]],{$$fac2}], \
			Pr["Sepf: separation unsuccessful"]; \
			Sepf[$expr,{$$fac2}]])])

/*: Findelem[$term,$list]
	returns a list of which elements of $list contain $term. 
	It is used by Simp. */
Findelem[$term,$list_=Listp[$list]] :: \
  (Lcl[%a]; %a : Map[In[$term,$1],$list];\
	    %a Ar[Len[%a]]; Del[0,%%])

Dterms[$exp_=$exp[0]='Plus] :: \
	(S[$exp,'Plus->'List]; Map[Den,%%]; Map[$1/Nc[$1],%%]; Union[%%])

Collect[$term,$expr_=$expr[0]='Plus] :: \
       (Lcl[%elem,%exp,%exprlist,%den,%i]; \
	%exprlist : S[$expr,'Plus->'List]; \
	%den : Map[Den,%exprlist]; \
	%elem : Findelem[$term,%den]; \
	If[P[Len[%elem] > 0], \
		(%exp : Ap['Plus,Map[%exprlist,%elem]]; \
		 %exp : Rat[%exp]; \
		 %exp : Eex[Num[%exp]]/Den[%exp]; \
		 %exprlist[%elem[1]] : %exp; \
		 Do[%i,2,Len[%exprlist],,%exprlist[%elem[%i]] : 0]; \
		 Ap['Plus,%exprlist]), \
		(Pr[];Pr["Simp: I Can't find",$term]; $expr)])

