📄 evaluate.c
字号:
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); /* va: garbage collection */ if (arg1->pn_value==NULL && v!=NULL) vec_free(v); if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind); 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(struct pnode *arg1, struct pnode *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: nostrchring on a scalar (%s)\n", v->v_name); return (NULL); } } if (ind->v_length != 1) { fprintf(cp_err, "Error:strchr %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 thestrchr, 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 res->v_compdata = (complex *) tmalloc(sizeof (complex) * length); /* And toss in the new data */ for (j = 0; j < up - down + 1; j++) { if (rev) k = (up - down) - j; else k = j; for (i = 0; i < blocksize; i++) if (isreal(res)) res->v_realdata[k * blocksize + i] = v->v_realdata[(down + j) * blocksize + i]; else { realpart(&res->v_compdata[k * blocksize + i]) = realpart(&v->v_compdata[(down + j) * blocksize + i]); imagpart(&res->v_compdata[k * blocksize + i]) = imagpart(&v->v_compdata[(down + j) * blocksize + i]); } } /* This is a problem -- the old scale will be no good. I guess we * should make an altered copy of the old scale also. */ /* Even though the old scale is no good and we should somehow decide * on a new scale, using the vector as its own scale is not the * solution. */ /* * res->v_scale = res; */ vec_new(res); /* va: garbage collection */ if (arg1->pn_value==NULL && v!=NULL) vec_free(v); if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind); return (res);}/* Apply a function to an argument. Complex functions are called as follows: * cx_something(data, type, length, &newlength, &newtype), * and returns a char * that is cast to complex or double. */static struct dvec *apply_func(struct func *func, struct pnode *arg){ struct dvec *v, *t, *newv = NULL, *end = NULL; int len, i; short type; char *data, buf[BSIZE_SP]; /* Special case. This is not good -- happens when vm(), etc are used * and it gets caught as a user-definable function. Usually v() * is caught in the parser. */ if (!func->fu_func) { if (!arg->pn_value /* || (arg->pn_value->v_length != 1) XXX */) { fprintf(cp_err, "Error: bad v() syntax\n"); return (NULL); } (void) sprintf(buf, "v(%s)", arg->pn_value->v_name); t = vec_fromplot(buf, plot_cur); if (!t) { fprintf(cp_err, "Error: no such vector %s\n", buf); return (NULL); } t = vec_copy(t); vec_new(t); return (t); } v = ft_evaluate(arg); if (v == NULL) return (NULL); for (; v; v = v->v_link2) { /* Some of the math routines generate SIGILL if the argument is * out of range. Catch this here. */ if (SETJMP(matherrbuf, 1)) {
(void) signal(SIGILL, SIG_DFL); return (NULL); } (void) signal(SIGILL, (SIGNAL_FUNCTION) sig_matherr); if (eq(func->fu_name, "interpolate") || eq(func->fu_name, "deriv")) /* Ack */ { void *(*f)(void *data, short int type, int length, int *newlength, short int *newtype, ...)=func->fu_func; data = ((*f) ((isreal(v) ? (void *) v->v_realdata : (void *) v->v_compdata), (short) (isreal(v) ? VF_REAL : VF_COMPLEX), v->v_length, &len, &type, v->v_plot, plot_cur, v->v_dims[0])); } else { data = ((*func->fu_func) ((isreal(v) ? (void *) v->v_realdata : (void *) v->v_compdata), (short) (isreal(v) ? VF_REAL : VF_COMPLEX), v->v_length, &len, &type)); } /* Back to normal */ (void) signal(SIGILL, SIG_DFL); if (!data) return (NULL); t = alloc(struct dvec); ZERO(t,struct dvec); t->v_flags = (v->v_flags & ~VF_COMPLEX & ~VF_REAL & ~VF_PERMANENT & ~VF_MINGIVEN & ~VF_MAXGIVEN); t->v_flags |= type;#ifdef FTEDEBUG if (ft_evdb) fprintf(cp_err, "apply_func: func %s to %s len %d, type %d\n", func->fu_name, v->v_name, len, type);#endif if (isreal(t)) t->v_realdata = (double *) data; else t->v_compdata = (complex *) data; if (eq(func->fu_name, "minus")) t->v_name = mkcname('a', func->fu_name, v->v_name); else if (eq(func->fu_name, "not")) t->v_name = mkcname('c', func->fu_name, v->v_name); else t->v_name = mkcname('b', v->v_name, (char *) NULL); t->v_type = v->v_type; /* This is strange too. */ t->v_length = len; t->v_scale = v->v_scale; /* Copy a few useful things */ t->v_defcolor = v->v_defcolor; t->v_gridtype = v->v_gridtype; t->v_plottype = v->v_plottype; t->v_numdims = v->v_numdims; for (i = 0; i < t->v_numdims; i++) t->v_dims[i] = v->v_dims[i]; vec_new(t); if (end) end->v_link2 = t; else newv = t; end = t; } /* va: garbage collection */ if (arg->pn_value==NULL && v!=NULL) vec_free(v); return (newv);}/* The unary minus operation. */struct dvec *op_uminus(struct pnode *arg){ return (apply_func(&func_uminus, arg));}struct dvec *op_not(struct pnode *arg){ return (apply_func(&func_not, arg));}/* Create a reasonable name for the result of a function application, etc. * The what values 'a' and 'b' mean "make a function name" and "make a * unary minus", respectively. */static char *mkcname(char what, char *v1, char *v2){ char buf[BSIZE_SP], *s; if (what == 'a') (void) sprintf(buf, "%s(%s)", v1, v2); else if (what == 'b') (void) sprintf(buf, "-(%s)", v1); else if (what == 'c') (void) sprintf(buf, "~(%s)", v1); else if (what == '[') (void) sprintf(buf, "%s[%s]", v1, v2); else if (what == 'R') (void) sprintf(buf, "%s[[%s]]", v1, v2); else (void) sprintf(buf, "(%s)%c(%s)", v1, what, v2); s = copy(buf); return (s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -