Jspice3
agraf.c File Reference
#include "spice.h"
#include "plotdefs.h"
Include dependency graph for agraf.c:

Go to the source code of this file.

Macros

#define FUDGE   7
 
#define MARGIN_BASE   11
 
#define LCHAR   '.'
 
#define MCHAR   'X'
 
#define PCHARS   "+*=$%!0123456789"
 

Functions

void ft_agraf (struct dvlist *dl0, char *grp)
 

Macro Definition Documentation

#define FUDGE   7

Definition at line 15 of file agraf.c.

#define LCHAR   '.'

Definition at line 17 of file agraf.c.

#define MARGIN_BASE   11

Definition at line 16 of file agraf.c.

#define MCHAR   'X'

Definition at line 18 of file agraf.c.

#define PCHARS   "+*=$%!0123456789"

Definition at line 19 of file agraf.c.

Function Documentation

void ft_agraf ( struct dvlist dl0,
char *  grp 
)

Definition at line 27 of file agraf.c.

31 {
32  struct grinit *gr = (struct grinit*)grp;
33  bool nobreakp, novalue;
34  bool ylogscale = false;
35  char *field, buf[BSIZE_SP];
36  char *line1, *line2, c, cb;
37  double xrange[2], yrange[2], x1, x2, yy1, y2, x, y;
38  double tenpowmag, diff, *values;
39  struct dvec *v;
40  struct dvlist *dl;
41  struct dvec *xscale = dl0->dl_dvec->v_scale;
42  struct plot *plot = dl0->dl_dvec->v_plot;
43  int maxx, maxy, omaxy; /* The size of the plotting area. */
44  int height;
45  int mag, hmt, lmt, dst, spacing, nsp, ypt, upper, lower, curline;
46  int margin = MARGIN_BASE;
47  int omargin;
48  int i, j, k;
49  int shift;
51 
52  bool xlog =
53  ((gr->gridtype == GRID_XLOG) || (gr->gridtype == GRID_LOGLOG));
54  bool ylog =
55  ((gr->gridtype == GRID_YLOG) || (gr->gridtype == GRID_LOGLOG));
56 
57 
58  /* ANSI C does not specify how many digits are in an exponent for %c
59  * We assumed it was 2. If it's more, shift starting position over.
60  */
61  (void) sprintf(buf, "%1.1e", 0.0); /* expect 0.0e+00 */
62  shift = strlen(buf) - 7;
63  margin += shift;
64 
65  /* Make sure the margin is correct */
66  omargin = margin;
67  if (!cp_getvar(kw_noasciiplotvalue, VT_BOOL, (char *) &novalue) &&
68  !vec_eq(xscale, dl0->dl_dvec)) {
69  margin *= 2;
70  }
71  else
72  novalue = true;
73  if ((xscale->v_gridtype == GRID_YLOG) ||
74  (xscale->v_gridtype == GRID_LOGLOG))
75  ylogscale = true;
76  if (!cp_getvar(kw_width, VT_NUM, (char *) &maxy)) {
77  maxy = DEF_WIDTH;
78  }
79  if (!cp_getvar(kw_height, VT_NUM, (char *) &height))
80  height = DEF_HEIGHT;
81  if (ft_nopage)
82  nobreakp = true;
83  else
84  cp_getvar(kw_nobreak, VT_BOOL, (char *) &nobreakp);
85  maxy -= (margin + FUDGE);
86  maxx = xscale->v_length;
87  xrange[0] = gr->xlims[0];
88  xrange[1] = gr->xlims[1];
89  yrange[0] = gr->ylims[0];
90  yrange[1] = gr->ylims[1];
91 
92  if (maxx < 2) {
93  fprintf(cp_err,
94  "Error: asciiplot can't handle scale with length < 2\n");
95  return;
96  }
97 
98  if (maxx <= 0) {
99  fprintf(cp_err, "Note: no points to plot\n");
100  return;
101  }
102 
103  for (dl = dl0, i = 0; dl; dl = dl->dl_next) {
104  dl->dl_dvec->v_linestyle = (PCHARS[i] ? PCHARS[i++] : '#');
105  }
106  /* Now allocate the field and stuff. */
107  field = tmalloc((maxy + 1) * (maxx + 1));
108  line1 = tmalloc(maxy + margin + FUDGE + 1);
109  line2 = tmalloc(maxy + margin + FUDGE + 1);
110  if (!novalue)
111  values = (double *) tmalloc(maxx * sizeof (double));
112 
113  /* Clear the field, put the lines in the right places, and create
114  * the headers.
115  */
116  for (i = 0, j = (maxx + 1) * (maxy + 1); i < j; i++)
117  field[i] = ' ';
118  for (i = 0, j = maxy + margin + FUDGE; i < j; i++) {
119  line1[i] = '-';
120  line2[i] = ' ';
121  }
122  line1[j] = line2[j] = '\0';
123 
124  /* The following is similar to the stuff in grid.c */
125  if ((xrange[0] > xrange[1]) || (yrange[0] > yrange[1])) {
126  fprintf(cp_err,
127  "ft_agraf: Internal Error: bad limits %lg, %lg, %lg, %lg\n",
128  xrange[0], xrange[1], yrange[0], yrange[1]);
129  return;
130  }
131 
132  /* gcc doesn't like !double */
133  if (gr->ylims[1] == 0.0) {
134  mag = (int) floor(mylog10(- gr->ylims[0]));
135  tenpowmag = pow(10.0, (double) mag);
136  }
137  else if (gr->ylims[0] == 0.0) {
138  mag = (int) floor(mylog10(gr->ylims[1]));
139  tenpowmag = pow(10.0, (double) mag);
140  }
141  else {
142  diff = gr->ylims[1] - gr->ylims[0];
143  mag = (int) floor(mylog10(diff));
144  tenpowmag = pow(10.0, (double) mag);
145  }
146 
147  lmt = (int) floor(gr->ylims[0] / tenpowmag);
148  yrange[0] = gr->ylims[0] = lmt * tenpowmag;
149  hmt = (int) ceil(gr->ylims[1] / tenpowmag);
150  yrange[1] = gr->ylims[1] = hmt * tenpowmag;
151 
152  dst = hmt - lmt;
153 
154  /* This is a strange case; I don't know why it's here. */
155  if (dst == 11)
156  dst = 12;
157 
158  if (dst == 1) {
159  dst = 10;
160  mag++;
161  hmt *= 10.0;
162  lmt *= 10.0;
163  }
164 
165  for (nsp = 4; nsp < 8; nsp++)
166  if (!(dst % nsp))
167  break;
168  if (nsp == 8)
169  for (nsp = 2; nsp < 4; nsp++)
170  if (!(dst % nsp))
171  break;
172  spacing = maxy / nsp;
173 
174  /* Reset the max X coordinate to deal with round-off error. */
175  omaxy = maxy + 1;
176  maxy = spacing * nsp;
177 
178  for (i = 0, j = lmt; j <= hmt; i += spacing, j += dst / nsp) {
179  for (k = 0; k < maxx; k++)
180  field[k * omaxy + i] = LCHAR;
181  line1[i + margin + 2 * shift] = '|';
182  (void) sprintf(buf, "%.2e", j * pow(10.0, (double) mag));
183  bcopy(buf, &line2[i + margin - ((j < 0) ? 2 : 1) - shift],
184  strlen(buf));
185  }
186  line1[i - spacing + margin + 1] = '\0';
187 
188  for (i = 1; i < omargin - 1 && xscale->v_name[i - 1]; i++)
189  line2[i] = xscale->v_name[i - 1];
190  if (!novalue)
191  for (i = omargin + 1;
192  i < margin - 2 && (dl0->dl_dvec->v_name[i - omargin - 1]);
193  i++)
194  line2[i] = dl0->dl_dvec->v_name[i - omargin - 1];
195 
196  /* Now the buffers are all set up properly. Plot points for each
197  * vector using interpolation. For each point on the x-axis, find the
198  * two bracketing points in xscale, and then interpolate their
199  * y values for each vector.
200  */
201 
202  upper = lower = 0;
203  for (i = 0; i < maxx; i++) {
204  if (gr->nointerp)
205  x = isreal(xscale) ? xscale->v_realdata[i] :
206  realpart(&xscale->v_compdata[i]);
207  else if (xlog && xrange[0] > 0.0 && xrange[1] > 0.0)
208  x = xrange[0] * pow( 10.0, mylog10(xrange[1]/xrange[0])
209  * i / (maxx - 1));
210  else
211  x = xrange[0] + (xrange[1] - xrange[0]) * i /
212  (maxx - 1);
213  while ((isreal(xscale) ? (xscale->v_realdata[upper] < x) :
214  (realpart(&xscale->v_compdata[upper]) < x)) &&
215  (upper < xscale->v_length))
216  upper++;
217  while ((isreal(xscale) ? (xscale->v_realdata[lower] < x) :
218  (realpart(&xscale->v_compdata[lower]) < x)) &&
219  (lower < xscale->v_length - 1))
220  lower++;
221  if ((isreal(xscale) ? (xscale->v_realdata[lower] > x) :
222  (realpart(&xscale->v_compdata[lower]) > x)) &&
223  (lower > 0))
224  lower--;
225  x1 = (isreal(xscale) ? xscale->v_realdata[lower] :
226  realpart(&xscale->v_compdata[lower]));
227  x2 = (isreal(xscale) ? xscale->v_realdata[upper] :
228  realpart(&xscale->v_compdata[upper]));
229  if (x1 > x2) {
230  fprintf(cp_err, "Error: X scale (%s) not monotonic\n",
231  xscale->v_name);
232  return;
233  }
234  for (dl = dl0; dl; dl = dl->dl_next) {
235  v = dl->dl_dvec;
236  yy1 = (isreal(v) ? v->v_realdata[lower] :
237  realpart(&v->v_compdata[lower]));
238  y2 = (isreal(v) ? v->v_realdata[upper] :
239  realpart(&v->v_compdata[upper]));
240  if (x1 == x2)
241  y = yy1;
242  else
243  y = yy1 + (y2 - yy1) * (x - x1) / (x2 - x1);
244  if (!novalue && (dl == dl0))
245  values[i] = y;
246  ypt = ft_findpoint(y, yrange, maxy, 0, ylogscale);
247  c = field[omaxy * i + ypt];
248  if ((c == ' ') || (c == LCHAR))
249  field[omaxy * i + ypt] = (char) v->v_linestyle;
250  else
251  field[omaxy * i + ypt] = MCHAR;
252  }
253  }
254 
255  for (i = 0; i < omaxy + margin; i++)
256  out_send("-");
257  out_send("\n");
258  i = (omaxy + margin - strlen(plot->pl_title)) / 2;
259  while (i-- > 0)
260  out_send(" ");
261  (void) strcpy(buf, plot->pl_title);
262  buf[maxy + margin] = '\0'; /* Cut off if too wide */
263  out_send(buf);
264  out_send("\n");
265  (void) sprintf(buf, "%s %s", plot->pl_name, plot->pl_date);
266  buf[maxy + margin] = '\0';
267  i = (omaxy + margin - strlen(buf)) / 2;
268  while (i-- > 0)
269  out_send(" ");
270  out_send(buf);
271  out_send("\n\n");
272  curline = 7;
273  out_send("Legend: ");
274  i = 0;
275  j = (maxx + margin - 8) / 20;
276  if (j == 0)
277  j = 1;
278  for (dl = dl0; dl; dl = dl->dl_next) {
279  v = dl->dl_dvec;
280  out_printf("%c = %-17s", (char) v->v_linestyle, v->v_name);
281  if (!(++i % j) && v->v_link2) {
282  out_send("\n ");
283  curline++;
284  }
285  }
286  out_send("\n");
287  for (i = 0; i < omaxy + margin; i++)
288  out_send("-");
289  out_send("\n");
290  i = 0;
291  out_printf("%s\n%s\n", line2, line1);
292  curline += 2;
293  for (i = 0; i < maxx; i++) {
294  if (gr->nointerp)
295  x = isreal(xscale) ? xscale->v_realdata[i] :
296  realpart(&xscale->v_compdata[i]);
297  else if (xlog && xrange[0] > 0.0 && xrange[1] > 0.0)
298  x = xrange[0] * pow( 10.0, mylog10(xrange[1]/xrange[0])
299  * i / (maxx - 1));
300  else
301  x = xrange[0] + (xrange[1] - xrange[0]) * i / (maxx - 1);
302  if (x < 0.0) {
303  out_printf("%.3e ", x);
304  }
305  else {
306  out_printf(" %.3e ", x);
307  }
308  if (!novalue) {
309  if (values[i] < 0.0) {
310  out_printf("%.3e ", values[i]);
311  }
312  else {
313  out_printf(" %.3e ", values[i]);
314  }
315  }
316  cb = field[(i + 1) * omaxy];
317  field[(i + 1) * omaxy] = '\0';
318  out_send(&field[i * omaxy]);
319  field[(i + 1) * omaxy] = cb;
320  out_send("\n");
321  if (((curline++ % height) == 0) && (i < maxx - 1) &&
322  !nobreakp) {
323  out_printf("%s\n%s\n\014\n%s\n%s\n", line1, line2,
324  line2, line1);
325  curline += 5;
326  }
327  }
328  out_printf("%s\n%s\n", line1, line2);
329 
330  tfree(field);
331  tfree(line1);
332  tfree(line2);
333  if (!novalue)
334  tfree(values);
335  return;
336 }
int ft_findpoint()
static char buf[MAXPROMPT]
Definition: arg.c:18
#define BSIZE_SP
Definition: misc.h:19
bool cp_getvar(char *n, int t, char *r)
Definition: help.c:184
char * pl_date
Definition: ftedata.h:63
struct dvlist * v_link2
Definition: ftedata.h:44
char * pl_title
Definition: ftedata.h:62
void out_printf()
char * strcpy()
char * pl_name
Definition: ftedata.h:64
#define FUDGE
Definition: agraf.c:15
if(TDesc==NULL)
Definition: cd.c:1326
Definition: ftedata.h:49
double * ylims
Definition: plotdefs.h:30
static IFvalue * values
Definition: inpptree.c:13
static char * upper()
Definition: ftedata.h:61
char * kw_width
Definition: options.c:430
#define LCHAR
Definition: agraf.c:17
complex * v_compdata
Definition: ftedata.h:29
#define DEF_WIDTH
Definition: ftedefs.h:15
struct dvlist * dl_next
Definition: ftedata.h:51
FILE * cp_err
Definition: help.c:101
GRIDTYPE gridtype
Definition: plotdefs.h:37
char * tmalloc()
bool nointerp
Definition: plotdefs.h:45
int v_linestyle
Definition: ftedata.h:37
char * kw_noasciiplotvalue
Definition: options.c:378
char * kw_height
Definition: options.c:362
#define tfree(x)
Definition: cdmacs.h:22
bool vec_eq()
#define DEF_HEIGHT
Definition: ftedefs.h:16
GRIDTYPE v_gridtype
Definition: ftedata.h:32
#define VT_NUM
Definition: cpstd.h:61
struct plot * v_plot
Definition: ftedata.h:42
struct dvec * v_scale
Definition: ftedata.h:45
static double c
Definition: vectors.c:16
#define isreal(v)
Definition: ftedata.h:54
#define MCHAR
Definition: agraf.c:18
Definition: ftedata.h:24
struct dvec * dl_dvec
Definition: ftedata.h:50
double * xlims
Definition: plotdefs.h:29
char * v_name
Definition: ftedata.h:25
#define VT_BOOL
Definition: cpstd.h:60
#define PCHARS
Definition: agraf.c:19
#define mylog10(xx)
Definition: ftedefs.h:53
void out_send()
void bcopy(char *from, char *to, int num)
Definition: string.c:339
int v_length
Definition: ftedata.h:34
double * v_realdata
Definition: ftedata.h:28
#define MARGIN_BASE
Definition: agraf.c:16
bool ft_nopage
Definition: options.c:23
char * kw_nobreak
Definition: options.c:381
#define realpart(cval)
Definition: cpstd.h:35