📄 evaluate.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* * Convert a parse tree to a list of data vectors. */#include "spice.h"#include "util.h"#include "cpdefs.h"#include "ftedefs.h"#include "ftedata.h"#include "fteparse.h"#include "ftecmath.h"#ifdef HAS_UNIX_SIGS#ifdef HAS_LONGJUMP#define HAS_SIGS_AND_LJMP#include <setjmp.h>#include <signal.h>#endif#endif#include "suffix.h"static struct dvec *apply_func();static struct dvec *doop();static char *mkcname();static SIGNAL_TYPE sig_matherr();#ifdef HAS_SIGS_AND_LJMP/* We are careful here to catch SIGILL and recognise them as math errors. * The only trouble is that the (void) signal handler we installed before will * be lost, but that's no great loss. */static jmp_buf matherrbuf;static SIGNAL_TYPEsig_matherr(){ fprintf(cp_err, "Error: argument out of range for math function\n"); longjmp(matherrbuf, 1); /* NOTREACHED */}#endif/* Note that ft_evaluate will return NULL on invalid expressions. */struct dvec *ft_evaluate(node) struct pnode *node;{ struct dvec *d; if (!node) return (NULL); else if (node->pn_value) d = node->pn_value; else if (node->pn_func) d = apply_func(node->pn_func, node->pn_left); else if (node->pn_op) { if (node->pn_op->op_arity == 1) d = (struct dvec *) ((*node->pn_op->op_func) (node->pn_left)); else if (node->pn_op->op_arity == 2) d = (struct dvec *) ((*node->pn_op->op_func) (node->pn_left, node->pn_right)); } else { fprintf(cp_err, "ft_evaluate: Internal Error: bad node\n"); return (NULL); } if (!d) { return NULL; } if (node->pn_name && !ft_evdb && d && !d->v_link2) d->v_name = copy(node->pn_name); if (!d->v_length) { fprintf(cp_err, "Error: no such vector %s\n", d->v_name); return (NULL); } else return (d);}/* The binary operations. */struct dvec *op_plus(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('+', cx_plus, arg1, arg2));}struct dvec *op_minus(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('-', cx_minus, arg1, arg2));}struct dvec *op_comma(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop(',', cx_comma, arg1, arg2));}struct dvec *op_times(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('*', cx_times, arg1, arg2));}struct dvec *op_mod(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('%', cx_mod, arg1, arg2));}struct dvec *op_divide(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('/', cx_divide, arg1, arg2));}struct dvec *op_power(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('^', cx_power, arg1, arg2));}struct dvec *op_eq(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('=', cx_eq, arg1, arg2));}struct dvec *op_gt(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('>', cx_gt, arg1, arg2));}struct dvec *op_lt(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('<', cx_lt, arg1, arg2));}struct dvec *op_ge(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('G', cx_ge, arg1, arg2));}struct dvec *op_le(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('L', cx_le, arg1, arg2));}struct dvec *op_ne(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('N', cx_ne, arg1, arg2));}struct dvec *op_and(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('&', cx_and, arg1, arg2));}struct dvec *op_or(arg1, arg2) struct pnode *arg1, *arg2;{ return (doop('|', cx_or, arg1, arg2));}/* This is an odd operation. The first argument is the name of a vector, and * the second is a range in the scale, so that v(1)[[10, 20]] gives all the * values of v(1) for which the TIME value is between 10 and 20. If there is * one argument it picks out the values which have that scale value. * NOTE that we totally ignore multi-dimensionality here -- the result is * a 1-dim vector. */struct dvec *op_range(arg1, arg2) struct pnode *arg1, *arg2;{ struct dvec *v, *ind, *res, *scale; /* , *nscale; */ double up, low, td; int len, i, j; bool rev = false; v = ft_evaluate(arg1); ind = ft_evaluate(arg2); if (!v || !ind) return (NULL); scale = v->v_scale; if (!scale) scale = v->v_plot->pl_scale; if (!scale) { fprintf(cp_err, "Error: no scale for vector %s\n", v->v_name); return (NULL); } if (ind->v_length != 1) { fprintf(cp_err, "Error: strange range specification\n"); return (NULL); } if (isreal(ind)) { up = low = *ind->v_realdata; } else { up = imagpart(ind->v_compdata); low = realpart(ind->v_compdata); } if (up < low) { td = up; up = low; low = td; rev = true; } for (i = len = 0; i < scale->v_length; i++) { td = isreal(scale) ? scale->v_realdata[i] : realpart(&scale->v_compdata[i]); if ((td <= up) && (td >= low)) len++; } res = alloc(struct dvec); ZERO(res,struct dvec); res->v_name = mkcname('R', v->v_name, ind->v_name); res->v_type = v->v_type; res->v_flags = v->v_flags; res->v_gridtype = v->v_gridtype; res->v_plottype = v->v_plottype; res->v_defcolor = v->v_defcolor; res->v_length = len; res->v_scale = /* nscale; */ scale; /* Dave says get rid of this res->v_numdims = v->v_numdims; for (i = 0; i < v->v_numdims; i++) res->v_dims[i] = v->v_dims[i]; */ res->v_numdims = 1; res->v_dims[0] = len; if (isreal(res)) res->v_realdata = (double *) tmalloc(sizeof (double) * len); else res->v_compdata = (complex *) tmalloc(sizeof (complex) * len); /* Toss in the data */ j = 0; for (i = (rev ? v->v_length - 1 : 0); i != (rev ? -1 : v->v_length); rev ? i-- : i++) { td = isreal(scale) ? scale->v_realdata[i] : realpart(&scale->v_compdata[i]); if ((td <= up) && (td >= low)) { if (isreal(res)) { res->v_realdata[j] = v->v_realdata[i]; } else { realpart(&res->v_compdata[j]) = realpart(&v->v_compdata[i]); imagpart(&res->v_compdata[j]) = imagpart(&v->v_compdata[i]); } j++; } } if (j != len) fprintf(cp_err, "Error: something funny..\n"); /* Note that we DON'T do a vec_new, since we want this vector to be * invisible to everybody except the result of this operation. * Doing this will cause a lot of core leaks, though. XXX */ vec_new(res); return (res);}/* This is another operation we do specially -- if the argument is a vector of * dimension n, n > 0, the result will be either a vector of dimension n - 1, * or a vector of dimension n with only a certain range of vectors present. */struct dvec *op_ind(arg1, arg2) struct pnode *arg1, *arg2;{ struct dvec *v, *ind, *res; int length, newdim, i, j, k, up, down; int majsize, blocksize; bool rev = false; v = ft_evaluate(arg1); ind = ft_evaluate(arg2); if (!v || !ind) return (NULL); /* First let's check to make sure that the vector is consistent */ if (v->v_numdims > 1) { for (i = 0, j = 1; i < v->v_numdims; i++) j *= v->v_dims[i]; if (v->v_length != j) { fprintf(cp_err, "op_ind: Internal Error: len %d should be %d\n", v->v_length, j); return (NULL); } } else { /* Just in case we were sloppy */ v->v_numdims = 1; v->v_dims[0] = v->v_length; if (v->v_length <= 1) { fprintf(cp_err, "Error: no indexing on a scalar (%s)\n", v->v_name); return (NULL); } } if (ind->v_length != 1) { fprintf(cp_err, "Error: index %s is not of length 1\n", ind->v_name); return (NULL); } majsize = v->v_dims[0]; blocksize = v->v_length / majsize; /* Now figure out if we should put the dim down by one. Because of the * way we parse the index, we figure that if the value is complex * (e.g, "[1,2]"), the guy meant a range. This is sort of bad though. */ if (isreal(ind)) { newdim = v->v_numdims - 1; down = up = ind->v_realdata[0]; } else { newdim = v->v_numdims; down = realpart(&ind->v_compdata[0]); up = imagpart(&ind->v_compdata[0]); } if (up < down) { i = up; up = down; down = i; rev = true; } if (up < 0) { fprintf(cp_err, "Warning: upper limit %d should be 0\n", up); up = 0; } if (up >= majsize) { fprintf(cp_err, "Warning: upper limit %d should be %d\n", up, majsize - 1); up = majsize - 1; } if (down < 0) { fprintf(cp_err, "Warning: lower limit %d should be 0\n", down); down = 0; } if (down >= majsize) { fprintf(cp_err, "Warning: lower limit %d should be %d\n", down, majsize - 1); down = majsize - 1; } if (up == down) length = blocksize; else length = blocksize * (up - down + 1); /* Make up the new vector. */ res = alloc(struct dvec); ZERO(res,struct dvec); res->v_name = mkcname('[', v->v_name, ind->v_name); res->v_type = v->v_type; res->v_flags = v->v_flags; res->v_defcolor = v->v_defcolor; res->v_gridtype = v->v_gridtype; res->v_plottype = v->v_plottype; res->v_length = length; res->v_numdims = newdim; if (up != down) { for (i = 0; i < newdim; i++) res->v_dims[i] = v->v_dims[i]; res->v_dims[0] = up - down + 1; } else { for (i = 0; i < newdim; i++) res->v_dims[i] = v->v_dims[i + 1]; } if (isreal(res)) res->v_realdata = (double *) tmalloc(sizeof (double) * length); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -