123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- xmodule simplog; % Simplify logarithms.
- % Authors: Mary Ann Moore and Arthur C. Norman.
- fluid '(!*intflag!* !*noneglogs !*expandlogs);
- global '(domainlist!*);
- exports simplog,simplogi,simplogsq;
- imports addf,addsq,comfac,quotf,prepf,mksp,simp!*,!*multsq,simptimes,
- minusf,negf,negsq,mk!*sq,carx,multsq,resimp,simpiden,simpplus,
- prepd,mksq,rerror,zfactor,sfchk;
- symbolic procedure simplog u;
- (if !*expandlogs then
- (resimp simplogi x where !*expandlogs=nil)
- else if eqcar(x,'quotient) and cadr x=1
- and (null !*precise or realvaluedp caddr x)
- then negsq simpiden('log . cddr x)
- else simpiden u)
- where x=carx(cdr u,'simplog);
- put('log,'simpfn,'simplog);
- flag('(log),'full);
- put('expandlogs,'simpfg,'((nil (rmsubs)) (t (rmsubs))));
- put('combinelogs,'simpfg,'((nil (rmsubs)) (t (rmsubs))));
- symbolic procedure simplogi(sq);
- % This version will only expand a log if at most one of the
- % arguments is complex. Otherwise you can finish up on the wrong
- % sheet.
- if atom sq then simplogsq simp!* sq
- else if car sq memq domainlist!* then simpiden list('log,sq)
- else if car sq eq 'times
- then if null !*precise or one_complexlist cdr sq
- then simpplus(for each u in cdr sq collect mk!*sq simplogi u)
- else !*kk2q {'log,sq}
- else if car sq eq 'quotient
- and (null !*precise or one_complexlist cdr sq)
- then addsq(simplogi cadr sq,negsq simplogi caddr sq)
- else if car sq eq 'expt
- then simptimes list(caddr sq,mk!*sq simplogi cadr sq)
- else if car sq eq 'nthroot
- then multsq!*(1 ./ caddr sq,simplogi cadr sq)
- % we had (nthroot of n).
- else if car sq eq 'sqrt then multsq!*(1 ./ 2,simplogi cadr sq)
- else if car sq = '!*sq then simplogsq cadr sq
- else simplogsq simp!* sq;
- symbolic procedure one_complexlist u;
- % True if at most one member of list u is complex.
- if null u then t
- else if realvaluedp car u then one_complexlist cdr u
- else null cdr u or realvaluedlist cdr u;
- symbolic procedure multsq!*(u,v);
- if !*intflag!* then !*multsq(u,v) else multsq(u,v);
- symbolic procedure simplogsq sq;
- % This procedure needs to be reworked to provide for proper sheet
- % handling.
- if null numr sq then rerror(alg,210,"Log 0 formed")
- else if denr sq=1 and domainp numr sq and !:onep numr sq
- then nil ./ 1
- else if !*precise then !*kk2q {'log,prepsq sq}
- else addsq(simplog2 numr sq,negsq simplog2 denr sq);
- symbolic procedure simplog2(sf);
- if atom sf
- then if null sf then rerror(alg,21,"Log 0 formed")
- else if numberp sf
- then if sf iequal 1 then nil ./ 1
- else if sf iequal 0 then rerror(alg,22,"Log 0 formed")
- else simplogn sf
- else formlog(sf)
- else if domainp sf then mksq({'log,prepd sf},1)
- else begin scalar form;
- form := comfac sf;
- if not null car form
- then return addsq(formlog(form .+ nil),
- simplog2 quotf(sf,form .+ nil));
- % We have killed common powers.
- form := cdr form;
- if form neq 1
- then return addsq(simplog2 form,simplog2 quotf(sf,form));
- % Remove a common factor from the sf.
- return formlog sf
- end;
- symbolic procedure simplogn u;
- % See comments in formlog for an explanation of the code.
- begin scalar y,z;
- y := zfactor u;
- if car y= '(-1 . 1) and null(y := mergeminus cdr y)
- then return !*kk2q {'log,u};
- for each x in y do
- z := addf(((mksp({'log,car x},1) .* cdr x) .+ nil),z);
- return z ./ 1
- end;
- symbolic procedure mergeminus u;
- begin scalar x;
- a: if null u then return nil
- else if remainder(cdar u,2)=1
- then return nconc(reversip x,((-caar u) . cdar u) . cdr u)
- else <<x := car u . x; u := cdr u; go to a>>
- end;
- symbolic procedure formlog sf;
- % Minus test commented out. Otherwise, we can get:
- % log(a) + log(-1) => log(a*(-1)) => log(-a).
- % log(a) - log(-1) => log(a/(-1)) => log(-a).
- % I.e., log(-a) can be log(a) + log(-1) or log(a) - log(-1).
- if null red sf then formlogterm sf
- % else if minusf sf and null !*noneglogs
- % then addf((mksp(list('log,-1),1) .* 1) .+ nil,
- % formlog2 negf sf) ./ 1
- else (formlog2 sf) ./ 1;
- symbolic procedure formlogterm(sf);
- begin scalar u;
- u := mvar sf;
- if not atom u and (car u member '(times sqrt expt nthroot))
- then u := addsq(simplog2 lc sf,
- multsq!*(simplogi u,simp!* ldeg sf))
- else if (lc sf iequal 1) and (ldeg sf iequal 1)
- then u := ((mksp(list('log,sfchk u),1) .* 1) .+ nil) ./ 1
- else u := addsq(simptimes list(list('log,sfchk u),ldeg sf),
- simplog2 lc sf);
- return u
- end;
- symbolic procedure formlog2 sf;
- ((mksp(list('log,prepf sf),1) .* 1) .+ nil);
- endmodule;
- end;
|