distrib.red 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. module distrib; % Routines for manipulating distributed forms.
  2. % Authors: Mary Ann Moore and Arthur C. Norman.
  3. fluid '(indexlist sqrtlist zlist);
  4. exports dfprintform,multbyarbpowers,negdf,quotdfconst,sub1ind, % var2df,
  5. vp1,vp2,plusdf,multdf,multdfconst,orddf;
  6. imports interr,addsq,negsq,exptsq,simp,domainp,mk!*sq,addf,
  7. multsq,invsq,minusp,mksp,sub1;
  8. %***********************************************************************
  9. % NOTE: The expressions lt,red,lc,lpow have been used on distributed
  10. % forms as the latter's structure is sufficiently similar to
  11. % s.f.'s. However lc df is a s.q. not a s.f. and lpow df is a
  12. % list of the exponents of the variables. This also makes
  13. % lt df different. Red df is d.f. as expected.
  14. %***********************************************************************
  15. symbolic procedure plusdf(u,v);
  16. % U and V are D.F.'s. Value is D.F. for U+V.
  17. if null u then v
  18. else if null v then u
  19. else if lpow u=lpow v then
  20. (lambda(x,y); if null numr x then y else (lpow u .* x) .+ y)
  21. (!*addsq(lc u,lc v),plusdf(red u,red v))
  22. else if orddf(lpow u,lpow v) then lt u .+ plusdf(red u,v)
  23. else (lt v) .+ plusdf(u,red v);
  24. symbolic procedure orddf(u,v);
  25. % U and V are the LPOW of a D.F. - i.e. the list of exponents.
  26. % Value is true if LPOW U '>' LPOW V and false otherwise.
  27. if null u then if null v then interr "Orddf = case"
  28. else interr "Orddf v longer than u"
  29. else if null v then interr "Orddf u longer than v"
  30. else if exptcompare(car u,car v) then t
  31. else if exptcompare(car v,car u) then nil
  32. else orddf(cdr u,cdr v);
  33. symbolic procedure exptcompare(x,y);
  34. if atom x then if atom y then x>y else nil
  35. else if atom y then t
  36. else car x > car y;
  37. symbolic procedure negdf u;
  38. if null u then nil
  39. else (lpow u .* negsq lc u) .+ negdf red u;
  40. symbolic procedure multdf(u,v);
  41. % U and V are D.F.'s. Value is D.F. for U*V.
  42. % Reduces squares of square-roots as it goes.
  43. if null u or null v then nil
  44. else begin scalar y;
  45. % use (a+b)*(c+d) = (a*c) + a*(c+d) + b*(c+d).
  46. y:=multerm(lt u,lt v); %leading terms;
  47. y:=plusdf(y,multdf(red u,v));
  48. y:=plusdf(y,multdf((lt u) .+ nil,red v));
  49. return y
  50. end;
  51. symbolic procedure multerm(u,v);
  52. % Multiply two terms to give a D.F.
  53. begin scalar coef;
  54. coef:=!*multsq(cdr u,cdr v); % coefficient part.
  55. return multdfconst(coef,mulpower(car u,car v))
  56. end;
  57. symbolic procedure mulpower(u,v);
  58. % U and v are exponent lists. multiply corresponding forms.
  59. begin scalar r,s;
  60. r:=addexptsdf(u,v);
  61. if not null sqrtlist then s:=reduceroots(r,zlist);
  62. r:=(r .* (1 ./ 1)) .+ nil;
  63. if not (s=nil) then r:=multdf(r,s);
  64. return r
  65. end;
  66. symbolic procedure reduceroots(r,zl);
  67. begin scalar s;
  68. while not null r do <<
  69. if eqcar(car zl,'sqrt) then
  70. s:=tryreduction(r,car zl,s);
  71. r:=cdr r; zl:=cdr zl >>;
  72. return s
  73. end;
  74. symbolic procedure tryreduction(r,var,s);
  75. begin scalar x;
  76. x:=car r; % current exponent.
  77. if not atom x then << r:=x; x:=car r >>; % numeric part.
  78. if (x=0) or (x=1) then return s; % no reduction possible.
  79. x:=divide(x,2);
  80. rplaca(r,cdr x); % reduce exponent as redorded.
  81. x:=car x;
  82. var:=simp cadr var; % sqrt arg as a s q.
  83. var:=!*exptsq(var,x);
  84. x:=multdfconst(1 ./ denr var,f2df numr var); % distribute.
  85. if s=nil then s:=x
  86. else s:=multdf(s,x);
  87. return s
  88. end;
  89. symbolic procedure addexptsdf(x,y);
  90. % X and Y are LPOW's of D.F. Value is list of sum of exponents.
  91. if null x then if null y then nil else interr "X too long"
  92. else if null y then interr "Y too long"
  93. else exptplus(car x,car y).addexptsdf(cdr x,cdr y);
  94. symbolic procedure exptplus(x,y);
  95. if atom x then if atom y then x+y else list (x+car y)
  96. else if atom y then list (car x +y)
  97. else interr "Bad exponent sum";
  98. symbolic procedure multdfconst(x,u);
  99. % X is S.Q. not involving Z variables of DF U. Value is DF for X*U.
  100. if null u or null numr x then nil
  101. % else lpow u .* !*multsq(x,lc u) .+ multdfconst(x,red u);
  102. % FJW: Does not handle i^2 correctly, so ...
  103. % (cf. solve!-for!-u in module isolve)
  104. else lpow u .* subs2q multsq(x,lc u) .+ multdfconst(x,red u);
  105. %symbolic procedure quotdfconst(x,u);
  106. % multdfconst(!*invsq x,u);
  107. symbolic procedure f2df p;
  108. % P is standard form. Value is P in D.F.
  109. if domainp p then dfconst(p ./ 1)
  110. else if mvar p member zlist then
  111. plusdf(multdf(vp2df(mvar p,tdeg lt p,zlist),f2df lc p),
  112. f2df red p)
  113. else plusdf(multdfconst(((lpow p .* 1) .+ nil) ./ 1,f2df lc p),
  114. f2df red p);
  115. % SYMBOLIC PROCEDURE VAR2DF(VAR,N,ZLIST);
  116. % ((VP1(VAR,N,ZLIST) .* (1 ./ 1)) .+ NIL);
  117. symbolic procedure vp1(var,degg,z);
  118. % Takes VAR and finds it in Z (=list), raises it to power DEGG and puts
  119. % the result in exponent list form for use in a distributed form.
  120. if null z then interr "Var not in z-list after all"
  121. else if var=car z then degg.vp2 cdr z
  122. else 0 . vp1(var,degg,cdr z);
  123. symbolic procedure vp2 z;
  124. % Makes exponent list of zeroes.
  125. if null z then nil
  126. else 0 . vp2 cdr z;
  127. symbolic procedure vp2df(var,exprn,z);
  128. % Makes VAR**EXPRN into exponent list and then converts the resulting
  129. % power into a distributed form. Special care needed with square-roots.
  130. if eqcar(var,'sqrt) and (exprn>1) then
  131. mulpower(vp1(var,exprn,z),vp2 z)
  132. else (vp1(var,exprn,z) .* (1 ./ 1)) .+ nil;
  133. symbolic procedure dfconst q;
  134. % Makes a distributed form from standard quotient constant Q.
  135. if numr q=nil then nil
  136. else ((vp2 zlist) .* q) .+ nil;
  137. % Df2q moved to a section of its own.
  138. symbolic procedure df2printform p;
  139. % Convert to a standard form good enough for printing.
  140. if null p then nil
  141. else begin
  142. scalar mv,co;
  143. mv:=xl2q(lpow p,zlist,indexlist);
  144. if mv=(1 ./ 1) then <<
  145. co:=lc p;
  146. if denr co=1 then return addf(numr co,
  147. df2printform red p);
  148. co:=mksp(mk!*sq co,1);
  149. return (co .* 1) .+ df2printform red p >>;
  150. co:=lc p;
  151. if not (denr co=1) then mv:=!*multsq(mv,1 ./ denr co);
  152. mv:=mksp(mk!*sq mv,1) .* numr co;
  153. return mv .+ df2printform red p
  154. end;
  155. symbolic procedure xl2q(l,z,il);
  156. % L is an exponent list from a D.F.,Z is the Z-list, IL is the list of
  157. % indices. Value is L converted to standard quotient.
  158. if null z then 1 ./ 1
  159. else if car l=0 then xl2q(cdr l,cdr z,cdr il)
  160. else if not atom car l then
  161. begin scalar temp;
  162. if caar l=0 then temp:= car il
  163. else temp:=list('plus,car il,caar l);
  164. temp:=mksp(list('expt,car z,temp),1);
  165. return !*multsq(((temp .* 1) .+ nil) ./ 1,
  166. xl2q(cdr l,cdr z,cdr il))
  167. end
  168. else if minusp car l then
  169. !*multsq(!*invsq(((mksp(car z,-car l) .* 1) .+ nil) ./ 1),
  170. xl2q(cdr l,cdr z,cdr il))
  171. else !*multsq(((mksp(car z,car l) .* 1) .+ nil) ./ 1,
  172. xl2q(cdr l,cdr z,cdr il));
  173. %symbolic procedure sub1ind power;
  174. % if atom power then power-1 else list sub1 car power;
  175. symbolic procedure multbyarbpowers u;
  176. % Multiplies the ordinary D.F., U, by arbitrary powers
  177. % of the z-variables,
  178. % i-1 j-1 k-1
  179. % i.e. x z z ... so result is D.F. with the exponent list
  180. % 1 2
  181. %appropriately altered to contain list elements instead of numeric ones.
  182. if null u then nil
  183. else ((addarbexptsdf lpow u) .* lc u) .+ multbyarbpowers red u;
  184. symbolic procedure addarbexptsdf x;
  185. % Adds the arbitrary powers to powers in exponent list, X, to produce
  186. % new exponent list. e.g. 3 -> (2) to represent x**3 now becoming :
  187. % 3 i-1 i+2
  188. % x * x = x .
  189. if null x then nil
  190. else list exptplus(car x,-1) . addarbexptsdf cdr x;
  191. endmodule;
  192. end;