plotsynt.red 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. module plotsynt; % Support for the syntax of the plot command.
  2. % Author: Herbert Melenk.
  3. fluid '(bye!-actions!*);
  4. % Create .. as the infix operator if not yet done.
  5. !*msg := nil; % prevent message ".. redefined" during load
  6. newtok '( (!. !.) !*interval!*);
  7. if not(gettype '!*interval!* = 'operator) then
  8. <<
  9. precedence .., or;
  10. algebraic operator ..;
  11. put('!*interval!*,'PRTCH,'! !.!.! );
  12. >>;
  13. mkop 'point;
  14. !*msg := t;
  15. fluid '(plot!-points!* plot!-refine!* plot!-contour!*);
  16. global '(plot_xrange plot_yrange plot_zrange);
  17. share plot_xmesh,plot_ymesh,plot_xrange,plot_yrange,plot_zrange;
  18. fluid '(plotprecision!*);
  19. plotprecision!* := 0.9995;
  20. fluid '(!*show_grid test_plot);
  21. switch show_grid;
  22. switch test_plot; % for test printouts
  23. if null plotmax!* then
  24. <<
  25. load!-package 'arith;
  26. if not !!plumax then roundconstants();
  27. plotmax!* := !!plumax; % IEEE double precision
  28. >>;
  29. plotmin!*:= 1.0/plotmax!*;
  30. fluid '(plotranges!* plotfunctions!* plotstyle!* !*plotoverflow
  31. !*roundbf);
  32. put('plot,'psopfn,'ploteval);
  33. symbolic procedure ploteval u;
  34. begin scalar m,!*exp;
  35. if null plotdriver!* then
  36. rederr "no active device driver for PLOT";
  37. m:=plotrounded(nil);
  38. plot!-points!* := {20};
  39. plot!-refine!* := 8;
  40. !*plotoverflow := nil;
  41. plotranges!* := plotfunctions!* := nil;
  42. plotstyle!* := 'lines;
  43. bye!-actions!* := union('((plotreset)),bye!-actions!*);
  44. plotdriver(init);
  45. for each option in u do ploteval1 plot!-reval option;
  46. errorset('(ploteval2),t,nil);
  47. plotrounded(m);
  48. end;
  49. symbolic procedure plot!-reval u;
  50. % Protected call reval: simplify u, but don't call any
  51. % algebraic procedure.
  52. begin scalar w;
  53. w:={nil};
  54. u:=plot!-reval1(u,w);
  55. return car w and u or reval u;
  56. end;
  57. symbolic procedure plot!-reval1(u,w);
  58. if idp u then reval u else
  59. if atom u or eqcar(u,'!:dn!:) or get(car u,'dname) then u else %WN
  60. if eq (car u,'!*sq) then plot!-reval1(reval u,w) else
  61. <<if flagp(car u,'opfn) and
  62. memq(car u,'(first second rest rhs lhs)) then
  63. << u := reval u; % lex Robin Tucker % WN
  64. plot!-reval1(u,w)>> else
  65. << if flagp(car u,'opfn) then car w:=t;
  66. car u . for each q in cdr u collect plot!-reval1(q,w) >> >>;
  67. symbolic procedure ploteval1 option;
  68. begin scalar x,do;
  69. do := get(plotdriver!*,'do);
  70. if pairp option and (x:=get(car option,do))
  71. then apply(x,list option) else
  72. if pairp option and (x:=get(car option,'plot!-do))
  73. then apply(x,list option) else
  74. if eqcar(option,'equal) and (x:=get(cadr option,do))
  75. then apply(x,list caddr option) else
  76. if eqcar(option,'equal) and (x:=get(cadr option,'plot!-do))
  77. then apply(x,list caddr option)
  78. else ploteval0 option;
  79. end;
  80. symbolic procedure ploteval0 option;
  81. begin scalar l,r,opt,w;
  82. opt:=get(plotdriver!*,'option);
  83. if flagp(option,opt) then
  84. <<plotoptions!*:=option . plotoptions!*; return>>;
  85. if eqcar(option,'list) then
  86. <<option := cdr option;
  87. if option and eqcar(car option,'list) then
  88. return (plotfunctions!*:=
  89. ('points.plotpoints option).plotfunctions!*);
  90. for each o in option do ploteval0 o; return;
  91. >>;
  92. if eqcar(option,'equal) and flagp(cadr option,opt) then
  93. <<plotoptions!*:=(cadr option.caddr option). plotoptions!*;
  94. return>>;
  95. if not eqcar(option,'equal) then
  96. <<plotfunctions!*:= (nil.option) . plotfunctions!*; return>>;
  97. % Handle equations.
  98. l:=plot!-reval cadr option;
  99. r:=plot!-reval caddr option;
  100. if plot!-checkcontour(l,r) then return
  101. plotfunctions!*:=('implicit.l) . plotfunctions!* else %WN 7.3.96
  102. if not idp l then typerr(option,"illegal option in PLOT");
  103. if l memq '(size terminal view) then
  104. <<plotoptions!*:=(l.r).plotoptions!*; return>>;
  105. % iteration over a range?
  106. if eqcar(r,'times) and eqcar(caddr r,'!*interval!*)
  107. and evalnumberp(w:=cadr r) and evalgreaterp(w,0) and
  108. not evalgreaterp(w,1)
  109. then <<plot!-points!*:=append(plot!-points!*,
  110. {l.reval{'floor,{'quotient,1,w}}});
  111. r:=caddr r>>;
  112. if eqcar(r,'quotient) and eqcar(cadr r,'!*interval!*)
  113. and fixp caddr r and caddr r > 0
  114. then <<plot!-points!*:=append(plot!-points!*,{l.caddr r});
  115. r:=cadr r>>;
  116. % range?
  117. if eqcar(r,'!*interval!*) then
  118. <<r:='!*interval!* . revalnuminterval(r,t);
  119. plotranges!* := (l . r) . plotranges!*>>
  120. else
  121. plotfunctions!* := (l . r) . plotfunctions!*;
  122. end;
  123. symbolic procedure ploteval2 ();
  124. % all options are collected now;
  125. begin scalar dvar,ivars,para,impl;
  126. for each u in plotfunctions!* do
  127. <<impl:=impl or car u eq 'implicit;
  128. para:=eqcar(cdr u,'point);
  129. if impl and dvar and dvar neq car u then
  130. rederr "mixture of implicit and regular plot not supported";
  131. dvar:=car u or dvar;
  132. ivars := plotindepvars(cdr u,ivars)>>;
  133. % classify
  134. if null dvar then
  135. <<dvar:='(x y z);
  136. for each x in ivars do dvar:=delete(x,dvar);
  137. if dvar then dvar:=if 'y memq dvar then 'y else car dvar;
  138. >>;
  139. if para and length ivars=1 then plotevalpara1(car ivars) else
  140. if para and length ivars=2 then plotevalpara2(car ivars,cadr ivars)
  141. else if length ivars=1 then ploteval2x(car ivars,dvar) else
  142. if length ivars=2 then ploteval3xy(car ivars,cadr ivars,dvar) else
  143. % WN was besseres!! if length ivars=3 and impl then
  144. ploteval3impl('x,'y,'z); %car ivars,cadr ivars,caddr ivars);
  145. comment else typerr('list . for each p in plotfunctions!* collect
  146. if null car p then cdr p else
  147. {'equal,car p,cdr p},
  148. " plot option or function");
  149. plotdriver(show);
  150. end;
  151. symbolic procedure plot!-checkcontour(l,r);
  152. % true if the job is a contour expression.
  153. if length plotindepvars(l,nil)=2
  154. or length plotindepvars(l,nil)=3 then % WN 7.3.96
  155. if r=0 then <<plot!-contour!*:={0};t>>
  156. else eqcar(r,'list) and
  157. <<plot!-contour!*:= for each x in cdr r collect
  158. <<x:=plot!-reval x; l:=l and adomainp x; x>>;
  159. l>>;
  160. symbolic procedure plotrange(x,d);
  161. begin scalar y;
  162. y:=assoc(x,plotranges!*);
  163. y:=if y then cdr y else d;
  164. if y=0 or null y then % return nil;
  165. y:={'!*INTERVAL!*, - plotmax!*, plotmax!*};
  166. if not eqcar(y,'!*INTERVAL!*) then
  167. typerr(y,"plot range");
  168. return {plotevalform0(rdwrap cadr y,nil) ,
  169. plotevalform0(rdwrap caddr y,nil)};
  170. end;
  171. symbolic procedure plot!-points(x);
  172. (if w then cdr w else car plot!-points!*)
  173. where w=assoc(x,cdr plot!-points!*);
  174. symbolic procedure plotseteq(u,v);
  175. null u and null v or car u member v
  176. and plotseteq(cdr u,delete(car u,v));
  177. symbolic procedure plotindepvars(u,v);
  178. if idp u then
  179. if member(u,v) or member(u,'(e pi))
  180. or u eq 'i and !*complex then v
  181. else u . v
  182. else if eqcar(u,'file) then cddr u
  183. else if pairp u then
  184. if eqcar(u,'!:dn!:) or get(car u,'dname) then v else
  185. % WN if get(car u,'dname) then v else
  186. if member(car u,'(plus minus difference times quotient expt)) or
  187. get(car u,'!:RD!:) or get(car u,'simpfn)
  188. or eqcar(getd(car u),'expr)
  189. then <<for each x in cdr u do v:=plotindepvars(x,v); v>>
  190. else typerr(u,"expression in function to plot")
  191. else v;
  192. remprop('plotshow,'stat);
  193. symbolic procedure plotshow();
  194. plotdriver(show);
  195. put('plotshow,'stat,'endstat);
  196. remprop('plotreset,'stat);
  197. symbolic procedure plotreset();
  198. plotdriver(reset);
  199. put('plotreset,'stat,'endstat);
  200. put('points,'plot!-do,
  201. function(lambda(x);car plot!-points!*:=ieval x));
  202. put('refine,'plot!-do,
  203. function(lambda(x);plot!-refine!*:=ieval x));
  204. endmodule; % plotsynt.
  205. end;