# Rem : (UP,UP,Name) -> UP
`UP/Rem` := proc(D,x,y,q) local a,b,c,da,db,dq,dr,i,k,C;

	C := D[CoefficientRing];
	if y = D[0] then ERROR(`division by zero`) fi;
	da := D[Degree](x); db := D[Degree](y); dq := da - db;
	if x = D[0] or da < db then
		if nargs = 4 then q := D[0] fi;
		RETURN(x)
	fi;

	a := D[ArrayCoeffs](x);
	b := D[ArrayCoeffs](y);
	c := array(0..dq);
	for i from 0 to dq do c[i] := C[0] od;

	dr := `UP/quoInPlace`(C,a,b,da,db,C[Inv](b[db]),c);
	if nargs = 4 then q := D[Polynom]([seq(c[k], k=0..dq)]) fi;
	if dr = -1 then RETURN(D[0]) fi;
	D[Polynom]([seq(a[k], k=0..dr)])

end:

# Computes a := Rem(a,b) and q := Quo(a,b) inplace
`UP/quoInPlace` := proc(C,a,b,da,db,l,q) local dr,e,i,j;
	dr := da;
	e := da - db;
	while e >= 0 do
	    q[e] := C[`*`](a[dr],l);
	    i := e;
	    for j from 0 to db-1 do
		a[i] := C[`-`](a[i],C[`*`](q[e],b[j]));
		i := i+1;
	    od;
	    dr := dr-1;
	    while dr >= 0 and a[dr] = C[0] do dr := dr-1 od;
	    e := dr - db
	od;
	dr
end:
save `Rem.m`;
quit
