module hypergeomRsolve;

fluid '(!*tracefps);

algebraic procedure hypergeomRsolve (r,k,a0);

% solves the recurrence equation
%
%  a(k+1) = r(k) * a(k), a(0) = a0
 
  begin scalar Re,NNN,DDD,c,p,q,ak,sols,II;

   P := {}; Q := {};
   C := 1;

   Re := R * (k + 1);

   NNN := old_factorize num Re; DDD := old_factorize den re;
  
   foreach nn in NNN do
   if freeof (nn,k) then c := c * nn
	else if deg(nn,k) =1 then
	<< C:= c*coeffn(nn,k,1);
	    P:= append (p,list(coeffn(nn,k,0)/coeffn(nn,k,1)))>>
	else if deg(nn,k) =2 then
	<< c := c *  lcof(nn,k);
		sols := solve(nn,k);
		for each s in sols do
		   << for i:=1:first multiplicities!* do
			P:= (- rhs s) . p;
		      multiplicities!* := rest multiplicities!*;
		  >>
	>>
	else rederr(" hypergeomRsolve failed");

   foreach dd in DDD do
   if freeof (DD,k) then c := c / dd
        else if deg(DD,k) =1 then
        << C:= C/coeffn(dd,k,1);
            Q:= append (Q,list(coeffn(dd,k,0)/coeffn(dd,k,1)))>>
        else if deg(DD,k) =2 then
             << c := c /  lcof(dd,k);
                sols := solve(dd,k);
                for each s in sols do
                   << for i:=1:first multiplicities!* do
                        Q:= (- rhs s) . Q;
                      multiplicities!* := rest multiplicities!*;
                  >>;
             >>
        else rederr(" hypergeomRsolve failed");

   RSOLVE := infinite;
   for each s in P do if fixp s and s < 0 then RSOLVE := finite;
   if symbolic !*traceFPS then  write "RSOLVE  = ",RSOLVE;

   P := for each s in P product pochhammer(s,k);
   Q := for each s in Q product pochhammer(s,k);

   ak := a0 * (C^k) * P/(q * factorial k);

% Do additional simplification here??

   return ak;
end;

% A special ruleset for powerseries; nn has a special meaning here and 
% should be treated as integer

algebraic <<

hgspec_pochhammer :=

{ Pochhammer(~kk,~nn) => 1 when nn=0,
  Pochhammer(~kk,nn) => 0 when kk = 0,
  Pochhammer(~kk,nn) => (-1)^nn * factorial(-kk)/factorial(-kk-nn)
			when fixp(kk) and kk <=0,
  Pochhammer(~kk,nn) => factorial(kk+nn-1)/factorial(kk-1) when fixp kk,
  Pochhammer(~kk,~w*nn) =>
     factorial(kk+w*nn-1)/factorial(kk-1) when fixp kk}
>>;

endmodule;
end;


