📄 vectors.c
字号:
return (pl);}/* Stick a new vector in the proper place in the plot list. */voidvec_new(d) struct dvec *d;{#ifdef FTEDEBUG if (ft_vecdb) fprintf(cp_err, "new vector %s\n", d->v_name);#endif /* Note that this can't happen. */ if (plot_cur == NULL) { fprintf(cp_err, "vec_new: Internal Error: no cur plot\n"); } if ((d->v_flags & VF_PERMANENT) && (plot_cur->pl_scale == NULL)) plot_cur->pl_scale = d; if (!d->v_plot) d->v_plot = plot_cur; if (d->v_numdims < 1) { d->v_numdims = 1; d->v_dims[0] = d->v_length; } d->v_next = d->v_plot->pl_dvecs; d->v_plot->pl_dvecs = d; return;}/* Because of the way that all vectors, including temporary vectors, * are linked together under the current plot, they can often be * left lying around. This gets rid of all vectors that don't have * the permanent flag set. Also, for the remaining vectors, it * clears the v_link2 pointer. */voidvec_gc(){ struct dvec *d, *nd; struct plot *pl; for (pl = plot_list; pl; pl = pl->pl_next) for (d = pl->pl_dvecs; d; d = nd) { nd = d->v_next; if (!(d->v_flags & VF_PERMANENT)) { if (ft_vecdb) fprintf(cp_err, "vec_gc: throwing away %s.%s\n", pl->pl_typename, d->v_name); vec_free(d); } } for (pl = plot_list; pl; pl = pl->pl_next) for (d = pl->pl_dvecs; d; d = d->v_next) d->v_link2 = NULL; return;}/* Free a dvector. This is sort of a pain because we also have to make sure * that it has been unlinked from its plot structure. If the name of the * vector is NULL, then we have already freed it so don't try again. (This * situation can happen with user-defined functions.) Note that this depends * on our having tfree set its argument to NULL. Note that if all the vectors * in a plot are gone it stays around... */voidvec_free(v) struct dvec *v;{ struct plot *pl; struct dvec *lv; if ((v == NULL) || (v->v_name == NULL)) return; pl = v->v_plot; /* Now we have to take this dvec out of the plot list. */ if (pl == NULL) fprintf(cp_err, "vec_free: Internal Error: plot ptr is 0\n"); if (pl->pl_dvecs == v) pl->pl_dvecs = v->v_next; else { for (lv = pl->pl_dvecs; lv->v_next; lv = lv->v_next) if (lv->v_next == v) break; if (lv->v_next == NULL) fprintf(cp_err, "vec_free: Internal Error: %s not in plot\n", v->v_name); lv->v_next = v->v_next; } if (pl->pl_scale == v) { if (pl->pl_dvecs) pl->pl_scale = pl->pl_dvecs; /* Random one... */ else pl->pl_scale = NULL; } tfree(v->v_name); if (isreal(v)) { tfree(v->v_realdata); } else { tfree(v->v_compdata); } tfree(v); return;}/* This is something we do in a few places... Since vectors get copied a lot, * we can't just compare pointers to tell if two vectors are 'really' the same. */boolvec_eq(v1, v2) struct dvec *v1, *v2;{ char *s1, *s2; if (v1->v_plot != v2->v_plot) return (false); s1 = vec_basename(v1); s2 = vec_basename(v2); if (cieq(s1, s2)) return (true); else return (false);}/* Return the name of the vector with the plot prefix stripped off. This * is no longer trivial since '.' doesn't always mean 'plot prefix'. */char *vec_basename(v) struct dvec *v;{ char buf[BSIZE_SP], *t, *s; int i; if (index(v->v_name, '.')) { for (t = v->v_name, i = 0; *t; t++) buf[i++] = *t; buf[i] = '\0'; if (cieq(v->v_plot->pl_typename, buf)) (void) strcpy(buf, t + 1); else (void) strcpy(buf, v->v_name); } else (void) strcpy(buf, v->v_name); for (t = buf; *t; t++) if (isupper(*t)) *t = tolower(*t); for (t = buf; isspace(*t); t++) ; s = t; for (t = s; *t; t++) ; while ((t > s) && isspace(t[-1])) *--t = '\0'; return (copy(s));}/* Sort all the vectors in d, first by plot name and then by vector name. * Do the right thing with numbers. */static struct dvec *sortvecs(d) struct dvec *d;{ struct dvec **array, *t; int i, j; for (t = d, i = 0; t; t = t->v_link2) i++; if (i < 2) return (d); array = (struct dvec **) tmalloc(i * sizeof (struct dvec *)); for (t = d, i = 0; t; t = t->v_link2) array[i++] = t; qsort((char *) array, i, sizeof (struct dvec *), veccmp); /* Now string everything back together... */ for (j = 0; j < i - 1; j++) array[j]->v_link2 = array[j + 1]; array[j]->v_link2 = NULL; d = array[0]; tfree(array); return (d);}static intveccmp(d1, d2) struct dvec **d1, **d2;{ int i; if ((i = namecmp((*d1)->v_plot->pl_typename, (*d2)->v_plot->pl_typename)) != 0) return (i); return (namecmp((*d1)->v_name, (*d2)->v_name));}/* If there are imbedded numeric strings, compare them numerically, not * alphabetically. */static intnamecmp(s, t) char *s, *t;{ int i, j; for (;;) { while ((*s == *t) && !isdigit(*s) && *s) s++, t++; if (!*s) return (0); if ((*s != *t) && (!isdigit(*s) || !isdigit(*t))) return (*s - *t); /* The beginning of a number... Grab the two numbers * and then compare them... */ for (i = 0; isdigit(*s); s++) i = i * 10 + *s - '0'; for (j = 0; isdigit(*t); t++) j = j * 10 + *t - '0'; if (i != j) return (i - j); }}/* Make a plot the current one. This gets called by cp_usrset() when one * does a 'set curplot = name'. */voidplot_setcur(name) char *name;{ struct plot *pl; if (cieq(name, "new")) { pl = plot_alloc("unknown"); pl->pl_title = copy("Anonymous"); pl->pl_name = copy("unknown"); pl->pl_date = copy(datestring( )); plot_new(pl); plot_cur = pl; return; } for (pl = plot_list; pl; pl = pl->pl_next) if (plot_prefix(name, pl->pl_typename)) break; if (!pl) { fprintf(cp_err, "Error: no such plot named %s\n", name); return; } if (plot_cur) plot_cur->pl_ccom = cp_kwswitch(CT_VECTOR, pl->pl_ccom); plot_cur = pl; return;}/* Add a plot to the plot list. This is different from plot_add() in that * all this does is update the list and the variable $plots. */voidplot_new(pl) struct plot *pl;{ pl->pl_next = plot_list; plot_list = pl; return;}/* This routine takes a multi-dimensional vector, treats it as a * group of 2-dimensional matrices and transposes each matrix. * The data array is replaced with a new one that has the elements * in the proper order. Otherwise the transposition is done in place. */voidvec_transpose(v) struct dvec *v;{ int dim0, dim1, nummatrices; int i, j, k, joffset, koffset, blocksize; struct dvec *d; double *newreal, *oldreal; complex *newcomp, *oldcomp; if (v->v_numdims < 2 || v->v_length <= 1) return; dim0 = v->v_dims[v->v_numdims-1]; dim1 = v->v_dims[v->v_numdims-2]; v->v_dims[v->v_numdims-1] = dim1; v->v_dims[v->v_numdims-2] = dim0; /* Assume length is a multiple of each dimension size. * This may not be safe, in which case a test should be * made that the length is the product of all the dimensions. */ blocksize = dim0*dim1; nummatrices = v->v_length / blocksize; /* Note: * olda[i,j] is at data[i*dim0+j] * newa[j,i] is at data[j*dim1+i] * where j is in [0, dim0-1] and i is in [0, dim1-1] * Since contiguous data in the old array is scattered in the new array * we can't use bcopy :(. There is probably a BLAS2 function for this * though. The formulation below gathers scattered old data into * consecutive new data. */ if (isreal(v)) { newreal = (double *) tmalloc(sizeof (double) * v->v_length); oldreal = v->v_realdata; koffset = 0; for ( k=0; k < nummatrices; k++ ) { joffset = 0; for ( j=0; j < dim0; j++ ) { for ( i=0; i < dim1; i++ ) { newreal[ koffset + joffset + i ] = oldreal[ koffset + i*dim0 + j ]; } joffset += dim1; /* joffset = j*dim0 */ } koffset += blocksize; /* koffset = k*blocksize = k*dim0*dim1 */ } tfree(oldreal); v->v_realdata = newreal; } else { newcomp = (complex *) tmalloc(sizeof (complex) * v->v_length); oldcomp = v->v_compdata; koffset = 0; for ( k=0; k < nummatrices; k++ ) { joffset = 0; for ( j=0; j < dim0; j++ ) { for ( i=0; i < dim1; i++ ) { realpart(&newcomp[ koffset + joffset + i ]) = realpart(&oldcomp[ koffset + i*dim0 + j ]); imagpart(&newcomp[ koffset + joffset + i ]) = imagpart(&oldcomp[ koffset + i*dim0 + j ]); } joffset += dim1; /* joffset = j*dim0 */ } koffset += blocksize; /* koffset = k*blocksize = k*dim0*dim1 */ } tfree(oldcomp); v->v_compdata = newcomp; }}/* This routine takes a multi-dimensional vector and turns it into a family * of 1-d vectors, linked together with v_link2. It is here so that plot * can do intelligent things. */struct dvec *vec_mkfamily(v) struct dvec *v;{ int size, numvecs, i, j, count[MAXDIMS]; int totalsize; struct dvec *vecs, *d; char buf[BSIZE_SP]; if (v->v_numdims < 2) return (v); size = v->v_dims[v->v_numdims - 1]; for (i = 0, numvecs = 1; i < v->v_numdims - 1; i++) numvecs *= v->v_dims[i]; for (i = 0, vecs = d = NULL; i < numvecs; i++) { if (vecs) { d = d->v_link2 = alloc(struct dvec); ZERO(d, struct dvec); } else { d = vecs = alloc(struct dvec); ZERO(d, struct dvec); } } for (i = 0; i < MAXDIMS; i++) count[i] = 0; for (d = vecs, j = 0; d; j++, d = d->v_link2) { (void) sprintf(buf, "%s%s", v->v_name, indexstring(count, v->v_numdims - 1)); d->v_name = copy(buf); d->v_type = v->v_type; d->v_flags = v->v_flags; d->v_minsignal = v->v_minsignal; d->v_maxsignal = v->v_maxsignal; d->v_gridtype = v->v_gridtype; d->v_plottype = v->v_plottype; d->v_scale = v->v_scale; /* Don't copy the default color, since there will be many * of these things... */ d->v_numdims = 1; d->v_length = size; if (isreal(v)) { totalsize = sizeof (double) * size; d->v_realdata = (double *) tmalloc(totalsize); bcopy((char *) v->v_realdata + totalsize * j, (char *) d->v_realdata, totalsize); } else { totalsize = sizeof (complex) * size; d->v_realdata = (double *) tmalloc(totalsize); bcopy((char *) v->v_compdata + totalsize * j, (char *) d->v_compdata, totalsize); } /* Add one to the counter. */ (void) incindex(count, v->v_numdims - 1, v->v_dims, v->v_numdims); } for (d = vecs; d; d = d->v_link2) vec_new(d); return (vecs);}/* This function will match "op" with "op1", but not "op1" with "op12". */boolplot_prefix(pre, str) char *pre, *str;{ if (!*pre) return (true); while (*pre && *str) { if (*pre != *str) break; pre++; str++; } if (*pre || (*str && isdigit(pre[-1]))) return (false); else return (true);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -