/*		POLYIS		19.2.81  */
/******************************
	POLYNOMIAL NORMAL FORM
******************************/


/* Use polynomial form for simplification (always succeeds) */

poly_form(true,true).
poly_form(false,false).

poly_form(Exp,Poly) :- !,
	poly_form1(Exp,New),
	tidy(New,Poly).

/* Look for terms to simplify */

poly_form1(Exp,Poly) :-
	Exp=..[Sym|Args], ispred(Sym), !,
	maplist(poly_form1,Args,PArgs),
	Poly=..[Sym|PArgs].

/* Apply to term */

poly_form1(Exp,Poly) :- !,
	wordsin(Exp,Vars),
	sublist(mult_occ(Exp),Vars,Vars1),
	poly_form(Vars1,Exp,Poly).



/* Test for predicate or logical connective */

ispred(&).	ispred(#).	ispred(=).
ispred(>).	ispred(>=).	ispred(<).	ispred(=<).



/* Put term in polynomial normal form with respect to list of variables*/

poly_form([],Exp,Exp) :- !.

poly_form([Var|Vars],Exp,Poly) :- !,
	poly(Var,Exp,Ebag1,simp),
	maplist(half_poly(Vars),Ebag1,Ebag2),
	make_poly(Var,Ebag2,Poly).


/* Apply poly_form to coeffs */

half_poly(Vars,pair(N,E1), pair(N,E2)) :- !,
	poly_form(Vars,E1,E2).


/* Put polynomials in normal form (succeeds only for polynomials) */

poly_norm(X,Poly,Pbag1) :- !,
	poly(X,Poly,Pbag,poly),
	maplist(poly_form_coeff,Pbag,Pbag1).

/* Tidy coefficients */
poly_form_coeff(pair(N,E),pair(N,E1)) :- poly_form(E,E1).


/* Forms bag of coefficients */

poly(X,X,[pair(1,1)],Flag) :- !.

poly(X,X^N,[pair(N,1)],poly) :- 
	integer(N), !.

poly(X,X^N,[pair(N,1)],simp) :-
	integer(N), !.

poly(X,(X^N)^(-1),[pair(N1,1)],Flag) :-
	integer(N), !,
	N1 is -N.

poly(X,E,[pair(0,E)],Flag) :-
	freeof(X,E), !.

poly(X,S+T,Ebag,Flag) :-!,
	poly(X,S,Sbag,Flag), poly(X,T,Tbag,Flag),
	add(Sbag,Tbag,Ebag).

poly(X,S*T,Ebag,Flag) :- !,
	poly(X,S,Sbag,Flag), poly(X,T,Tbag,Flag),
	times(Sbag,Tbag,Ebag).

poly(X,S^N,Ebag,Flag) :-
	integer(N),N > 0, !,
	poly(X,S,Sbag,Flag),
	binomial(Sbag,N,Ebag).

poly(X,E,[pair(0,E1)],simp) :- !,
	E=..[Sym|Args],    
	maplist(poly_form1,Args,Args1),
	E1=..[Sym|Args1].

/* Add two coefficients bags - code in POLPAK */

/* Multiply two coefficient bags - code in POLPAK */

/* Binomial expansion of coefficient bag */


binomial(Bag, 0, [pair(0,1)]) :- !.

binomial(Bag, 1, Bag) :- !.

binomial(Sbag, N, Ebag) :- !,
	N1 is N-1,
	binomial(Sbag,N1,Ebag1),
	times(Sbag,Ebag1,Ebag).


/* Reconstitute bag of coefficients into polynomial */

make_poly(X,Bag1,Poly) :- !,
	maplist(reify(X),Bag1,Bag2),
	recomp(Poly,[+|Bag2]).

/* reify coefficient and power into product */

reify(X,pair(0,E),E) :- !.
reify(X,pair(1,E),E*X) :- !.
reify(X,pair(N,E),E*X^N) :- !.

