simplog.red 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. xmodule simplog; % Simplify logarithms.
  2. % Authors: Mary Ann Moore and Arthur C. Norman.
  3. fluid '(!*intflag!* !*noneglogs !*expandlogs);
  4. global '(domainlist!*);
  5. exports simplog,simplogi,simplogsq;
  6. imports addf,addsq,comfac,quotf,prepf,mksp,simp!*,!*multsq,simptimes,
  7. minusf,negf,negsq,mk!*sq,carx,multsq,resimp,simpiden,simpplus,
  8. prepd,mksq,rerror,zfactor,sfchk;
  9. symbolic procedure simplog u;
  10. (if !*expandlogs then
  11. (resimp simplogi x where !*expandlogs=nil)
  12. else if eqcar(x,'quotient) and cadr x=1
  13. and (null !*precise or realvaluedp caddr x)
  14. then negsq simpiden('log . cddr x)
  15. else simpiden u)
  16. where x=carx(cdr u,'simplog);
  17. put('log,'simpfn,'simplog);
  18. flag('(log),'full);
  19. put('expandlogs,'simpfg,'((nil (rmsubs)) (t (rmsubs))));
  20. put('combinelogs,'simpfg,'((nil (rmsubs)) (t (rmsubs))));
  21. symbolic procedure simplogi(sq);
  22. % This version will only expand a log if at most one of the
  23. % arguments is complex. Otherwise you can finish up on the wrong
  24. % sheet.
  25. if atom sq then simplogsq simp!* sq
  26. else if car sq memq domainlist!* then simpiden list('log,sq)
  27. else if car sq eq 'times
  28. then if null !*precise or one_complexlist cdr sq
  29. then simpplus(for each u in cdr sq collect mk!*sq simplogi u)
  30. else !*kk2q {'log,sq}
  31. else if car sq eq 'quotient
  32. and (null !*precise or one_complexlist cdr sq)
  33. then addsq(simplogi cadr sq,negsq simplogi caddr sq)
  34. else if car sq eq 'expt
  35. then simptimes list(caddr sq,mk!*sq simplogi cadr sq)
  36. else if car sq eq 'nthroot
  37. then multsq!*(1 ./ caddr sq,simplogi cadr sq)
  38. % we had (nthroot of n).
  39. else if car sq eq 'sqrt then multsq!*(1 ./ 2,simplogi cadr sq)
  40. else if car sq = '!*sq then simplogsq cadr sq
  41. else simplogsq simp!* sq;
  42. symbolic procedure one_complexlist u;
  43. % True if at most one member of list u is complex.
  44. if null u then t
  45. else if realvaluedp car u then one_complexlist cdr u
  46. else null cdr u or realvaluedlist cdr u;
  47. symbolic procedure multsq!*(u,v);
  48. if !*intflag!* then !*multsq(u,v) else multsq(u,v);
  49. symbolic procedure simplogsq sq;
  50. % This procedure needs to be reworked to provide for proper sheet
  51. % handling.
  52. if null numr sq then rerror(alg,210,"Log 0 formed")
  53. else if denr sq=1 and domainp numr sq and !:onep numr sq
  54. then nil ./ 1
  55. else if !*precise then !*kk2q {'log,prepsq sq}
  56. else addsq(simplog2 numr sq,negsq simplog2 denr sq);
  57. symbolic procedure simplog2(sf);
  58. if atom sf
  59. then if null sf then rerror(alg,21,"Log 0 formed")
  60. else if numberp sf
  61. then if sf iequal 1 then nil ./ 1
  62. else if sf iequal 0 then rerror(alg,22,"Log 0 formed")
  63. else simplogn sf
  64. else formlog(sf)
  65. else if domainp sf then mksq({'log,prepd sf},1)
  66. else begin scalar form;
  67. form := comfac sf;
  68. if not null car form
  69. then return addsq(formlog(form .+ nil),
  70. simplog2 quotf(sf,form .+ nil));
  71. % We have killed common powers.
  72. form := cdr form;
  73. if form neq 1
  74. then return addsq(simplog2 form,simplog2 quotf(sf,form));
  75. % Remove a common factor from the sf.
  76. return formlog sf
  77. end;
  78. symbolic procedure simplogn u;
  79. % See comments in formlog for an explanation of the code.
  80. begin scalar y,z;
  81. y := zfactor u;
  82. if car y= '(-1 . 1) and null(y := mergeminus cdr y)
  83. then return !*kk2q {'log,u};
  84. for each x in y do
  85. z := addf(((mksp({'log,car x},1) .* cdr x) .+ nil),z);
  86. return z ./ 1
  87. end;
  88. symbolic procedure mergeminus u;
  89. begin scalar x;
  90. a: if null u then return nil
  91. else if remainder(cdar u,2)=1
  92. then return nconc(reversip x,((-caar u) . cdar u) . cdr u)
  93. else <<x := car u . x; u := cdr u; go to a>>
  94. end;
  95. symbolic procedure formlog sf;
  96. % Minus test commented out. Otherwise, we can get:
  97. % log(a) + log(-1) => log(a*(-1)) => log(-a).
  98. % log(a) - log(-1) => log(a/(-1)) => log(-a).
  99. % I.e., log(-a) can be log(a) + log(-1) or log(a) - log(-1).
  100. if null red sf then formlogterm sf
  101. % else if minusf sf and null !*noneglogs
  102. % then addf((mksp(list('log,-1),1) .* 1) .+ nil,
  103. % formlog2 negf sf) ./ 1
  104. else (formlog2 sf) ./ 1;
  105. symbolic procedure formlogterm(sf);
  106. begin scalar u;
  107. u := mvar sf;
  108. if not atom u and (car u member '(times sqrt expt nthroot))
  109. then u := addsq(simplog2 lc sf,
  110. multsq!*(simplogi u,simp!* ldeg sf))
  111. else if (lc sf iequal 1) and (ldeg sf iequal 1)
  112. then u := ((mksp(list('log,sfchk u),1) .* 1) .+ nil) ./ 1
  113. else u := addsq(simptimes list(list('log,sfchk u),ldeg sf),
  114. simplog2 lc sf);
  115. return u
  116. end;
  117. symbolic procedure formlog2 sf;
  118. ((mksp(list('log,prepf sf),1) .* 1) .+ nil);
  119. endmodule;
  120. end;