MODULE FRACDI;

% Author: James H. Davenport.

FLUID '(BASIC!-LISTOFALLSQRTS BASIC!-LISTOFNEWSQRTS EXPSUB INTVAR
    SQRT!-INTVAR);

GLOBAL '(COATES!-FDI);

EXPORTS FDI!-PRINT,FDI!-REVERTSQ,FDI!-UPGRADE,
   FRACTIONAL!-DEGREE!-AT!-INFINITY;

% internal!-fluid '(expsub);

SYMBOLIC PROCEDURE FDI!-PRINT();
<< PRINC "We substitute ";
   PRINC INTVAR;
   PRINC "**";
   PRINC COATES!-FDI;
   PRINC " for ";
   PRINC INTVAR;
   PRINTC " in order to avoid fractional degrees at infinity" >>;


SYMBOLIC PROCEDURE FDI!-REVERTSQ U;
IF COATES!-FDI IEQUAL 1
  THEN U
  ELSE (FDI!-REVERT NUMR U) ./ (FDI!-REVERT DENR U);


SYMBOLIC PROCEDURE FDI!-REVERT U;
IF NOT INVOLVESF(U,INTVAR)
  THEN U
  ELSE ADDF(FDI!-REVERT RED U,
        !*MULTF(FDI!-REVERTPOW LPOW U,
            FDI!-REVERT LC U));


SYMBOLIC PROCEDURE FDI!-REVERTPOW POW;
IF NOT DEPENDSP(CAR POW,INTVAR)
  THEN (POW .* 1) .+ NIL
  ELSE IF CAR POW EQ INTVAR
    THEN BEGIN
      SCALAR V;
      V:=DIVIDE(CDR POW,COATES!-FDI);
      IF CDR POW=0
        THEN RETURN (MKSP(INTVAR,CAR POW) .* 1) .+ NIL
    ELSE INTERR "Unable to revert fdi";
      END
    ELSE IF EQ(CAR POW,'SQRT)
      THEN SIMPSQRT2 FDI!-REVERT !*Q2F SIMP ARGOF CAR POW
      ELSE INTERR "Unrecognised term to revert";


SYMBOLIC PROCEDURE FDI!-UPGRADE PLACE;
BEGIN
  SCALAR ANS,U,EXPSUB,N;
  N:=COATES!-FDI;
  FOR EACH U IN PLACE DO
    IF EQCAR(U:=RSUBS U,'EXPT)
      THEN N:=N / CADDR U;
      % if already upgraded, we must take account of this.
  IF N = 1
    THEN RETURN PLACE;
  EXPSUB:=LIST(INTVAR,'EXPT,INTVAR,N);
  ANS:=NCONC(BASICPLACE PLACE,LIST EXPSUB);
  EXPSUB:=LIST EXPSUB; % this prevents later nconc from causing trouble.
  U:=EXTENPLACE PLACE;
  WHILE U DO BEGIN
    SCALAR V,W,RFU;
    V:=FDI!-UPGR2 LFIRSTSUBS U;
    IF V IEQUAL 1
      THEN RETURN (U:=CDR U);
    IF EQCAR(RFU:=RFIRSTSUBS U,'MINUS)
      THEN W:=ARGOF RFU
      ELSE IF EQCAR(RFU,'SQRT)
        THEN W:=RFU
    ELSE INTERR "Unknown place format";
    W:=FDI!-UPGR2 W;
    IF W IEQUAL 1
      THEN INTERR "Place collapses under rewriting";
    IF EQCAR(RFU,'MINUS)
      THEN ANS:=NCONC(ANS,LIST LIST(V,'MINUS,W))
      ELSE ANS:=NCONC(ANS,LIST(V.W));
    U:=CDR U;
    RETURN
    END;
  SQRTSAVE(BASIC!-LISTOFALLSQRTS,
       BASIC!-LISTOFNEWSQRTS,
           BASICPLACE ANS);
  RETURN ANS
  END;


SYMBOLIC PROCEDURE FDI!-UPGR2 U;
BEGIN
  SCALAR V,MV;
% V:=SUBSTITUTESQ(SIMP U,EXPSUB);
% The above line doesn't work due to int(sqrt(x-1)/sqrt(x+1),x);
% where the attempt to make sqrt(x^2-1) is frustrated by the presence of
% sqrt(x-1) and sqrt(x+1) which get SIMPed (even after we allow for the
% NEWPLACE call in COATES
  V:=XSUBSTITUTEP(U,EXPSUB);
  IF DENR V NEQ 1
    THEN GOTO ERROR;
  V:=NUMR V;
LOOP:
  IF ATOM V
    THEN RETURN V;
  IF RED V
    THEN GO TO ERROR;
  MV:=MVAR V;
  IF (NOT DEPENDSP(MV,INTVAR)) OR (MV EQ INTVAR)
    THEN <<
      V:=LC V;
      GOTO LOOP >>;
  IF EQCAR(MV,'SQRT) AND NOT SQRTSINSF(LC V,NIL,INTVAR)
      THEN RETURN MV;
ERROR:
  PRINTC "*** Format error ***";
  PRINC "unable to go x:=x**";
  PRINTC COATES!-FDI;
  SUPERPRINT U;
  interr "Failure to make integral at infinity"
  END;


SYMBOLIC PROCEDURE FRACTIONAL!-DEGREE!-AT!-INFINITY SQRTS;
IF SQRTS
  THEN LCMN(FDI2 CAR SQRTS,FRACTIONAL!-DEGREE!-AT!-INFINITY CDR SQRTS)
  ELSE 1;


SYMBOLIC PROCEDURE FDI2 U;
   % Returns the denominator of the degree of x at infinity
   % in the sqrt expression u.
BEGIN
  SCALAR N;
  U:=SUBSTITUTESQ(SIMP U,LIST LIST(INTVAR,'QUOTIENT,1,INTVAR));
  N:=0;
  WHILE INVOLVESQ(U,SQRT!-INTVAR) DO <<
    N:=IADD1 N;
    U:=SUBSTITUTESQ(U,LIST LIST(INTVAR,'EXPT,INTVAR,2)) >>;
  RETURN (2**N)
  END;


SYMBOLIC PROCEDURE LCMN(I,J);
  I*J/GCDN(I,J);

% unfluid '(expsub);

ENDMODULE;

END;
