module constre;

algebraic procedure constantRE(cap_R,leadcoeff,dffpointer,k,x);

% solve  constant RE
%
%   a(k+1) = cap_R(k) * a(k)
%
%  where leadcoeff is the leading coefficient of the RE
%  and DF is a table where DF(dffpointer+i) = df(f,x,i)

  begin scalar denr,fract,ii,m0,m1,c0,ck,S,c,df2,q,r2,lterm,nn,
	s0, leadcoeff2;
	denr := solve(leadcoeff,k);
	m0 := {};
	foreach xx in denr do
		if type_rational rhs xx then  m0 := ((rhs xx)+1) . m0;
	if not(m0 = {}) then m0 := max(m0) else m0 := 0;

	if symbolic !*traceFPS then
		 << write ">>> m0 = ",m0;
		    write "RE is constant";
		    write "RE: for all k >= ",m0,": a (k + 1) = "
			,cap_R * a(k);
		    write "leadcoeff := ",leadcoeff; >>;
	
	fract := {};
	foreach xx in denr do 
		if type_fraction(rhs xx) then
			 fract := den(rhs xx) . fract;
	if not(fract = {}) then 
		<< q := first fract;
		   dff(dffpointer + 10) := sub(x=x^q,dff(dffpointer));
		   if symbolic !*traceFPS then <<
			write "RE modified to nn= ",k/q;
			write "=> f := ",dff(dffpointer + 10)>>;
		   S := constantRE(sub(k=k/q,cap_R),
			sub(k=k/q,leadcoeff),dffpointer + 10,k,x);
		   return sub(x=x^(1/q),S); >>;

	if m0 < 0  then <<
                nn:= -m0 + 1;
		dff(dffpointer + 10) := df2 := x^nn * dff(dffpointer);
		if symbolic !*traceFPS then <<
			write "working with ",x^nn,"*f";
			write "=> f :=" ,df2 >>;
                S := constantRE(sub(k=k-nn,cap_R),sub(k=k-nn,leadcoeff),
					dffpointer + 10,k,x);
		return update_coeff(S,x,-nn);
	>>;
	
        if m0 = 0 then <<
		if symbolic !*traceFPS then write "PS does not exist";
		return failed>>;

	if m0 > 0  then <<
	m1 := {};
	foreach xx in denr do if type_rational rhs xx then
			 m1 := append(list (rhs xx +1),m1);
	m1 := min m1;
	if m1 < 0 then << 
		dff(dffpointer + 10) := df2 := x^(-m1)*dff(dffpointer);
	if symbolic !*traceFPS then <<
                        write "working with ",x^(-m1),"*f";
                        write "=> f :=" ,df2 >>;
		S := constantRE(sub(k=k+m1,cap_R),sub(k=k+m1,leadcoeff),
                                        dffpointer + 10,k,x);
                return update_coeff(S,x,m1)
		>>;
	>>;

        % { m1 >= 0 }

        S := 0; S0 := 0;
	for i:=0:m0 do
		<< 
		if i > m1 then 
		  dff(dffpointer + i) := df(dff(dffpointer + i-1),x);
		c0 := limit(dff(dffpointer + i),x,0);
		if (not numberp c0 and part(c0,0) = limit) then
			<<  write "Could not find the limit of: "
				,dff(dffpointer + i),",",x,",",0;
		    rederr("problem using limit operator") >> else
		<<
		c0 := c0/factorial (i);
		S := S + c0*x^i ;
		if symbolic !*traceFPS then write " S = ",s;
		>> >>;
  return (S);

end;

endmodule;

end;

