# Para declarar un anillo de polinomios ordenado, se ha de pasar el anillo de 
# polinomios D como primer parametro y un procedure Sign:D->{0,1,-1} que ha 
# sido definido previamente. La idea, es que si el orden viene dado por un TDT 
# T, y su n-esima raiz, antes de invocar OUP hago algo como 
# Sign:= proc(a) ransi(T,a,n) end; . 
# Authors: Felipe Cucker and Michael Monagan June/91


OrderedUnivariatePolynomial := proc() local D,P,R,S,Z,env; option remember;

	env := [ 'PP'=P, 'SS'=S, 'RR'=R ];
	D := args[1];
	if not hasCategory(D,UnivariatePolynomial) then
		ERROR(`1st argument must be a UnivariatePolynomial`) fi;
	R := D[CoefficientRing];
	if not hasCategory(R,OrderedDomain) then
		ERROR(`1st argument must over an OrderedDomain`) fi;
	if nargs > 1 then
	    S := args[2];
	    if not type(S,procedure) then
		ERROR(`2nd argument must be a function`) fi;
	else
	    S := subs(env, proc(b) local i,s;
    		s := 0;
    		for i from 0 to PP[Degree](b) while s = 0 do
		    s := RR[Sign](PP[Coeff](b,i))
		od;
    		s;
	    end):
	fi;
	if nargs > 2 then
            Z := args[3];
            if not type(Z,procedure) then
		ERROR(`3rd argument must be a function`) fi;
	fi;

	P := UnivariatePolynomial(R,OrderedDomain());
	P[DomainName] := OrderedUnivariatePolynomial;

	# Rep := List of coefficients
	P[Type] := D[Type];
	P[0] := D[0];
	P[1] := D[1];
	P[Variable] := D[Variable];
	P[Degree] := D[Degree];
	P[Ldegree] := D[Ldegree];
	P[Coeff] := D[Coeff];
	P[Polynom] := D[Polynom];
	P[SetCoeffs] := D[SetCoeffs];
	P[ListCoeffs] := D[ListCoeffs];
	P[PseudoRem] := D[PseudoRem];
	P[Sign] := S;
        if nargs > 2 then P[Zero] := Z fi;
	P[`<`] := subs( env, proc(a,b) SS(PP[`-`](a,b)) end);
	op(P)

end:

save `OUP.m`;
quit
