Jspice3
doplot.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Wayne A. Christopher
5  1992 David A. Gates ( ft_xgraph() )
6  1993 Stephen R. Whiteley
7 ****************************************************************************/
8 
9 /*
10  * Plotting routines
11  */
12 
13 #include "spice.h"
14 #include "ftedefs.h"
15 #include "plotdefs.h"
16 
17 #ifdef __STDC__
18 static bool plotit(wordlist*,char*,char*);
19 static bool asciilin(struct dvlist*,bool*);
20 static void parsewl(wordlist**,bool*,bool*,bool*);
21 static bool fixlimits(struct dvlist*,double*,double*,bool);
22 static double *getlims(wordlist**,char*,int);
23 static char *getword(wordlist**,char*);
24 static bool getflag(wordlist**,char*);
25 static void compress(struct dvec*,double*,double*);
26 #else
27 static bool plotit();
28 static bool asciilin();
29 static void parsewl();
30 static bool fixlimits();
31 static double *getlims();
32 static char *getword();
33 static bool getflag();
34 static void compress();
35 #endif
36 
37 static bool sameflag;
38 
39 void
41 
42 /* asciiplot file name ... [xlimit] xhi xlo] [vs xname] */
43 wordlist *wl;
44 {
45  (void) plotit(wl, (char *) NULL, "lpr");
46  return;
47 }
48 
49 
50 /* xgraph file plotargs
51  */
52 
53 void
55 
56 wordlist *wl;
57 {
58  char *fname;
59  char buf[BSIZE_SP];
60  bool tempf = false;
61  char *devtype;
62 
63  if (wl) {
64  fname = wl->wl_word;
65  wl = wl->wl_next;
66  }
67  if (!wl) {
68  return;
69  }
70  if (cieq(fname, "temp") || cieq(fname, "tmp")) {
71  fname = smktemp("xg");
72  tempf = true;
73  }
74 
75  (void) plotit(wl, fname, "xgraph");
76  return;
77 }
78 
79 
80 void
82 
83 /* hardcopy file plotargs, or 'hardcopy file' -- with no other args this
84  * prompts the user for a window to dump to a plot file.
85  */
86 wordlist *wl;
87 {
88  ft_hardcopy(wl, NULL, true, NULL, false);
89 }
90 
91 
92 void
93 ft_hardcopy(wl, graph, copygraph, mesg, fileonly)
94 
95 /* Makes hardcopy of graph if not null. If copygraph is true, it is
96  * assumed that graph is being displayed in a window, and a copy is
97  * made. Otherwise, graph is assumed to have been created specifically
98  * for the copy, and is destroyed. No effect if graph is null.
99  */
100 wordlist *wl;
101 GRAPH *graph;
102 bool copygraph;
103 char *mesg;
104 bool fileonly;
105 {
106  char *fname, *devtype, *s;
107  char buf[BSIZE_SP], device[BSIZE_SP];
108  bool tempf = false;
109  GRAPH *tempgraph;
110  extern char *kw_hcopydev, *kw_hcopydevtype;
111 
112  *device = '\0';
113  if (!fileonly) {
114  if (!cp_getvar(kw_hcopydev, VT_STRING, device)) {
115  s = getenv("PRINTER");
116  if (s)
117  strcpy(device, s);
118  }
119  if (!*device) {
120  device[0] = 'l'; device[1] = 'p'; device[2] = '\0';
121  }
122  }
123 
124  if (wl) {
125  fname = wl->wl_word;
126  wl = wl->wl_next;
127  }
128  else {
129  fname = smktemp("hc");
130  tempf = true;
131  }
132 
133  if (!cp_getvar(kw_hcopydevtype, VT_STRING, buf)) {
134  devtype = "postscript";
135  }
136  else {
137  devtype = buf;
138  }
139 
140  if (graph) {
141 
142  if (DevSwitch(devtype)) return;
143  if (copygraph)
144  tempgraph = CopyGraph(graph);
145  else
146  tempgraph = graph;
147  tempgraph->devdep = copy(fname);
148  if (DevNewViewport(tempgraph)) {
149  DestroyGraph(tempgraph->graphid);
150  DevSwitch(NULL);
151  return;
152  }
153  (*tempgraph->redraw)(tempgraph);
154  PushGraphContext(tempgraph);
155  DevHalt();
156  PopGraphContext();
157  DestroyGraph(tempgraph->graphid);
158  DevSwitch(NULL);
159  }
160  else {
161  if (!wl) {
162  wl = outmenuprompt("which variable ? ");
163  if (!wl)
164  return;
165  }
166  if (DevSwitch(devtype)) return;
167 
168  if (!plotit(wl, fname, (char *) NULL)) {
169  DevSwitch(NULL); /* remember to switch back */
170  return;
171  }
172 
173  DevSwitch(NULL);
174  }
175 
176  ft_makehardcopy(copygraph ? graph : NULL, fname, devtype, device, mesg);
177 
178  if (tempf) {
179  if (*device)
180  (void) unlink(fname);
181  txfree(fname);
182  }
183 
184  return;
185 }
186 
187 
188 void
190 
191 /* plot name ... [xl[imit]] xlo xhi] [yl[imit ylo yhi] [vs xname] */
192 wordlist *wl;
193 {
194  (void) plotit(wl, (char *) NULL, (char *) NULL);
195  return;
196 }
197 
198 
199 struct grstuff {
200  double xlim[2];
201  double ylim[2];
202  double xcompress;
203  double xindices[2];
204  double xdelta;
205  double ydelta;
206  bool xlimset;
207  bool ylimset;
208  bool xcompset;
209  bool xindset;
210  bool xdeltaset;
211  bool ydeltaset;
212  bool nointerp;
213  int gtype;
214  int ptype;
215  char *xlabel;
216  char *ylabel;
217  char *title;
218  char *commandline;
219 };
220 static struct grstuff grs;
221 
222 
223 static bool
224 plotit(wl, hcopy, devname)
225 
226 /* The common routine for all plotting commands. This does hardcopy
227  * and graphics plotting.
228  */
229 wordlist *wl;
230 char *hcopy, *devname;
231 {
232  GRAPH *graph;
233  struct pnode *n, *names;
234  struct dvec *d, *lv;
235  struct dvlist *dl0, *dl, *tl, *dn, *lastv;
236  struct grinit gr;
237  double ylims[2], xlims[2];
238  int i;
239  bool sameflag, gfound, pfound, oneval = false;
240  char buf[BSIZE_SP];
241  wordlist *ww;
242 
243  parsewl(&wl,&sameflag,&gfound,&pfound);
244 
245  if (!wl) {
246  fprintf(cp_err, "Error: no vectors given\n");
247  return (false);
248  }
249 
250  /* If we have forms like v(1) vs -v(2), force a unary - by converting
251  * to v(1) vs --v(2)
252  */
253 
254  for (ww = wl; ww; ww = ww->wl_next) {
255  if (eq(ww->wl_word,"vs")) {
256  ww = ww->wl_next;
257  if (ww && *ww->wl_word == '-' && *(ww->wl_word+1) != '-') {
258  sprintf(buf,"-%s",ww->wl_word);
259  txfree(ww->wl_word);
260  ww->wl_word = copy(buf);
261  }
262  }
263  }
264 
265  /* Now parse the vectors. We have a list of the form
266  * "a b vs c d e vs f g h". Since it's a bit of a hassle for
267  * us to parse the vector boundaries here, we do this -- call
268  * ft_getpnames() without the check flag, and then look for 0-length
269  * vectors with the name "vs"... This is a sort of a gross hack,
270  * since we have to check for 0-length vectors ourselves after
271  * evaulating the pnodes...
272  */
273 
274  names = ft_getpnames(wl, false);
275  if (names == NULL)
276  return (false);
277 
278  /* hack! have to fool ft_evaluate() */
279  for (n = names; n; n = n->pn_next) {
280  d = n->pn_value;
281  if (d && d->v_length == 0 && eq(d->v_name,"vs"))
282  d->v_length = -1;
283  }
284 
285  dl0 = ft_dvlist(names);
286  if (dl0 == NULL)
287  return (false);
288 
289  tl = NULL;
290  lastv = NULL;
291  for (dl = dl0; dl; dl = dn) {
292  dn = dl->dl_next;
293  d = dl->dl_dvec;
294  if (d->v_length == -1 && eq(d->v_name,"vs")) {
295  d->v_length = 0; /* just in case */
296  if (!tl || !dn) {
297  fprintf(cp_err, "Error: misplaced vs arg\n");
298  vec_dlfree(dl0);
299  return (false);
300  }
301  if (!lastv)
302  tl = dl0;
303  else
304  tl = lastv->dl_next;
305  for ( ; tl != dl; lastv = tl, tl = tl->dl_next)
306  tl->dl_dvec->v_scale = dn->dl_dvec;
307  dn = dn->dl_next;
308  lastv->dl_next = dn;
309  tl = NULL;
310  txfree((char*)dl);
311  txfree((char*)dn);
312  }
313  else
314  tl = dl;
315  }
316 
317  /* Now check for 0-length vectors. */
318  for (dl = dl0; dl; dl = dl->dl_next) {
319  if (!dl->dl_dvec->v_length) {
320  fprintf(cp_err, "Error: %s: no such vector\n",
321  dl->dl_dvec->v_name);
322  vec_dlfree(dl0);
323  return (false);
324  }
325  }
326 
327  if (devname && (eq(devname,"xgraph") || eq(devname,"lpr"))) {
328  /* If there are higher dimensional vectors, transform them into a
329  * family of vectors.
330  */
331  tl = NULL;
332  for (dl = dl0; dl; dl = dn) {
333  dn = dl->dl_next;
334  d = dl->dl_dvec;
335  if (d->v_numdims > 1) {
336  lv = vec_mkfamily(d);
337  if (lv && lv->v_link2) {
338  if (!tl)
339  dl0 = lv->v_link2;
340  else
341  tl->dl_next = lv->v_link2;
342  for (dl = lv->v_link2; dl->dl_next; dl = dl->dl_next);
343  dl->dl_next = dn;
344  tl = dl;
345  }
346  else {
347  if (!tl)
348  dl0 = dn;
349  else
350  tl->dl_next = dn;
351  }
352  txfree((char*)dl);
353  }
354  else
355  tl = dl;
356  }
357  }
358 
359  /* Now fill in the scales for vectors who aren't already fixed up. */
360  for (dl = dl0; dl; dl = dl->dl_next) {
361  d = dl->dl_dvec;
362  if (!d->v_scale) {
363  if (d->v_plot->pl_scale)
364  d->v_scale = d->v_plot->pl_scale;
365  else
366  d->v_scale = d;
367  }
368  }
369 
370  /* See if the log flag is set anywhere... */
371  if (!gfound) {
372  for (dl = dl0; dl; dl = dl->dl_next) {
373  d = dl->dl_dvec;
374  if (d->v_scale && (d->v_scale->v_gridtype == GRID_XLOG))
375  grs.gtype = GRID_XLOG;
376  }
377  for (dl = dl0; dl; dl = dl->dl_next) {
378  d = dl->dl_dvec;
379  if (d->v_gridtype == GRID_YLOG) {
380  if ((grs.gtype == GRID_XLOG) ||
381  (grs.gtype == GRID_LOGLOG))
383  else
384  grs.gtype = GRID_YLOG;
385  }
386  }
387  for (dl = dl0; dl; dl = dl->dl_next) {
388  d = dl->dl_dvec;
389  if (d->v_gridtype == GRID_SMITH) {
390  grs.gtype = GRID_SMITH;
391  break;
392  }
393  else if (d->v_gridtype == GRID_POLAR) {
394  grs.gtype = GRID_POLAR;
395  break;
396  }
397  }
398  }
399 
400  /* See if there are any default plot types... Here, like above, we
401  * don't do entirely the best thing when there is a mixed set of
402  * default plot types...
403  */
404  if (!sameflag && !pfound) {
405  grs.ptype = PLOT_LIN;
406  for (dl = dl0; dl; dl = dl->dl_next) {
407  d = dl->dl_dvec;
408  if (d->v_plottype != PLOT_LIN) {
409  grs.ptype = d->v_plottype;
410  break;
411  }
412  }
413  }
414 
415  /* Check and see if this is pole zero stuff. */
416  if ((dl0->dl_dvec->v_type == SV_POLE) ||
417  (dl0->dl_dvec->v_type == SV_ZERO))
418  oneval = true;
419 
420  for (dl = dl0; dl; dl = dl->dl_next) {
421  d = dl->dl_dvec;
422  if (((d->v_type == SV_POLE) || (d->v_type == SV_ZERO)) !=
423  oneval ? 1 : 0) {
424  fprintf(cp_err,
425 "Error: plot must be either all pole-zero or contain no poles or zeros\n");
426  return (false);
427  }
428  }
429 
430  if ((grs.gtype == GRID_POLAR) || (grs.gtype == GRID_SMITH))
431  oneval = true;
432 
433  /* If we are plotting scalars, make sure there is enough
434  * data to fit on the screen.
435  */
436 
437  for (dl = dl0; dl; dl = dl->dl_next) {
438  d = dl->dl_dvec;
439  if (d->v_length != d->v_scale->v_length)
440  plot_extend(d, d->v_scale->v_length);
441  }
442 
443  /* Now patch up each vector with the compression and the index
444  * selection.
445  */
446  if (grs.xcompset || grs.xindset) {
447  for (dl = dl0; dl; dl = dl->dl_next) {
448  d = dl->dl_dvec;
450  d->v_scale = vec_copy(d->v_scale);
451  vec_newtemp(d->v_scale);
453  }
454  }
455 
456  if (!fixlimits(dl0,xlims,ylims,oneval)) {
457  vec_dlfree(dl0);
458  return (false);
459  }
460 
461  gr.xlims = xlims;
462  gr.ylims = ylims;
463  gr.plotname = grs.title ? grs.title : dl0->dl_dvec->v_plot->pl_title;
464  gr.hcopy = hcopy;
465  gr.xdelta = grs.xdeltaset ? grs.xdelta : 0.0;
466  gr.ydelta = grs.ydeltaset ? grs.ydelta : 0.0;
467  gr.gridtype = grs.gtype;
468  gr.plottype = grs.ptype;
469  gr.xlabel = grs.xlabel;
470  gr.ylabel = grs.ylabel;
471  gr.pname = plot_cur->pl_typename;
473  gr.nointerp = grs.nointerp;
474 
475  /* See if there is one type we can give for the y scale... */
476  gr.ytype = dl0->dl_dvec->v_type;
477  for (dl = dl0->dl_next; dl; dl = dl->dl_next) {
478  if (dl->dl_dvec->v_type != gr.ytype) {
479  gr.ytype = SV_NOTYPE;
480  break;
481  }
482  }
483  for (dl = dl0, i = 0; dl; dl = dl->dl_next, i++) ;
484  gr.nplots = i;
485 
486  /* Figure out the X name and the X type. This is sort of bad... */
487  gr.xname = oneval ? NULL : dl0->dl_dvec->v_scale->v_name;
488  gr.xtype = dl0->dl_dvec->v_scale->v_type;
489 
490  if (devname) {
491  if (eq(devname, "xgraph")) {
492  /* Interface to XGraph-11 Plot Program */
493  ft_xgraph(dl0,(char*)&gr);
494  vec_dlfree(dl0);
495  return (true);
496  }
497  if (eq(devname, "lpr")) {
498  /* yecch, line printer plot */
499  if (!asciilin(dl0,&gr.nointerp)) {
500  vec_dlfree(dl0);
501  return (false);
502  }
503  ft_agraf(dl0, (char*)&gr);
504  vec_dlfree(dl0);
505  return (true);
506  }
507  }
508 
509  /* The graph->plotdata dveclist as returned from gr_init contains
510  * pointers to the actual dvecs, for iplot. Thus, we must copy
511  * them before destroying the graph.
512  */
513  graph = gr_init(dl0,(char*)&gr);
514  if (graph == NULL)
515  return (false);
516 
517  /* copy the dveclist, then free the old structures */
518  graph->plotdata =
519  (*graph->copydata)(graph->plotdata);
520  vec_dlfree(dl0);
521 
522  if (!dispdev->windows) {
523  PushGraphContext(graph);
524  gr_end();
525  DevHalt();
526  PopGraphContext();
527  DestroyGraph(graph->graphid);
528  }
529  return (true);
530 }
531 
532 
533 static bool
535 
536 struct dvlist *dl0;
537 bool *nointerp;
538 /* check if we should (can) linearize */
539 {
540  struct plot *p = plot_cur;
541  struct dvec *d, *newv_scale;
542  struct dvlist *dl;
543  double *newdata, *newscale;
544  double ttime;
545  double dummy;
546  int i, newlen;
547 
548  if (!( !p || !p->pl_scale || !isreal(p->pl_scale) ||
549  !ciprefix("tran", p->pl_typename) ||
550  ((p->pl_stop - p->pl_start)*p->pl_step <= 0.0) ||
551  ((p->pl_stop - p->pl_start) < p->pl_step) )) {
552 
553  newlen = (p->pl_stop - p->pl_start) / p->pl_step + 1.5;
554 
555  newscale = (double *) tmalloc(newlen * sizeof(double));
556  d = dl0->dl_dvec;
557 
558  newv_scale = alloc(struct dvec);
559  newv_scale->v_flags = d->v_scale->v_flags;
560  newv_scale->v_type = d->v_scale->v_type;
561  newv_scale->v_gridtype = d->v_scale->v_gridtype;
562  newv_scale->v_length = newlen;
563  newv_scale->v_name = copy(d->v_scale->v_name);
564  newv_scale->v_realdata = newscale;
565  vec_newtemp(newv_scale);
566 
567  for (i = 0, ttime = p->pl_start; i < newlen;
568  i++, ttime += p->pl_step)
569  newscale[i] = ttime;
570 
571  for (dl = dl0; dl; dl = dl->dl_next) {
572  d = dl->dl_dvec;
573  newdata = (double *) tmalloc(newlen * sizeof (double));
574 
575  if (!ft_interpolate(d->v_realdata, newdata,
577  newscale, newlen, 1)) {
578  fprintf(cp_err,
579  "Error: can't interpolate %s\n", d->v_name);
580  return(false);
581  }
582 
583  tfree(d->v_realdata);
584  d->v_realdata = newdata;
585 
586  /* Why go to all this trouble if agraf ignores it? */
587  *nointerp = true;
588  }
589  dl0->dl_dvec->v_scale = newv_scale;
590  }
591  return (true);
592 }
593 
594 
595 struct sPlotFlags {
596  char *name;
597  int type;
598 };
599 static struct sPlotFlags gtypes[] = {
600  {"lingrid",GRID_LIN},
601  {"loglog",GRID_LOGLOG},
602  {"nogrid",GRID_NONE},
603  {"xlog",GRID_XLOG},
604  {"ylog",GRID_YLOG},
605  {"polar",GRID_POLAR},
606  {"smith",GRID_SMITH}
607 };
608 #define NumGrTypes sizeof(gtypes)/sizeof(struct sPlotFlags)
609 
610 static struct sPlotFlags ptypes[] = {
611  {"linplot",PLOT_LIN},
612  {"combplot",PLOT_COMB},
613  {"pointplot",PLOT_POINT}
614 };
615 #define NumPlTypes sizeof(ptypes)/sizeof(struct sPlotFlags)
616 
617 
618 
619 static void
620 parsewl(pwl,sameflag,gfound,pfound)
621 
622 /* Parse the plot command wordlist. */
623 wordlist **pwl;
624 bool *sameflag, *gfound,*pfound;
625 {
626  double *dd;
627  int i;
628  wordlist *wwl;
629  char buf[BSIZE_SP], *s;
630  extern char *kw_gridstyle, *kw_plotstyle;
631 
632  *gfound = false;
633  *pfound = false;
634 
635  /* First get the command line, without the limits. */
636  wwl = wl_copy(*pwl);
637  (void) getlims(&wwl, "xl", 2);
638  (void) getlims(&wwl, "xlimit", 2);
639  (void) getlims(&wwl, "yl", 2);
640  (void) getlims(&wwl, "ylimit", 2);
641  s = wl_flatten(wwl);
642  (void) sprintf(buf, "plot %s", s);
644  grs.commandline = copy(buf);
645  wl_free(wwl);
646  txfree(s);
647 
648  /* Now extract all the parameters. */
649 
650  *pwl = wl_copy(*pwl);
651 
652  *sameflag = getflag(pwl, "samep");
653 
654  if (!*sameflag || !grs.xlimset) {
655  dd = getlims(pwl, "xl", 2);
656  if (!dd)
657  dd = getlims(pwl, "xlimit", 2);
658  if (dd) {
659  grs.xlim[0] = dd[0];
660  grs.xlim[1] = dd[1];
661  grs.xlimset = true;
662  }
663  else
664  grs.xlimset = false;
665  }
666  else {
667  (void) getlims(pwl, "xl", 2);
668  (void) getlims(pwl, "xlimit", 2);
669  }
670 
671  if (!*sameflag || !grs.ylimset) {
672  dd = getlims(pwl, "yl", 2);
673  if (!dd)
674  dd = getlims(pwl, "ylimit", 2);
675  if (dd) {
676  grs.ylim[0] = dd[0];
677  grs.ylim[1] = dd[1];
678  grs.ylimset = true;
679  }
680  else
681  grs.ylimset = false;
682  }
683  else {
684  (void) getlims(pwl, "yl", 2);
685  (void) getlims(pwl, "ylimit", 2);
686  }
687 
688  if (!*sameflag || !grs.xcompset) {
689  dd = getlims(pwl, "xcompress", 1);
690  if (!dd)
691  dd = getlims(pwl, "xcomp", 1);
692  if (dd) {
693  grs.xcompress = dd[0];
694  grs.xcompset = true;
695  }
696  else
697  grs.xcompset = false;
698  }
699  else {
700  (void) getlims(pwl, "xcompress", 1);
701  (void) getlims(pwl, "xcomp", 1);
702  }
703 
704  if (!*sameflag || !grs.xindset) {
705  dd = getlims(pwl, "xindices", 2);
706  if (!dd)
707  dd = getlims(pwl, "xind", 2);
708  if (dd) {
709  grs.xindices[0] = dd[0];
710  grs.xindices[1] = dd[1];
711  grs.xindset = true;
712  }
713  else
714  grs.xindset = false;
715  }
716  else {
717  (void) getlims(pwl, "xindices", 2);
718  (void) getlims(pwl, "xind", 2);
719  }
720 
721  if (!*sameflag || !grs.xdeltaset) {
722  dd = getlims(pwl, "xdelta", 1);
723  if (!dd)
724  dd = getlims(pwl, "xdel", 1);
725  if (dd) {
726  grs.xdelta = dd[0];
727  grs.xdeltaset = true;
728  }
729  else
730  grs.xdeltaset = false;
731  }
732  else {
733  (void) getlims(pwl, "xdelta", 1);
734  (void) getlims(pwl, "xdel", 1);
735  }
736  if (!*sameflag || !grs.ydeltaset) {
737  dd = getlims(pwl, "ydelta", 1);
738  if (!dd)
739  dd = getlims(pwl, "ydel", 1);
740  if (dd) {
741  grs.ydelta = dd[0];
742  grs.ydeltaset = true;
743  }
744  else
745  grs.ydeltaset = false;
746  }
747  else {
748  (void) getlims(pwl, "ydelta", 1);
749  (void) getlims(pwl, "ydel", 1);
750  }
751 
752  /* Get the grid type and the point type. Note we can't do if-else
753  * here because we want to catch all the grid types.
754  */
755  for (i = 0; i < NumGrTypes; i++) {
756  if (getflag(pwl, gtypes[i].name)) {
757  if (*gfound)
758  fprintf(cp_err,
759  "Warning: too many grid types given\n");
760  else {
761  grs.gtype = gtypes[i].type;
762  *gfound = true;
763  }
764  }
765  }
766 
767  if (!*sameflag && !*gfound) {
768  if (cp_getvar(kw_gridstyle, VT_STRING, buf)) {
769  for (i = 0; i < NumGrTypes; i++) {
770  if (eq(buf, gtypes[i].name)) {
771  grs.gtype = gtypes[i].type;
772  break;
773  }
774  }
775  if (i == NumGrTypes) {
776  fprintf(cp_err, "Warning: strange grid type %s\n", buf);
777  grs.gtype = GRID_LIN;
778  }
779  *gfound = true;
780  }
781  else
782  grs.gtype = GRID_LIN;
783  }
784 
785  /* Now get the point type. */
786 
787  for (i = 0; i < NumPlTypes; i++) {
788  if (getflag(pwl, ptypes[i].name)) {
789  if (*pfound)
790  fprintf(cp_err,
791  "Warning: too many plot types given\n");
792  else {
793  grs.ptype = ptypes[i].type;
794  *pfound = true;
795  }
796  }
797  }
798 
799  if (!*sameflag && !*pfound) {
800  if (cp_getvar(kw_plotstyle, VT_STRING, buf)) {
801  for (i = 0; i < NumGrTypes; i++) {
802  if (eq(buf, ptypes[i].name)) {
803  grs.ptype = ptypes[i].type;
804  break;
805  }
806  }
807  if (i == NumPlTypes) {
808  fprintf(cp_err, "Warning: strange plot type %s\n", buf);
809  grs.ptype = PLOT_LIN;
810  }
811  *pfound = true;
812  }
813  else
814  grs.ptype = PLOT_LIN;
815  }
816 
817  s = getword(pwl, "xlabel");
818  if (!*sameflag || (!grs.xlabel && s)) {
819  txfree(grs.xlabel);
820  grs.xlabel = s;
821  }
822  else
823  txfree(s);
824 
825  s = getword(pwl, "ylabel");
826  if (!*sameflag || (!grs.ylabel && s)) {
827  txfree(grs.ylabel);
828  grs.ylabel = s;
829  }
830  else
831  txfree(s);
832 
833  s = getword(pwl, "title");
834  if (!*sameflag || (!grs.title && s)) {
835  txfree(grs.title);
836  grs.title = s;
837  }
838  else
839  txfree(s);
840 
841 
842  if (!*sameflag)
843  grs.nointerp = getflag(pwl, "nointerp");
844  else if (getflag(pwl, "nointerp"))
845  grs.nointerp = true;
846 }
847 
848 
849 static bool
850 fixlimits(dl0,xlims,ylims,oneval)
851 
852 struct dvlist *dl0;
853 double *xlims,*ylims;
854 bool oneval;
855 {
856  double *dd, tt, mx, my, rad;
857  struct dvlist *dl;
858  struct dvec *d;
859 
860  /* Figure out the proper x- and y-axis limits. */
861  if (grs.ylimset) {
862  if (grs.gtype == GRID_SMITH) {
863  if (grs.xlimset) {
864  SMITH_tfm(grs.xlim[0], grs.ylim[0], &tt, &ylims[0]);
865  SMITH_tfm(grs.xlim[1], grs.ylim[1], &tt, &ylims[1]);
866  }
867  else {
868  SMITH_tfm(0.0, grs.ylim[0], &tt, &ylims[0]);
869  SMITH_tfm(0.0, grs.ylim[1], &tt, &ylims[1]);
870  }
871  }
872  else {
873  ylims[0] = grs.ylim[0];
874  ylims[1] = grs.ylim[1];
875  }
876  }
877  else if (oneval) {
878  ylims[0] = 1;
879  ylims[1] = -1;
880  for (dl = dl0; dl; dl = dl->dl_next) {
881  d = dl->dl_dvec;
882  if (grs.gtype == GRID_SMITH) {
883  dd = ft_SMITHminmax(d, true);
884  if (dd[0] < 0.0)
885  dd[0] *= 1.1;
886  else
887  dd[0] *= 0.9;
888  if (dd[1] >= 0.0)
889  dd[1] *= 1.1;
890  else
891  dd[1] *= 0.9;
892  }
893  else
894  dd = ft_minmax(d, true);
895 
896  if (ylims[0] > ylims[1]) {
897  ylims[0] = dd[0];
898  ylims[1] = dd[1];
899  }
900  else {
901  if (dd[0] < ylims[0]) ylims[0] = dd[0];
902  if (dd[1] > ylims[1]) ylims[1] = dd[1];
903  }
904  }
905  }
906  else {
907  ylims[0] = 1;
908  ylims[1] = -1;
909  for (dl = dl0; dl; dl = dl->dl_next) {
910  d = dl->dl_dvec;
911  dd = ft_minmax(d, true);
912  if (ylims[0] > ylims[1]) {
913  ylims[0] = dd[0];
914  ylims[1] = dd[1];
915  }
916  else {
917  if (dd[0] < ylims[0]) ylims[0] = dd[0];
918  if (dd[1] > ylims[1]) ylims[1] = dd[1];
919  }
920  }
921 
922  /* XXX */
923  for (dl = dl0; dl; dl = dl->dl_next) {
924  d = dl->dl_dvec;
925  if (d->v_flags & VF_MINGIVEN)
926  if (ylims[0] < d->v_minsignal)
927  ylims[0] = d->v_minsignal;
928  if (d->v_flags & VF_MAXGIVEN)
929  if (ylims[1] > d->v_maxsignal)
930  ylims[1] = d->v_maxsignal;
931  }
932  }
933 
934  if (grs.xlimset) {
935  if (grs.gtype == GRID_SMITH) {
936  if (grs.ylimset) {
937  SMITH_tfm(grs.xlim[0], grs.ylim[0], &xlims[0], &tt);
938  SMITH_tfm(grs.xlim[1], grs.ylim[1], &xlims[1], &tt);
939  }
940  else {
941  SMITH_tfm(grs.xlim[0], 0.0, &xlims[0], &tt);
942  SMITH_tfm(grs.xlim[1], 0.0, &xlims[1], &tt);
943  }
944  }
945  else {
946  xlims[0] = grs.xlim[0];
947  xlims[1] = grs.xlim[1];
948  }
949  }
950  else if (oneval) {
951  xlims[0] = 1;
952  xlims[1] = -1;
953  for (dl = dl0; dl; dl = dl->dl_next) {
954  d = dl->dl_dvec;
955  if (grs.gtype == GRID_SMITH) {
956  dd = ft_SMITHminmax(d, false);
957  if (dd[0] < 0.0)
958  dd[0] *= 1.1;
959  else
960  dd[0] *= 0.9;
961  if (dd[1] >= 0.0)
962  dd[1] *= 1.1;
963  else
964  dd[1] *= 0.9;
965  }
966  else
967  dd = ft_minmax(d, false);
968 
969  if (xlims[0] > xlims[1]) {
970  xlims[0] = dd[0];
971  xlims[1] = dd[1];
972  }
973  else {
974  if (dd[0] < xlims[0]) xlims[0] = dd[0];
975  if (dd[1] > xlims[1]) xlims[1] = dd[1];
976  }
977  }
978  }
979  else {
980  xlims[0] = 1;
981  xlims[1] = -1;
982  for (dl = dl0; dl; dl = dl->dl_next) {
983  d = dl->dl_dvec;
984  dd = ft_minmax(d->v_scale, true);
985  if (xlims[0] > xlims[1]) {
986  xlims[0] = dd[0];
987  xlims[1] = dd[1];
988  }
989  else {
990  if (dd[0] < xlims[0]) xlims[0] = dd[0];
991  if (dd[1] > xlims[1]) xlims[1] = dd[1];
992  }
993  }
994  for (dl = dl0; dl; dl = dl->dl_next) {
995  d = dl->dl_dvec;
996  if (d->v_scale->v_flags & VF_MINGIVEN)
997  if (xlims[0] < d->v_scale->v_minsignal)
998  xlims[0] = d->v_scale->v_minsignal;
999  if (d->v_scale->v_flags & VF_MAXGIVEN)
1000  if (xlims[1] > d->v_scale->v_maxsignal)
1001  xlims[1] = d->v_scale->v_maxsignal;
1002  }
1003  }
1004 
1005  /* Do some coercion of the limits to make them reasonable. */
1006  if ((xlims[0] == 0) && (xlims[1] == 0)) {
1007  xlims[0] = -1.0;
1008  xlims[1] = 1.0;
1009  }
1010  if ((ylims[0] == 0) && (ylims[1] == 0)) {
1011  ylims[0] = -1.0;
1012  ylims[1] = 1.0;
1013  }
1014  if (xlims[0] > xlims[1]) {
1015  tt = xlims[1];
1016  xlims[1] = xlims[0];
1017  xlims[0] = tt;
1018  }
1019  if (ylims[0] > ylims[1]) {
1020  tt = ylims[1];
1021  ylims[1] = ylims[0];
1022  ylims[0] = tt;
1023  }
1024  if (xlims[0] == xlims[1]) {
1025  xlims[0] *= (xlims[0] > 0) ? 0.9 : 1.1;
1026  xlims[1] *= (xlims[1] > 0) ? 1.1 : 0.9;
1027  }
1028  if (ylims[0] == ylims[1]
1029  || fabs(ylims[0])/(ylims[1]-ylims[0]) > 1.0e9
1030  || fabs(ylims[1])/(ylims[1]-ylims[0]) > 1.0e9) {
1031  ylims[0] *= (ylims[0] > 0) ? 0.9 : 1.1;
1032  ylims[1] *= (ylims[1] > 0) ? 1.1 : 0.9;
1033  }
1034 
1035  /* Now shrink the limits very slightly -- this helps prevent round-off
1036  * error from doing bad things.
1037  */
1038  if (grs.gtype != GRID_LOGLOG && grs.gtype != GRID_XLOG
1039  && grs.gtype != GRID_POLAR && grs.gtype != GRID_SMITH) {
1040  tt = xlims[1] - xlims[0];
1041  xlims[0] += tt * 0.001;
1042  xlims[1] -= tt * 0.001;
1043  }
1044  if (grs.gtype != GRID_LOGLOG && grs.gtype != GRID_YLOG
1045  && grs.gtype != GRID_POLAR && grs.gtype != GRID_SMITH) {
1046  tt = ylims[1] - ylims[0];
1047  ylims[0] += tt * 0.001;
1048  ylims[1] -= tt * 0.001;
1049  }
1050 
1051  if ((xlims[0] < 0.0) && ((grs.gtype == GRID_XLOG) ||
1052  (grs.gtype == GRID_LOGLOG))) {
1053  fprintf(cp_err,
1054  "Error: X values must be >= 0 for log scale\n");
1055  return (false);
1056  }
1057  if ((ylims[0] < 0.0) && ((grs.gtype == GRID_YLOG) ||
1058  (grs.gtype == GRID_LOGLOG))) {
1059  fprintf(cp_err,
1060  "Error: Y values must be >= 0 for log scale\n");
1061  return (false);
1062  }
1063 
1064  /* Fix the plot limits for smith and polar grids. */
1065  if (!grs.xlimset && !grs.ylimset && (grs.gtype == GRID_POLAR)) {
1066  /* (0,0) must be in the center of the screen. */
1067  mx = (fabs(xlims[0]) > fabs(xlims[1])) ? fabs(xlims[0]) :
1068  fabs(xlims[1]);
1069  my = (fabs(ylims[0]) > fabs(ylims[1])) ? fabs(ylims[0]) :
1070  fabs(ylims[1]);
1071  rad = (mx > my) ? mx : my;
1072  /* rad = sqrt(mx * mx + my * my); */
1073  xlims[0] = - rad;
1074  xlims[1] = rad;
1075  ylims[0] = - rad;
1076  ylims[1] = rad;
1077  }
1078  else if (!grs.xlimset && !grs.ylimset && (grs.gtype == GRID_SMITH)) {
1079  mx = (fabs(xlims[0]) > fabs(xlims[1])) ? fabs(xlims[0]) :
1080  fabs(xlims[1]);
1081  my = (fabs(ylims[0]) > fabs(ylims[1])) ? fabs(ylims[0]) :
1082  fabs(ylims[1]);
1083  rad = (mx > my) ? mx : my;
1084 #ifdef notdef
1085  /* XXX */
1086  xlims[0] = - rad;
1087  xlims[1] = rad;
1088  ylims[0] = - rad;
1089  ylims[1] = rad;
1090 #endif
1091  xlims[0] = -1.0;
1092  xlims[1] = 1.0;
1093  ylims[0] = -1.0;
1094  ylims[1] = 1.0;
1095  }
1096  return (true);
1097 }
1098 
1099 
1100 static double *
1101 getlims(wl, name, number)
1102 
1103 /* This routine gets parameters from the command line, which are of the
1104  * form "name number ..." It returns static data. number <= 2.
1105  */
1106 wordlist **wl;
1107 char *name;
1108 int number;
1109 {
1110  double *td;
1111  wordlist *beg, *wk;
1112  char *ss;
1113  int n;
1114  static double d[2];
1115 
1116  for (beg = *wl; beg; beg = beg->wl_next) {
1117  if (eq(beg->wl_word, name)) {
1118  wk = beg;
1119  if (number) {
1120  for (n = 0; n < number; n++) {
1121  wk = wk->wl_next;
1122  if (!wk) {
1123  fprintf(cp_err,
1124  "Syntax error.\n");
1125  return (NULL);
1126  }
1127  ss = wk->wl_word;
1128  td = ft_numparse(&ss, false);
1129  if (td == NULL)
1130  goto bad;
1131  d[n] = *td;
1132  }
1133  }
1134  else
1135  d[0] = 1.0;
1136 
1137  if (beg->wl_prev)
1138  beg->wl_prev->wl_next = wk->wl_next;
1139  if (wk->wl_next)
1140  wk->wl_next->wl_prev = beg->wl_prev;
1141  if (beg == *wl)
1142  *wl = wk->wl_next;
1143  wk->wl_next = NULL;
1144  wl_free(beg);
1145  return (d);
1146  }
1147  }
1148  return (NULL);
1149 bad:
1150  fprintf(cp_err, "Error: bad %s parameters.\n", name);
1151  return (NULL);
1152 }
1153 
1154 
1155 static char *
1156 getword(wl, name)
1157 
1158 /* Return a parameter of the form "xlabel foo" */
1159 wordlist **wl;
1160 char *name;
1161 {
1162  wordlist *beg;
1163  char *s;
1164 
1165  for (beg = *wl; beg; beg = beg->wl_next) {
1166  if (eq(beg->wl_word, name)) {
1167  if (!beg->wl_next) {
1168  fprintf(cp_err, "Syntax error.\n");
1169  return (NULL);
1170  }
1171  s = copy(beg->wl_next->wl_word);
1172  if (beg->wl_prev)
1173  beg->wl_prev->wl_next = beg->wl_next->wl_next;
1174  if (beg->wl_next->wl_next)
1175  beg->wl_next->wl_next->wl_prev = beg->wl_prev;
1176  if (beg == *wl)
1177  *wl = beg->wl_next->wl_next;
1178  beg->wl_next->wl_next = NULL;
1179  wl_free(beg);
1180  return (s);
1181  }
1182  }
1183  return (NULL);
1184 }
1185 
1186 
1187 static bool
1188 getflag(wl, name)
1189 
1190 /* Check for and remove a one-word keyword. */
1191 wordlist **wl;
1192 char *name;
1193 {
1194  wordlist *beg;
1195 
1196  for (beg = *wl; beg; beg = beg->wl_next) {
1197  if (eq(beg->wl_word, name)) {
1198  if (beg->wl_prev)
1199  beg->wl_prev->wl_next = beg->wl_next;
1200  if (beg->wl_next)
1201  beg->wl_next->wl_prev = beg->wl_prev;
1202  if (beg = *wl)
1203  *wl = beg->wl_next;
1204  txfree(beg->wl_word);
1205  txfree((char*)beg);
1206  return (true);
1207  }
1208  }
1209  return (false);
1210 }
1211 
1212 
1213 void
1214 plot_extend(v, length)
1215 
1216 /* Extend a data vector to length by replicating the
1217  * last element, or truncate it if it is too long.
1218  */
1219 struct dvec *v;
1220 int length;
1221 {
1222  int i;
1223  complex c, *oc;
1224  double d, *od;
1225 
1226  if (v->v_length == length)
1227  return;
1228  if (v->v_length > length) {
1229  v->v_length = length;
1230  return;
1231  }
1232  if (isreal(v)) {
1233  od = v->v_realdata;
1234  v->v_realdata = (double *) tmalloc(length * sizeof (double));
1235  for (i = 0; i < v->v_length; i++)
1236  v->v_realdata[i] = od[i];
1237  d = od[--i];
1238  while (i < length)
1239  v->v_realdata[i++] = d;
1240  tfree(od);
1241  }
1242  else {
1243  oc = v->v_compdata;
1244  v->v_compdata = (complex *) tmalloc(length * sizeof (complex));
1245  for (i = 0; i < v->v_length; i++) {
1246  realpart(&v->v_compdata[i]) = realpart(&oc[i]);
1247  imagpart(&v->v_compdata[i]) = imagpart(&oc[i]);
1248  }
1249  realpart(&c) = realpart(&oc[--i]);
1250  imagpart(&c) = imagpart(&oc[i]);
1251  while (i < length) {
1252  realpart(&v->v_compdata[i]) = realpart(&c);
1253  imagpart(&v->v_compdata[i++]) = imagpart(&c);
1254  tfree(oc);
1255  }
1256  }
1257  v->v_length = length;
1258  return;
1259 }
1260 
1261 
1262 static void
1263 compress(d, xcomp, xind)
1264 
1265 /* Collapse every *xcomp elements into one, and use only the elements
1266  * between xind[0] and xind[1]. Do this for each block of a multi-
1267  * dimensional vector.
1268  */
1269 struct dvec *d;
1270 double *xcomp, *xind;
1271 {
1272  int cfac, ihi, ilo, newlen, i, j, blocks, bsize;
1273  double *dd;
1274  complex *cc;
1275 
1276  if (d->v_numdims > 1) {
1277  bsize = d->v_dims[d->v_numdims-1];
1278  blocks = d->v_length/bsize;
1279  }
1280  else {
1281  bsize = d->v_length;
1282  blocks = 1;
1283  }
1284 
1285  if (xind) {
1286  ilo = (int) xind[0];
1287  ihi = (int) xind[1];
1288 
1289  if ((ilo <= ihi) && (ilo > 0) && (ilo < bsize) &&
1290  (ihi > 1) && (ihi <= bsize)) {
1291 
1292  i = d->v_length - blocks*bsize;
1293  if (i > ihi)
1294  blocks++;
1295  if (blocks) {
1296  newlen = ihi - ilo;
1297  if (isreal(d)) {
1298  double *src, *dst;
1299 
1300  dd = (double *) tmalloc(newlen*blocks * sizeof(double));
1301  dst = dd;
1302  src = d->v_realdata + ilo;
1303  for (i = 0; i < blocks; i++) {
1304  DCOPY(src, dst, newlen);
1305  src += bsize;
1306  dst += newlen;
1307  }
1308  txfree((char*)d->v_realdata);
1309  d->v_realdata = dd;
1310  }
1311  else {
1312  complex *src, *dst;
1313 
1314  cc = (complex *) tmalloc(newlen*blocks * sizeof(complex));
1315  dst = cc;
1316  src = d->v_compdata + ilo;
1317  for (i = 0; i < blocks; i++) {
1318  CCOPY(src, dst, newlen);
1319  src += bsize;
1320  dst += newlen;
1321  }
1322  txfree((char*)d->v_compdata);
1323  d->v_compdata = cc;
1324  }
1325  d->v_length = newlen*blocks;
1326  if (d->v_numdims <= 1) {
1327  d->v_numdims = 1;
1328  d->v_dims[0] = newlen;
1329  }
1330  else
1331  d->v_dims[d->v_numdims-1] = newlen;
1332  }
1333  }
1334  }
1335 
1336  if (xcomp) {
1337  cfac = (int) *xcomp;
1338  if ((cfac > 1) && (cfac < bsize)) {
1339  newlen = bsize/cfac;
1340  for (j = 0; j < blocks; j++) {
1341  for (i = 0; i < newlen; i++)
1342  if (isreal(d))
1343  d->v_realdata[i + j*newlen] =
1344  d->v_realdata[i*cfac + j*bsize];
1345  else
1346  d->v_compdata[i + j*newlen] =
1347  d->v_compdata[i*cfac + j*bsize];
1348  }
1349  d->v_length = blocks*newlen;
1350  if (d->v_numdims <= 1)
1351  d->v_dims[0] = d->v_length;
1352  else
1353  d->v_dims[d->v_numdims-1] = d->v_length;
1354  }
1355  }
1356  return;
1357 }
1358 
1359 
1360 
1361 #define XG_MAXVECTORS 64
1362 
1363 
1364 void
1365 ft_xgraph(dl0,grp)
1366 
1367 /*
1368  * Xgraph-11 plots.
1369  */
1370 struct dvlist *dl0;
1371 char *grp;
1372 {
1373  struct grinit *gr = (struct grinit*)grp;
1374  FILE *file;
1375  struct dvec *v, *scale;
1376  struct dvlist *dl;
1377  double xval, yval;
1378  int i, numVecs, linewidth;
1379  bool xlog, ylog, nogrid, markers;
1380  char buf[BSIZE_SP], *text;
1381  extern char *kw_xglinewidth, *kw_xgmarkers;
1382 
1383  /* Sanity checking. */
1384  for (dl = dl0, numVecs = 0; dl; dl = dl->dl_next) {
1385  numVecs++;
1386  }
1387  if (numVecs == 0) {
1388  return;
1389  }
1390  else if (numVecs > XG_MAXVECTORS) {
1391  fprintf( cp_err, "Error: too many vectors for Xgraph.\n" );
1392  return;
1393  }
1394  if (!cp_getvar(kw_xglinewidth, VT_NUM, (char*)&linewidth))
1395  linewidth = 1;
1396  if (linewidth < 1) linewidth = 1;
1397 
1398  if (!cp_getvar(kw_xgmarkers, VT_BOOL, (char*)&markers)) {
1399  markers = false;
1400  }
1401 
1402  /* Make sure the gridtype is supported. */
1403  switch (gr->gridtype) {
1404  case GRID_LIN:
1405  nogrid = xlog = ylog = false;
1406  break;
1407  case GRID_XLOG:
1408  xlog = true;
1409  nogrid = ylog = false;
1410  break;
1411  case GRID_YLOG:
1412  ylog = true;
1413  nogrid = xlog = false;
1414  break;
1415  case GRID_LOGLOG:
1416  xlog = ylog = true;
1417  nogrid = false;
1418  break;
1419  case GRID_NONE:
1420  for (dl = dl0, numVecs = 0; dl; dl = dl->dl_next)
1421  nogrid = true;
1422  xlog = ylog = false;
1423  break;
1424  default:
1425  fprintf( cp_err, "Error: grid type unsupported by Xgraph.\n" );
1426  return;
1427  }
1428 
1429  /* Open the output file. */
1430  if (!(file = fopen(gr->hcopy, "w"))) {
1431  perror(gr->hcopy);
1432  return;
1433  }
1434 
1435  /* Set up the file header. */
1436  if (gr->plotname)
1437  fprintf( file, "TitleText: %s\n", gr->plotname );
1438  if (gr->xlabel)
1439  fprintf( file, "XUnitText: %s\n", gr->xlabel );
1440  if (gr->ylabel) {
1441  fprintf( file, "YUnitText: %s\n", gr->ylabel );
1442  }
1443  if (nogrid) {
1444  fprintf( file, "Ticks: True\n" );
1445  }
1446  if (xlog) {
1447  fprintf( file, "LogX: True\n" );
1448  if (gr->xlims) {
1449  fprintf( file, "XLowLimit: % e\n", log10(gr->xlims[0]) );
1450  fprintf( file, "XHighLimit: % e\n", log10(gr->xlims[1]) );
1451  }
1452  }
1453  else {
1454  if (gr->xlims) {
1455  fprintf( file, "XLowLimit: % e\n", gr->xlims[0] );
1456  fprintf( file, "XHighLimit: % e\n", gr->xlims[1] );
1457  }
1458  }
1459  if (ylog) {
1460  fprintf( file, "LogY: True\n" );
1461  if (gr->ylims) {
1462  fprintf( file, "YLowLimit: % e\n", log10(gr->ylims[0]) );
1463  fprintf( file, "YHighLimit: % e\n", log10(gr->ylims[1]) );
1464  }
1465  }
1466  else {
1467  if (gr->ylims) {
1468  fprintf( file, "YLowLimit: % e\n", gr->ylims[0] );
1469  fprintf( file, "YHighLimit: % e\n", gr->ylims[1] );
1470  }
1471  }
1472  fprintf( file, "LineWidth: %d\n", linewidth );
1473  fprintf( file, "BoundBox: True\n" );
1474  if (gr->plottype == PLOT_COMB) {
1475  fprintf( file, "BarGraph: True\n" );
1476  fprintf( file, "NoLines: True\n" );
1477  }
1478  else if (gr->plottype == PLOT_POINT) {
1479  if (markers) {
1480  fprintf( file, "Markers: True\n" );
1481  }
1482  else {
1483  fprintf( file, "LargePixels: True\n" );
1484  }
1485  fprintf( file, "NoLines: True\n" );
1486  }
1487 
1488  /* Write out the data. */
1489  for (dl = dl0; dl; dl = dl->dl_next) {
1490  v = dl->dl_dvec;
1491  scale = v->v_scale;
1492  if (v->v_name) {
1493  fprintf( file, "\"%s\"\n", v->v_name );
1494  }
1495  for ( i = 0; i < scale->v_length; i++ ) {
1496  xval = isreal(scale) ?
1497  scale->v_realdata[i] : realpart(&scale->v_compdata[i]);
1498  yval = isreal(v) ?
1499  v->v_realdata[i] : realpart(&v->v_compdata[i]);
1500  fprintf( file, "% e % e\n", xval, yval );
1501  }
1502  fprintf( file, "\n" );
1503  }
1504  (void) fclose( file );
1505  (void) sprintf( buf, "xgraph %s &", gr->hcopy );
1506  (void) system( buf );
1507  return;
1508 }
static bool asciilin()
static char buf[MAXPROMPT]
Definition: arg.c:18
bool xcompset
Definition: doplot.c:208
#define BSIZE_SP
Definition: misc.h:19
Definition: outitf.c:1049
#define eq(a, b)
Definition: misc.h:29
DISPDEVICE device[]
Definition: display.c:24
double v_minsignal
Definition: ftedata.h:30
int ciprefix()
Definition: subckt.c:18
double xcompress
Definition: doplot.c:202
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
static int newscale()
static void parsewl()
GRAPH * gr_init()
char * pl_typename
Definition: ftedata.h:65
bool ylimset
Definition: doplot.c:207
void com_plot(wordlist *wl)
Definition: doplot.c:189
PLOTTYPE plottype
Definition: plotdefs.h:38
struct dvlist * v_link2
Definition: ftedata.h:44
int cieq()
void vec_newtemp()
char * pl_title
Definition: ftedata.h:62
char * strcpy()
Definition: cddefs.h:119
double pl_step
Definition: ftedata.h:78
void ft_agraf()
struct plot * plot_cur
Definition: vectors.c:43
int system(char *str)
Definition: libfuncs.c:85
struct dvlist * ft_dvlist()
double xindices[2]
Definition: doplot.c:203
static void dummy()
Definition: mfbcursr.c:550
char * kw_xglinewidth
Definition: options.c:433
Definition: ftedata.h:49
Definition: xforms.c:16
bool xindset
Definition: doplot.c:209
int ptype
Definition: doplot.c:214
char * kw_gridstyle
Definition: options.c:359
struct pnode * ft_getpnames()
DISPDEVICE * dispdev
Definition: display.c:112
char * ylabel
Definition: plotdefs.h:40
double * ylims
Definition: plotdefs.h:30
char * plotname
Definition: plotdefs.h:32
int type
Definition: doplot.c:597
double * ft_numparse()
Definition: cpstd.h:29
Definition: ftedata.h:61
bool ft_interpolate()
Definition: library.c:18
GRDATA(* copydata)()
Definition: ftegraph.h:72
void ft_xgraph(struct dvlist *dl0, char *grp)
Definition: doplot.c:1365
char * kw_xgmarkers
Definition: options.c:434
double xdelta
Definition: plotdefs.h:35
int DevNewViewport()
void com_xgraph(wordlist *wl)
Definition: doplot.c:54
static bool sameflag
Definition: doplot.c:37
char * name
Definition: doplot.c:596
Definition: cddefs.h:215
#define alloc(type)
Definition: cdmacs.h:21
struct dvec * vec_mkfamily()
complex * v_compdata
Definition: ftedata.h:29
#define DCOPY(s, d, n)
Definition: ftedefs.h:55
#define CCOPY(s, d, n)
Definition: ftedefs.h:59
char * copy()
char * getenv(char *c)
Definition: libfuncs.c:106
bool xlimset
Definition: doplot.c:206
SMITH_tfm(double re, double im, double *x, double *y)
Definition: points.c:121
wordlist * outmenuprompt()
double * ft_SMITHminmax()
struct dvlist * dl_next
Definition: ftedata.h:51
int gtype
Definition: doplot.c:213
void wl_free()
#define XG_MAXVECTORS
Definition: doplot.c:1361
static struct grstuff grs
Definition: doplot.c:220
FILE * cp_err
Definition: help.c:101
GRIDTYPE gridtype
Definition: plotdefs.h:37
bool windows
Definition: plotdev.h:61
char * tmalloc()
bool ydeltaset
Definition: doplot.c:211
bool nointerp
Definition: plotdefs.h:45
struct wordlist * wl_prev
Definition: cpstd.h:24
#define NumGrTypes
Definition: doplot.c:608
Definition: cddefs.h:237
void DevHalt()
Definition: display.c:226
#define tfree(x)
Definition: cdmacs.h:22
double v_maxsignal
Definition: ftedata.h:31
static bool fixlimits()
void txfree()
struct dvec * pl_scale
Definition: ftedata.h:68
void PushGraphContext()
#define NULL
Definition: spdefs.h:121
char * xname
Definition: plotdefs.h:31
char * title
Definition: doplot.c:217
int graphid
Definition: ftegraph.h:30
GRDATA plotdata
Definition: ftegraph.h:33
GRIDTYPE v_gridtype
Definition: ftedata.h:32
#define SV_ZERO
Definition: fteconst.h:21
int unlink(char *fn)
Definition: libfuncs.c:96
#define VT_NUM
Definition: cpstd.h:61
struct plot * v_plot
Definition: ftedata.h:42
bool nointerp
Definition: doplot.c:212
struct dvec * v_scale
Definition: ftedata.h:45
Definition: ftegraph.h:29
GRAPH * CopyGraph()
void com_asciiplot(wordlist *wl)
Definition: doplot.c:40
char * smktemp()
struct pnode * pn_next
Definition: fteparse.h:23
static double c
Definition: vectors.c:16
char * commandline
Definition: doplot.c:218
#define VT_STRING
Definition: cpstd.h:63
#define isreal(v)
Definition: ftedata.h:54
void perror()
Definition: ftedata.h:24
struct dvec * dl_dvec
Definition: ftedata.h:50
double * xlims
Definition: plotdefs.h:29
char * ylabel
Definition: doplot.c:216
char * v_name
Definition: ftedata.h:25
#define imagpart(cval)
Definition: cpstd.h:36
char * pname
Definition: plotdefs.h:43
#define VT_BOOL
Definition: cpstd.h:60
char * hcopy
Definition: plotdefs.h:33
#define NumPlTypes
Definition: doplot.c:615
char * xlabel
Definition: plotdefs.h:39
Definition: cpstd.h:21
char * devdep
Definition: ftegraph.h:144
#define VF_MAXGIVEN
Definition: fteconst.h:45
char * kw_hcopydev
Definition: help.c:105
void PopGraphContext()
Definition: graphdb.c:270
int DestroyGraph()
while(TDesc->tSucc!=NULL)
Definition: cd.c:1335
char * xlabel
Definition: doplot.c:215
void vec_dlfree()
double xdelta
Definition: doplot.c:204
double ylim[2]
Definition: doplot.c:201
double ydelta
Definition: plotdefs.h:36
int v_type
Definition: ftedata.h:26
int ft_makehardcopy()
struct dvec * pn_value
Definition: fteparse.h:18
Definition: netlist.c:477
bool xdeltaset
Definition: doplot.c:210
double pl_start
Definition: ftedata.h:76
void plot_extend(struct dvec *v, int length)
Definition: doplot.c:1214
static bool plotit()
struct wordlist * wl_next
Definition: cpstd.h:23
#define SV_POLE
Definition: fteconst.h:20
int v_numdims
Definition: ftedata.h:40
PLOTTYPE v_plottype
Definition: ftedata.h:33
int nplots
Definition: plotdefs.h:34
void ft_hardcopy(wordlist *wl, GRAPH *graph, bool copygraph, char *mesg, bool fileonly)
Definition: doplot.c:93
char * wl_word
Definition: cpstd.h:22
static struct sPlotFlags gtypes[]
Definition: doplot.c:599
void(* redraw)()
Definition: ftegraph.h:70
double * ft_minmax()
char * commandline
Definition: plotdefs.h:44
static double * getlims()
int v_length
Definition: ftedata.h:34
double pl_stop
Definition: ftedata.h:77
int DevSwitch()
static char * getword()
short v_flags
Definition: ftedata.h:27
double * v_realdata
Definition: ftedata.h:28
char * wl_flatten()
static struct sPlotFlags ptypes[]
Definition: doplot.c:610
static bool getflag()
void gr_end()
Definition: graf.c:168
int xtype
Definition: plotdefs.h:41
char * kw_hcopydevtype
Definition: options.c:361
static void compress()
struct dvec * vec_copy()
void com_hardcopy(wordlist *wl)
Definition: doplot.c:81
double xlim[2]
Definition: doplot.c:200
#define VF_MINGIVEN
Definition: fteconst.h:44
char * kw_plotstyle
Definition: options.c:402
int ytype
Definition: plotdefs.h:42
double ydelta
Definition: doplot.c:205
#define realpart(cval)
Definition: cpstd.h:35
Definition: fteparse.h:16
#define SV_NOTYPE
Definition: fteconst.h:11
wordlist * wl_copy()