subs2q.red 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. module subs2q; % Routines for substituting for powers.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 1991 The RAND Corporation. All rights reserved.
  4. fluid '(!*exp !*mcd !*structure !*sub2 alglist!* dmode!* frlis!*);
  5. fluid '(powlis!* powlis1!*);
  6. global '(!*resubs simpcount!* simplimit!*);
  7. Comment If STRUCTURE is ON, then expressions like (a**(b/2))**2 are not
  8. simplified, to allow some attempt at a structure theorem use, especially
  9. in the integrator;
  10. symbolic procedure subs2q u;
  11. % Perform power substitutions on u. Check whether substitions
  12. % on numerator and denominator change these before doing
  13. % quotient (to avoid undoing rationalization of denominator).
  14. ((if denr x=1 and denr y=1 and numr x=v and numr y=w then u
  15. else quotsq(x,y))
  16. where x=subs2f v, y=subs2f w)
  17. where v=numr u, w=denr u;
  18. symbolic procedure subs2f u;
  19. begin scalar x;
  20. if simpcount!*>simplimit!*
  21. then <<simpcount!* := 0;
  22. rerror(poly,21,"Simplification recursion too deep")>>;
  23. simpcount!* := simpcount!*+1;
  24. !*sub2 := nil;
  25. x := subs2f1 u;
  26. if (!*sub2 or powlis1!*) and !*resubs
  27. then if numr x=u and denr x=1 then !*sub2 := nil
  28. else x := subs2q x;
  29. simpcount!* := simpcount!*-1;
  30. return x
  31. end;
  32. symbolic procedure subs2f1 u;
  33. if domainp u then !*d2q u
  34. else begin scalar kern,v,w,x,y,z;
  35. kern := mvar u;
  36. z := nil ./ 1;
  37. a: if null u or degr(u,kern)=0 then go to a1;
  38. y := lt u .+ y;
  39. u := red u;
  40. go to a;
  41. a1: x := powlis!*;
  42. a2: if null x then go to b
  43. else if caaar y = caar x
  44. then <<w := subs2p(caar y,cadar x,cadddr car x); go to e1>>
  45. % else if eqcar(kern,'sqrt) and cadr kern = caar x
  46. % then <<w := raddsq(subs2p(cadr kern . cdaar y,
  47. % cadar x,cadddr car x),2);% go to e1>>;
  48. else if eqcar(kern,'expt)
  49. and cadr kern = caar x
  50. and eqcar(caddr kern,'quotient)
  51. and cadr caddr kern = 1
  52. and numberp caddr caddr kern
  53. then <<v := divide(cdaar y,caddr caddr kern);
  54. % if car v neq 0 then w := mksq(cadr kern,car v)
  55. % Use simp/exptsq to make sure I converted in complex mode.
  56. if car v neq 0 then w := exptsq(simp cadr kern,car v)
  57. else w := 1 ./ 1;
  58. if cdr v neq 0
  59. then <<begin scalar alglist!*,dmode!*;
  60. % We must do exponent arithmetic in integer
  61. % mode.
  62. v := cancel(cdr v.caddr caddr kern)
  63. end;
  64. w := multsq(raddsq(subs2p(cadr kern . car v,
  65. cadar x,cadddr car x),
  66. cdr v),w)>>;
  67. go to e1>>;
  68. x := cdr x;
  69. go to a2;
  70. b: x := powlis1!*;
  71. l2: if null x then go to l3
  72. else if w:= mtchp(caar y,caar x,caddar x,caadar x,cdadar x)
  73. then go to e1;
  74. x := cdr x;
  75. go to l2;
  76. l3: if eqcar(kern,'expt) and not !*structure then go to l1;
  77. z := addsq(multpq(caar y,subs2f1 cdar y),z);
  78. c: y := cdr y;
  79. if y then go to a1;
  80. d: y := subs2f1 u;
  81. % mkprod checks structure in "constant" term.
  82. if null !*exp then y := mkprod numr y ./ mkprod denr y;
  83. return addsq(z,y);
  84. e1: z := addsq(multsq(w,subs2f1 cdar y),z);
  85. go to c;
  86. l1: if cdaar y=1 and not eqcar(cadr kern,'expt) % ONEP
  87. then w := mksq(kern,1)
  88. else w := simpexpt list(cadr kern,
  89. list('times,caddr kern,cdaar y));
  90. z := addsq(multsq(w,subs2f1 cdar y),z);
  91. y := cdr y;
  92. if y then go to l1 else go to d;
  93. end;
  94. symbolic procedure subs2p(u,v,w);
  95. % U is a power, V an integer, and W an algebraic expression, such
  96. % that CAR U**V=W. Value is standard quotient for U with this
  97. % substitution.
  98. begin
  99. if not fixp cdr u or car(v := divide(cdr u,v))=0
  100. then return !*p2q u;
  101. w := exptsq(simp w,car v);
  102. return if cdr v=0 then w else multpq(car u .** cdr v,w)
  103. end;
  104. symbolic procedure raddsq(u,n);
  105. %U is a standard quotient, N and integer. Value is sq for U**(1/N);
  106. simpexpt list(mk!*sq u,list('quotient,1,n));
  107. symbolic procedure mtchp(u,v,w,flg,bool);
  108. %U is a standard power, V a power to be matched against.
  109. %W is the replacement expression.
  110. %FLG is a flag which is T if an exact power match required.
  111. %BOOL is a boolean expression to be satisfied for substitution.
  112. %Value is the substitution standard quotient if a match found,
  113. %NIL otherwise;
  114. begin scalar x;
  115. x := mtchp1(u,v,flg,bool);
  116. a: if null x then return nil
  117. else if lispeval subla(car x,bool) then go to b;
  118. x := cdr x;
  119. go to a;
  120. b: v := divide(cdr u,subla(car x,cdr v));
  121. w := exptsq(simp subla(car x,w),car v);
  122. if cdr v neq 0 then w := multpq(car u .** cdr v,w);
  123. return w
  124. end;
  125. symbolic procedure mtchp1(u,v,flg,bool);
  126. %U is a standard power, V a power to be matched against.
  127. %FLG is a flag which is T if an exact power match required.
  128. %BOOL is a boolean expression to be satisfied for substitution.
  129. %Value is a list of possible free variable pairings which
  130. %match conditions;
  131. begin scalar x;
  132. if u=v then return list nil
  133. else if not (x:= mchk!*(car u,car v)) then return nil
  134. else if cdr v memq frlis!*
  135. % do not match a free power to 1 or a conflicting match.
  136. then if cdr u=1 or not(x:= powmtch(cdr v,x,cdr u))
  137. then return nil
  138. else return mapcons(x,cdr v . cdr u)
  139. else if (flg and not(cdr u=cdr v))
  140. or not numberp cdr v or not numberp cdr u
  141. or (if !*mcd then cdr u<cdr v
  142. else (cdr u*cdr v)<0 or
  143. %implements explicit sign matching;
  144. abs cdr u<abs cdr v)
  145. then return nil
  146. else return x
  147. end;
  148. symbolic procedure powmtch(u,v,w);
  149. % Match a free power u against list of pairings v for value w.
  150. % Note from ACH: I have not yet found a case where this process
  151. % results in a match, even if a non-NIL value is returned. An
  152. % example with this procedure being necessary would be appreciated.
  153. if null v then nil
  154. else (if null x or cdr x=w then car v . powmtch(u,cdr v,w)
  155. else powmtch(u,cdr v,w))
  156. where x=atsoc(u,car v);
  157. symbolic procedure mchk!*(u,v);
  158. begin scalar x;
  159. if x := mchk(u,v) then return x
  160. else if !*mcd or not (sfp u and sfp v) then return nil
  161. else return mchk(prepf u,prepf v)
  162. end;
  163. endmodule;
  164. end;