123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- module plotsynt; % Support for the syntax of the plot command.
- % Author: Herbert Melenk.
- fluid '(bye!-actions!*);
- % Create .. as the infix operator if not yet done.
- !*msg := nil; % prevent message ".. redefined" during load
- newtok '( (!. !.) !*interval!*);
- if not(gettype '!*interval!* = 'operator) then
- <<
- precedence .., or;
- algebraic operator ..;
- put('!*interval!*,'PRTCH,'! !.!.! );
- >>;
- mkop 'point;
- !*msg := t;
- fluid '(plot!-points!* plot!-refine!* plot!-contour!*);
- global '(plot_xrange plot_yrange plot_zrange);
- share plot_xmesh,plot_ymesh,plot_xrange,plot_yrange,plot_zrange;
- fluid '(plotprecision!*);
- plotprecision!* := 0.9995;
- fluid '(!*show_grid test_plot);
- switch show_grid;
- switch test_plot; % for test printouts
- if null plotmax!* then
- <<
- load!-package 'arith;
- if not !!plumax then roundconstants();
- plotmax!* := !!plumax; % IEEE double precision
- >>;
- plotmin!*:= 1.0/plotmax!*;
- fluid '(plotranges!* plotfunctions!* plotstyle!* !*plotoverflow
- !*roundbf);
- put('plot,'psopfn,'ploteval);
- symbolic procedure ploteval u;
- begin scalar m,!*exp;
- if null plotdriver!* then
- rederr "no active device driver for PLOT";
- m:=plotrounded(nil);
- plot!-points!* := {20};
- plot!-refine!* := 8;
- !*plotoverflow := nil;
- plotranges!* := plotfunctions!* := nil;
- plotstyle!* := 'lines;
- bye!-actions!* := union('((plotreset)),bye!-actions!*);
- plotdriver(init);
- for each option in u do ploteval1 plot!-reval option;
- errorset('(ploteval2),t,nil);
- plotrounded(m);
- end;
-
- symbolic procedure plot!-reval u;
- % Protected call reval: simplify u, but don't call any
- % algebraic procedure.
- begin scalar w;
- w:={nil};
- u:=plot!-reval1(u,w);
- return car w and u or reval u;
- end;
- symbolic procedure plot!-reval1(u,w);
- if idp u then reval u else
- if atom u or eqcar(u,'!:dn!:) or get(car u,'dname) then u else %WN
- if eq (car u,'!*sq) then plot!-reval1(reval u,w) else
- <<if flagp(car u,'opfn) and
- memq(car u,'(first second rest rhs lhs)) then
- << u := reval u; % lex Robin Tucker % WN
- plot!-reval1(u,w)>> else
- << if flagp(car u,'opfn) then car w:=t;
- car u . for each q in cdr u collect plot!-reval1(q,w) >> >>;
- symbolic procedure ploteval1 option;
- begin scalar x,do;
- do := get(plotdriver!*,'do);
- if pairp option and (x:=get(car option,do))
- then apply(x,list option) else
- if pairp option and (x:=get(car option,'plot!-do))
- then apply(x,list option) else
- if eqcar(option,'equal) and (x:=get(cadr option,do))
- then apply(x,list caddr option) else
- if eqcar(option,'equal) and (x:=get(cadr option,'plot!-do))
- then apply(x,list caddr option)
- else ploteval0 option;
- end;
-
- symbolic procedure ploteval0 option;
- begin scalar l,r,opt,w;
- opt:=get(plotdriver!*,'option);
- if flagp(option,opt) then
- <<plotoptions!*:=option . plotoptions!*; return>>;
- if eqcar(option,'list) then
- <<option := cdr option;
- if option and eqcar(car option,'list) then
- return (plotfunctions!*:=
- ('points.plotpoints option).plotfunctions!*);
- for each o in option do ploteval0 o; return;
- >>;
- if eqcar(option,'equal) and flagp(cadr option,opt) then
- <<plotoptions!*:=(cadr option.caddr option). plotoptions!*;
- return>>;
- if not eqcar(option,'equal) then
- <<plotfunctions!*:= (nil.option) . plotfunctions!*; return>>;
- % Handle equations.
- l:=plot!-reval cadr option;
- r:=plot!-reval caddr option;
- if plot!-checkcontour(l,r) then return
- plotfunctions!*:=('implicit.l) . plotfunctions!* else %WN 7.3.96
- if not idp l then typerr(option,"illegal option in PLOT");
- if l memq '(size terminal view) then
- <<plotoptions!*:=(l.r).plotoptions!*; return>>;
- % iteration over a range?
- if eqcar(r,'times) and eqcar(caddr r,'!*interval!*)
- and evalnumberp(w:=cadr r) and evalgreaterp(w,0) and
- not evalgreaterp(w,1)
- then <<plot!-points!*:=append(plot!-points!*,
- {l.reval{'floor,{'quotient,1,w}}});
- r:=caddr r>>;
- if eqcar(r,'quotient) and eqcar(cadr r,'!*interval!*)
- and fixp caddr r and caddr r > 0
- then <<plot!-points!*:=append(plot!-points!*,{l.caddr r});
- r:=cadr r>>;
- % range?
- if eqcar(r,'!*interval!*) then
- <<r:='!*interval!* . revalnuminterval(r,t);
- plotranges!* := (l . r) . plotranges!*>>
- else
- plotfunctions!* := (l . r) . plotfunctions!*;
- end;
- symbolic procedure ploteval2 ();
- % all options are collected now;
- begin scalar dvar,ivars,para,impl;
- for each u in plotfunctions!* do
- <<impl:=impl or car u eq 'implicit;
- para:=eqcar(cdr u,'point);
- if impl and dvar and dvar neq car u then
- rederr "mixture of implicit and regular plot not supported";
- dvar:=car u or dvar;
- ivars := plotindepvars(cdr u,ivars)>>;
- % classify
- if null dvar then
- <<dvar:='(x y z);
- for each x in ivars do dvar:=delete(x,dvar);
- if dvar then dvar:=if 'y memq dvar then 'y else car dvar;
- >>;
- if para and length ivars=1 then plotevalpara1(car ivars) else
- if para and length ivars=2 then plotevalpara2(car ivars,cadr ivars)
- else if length ivars=1 then ploteval2x(car ivars,dvar) else
- if length ivars=2 then ploteval3xy(car ivars,cadr ivars,dvar) else
- % WN was besseres!! if length ivars=3 and impl then
- ploteval3impl('x,'y,'z); %car ivars,cadr ivars,caddr ivars);
- comment else typerr('list . for each p in plotfunctions!* collect
- if null car p then cdr p else
- {'equal,car p,cdr p},
- " plot option or function");
- plotdriver(show);
- end;
- symbolic procedure plot!-checkcontour(l,r);
- % true if the job is a contour expression.
- if length plotindepvars(l,nil)=2
- or length plotindepvars(l,nil)=3 then % WN 7.3.96
- if r=0 then <<plot!-contour!*:={0};t>>
- else eqcar(r,'list) and
- <<plot!-contour!*:= for each x in cdr r collect
- <<x:=plot!-reval x; l:=l and adomainp x; x>>;
- l>>;
- symbolic procedure plotrange(x,d);
- begin scalar y;
- y:=assoc(x,plotranges!*);
- y:=if y then cdr y else d;
- if y=0 or null y then % return nil;
- y:={'!*INTERVAL!*, - plotmax!*, plotmax!*};
- if not eqcar(y,'!*INTERVAL!*) then
- typerr(y,"plot range");
- return {plotevalform0(rdwrap cadr y,nil) ,
- plotevalform0(rdwrap caddr y,nil)};
- end;
- symbolic procedure plot!-points(x);
- (if w then cdr w else car plot!-points!*)
- where w=assoc(x,cdr plot!-points!*);
- symbolic procedure plotseteq(u,v);
- null u and null v or car u member v
- and plotseteq(cdr u,delete(car u,v));
- symbolic procedure plotindepvars(u,v);
- if idp u then
- if member(u,v) or member(u,'(e pi))
- or u eq 'i and !*complex then v
- else u . v
- else if eqcar(u,'file) then cddr u
- else if pairp u then
- if eqcar(u,'!:dn!:) or get(car u,'dname) then v else
- % WN if get(car u,'dname) then v else
- if member(car u,'(plus minus difference times quotient expt)) or
- get(car u,'!:RD!:) or get(car u,'simpfn)
- or eqcar(getd(car u),'expr)
- then <<for each x in cdr u do v:=plotindepvars(x,v); v>>
- else typerr(u,"expression in function to plot")
- else v;
- remprop('plotshow,'stat);
-
- symbolic procedure plotshow();
- plotdriver(show);
- put('plotshow,'stat,'endstat);
- remprop('plotreset,'stat);
- symbolic procedure plotreset();
- plotdriver(reset);
- put('plotreset,'stat,'endstat);
- put('points,'plot!-do,
- function(lambda(x);car plot!-points!*:=ieval x));
- put('refine,'plot!-do,
- function(lambda(x);plot!-refine!*:=ieval x));
- endmodule; % plotsynt.
- end;
|