MODULE ANTISUBS;
% Author: James H. Davenport.
EXPORTS ANTISUBS;
IMPORTS INTERR,DEPENDSP,setdiff;
SYMBOLIC PROCEDURE ANTISUBS(PLACE,X);
% Produces the inverse substitution to a substitution list.
BEGIN
SCALAR ANSWER,W;
WHILE PLACE AND
(X=CAAR PLACE) DO<<
W:=CDAR PLACE;
% w is the substitution rule.
IF ATOM W
THEN IF W NEQ X
THEN INTERR "False atomic substitution"
ELSE NIL
ELSE ANSWER:=(X.ANTI2(W,X)).ANSWER;
PLACE:=CDR PLACE>>;
IF NULL ANSWER
THEN ANSWER:=(X.X).ANSWER;
RETURN ANSWER
END;
SYMBOLIC PROCEDURE ANTI2(EEXPR,X);
%Produces the function inverse to the eexpr provided.
IF ATOM EEXPR
THEN IF EEXPR EQ X
THEN X
ELSE INTERR "False atom"
ELSE IF CAR EEXPR EQ 'PLUS
THEN DEPLUS(CDR EEXPR,X)
ELSE IF CAR EEXPR EQ 'MINUS
THEN SUBST(LIST('MINUS,X),X,ANTI2(CADR EEXPR,X))
ELSE IF CAR EEXPR EQ 'QUOTIENT
THEN IF DEPENDSP(CADR EEXPR,X)
THEN IF DEPENDSP(CADDR EEXPR,X)
THEN INTERR "Complicated division"
ELSE SUBST(LIST('TIMES,CADDR EEXPR,X),X,ANTI2(CADR EEXPR,X))
ELSE IF DEPENDSP(CADDR EEXPR,X)
THEN SUBST(LIST('QUOTIENT,CADR EEXPR,X),X,
ANTI2(CADDR EEXPR,X))
ELSE INTERR "No division"
ELSE IF CAR EEXPR EQ 'EXPT
THEN IF CADDR EEXPR IEQUAL 2
THEN SUBST(LIST('SQRT,X),X,ANTI2(CADR EEXPR,X))
ELSE INTERR "Unknown root"
ELSE IF CAR EEXPR EQ 'TIMES
THEN DETIMES(CDR EEXPR,X)
ELSE IF CAR EEXPR EQ 'DIFFERENCE
THEN DEPLUS(LIST(CADR EEXPR,LIST('MINUS,CADDR EEXPR)),X)
ELSE INTERR "Unrecognised form in antisubs";
SYMBOLIC PROCEDURE DETIMES(P!-LIST,VAR);
% Copes with lists 'times.
BEGIN
SCALAR U,V;
U:=DEPLIST(P!-LIST,VAR);
V:=setdiff(P!-LIST,u);
IF NULL V
THEN V:=VAR
ELSE IF NULL CDR V
THEN V:=LIST('QUOTIENT,VAR,CAR V)
ELSE V:=LIST('QUOTIENT,VAR,'TIMES.V);
IF (NULL U) OR
(CDR U)
THEN INTERR "Weird multiplication";
RETURN SUBST(V,VAR,ANTI2(CAR U,VAR))
END;
SYMBOLIC PROCEDURE DEPLIST(P!-LIST,VAR);
% Returns a list of those elements of p!-list which depend on var.
IF NULL P!-LIST
THEN NIL
ELSE IF DEPENDSP(CAR P!-LIST,VAR)
THEN (CAR P!-LIST).DEPLIST(CDR P!-LIST,VAR)
ELSE DEPLIST(CDR P!-LIST,VAR);
SYMBOLIC PROCEDURE DEPLUS(P!-LIST,VAR);
% Copes with lists 'plus.
BEGIN
SCALAR U,V;
U:=DEPLIST(P!-LIST,VAR);
V:=setdiff(P!-LIST,u);
IF NULL V
THEN V=VAR
ELSE IF NULL CDR V
THEN V:=LIST('PLUS,VAR,LIST('MINUS,CAR V))
ELSE V:=LIST('PLUS,VAR,LIST('MINUS,'PLUS.V));
IF (NULL U) OR
(CDR U)
THEN INTERR "Weird addition";
RETURN SUBST(V,VAR,ANTI2(CAR U,VAR))
END;
ENDMODULE;
END;