⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evaluate.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********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 + -