/* simple printout of data into a file, similar to data table in ft_gnuplot command: wrsimple file vecs */ void ft_writesimple(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs) { FILE *file_data; struct dvec *v, *scale = NULL; double xval; int i, numVecs; bool appendwrite; char filename_data[128]; NG_IGNORE(xlims); NG_IGNORE(ylims); NG_IGNORE(title); NG_IGNORE(xlabel); NG_IGNORE(ylabel); NG_IGNORE(gridtype); NG_IGNORE(plottype); sprintf(filename_data, "%s.data", filename); appendwrite = cp_getvar("appendwrite", CP_BOOL, NULL); /* Sanity checking. */ for (v = vecs, numVecs = 0; v; v = v->v_link2) numVecs++; if (numVecs == 0) return; /* Open the output data file. */ if ((file_data = fopen(filename_data, appendwrite ? "a" : "w")) == NULL) { perror(filename); return; } i = 0; for (v = vecs; v; v = v->v_link2) scale = v->v_scale; /* Write out the data as simple arrays */ for (i = 0; i < scale->v_length; i++) { for (v = vecs; v; v = v->v_link2) { scale = v->v_scale; xval = isreal(scale) ? scale->v_realdata[i] : realpart(scale->v_compdata[i]); if (isreal(v)) fprintf(file_data, "% e % e ", xval, v->v_realdata[i]); else fprintf(file_data, "% e % e % e ", xval, realpart(v->v_compdata[i]), imagpart(v->v_compdata[i])); } fprintf(file_data, "\n"); } (void) fclose(file_data); }
void lincopy(struct dvec *ov, double *newscale, int newlen, struct dvec *oldscale) { struct dvec *v; double *nd; if (!isreal(ov)) { fprintf(cp_err, "Warning: %s is not real\n", ov->v_name); return; } if (ov->v_length < oldscale->v_length) { fprintf(cp_err, "Warning: %s is too short\n", ov->v_name); return; } v = alloc(struct dvec); v->v_name = copy(ov->v_name); v->v_type = ov->v_type; v->v_flags = ov->v_flags; v->v_flags |= VF_PERMANENT; v->v_length = newlen; nd = (double *) tmalloc(newlen * sizeof (double)); if (!ft_interpolate(ov->v_realdata, nd, oldscale->v_realdata, oldscale->v_length, newscale, newlen, 1)) { fprintf(cp_err, "Error: can't interpolate %s\n", ov->v_name); return; } v->v_realdata = nd; vec_new(v); return; }
static void xtend(struct dvec *v, int length) { int i; if (v->v_length == length) return; if (v->v_length > length) { dvec_trunc(v, length); return; } i = v->v_length; dvec_realloc(v, length, NULL); if (isreal(v)) { double d = NAN; if (i > 0) d = v->v_realdata[i - 1]; while (i < length) v->v_realdata[i++] = d; } else { ngcomplex_t c = {NAN, NAN}; if (i > 0) c = v->v_compdata[i - 1]; while (i < length) v->v_compdata[i++] = c; } }
double * DBgetData(struct plot *plot, char *name, int lengthWanted) { struct dvec *v; double *data; int i; v = vec_fromplot(name,plot); if (!v) { fprintf( stderr, "Error: cannot locate variable '%s'\n", name ); return(NULL); } if (v->v_length != lengthWanted ) { fprintf( stderr, "Error: vector '%s' has incorrect length\n", name ); return(NULL); } data = TMALLOC(double, v->v_length); if (isreal(v)) { bcopy(v->v_realdata, data, sizeof (double) * (size_t) v->v_length); } else { for (i=0; i < v->v_length; i++) { data[i] = realpart(v->v_compdata[i]); } } return(data); }
//double * //ft_SMITHminmax(struct dvec *v, bool yval) double * ft_SMITHminmax(struct dvec *v, int yval) { static double res[2]; register int i; double d, d2; res[0] = HUGE; res[1] = - res[0]; for (i = 0; i < v->v_length; i++) { if (isreal(v)) SMITH_tfm(v->v_realdata[i], 0.0, &d, &d2); else SMITH_tfm(realpart(v->v_compdata[i]), imagpart(v->v_compdata[i]), &d, &d2); /* Are we are looking for min/max X or Y ralue */ if (yval) d = d2; if (d < res[0]) res[0] = d; if (d > res[1]) res[1] = d; } return (res); }
struct variable * cp_enqvar(char *word) { struct dvec *d; struct variable *vv, *tv; struct plot *pl; int i; if (*word == '&') { word++; d = vec_get(word); if (!d) return (NULL); if (d->v_length == 1) { vv = alloc(struct variable); vv->va_next = NULL; vv->va_name = copy(word); vv->va_type = CP_REAL; if (isreal(d)) vv->va_real = d->v_realdata[0]; else vv->va_real = realpart(d->v_compdata[0]); } else {
void dd (header *hd) { header *st=hd,*hd1,*result; int c1,c2,i,j,r; double *m1,*m2,*mr; complex *mc1,*mc2,*mcr,hc1,hc2; interval *mi1,*mi2,*mir,hi1,hi2; hd1=next_param(st); equal_params_2(&hd,&hd1); if (error) return; getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg(); getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg(); if (c1!=c2) wrong_arg(); if (iscomplex(hd)) /* complex values */ { mc1=(complex *)m1; mc2=(complex *)m2; result=new_cmatrix(1,c1,""); if (error) return; mcr=(complex *)matrixof(result); memmove((char *)mcr,(char *)mc2,c1*sizeof(complex)); for (i=1; i<c1; i++) { for (j=c1-1; j>=i; j--) { if (mc1[j][0]==mc1[j-i][0] && mc1[j][1]==mc1[j-i][1]) wrong_arg(); c_sub(mcr[j],mcr[j-1],hc1); c_sub(mc1[j],mc1[j-i],hc2); c_div(hc1,hc2,mcr[j]); } } } else if (isinterval(hd)) /* complex values */ { mi1=(complex *)m1; mi2=(complex *)m2; result=new_imatrix(1,c1,""); if (error) return; mir=(interval *)matrixof(result); memmove((char *)mir,(char *)mi2,c1*sizeof(interval)); for (i=1; i<c1; i++) { for (j=c1-1; j>=i; j--) { i_sub(mir[j],mir[j-1],hi1); if (hi1[0]<=0 && hi1[1]>=0) { output("Interval points coincide\n"); error=1; return; } i_sub(mi1[j],mi1[j-i],hi2); i_div(hi1,hi2,mir[j]); } } } else if (isreal(hd)) { result=new_matrix(1,c1,""); if (error) return; mr=matrixof(result); memmove((char *)mr,(char *)m2,c1*sizeof(double)); for (i=1; i<c1; i++) { for (j=c1-1; j>=i; j--) { if (m1[j]==m1[j-i]) wrong_arg(); mr[j]=(mr[j]-mr[j-1])/(m1[j]-m1[j-i]); } } } else wrong_arg(); moveresult(st,result); }
void polymult (header *hd) { header *st=hd,*hd1,*result; int c,c1,c2,i,r,j,k; double *m1,*m2,*mr,x; complex *mc1,*mc2,*mcr,xc,hc; interval *mi1,*mi2,*mir,xi,hi; hd1=next_param(st); equal_params_2(&hd,&hd1); if (error) return; getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg(); getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg(); if ((LONG)c1+c2-1>INT_MAX) wrong_arg(); c=c1+c2-1; if (iscomplex(hd)) { mc1=(complex *)m1; mc2=(complex *)m2; result=new_cmatrix(1,c,""); if (error) return; mcr=(complex *)matrixof(result); c_copy(xc,*mc1); mc1++; for (i=0; i<c2; i++) c_mult(xc,mc2[i],mcr[i]); for (j=1; j<c1; j++) { c_copy(xc,*mc1); mc1++; for (k=j,i=0; i<c2-1; i++,k++) { c_mult(xc,mc2[i],hc); c_add(hc,mcr[k],mcr[k]); } c_mult(xc,mc2[i],mcr[k]); } } else if (isinterval(hd)) { mi1=(interval *)m1; mi2=(interval *)m2; result=new_imatrix(1,c,""); if (error) return; mir=(interval *)matrixof(result); i_copy(xi,*mi1); mi1++; for (i=0; i<c2; i++) i_mult(xi,mi2[i],mir[i]); for (j=1; j<c1; j++) { i_copy(xi,*mi1); mi1++; for (k=j,i=0; i<c2-1; i++,k++) { i_mult(xi,mi2[i],hi); c_add(hi,mir[k],mir[k]); } c_mult(xi,mi2[i],mir[k]); } } else if (isreal(hd)) { result=new_matrix(1,c,""); if (error) return; mr=matrixof(result); x=*m1++; for (i=0; i<c2; i++) mr[i]=x*m2[i]; for (j=1; j<c1; j++) { x=*m1++; for (k=j,i=0; i<c2-1; i++,k++) mr[k]+=x*m2[i]; mr[k]=x*m2[i]; } } else wrong_arg(); moveresult(st,result); }
struct dvec * vec_copy(struct dvec *v) { struct dvec *nv; int i; if (!v) return (NULL); nv = dvec_alloc(copy(v->v_name), v->v_type, v->v_flags & ~VF_PERMANENT, v->v_length, NULL); if (isreal(v)) bcopy(v->v_realdata, nv->v_realdata, sizeof(double) * (size_t) v->v_length); else bcopy(v->v_compdata, nv->v_compdata, sizeof(ngcomplex_t) * (size_t) v->v_length); nv->v_minsignal = v->v_minsignal; nv->v_maxsignal = v->v_maxsignal; nv->v_gridtype = v->v_gridtype; nv->v_plottype = v->v_plottype; /* Modified to copy the rlength of origin to destination vecor * instead of always putting it to 0. * As when it comes to make a print does not leave M1 @ @ M1 = 0.0, * to do so in the event that rlength = 0 not print anything on screen * nv-> v_rlength = 0; * Default -> v_rlength = 0 and only if you come from a print or M1 @ * @ M1 [all] rlength = 1, after control is one of * if (v-> v_rlength == 0) com_print (wordlist * wl) */ nv->v_rlength = v->v_rlength; nv->v_outindex = 0; /*XXX???*/ nv->v_linestyle = 0; /*XXX???*/ nv->v_color = 0; /*XXX???*/ nv->v_defcolor = v->v_defcolor; nv->v_numdims = v->v_numdims; for (i = 0; i < v->v_numdims; i++) nv->v_dims[i] = v->v_dims[i]; nv->v_plot = v->v_plot; nv->v_next = NULL; nv->v_link2 = NULL; nv->v_scale = v->v_scale; return (nv); }
void polyadd (header *hd) { header *st=hd,*hd1,*result; int c,c1,c2,i,r; double *m1,*m2,*mr; complex *mc1,*mc2,*mcr; interval *mi1,*mi2,*mir; hd1=next_param(st); equal_params_2(&hd,&hd1); if (error) return; getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg(); getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg(); c=max(c1,c2); if (iscomplex(hd)) /* complex values */ { mc1=(complex *)m1; mc2=(complex *)m2; result=new_cmatrix(1,c,""); if (error) return; mcr=(complex *)matrixof(result); for (i=0; i<c; i++) { if (i>=c1) { c_copy(*mcr,*mc2); mcr++; mc2++; } else if (i>=c2) { c_copy(*mcr,*mc1); mcr++; mc1++; } else { c_add(*mc1,*mc2,*mcr); mc1++; mc2++; mcr++; } } } else if (isinterval(hd)) { mi1=(interval *)m1; mi2=(interval *)m2; result=new_imatrix(1,c,""); if (error) return; mir=(interval *)matrixof(result); for (i=0; i<c; i++) { if (i>=c1) { i_copy(*mir,*mi2); mir++; mi2++; } else if (i>=c2) { i_copy(*mir,*mi1); mir++; mi1++; } else { i_add(*mi1,*mi2,*mir); mi1++; mi2++; mir++; } } } else if (isreal(hd)) { result=new_matrix(1,c,""); if (error) return; mr=matrixof(result); for (i=0; i<c; i++) { if (i>=c1) { *mr++ = *m2++; } else if (i>=c2) { *mr++ = *m1++; } else { *mr++ = *m1++ + *m2++; } } } else wrong_arg(); moveresult(st,result); }
/* Copy the data from a vector into a buffer with larger dimensions. */ static void dimxpand(struct dvec *v, int *newdims, double *data) { ngcomplex_t *cdata = (ngcomplex_t *) data; bool realflag = isreal(v); int i, j, o, n, t, u; int ncount[MAXDIMS], ocount[MAXDIMS]; for (i = 0; i < MAXDIMS; i++) ncount[i] = ocount[i] = 0; for (;;) { for (o = n = i = 0; i < v->v_numdims; i++) { for (j = i, t = u = 1; j < v->v_numdims; j++) { t *= v->v_dims[j]; u *= newdims[j]; } o += ocount[i] * t; n += ncount[i] * u; } if (realflag) { data[n] = v->v_realdata[o]; } else { cdata[n] = v->v_compdata[o]; } /* Now find the nextstrchr element... */ for (i = v->v_numdims - 1; i >= 0; i--) if ((ocount[i] < v->v_dims[i] - 1) && (ncount[i] < newdims[i] - 1)) { ocount[i]++; ncount[i]++; break; } else { ocount[i] = ncount[i] = 0; } if (i < 0) break; } }
bool vec_iszero(struct dvec *v) { int i; for (; v; v = v->v_link2) if (isreal(v)) for (i = 0; i < v->v_length; i++) { if (v->v_realdata[i] != 0.0) return FALSE; } else for (i = 0; i < v->v_length; i++) { if (realpart(v->v_compdata[i]) != 0.0) return FALSE; if (imagpart(v->v_compdata[i]) != 0.0) return FALSE; } return TRUE; }
bool cp_istrue(wordlist *wl) { int i; struct dvec *v; struct pnode *pn; /* fprintf(stderr, "isTRUE: "); wl_print(wl, stderr); fprintf(stderr, "\n"); */ /* First do all the csh-type stuff here... */ wl = wl_copy(wl); wl = cp_variablesubst(wl); wl = cp_bquote(wl); cp_striplist(wl); pn = ft_getpnames(wl, TRUE); wl_free(wl); v = ft_evaluate(pn); /* It makes no sense to say while (all), but what the heck... */ while (v) { if (isreal(v)) { for (i = 0; i < v->v_length; i++) if (v->v_realdata[i] != 0.0) { free_pnode(pn); return (TRUE); } } else { for (i = 0; i < v->v_length; i++) if ((realpart(&v->v_compdata[i]) != 0.0) || (imagpart(&v->v_compdata[i]) != 0.0)) { free_pnode(pn); return (TRUE); } } v = v->v_link2; } free_pnode(pn); return (FALSE); }
bool cp_istrue(wordlist *wl) { int i; struct dvec *v; struct pnode *names; /* First do all the csh-type stuff here... */ wl = wl_copy(wl); wl = cp_variablesubst(wl); wl = cp_bquote(wl); cp_striplist(wl); names = ft_getpnames(wl, TRUE); wl_free(wl); v = ft_evaluate(names); for (; v; v = v->v_link2) if (isreal(v)) { for (i = 0; i < v->v_length; i++) if (v->v_realdata[i] != 0.0) { free_pnode(names); return (TRUE); } } else { for (i = 0; i < v->v_length; i++) if ((realpart(v->v_compdata[i]) != 0.0) || (imagpart(v->v_compdata[i]) != 0.0)) { free_pnode(names); return (TRUE); } } free_pnode(names); return (FALSE); }
//double * //ft_minmax(struct dvec *v, bool real) double * ft_minmax(struct dvec *v, int real) { static double res[2]; register int i; double d; res[0] = HUGE; res[1] = - res[0]; for (i = 0; i < v->v_length; i++) { if (isreal(v)) d = v->v_realdata[i]; else if (real) d = realpart(v->v_compdata[i]); else d = imagpart(v->v_compdata[i]); if (d < res[0]) res[0] = d; if (d > res[1]) res[1] = d; } return (res); }
int fourier(wordlist *wl, struct plot *current_plot) { struct dvec *time, *vec; struct pnode *pn, *names; double *ff, fundfreq, *data = NULL; int nfreqs, fourgridsize, polydegree; double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */ double thd, *timescale = NULL; char *s; int i, err, fw; char xbuf[20]; int shift; int rv = 1; char newvecname[32]; struct dvec *n; int newveccount = 1; static int callstof = 1; if (!current_plot) return 1; sprintf(xbuf, "%1.1e", 0.0); shift = (int) strlen(xbuf) - 7; if (!current_plot || !current_plot->pl_scale) { fprintf(cp_err, "Error: no vectors loaded.\n"); return 1; } if (!cp_getvar("nfreqs", CP_NUM, &nfreqs) || nfreqs < 1) nfreqs = 10; if (!cp_getvar("polydegree", CP_NUM, &polydegree) || polydegree < 0) polydegree = 1; if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize) || fourgridsize < 1) fourgridsize = DEF_FOURGRIDSIZE; time = current_plot->pl_scale; if (!isreal(time)) { fprintf(cp_err, "Error: fourier needs real time scale\n"); return 1; } s = wl->wl_word; if ((ff = ft_numparse(&s, FALSE)) == NULL || (*ff <= 0.0)) { fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word); return 1; } fundfreq = *ff; freq = TMALLOC(double, nfreqs); mag = TMALLOC(double, nfreqs); phase = TMALLOC(double, nfreqs); nmag = TMALLOC(double, nfreqs); nphase = TMALLOC(double, nfreqs); wl = wl->wl_next; names = ft_getpnames(wl, TRUE); for (pn = names; pn; pn = pn->pn_next) { vec = ft_evaluate(pn); for (; vec; vec = vec->v_link2) { if (vec->v_length != time->v_length) { fprintf(cp_err, "Error: lengths don't match: %d, %d\n", vec->v_length, time->v_length); continue; } if (!isreal(vec)) { fprintf(cp_err, "Error: %s isn't real!\n", vec->v_name); continue; } if (polydegree) { double *dp, d; /* Build the grid... */ timescale = TMALLOC(double, fourgridsize); data = TMALLOC(double, fourgridsize); dp = ft_minmax(time, TRUE); /* Now get the last fund freq... */ d = 1 / fundfreq; /* The wavelength... */ if (dp[1] - dp[0] < d) { fprintf(cp_err, "Error: wavelength longer than time span\n"); goto done; } else if (dp[1] - dp[0] > d) { dp[0] = dp[1] - d; } d = (dp[1] - dp[0]) / fourgridsize; for (i = 0; i < fourgridsize; i++) timescale[i] = dp[0] + i * d; /* Now interpolate the data... */ if (!ft_interpolate(vec->v_realdata, data, time->v_realdata, vec->v_length, timescale, fourgridsize, polydegree)) { fprintf(cp_err, "Error: can't interpolate\n"); goto done; } } else { fourgridsize = vec->v_length; data = vec->v_realdata; timescale = time->v_realdata; } err = CKTfour(fourgridsize, nfreqs, &thd, timescale, data, fundfreq, freq, mag, phase, nmag, nphase); if (err != OK) { ft_sperror(err, "fourier"); goto done; } fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name); fprintf(cp_out, " No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d\n\n", nfreqs, thd, fourgridsize, polydegree); /* Each field will have width cp_numdgt + 6 (or 7 * with HP-UX) + 1 if there is a - sign. */ fw = ((cp_numdgt > 0) ? cp_numdgt : 6) + 5 + shift; fprintf(cp_out, "Harmonic %-*s %-*s %-*s %-*s %-*s\n", fw, "Frequency", fw, "Magnitude", fw, "Phase", fw, "Norm. Mag", fw, "Norm. Phase"); fprintf(cp_out, "-------- %-*s %-*s %-*s %-*s %-*s\n", fw, "---------", fw, "---------", fw, "-----", fw, "---------", fw, "-----------"); for (i = 0; i < nfreqs; i++) { char *pnumfr, *pnumma, *pnumph, *pnumnm, *pnumnp; pnumfr = pnum(freq[i]); pnumma = pnum(mag[i]); pnumph = pnum(phase[i]); pnumnm = pnum(nmag[i]); pnumnp = pnum(nphase[i]); fprintf(cp_out, " %-4d %-*s %-*s %-*s %-*s %-*s\n", i, fw, pnumfr, fw, pnumma, fw, pnumph, fw, pnumnm, fw, pnumnp); tfree(pnumfr); tfree(pnumma); tfree(pnumph); tfree(pnumnm); tfree(pnumnp); } fputs("\n", cp_out); /* generate name for new vector, using vec->name */ sprintf(newvecname, "fourier%d%d", callstof, newveccount); /* create and assign a new vector n */ /* with size 3 * nfreqs in current plot */ n = alloc(struct dvec); ZERO(n, struct dvec); n->v_name = copy(newvecname); n->v_type = SV_NOTYPE; n->v_flags = (VF_REAL | VF_PERMANENT); n->v_length = 3 * nfreqs; n->v_numdims = 2; n->v_dims[0] = 3; n->v_dims[1] = nfreqs; n->v_realdata = TMALLOC(double, n->v_length); vec_new(n); /* store data in vector: freq, mag, phase */ for (i = 0; i < nfreqs; i++) { n->v_realdata[i] = freq[i]; n->v_realdata[i + nfreqs] = mag[i]; n->v_realdata[i + 2 * nfreqs] = phase[i]; } newveccount++; if (polydegree) { tfree(timescale); tfree(data); } timescale = NULL; data = NULL; } }
struct variable * cp_enqvar(char *word) { struct dvec *d; struct variable *vv; if (*word == '&') { word++; d = vec_get(word); if (!d) return (NULL); if (d->v_link2) fprintf(cp_err, "Warning: only one vector may be accessed with the $& notation.\n"); if (d->v_length == 1) { double value = isreal(d) ? d->v_realdata[0] : realpart(d->v_compdata[0]); return var_alloc_real(copy(word), value, NULL); } else { struct variable *list = NULL; int i; for (i = d->v_length; --i >= 0;) { double value = isreal(d) ? d->v_realdata[i] : realpart(d->v_compdata[i]); list = var_alloc_real(NULL, value, list); } return var_alloc_vlist(copy(word), list, NULL); } } if (plot_cur) { for (vv = plot_cur->pl_env; vv; vv = vv->va_next) if (eq(vv->va_name, word)) return (vv); if (eq(word, "curplotname")) return var_alloc_string(copy(word), copy(plot_cur->pl_name), NULL); if (eq(word, "curplottitle")) return var_alloc_string(copy(word), copy(plot_cur->pl_title), NULL); if (eq(word, "curplotdate")) return var_alloc_string(copy(word), copy(plot_cur->pl_date), NULL); if (eq(word, "curplot")) return var_alloc_string(copy(word), copy(plot_cur->pl_typename), NULL); if (eq(word, "plots")) { struct variable *list = NULL; struct plot *pl; for (pl = plot_list; pl; pl = pl->pl_next) list = var_alloc_string(NULL, copy(pl->pl_typename), list); return var_alloc_vlist(copy(word), list, NULL); } } if (ft_curckt) for (vv = ft_curckt->ci_vars; vv; vv = vv->va_next) if (eq(vv->va_name, word)) return (vv); return (NULL); }
void com_diff(wordlist *wl) { double vntol, abstol, reltol, tol, cmax, cm1, cm2; struct plot *p1, *p2 = NULL; struct dvec *v1, *v2; double d1, d2; ngcomplex_t c1, c2, c3; int i, j; char *v1_name; /* cannonical v1 name */ char *v2_name; /* cannonical v2 name */ NGHASHPTR crossref_p; /* cross reference hash table */ SPICE_DSTRING ibuf; /* used to build cannonical name */ wordlist *tw; char numbuf[BSIZE_SP], numbuf2[BSIZE_SP], numbuf3[BSIZE_SP], numbuf4[BSIZE_SP]; /* For printnum */ if (!cp_getvar("diff_vntol", CP_REAL, &vntol)) vntol = 1.0e-6; if (!cp_getvar("diff_abstol", CP_REAL, &abstol)) abstol = 1.0e-12; if (!cp_getvar("diff_reltol", CP_REAL, &reltol)) reltol = 0.001; /* Let's try to be clever about defaults. This code is ugly. */ if (!wl || !wl->wl_next) { if (plot_list && plot_list->pl_next && !plot_list->pl_next->pl_next) { p1 = plot_list; p2 = plot_list->pl_next; if (wl && !eq(wl->wl_word, p1->pl_typename) && !eq(wl->wl_word, p2->pl_typename)) { fprintf(cp_err, "Error: no such plot \"%s\"\n", wl->wl_word); return; } fprintf(cp_err, "Plots are \"%s\" and \"%s\"\n", plot_list->pl_typename, plot_list->pl_next->pl_typename); if (wl) wl = NULL; } else { fprintf(cp_err, "Error: plot names not given.\n"); return; } } else { for (p1 = plot_list; p1; p1 = p1->pl_next) if (eq(wl->wl_word, p1->pl_typename)) break; if (!p1) { fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word); return; } wl = wl->wl_next; } if (!p2) { for (p2 = plot_list; p2; p2 = p2->pl_next) if (eq(wl->wl_word, p2->pl_typename)) break; if (!p2) { fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word); return; } wl = wl->wl_next; } /* Now do some tests to make sure these plots are really the * same type, etc. */ if (!eq(p1->pl_name, p2->pl_name)) fprintf(cp_err, "Warning: plots %s and %s seem to be of different types\n", p1->pl_typename, p2->pl_typename); if (!eq(p1->pl_title, p2->pl_title)) fprintf(cp_err, "Warning: plots %s and %s seem to be from different circuits\n", p1->pl_typename, p2->pl_typename); /* This may not be the best way to do this. It wasn't :). The original * was O(n2) - not good. Now use a hash table to reduce it to O(n). */ for (v1 = p1->pl_dvecs; v1; v1 = v1->v_next) v1->v_link2 = NULL; spice_dstring_init(&ibuf); crossref_p = nghash_init(NGHASH_MIN_SIZE); nghash_unique(crossref_p, FALSE); for (v2 = p2->pl_dvecs; v2; v2 = v2->v_next) { v2->v_link2 = NULL; v2_name = cannonical_name(v2->v_name, &ibuf); nghash_insert(crossref_p, v2_name, v2); } for (v1 = p1->pl_dvecs; v1; v1 = v1->v_next) { v1_name = cannonical_name(v1->v_name, &ibuf); for (v2 = nghash_find(crossref_p, v1_name); v2; v2 = nghash_find_again(crossref_p, v1_name)) { if (!v2->v_link2 && ((v1->v_flags & (VF_REAL | VF_COMPLEX)) == (v2->v_flags & (VF_REAL | VF_COMPLEX))) && (v1->v_type == v2->v_type)) { v1->v_link2 = v2; v2->v_link2 = v1; break; } } } spice_dstring_free(&ibuf); nghash_free(crossref_p, NULL, NULL); for (v1 = p1->pl_dvecs; v1; v1 = v1->v_next) if (!v1->v_link2) fprintf(cp_err, ">>> %s vector %s in %s not in %s, or of wrong type\n", isreal(v1) ? "real" : "complex", v1->v_name, p1->pl_typename, p2->pl_typename); for (v2 = p2->pl_dvecs; v2; v2 = v2->v_next) if (!v2->v_link2) fprintf(cp_err, ">>> %s vector %s in %s not in %s, or of wrong type\n", isreal(v2) ? "real" : "complex", v2->v_name, p2->pl_typename, p1->pl_typename); /* Throw out the ones that aren't in the arg list */ if (wl && !eq(wl->wl_word, "all")) { /* Just in case */ for (v1 = p1->pl_dvecs; v1; v1 = v1->v_next) if (v1->v_link2) { for (tw = wl; tw; tw = tw->wl_next) if (nameeq(v1->v_name, tw->wl_word)) break; if (!tw) v1->v_link2 = NULL; } for (v2 = p2->pl_dvecs; v2; v2 = v2->v_next) if (v2->v_link2) { for (tw = wl; tw; tw = tw->wl_next) if (nameeq(v2->v_name, tw->wl_word)) break; if (!tw) v2->v_link2 = NULL; } } /* Now we have all the vectors linked to their twins. Travel * down each one and print values that differ enough. */ for (v1 = p1->pl_dvecs; v1; v1 = v1->v_next) { if (!v1->v_link2) continue; v2 = v1->v_link2; if (v1->v_type == SV_VOLTAGE) tol = vntol; else tol = abstol; j = MAX(v1->v_length, v2->v_length); for (i = 0; i < j; i++) { if (v1->v_length <= i) { fprintf(cp_out, ">>> %s is %d long in %s and %d long in %s\n", v1->v_name, v1->v_length, p1->pl_typename, v2->v_length, p2->pl_typename); break; } else if (v2->v_length <= i) { fprintf(cp_out, ">>> %s is %d long in %s and %d long in %s\n", v2->v_name, v2->v_length, p2->pl_typename, v1->v_length, p1->pl_typename); break; } else { if (isreal(v1)) { d1 = v1->v_realdata[i]; d2 = v2->v_realdata[i]; if (MAX(fabs(d1), fabs(d2)) * reltol + tol < fabs(d1 - d2)) { printnum(numbuf, d1); fprintf(cp_out, "%s.%s[%d] = %-15s ", p1->pl_typename, v1->v_name, i, numbuf); printnum(numbuf, d2); fprintf(cp_out, "%s.%s[%d] = %s\n", p2->pl_typename, v2->v_name, i, numbuf); } } else { c1 = v1->v_compdata[i]; c2 = v2->v_compdata[i]; realpart(c3) = realpart(c1) - realpart(c2); imagpart(c3) = imagpart(c1) - imagpart(c2); /* Stupid evil PC compilers */ cm1 = cmag(c1); cm2 = cmag(c2); cmax = MAX(cm1, cm2); if (cmax * reltol + tol < cmag(c3)) { printnum(numbuf, realpart(c1)); printnum(numbuf2, imagpart(c1)); printnum(numbuf3, realpart(c2)); printnum(numbuf4, imagpart(c2)); fprintf(cp_out, "%s.%s[%d] = %-10s, %-10s %s.%s[%d] = %-10s, %s\n", p1->pl_typename, v1->v_name, i, numbuf, numbuf2, p2->pl_typename, v2->v_name, i, numbuf3, numbuf4); } } } } } }
void gr_iplot(struct plot *plot) { struct dbcomm *db; int dontpop; /* So we don't pop w/o push. */ char buf[30]; hit = 0; for (db = dbs; db; db = db->db_next) { if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) { if (db->db_graphid) PushGraphContext(FindGraph(db->db_graphid)); set(plot, db, FALSE, VF_PLOT); dontpop = 0; if (iplot(plot, db->db_graphid)) { /* graph just assigned */ db->db_graphid = currentgraph->graphid; dontpop = 1; } set(plot, db, TRUE, VF_PLOT); if (!dontpop && db->db_graphid) PopGraphContext(); } else if (db->db_type == DB_TRACENODE || db->db_type == DB_TRACEALL) { struct dvec *v, *u; int len; set(plot, db, FALSE, VF_PRINT); len = plot->pl_scale->v_length; dontpop = 0; for (v = plot->pl_dvecs; v; v = v->v_next) { if (v->v_flags & VF_PRINT) { u = plot->pl_scale; if (len <= 1 || hit <= 0 || hit2 < 0) { if (len <= 1 || hit2 < 0) term_clear(); else term_home(); hit = 1; hit2 = 1; printf( "\tExecution trace (remove with the \"delete\" command)"); term_cleol(); printf("\n"); if (u) { printf("%12s:", u->v_name); if (isreal(u)) { printf("%s", getitright(buf, u->v_realdata[len - 1])); } else { /* MW. Complex data here, realdata is NULL (why someone use realdata here again) */ printf("%s", getitright(buf, u->v_compdata[len - 1].cx_real)); printf(", %s", getitright(buf, u->v_compdata[len - 1].cx_imag)); } term_cleol(); printf("\n"); } } if (v == u) continue; printf("%12s:", v->v_name); if (isreal(v)) { printf("%s", getitright(buf, v->v_realdata[len - 1])); } else { /* MW. Complex data again */ printf("%s", getitright(buf, v->v_compdata[len - 1].cx_real)); printf(", %s", getitright(buf, v->v_compdata[len - 1].cx_imag)); } term_cleol(); printf("\n"); } } set(plot, db, TRUE, VF_PRINT); } } }
void raw_write(char *name, struct plot *pl, bool app, bool binary) { FILE *fp; bool realflag = TRUE, writedims; bool raw_padding; int length, numdims, dims[MAXDIMS]; int nvars, i, j, prec; struct dvec *v, *lv; wordlist *wl; struct variable *vv; double dd; char buf[BSIZE_SP]; char *branch; raw_padding = !cp_getvar("nopadding", CP_BOOL, NULL); /* Why bother printing out an empty plot? */ if (!pl->pl_dvecs) { fprintf(cp_err, "Error: plot is empty, nothing written.\n"); return; } if (raw_prec != -1) prec = raw_prec; else prec = DEFPREC; #if defined(__MINGW32__) || defined(_MSC_VER) /* - Binary file binary write - hvogt 15.03.2000 ---------------------*/ if (binary) { if ((fp = fopen(name, app ? "ab" : "wb")) == NULL) { perror(name); return; } fprintf(cp_out, "binary raw file\n"); } else { if ((fp = fopen(name, app ? "a" : "w")) == NULL) { perror(name); return; } fprintf(cp_out, "ASCII raw file\n"); } /* --------------------------------------------------------------------*/ #else if (!(fp = fopen(name, app ? "a" : "w"))) { perror(name); return; } #endif numdims = nvars = length = 0; for (v = pl->pl_dvecs; v; v = v->v_next) { if (iscomplex(v)) realflag = FALSE; nvars++; /* Find the length and dimensions of the longest vector * in the plot. * Be paranoid and assume somewhere we may have * forgotten to set the dimensions of 1-D vectors. */ if (v->v_numdims <= 1) { v->v_numdims = 1; v->v_dims[0] = v->v_length; } if (v->v_length > length) { length = v->v_length; numdims = v->v_numdims; for (j = 0; j < numdims; j++) { dims[j] = v->v_dims[j]; } } } fprintf(fp, "Title: %s\n", pl->pl_title); fprintf(fp, "Date: %s\n", pl->pl_date); fprintf(fp, "Plotname: %s\n", pl->pl_name); fprintf(fp, "Flags: %s%s\n", realflag ? "real" : "complex", raw_padding ? "" : " unpadded"); fprintf(fp, "No. Variables: %d\n", nvars); fprintf(fp, "No. Points: %d\n", length); if (numdims > 1) { dimstring(dims, numdims, buf); fprintf(fp, "Dimensions: %s\n", buf); } for (wl = pl->pl_commands; wl; wl = wl->wl_next) fprintf(fp, "Command: %s\n", wl->wl_word); for (vv = pl->pl_env; vv; vv = vv->va_next) { wl = cp_varwl(vv); if (vv->va_type == CP_BOOL) { fprintf(fp, "Option: %s\n", vv->va_name); } else { fprintf(fp, "Option: %s = ", vv->va_name); if (vv->va_type == CP_LIST) fprintf(fp, "( "); wl_print(wl, fp); if (vv->va_type == CP_LIST) fprintf(fp, " )"); (void) putc('\n', fp); } } /* Before we write the stuff out, make sure that the scale is the first * in the list. */ for (lv = NULL, v = pl->pl_dvecs; v != pl->pl_scale; v = v->v_next) lv = v; if (lv) { lv->v_next = v->v_next; v->v_next = pl->pl_dvecs; pl->pl_dvecs = v; } fprintf(fp, "Variables:\n"); for (i = 0, v = pl->pl_dvecs; v; v = v->v_next) { if (v->v_type == SV_CURRENT) { branch = NULL; if ((branch = strstr(v->v_name, "#branch")) != NULL) { *branch = '\0'; } fprintf(fp, "\t%d\ti(%s)\t%s", i++, v->v_name, ft_typenames(v->v_type)); if (branch != NULL) *branch = '#'; } else if (v->v_type == SV_VOLTAGE) { fprintf(fp, "\t%d\t%s\t%s", i++, v->v_name, ft_typenames(v->v_type)); } else { fprintf(fp, "\t%d\t%s\t%s", i++, v->v_name, ft_typenames(v->v_type)); } if (v->v_flags & VF_MINGIVEN) fprintf(fp, " min=%e", v->v_minsignal); if (v->v_flags & VF_MAXGIVEN) fprintf(fp, " max=%e", v->v_maxsignal); if (v->v_defcolor) fprintf(fp, " color=%s", v->v_defcolor); if (v->v_gridtype) fprintf(fp, " grid=%d", v->v_gridtype); if (v->v_plottype) fprintf(fp, " plot=%d", v->v_plottype); /* Only write dims if they are different from default. */ writedims = FALSE; if (v->v_numdims != numdims) { writedims = TRUE; } else { for (j = 0; j < numdims; j++) if (dims[j] != v->v_dims[j]) writedims = TRUE; } if (writedims) { dimstring(v->v_dims, v->v_numdims, buf); fprintf(fp, " dims=%s", buf); } (void) putc('\n', fp); } if (binary) { fprintf(fp, "Binary:\n"); for (i = 0; i < length; i++) { for (v = pl->pl_dvecs; v; v = v->v_next) { /* Don't run off the end of this vector's data. */ if (i < v->v_length) { if (realflag) { dd = (isreal(v) ? v->v_realdata[i] : realpart(v->v_compdata[i])); (void) fwrite(&dd, sizeof(double), 1, fp); } else if (isreal(v)) { dd = v->v_realdata[i]; (void) fwrite(&dd, sizeof(double), 1, fp); dd = 0.0; (void) fwrite(&dd, sizeof(double), 1, fp); } else { dd = realpart(v->v_compdata[i]); (void) fwrite(&dd, sizeof(double), 1, fp); dd = imagpart(v->v_compdata[i]); (void) fwrite(&dd, sizeof(double), 1, fp); } } else if (raw_padding) { dd = 0.0; if (realflag) { (void) fwrite(&dd, sizeof(double), 1, fp); } else { (void) fwrite(&dd, sizeof(double), 1, fp); (void) fwrite(&dd, sizeof(double), 1, fp); } } } } } else { fprintf(fp, "Values:\n"); for (i = 0; i < length; i++) { fprintf(fp, " %d", i); for (v = pl->pl_dvecs; v; v = v->v_next) { if (i < v->v_length) { if (realflag) fprintf(fp, "\t%.*e\n", prec, isreal(v) ? v->v_realdata[i] : realpart(v->v_compdata[i])); else if (isreal(v)) fprintf(fp, "\t%.*e,0.0\n", prec, v->v_realdata[i]); else fprintf(fp, "\t%.*e,%.*e\n", prec, realpart(v->v_compdata[i]), prec, imagpart(v->v_compdata[i])); } else if (raw_padding) { if (realflag) fprintf(fp, "\t%.*e\n", prec, 0.0); else fprintf(fp, "\t%.*e,%.*e\n", prec, 0.0, prec, 0.0); } } (void) putc('\n', fp); } } (void) fclose(fp); }
static int iplot(struct plot *pl, int id) { int len = pl->pl_scale->v_length; struct dvec *v, *xs = pl->pl_scale; double *lims, dy; double start, stop, step; register int j; bool changed = FALSE; int yt; char *yl = NULL; double xlims[2], ylims[2]; static REQUEST reqst = { checkup_option, NULL }; int inited = 0; char commandline[513]; for (j = 0, v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) j++; if (!j) return (0); if (ft_grdb) fprintf(cp_err, "Entering iplot, len = %d\n", len); if (len < IPOINTMIN) { /* Nothing yet */ return (0); } else if (len == IPOINTMIN || !id) { resumption = FALSE; /* Draw the grid for the first time, and plot everything. */ lims = ft_minmax(xs, TRUE); xlims[0] = lims[0]; xlims[1] = lims[1]; ylims[0] = HUGE; ylims[1] = - ylims[0]; for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { lims = ft_minmax(v, TRUE); if (ylims[0] > lims[0]) ylims[0] = lims[0]; if (ylims[1] < lims[1]) ylims[1] = lims[1]; if (!yl) yl = v->v_name; } /* generate a small difference between ymin and ymax to catch the y=const case */ if (ylims[0] == ylims[1]) ylims[1] += 1e-9; if (ft_grdb) fprintf(cp_err, "iplot: after 5, xlims = %G, %G, ylims = %G, %G\n", xlims[0], xlims[1], ylims[0], ylims[1]); for (yt = pl->pl_dvecs->v_type, v = pl->pl_dvecs->v_next; v; v = v->v_next) if ((v->v_flags & VF_PLOT) && (v->v_type != yt)) { yt = SV_NOTYPE; break; } /* note: have command options for iplot to specify xdelta, etc. So don't need static variables hack. Assume default values for now. */ sprintf(commandline, "plot %s", yl); (void) gr_init(xlims, ylims, xs->v_name, pl->pl_title, NULL, j, 0.0, 0.0, GRID_LIN, PLOT_LIN, xs->v_name, yl, xs->v_type, yt, plot_cur->pl_typename, commandline); for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { gr_start_internal(v, FALSE); ft_graf(v, xs, TRUE); } inited = 1; } else { /* plot the last points and resize if needed */ Input(&reqst, NULL); /* First see if we have to make the screen bigger */ dy = (isreal(xs) ? xs->v_realdata[len - 1] : realpart(xs->v_compdata[len - 1])); if (ft_grdb) fprintf(cp_err, "x = %G\n", dy); if (!if_tranparams(ft_curckt, &start, &stop, &step) || !ciprefix("tran", pl->pl_typename)) { stop = HUGE; start = - stop; } /* checking for x lo */ while (dy < currentgraph->data.xmin) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: xlo %G -> %G\n", currentgraph->data.xmin, currentgraph->data.xmin - (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR); /* set the new x lo value */ currentgraph->data.xmin -= (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR; if (currentgraph->data.xmin < start) { currentgraph->data.xmin = start; break; } } if (currentgraph->data.xmax < currentgraph->data.xmin) currentgraph->data.xmax = currentgraph->data.xmin; /* checking for x hi */ while (dy > currentgraph->data.xmax) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: xhi %G -> %G\n", currentgraph->data.xmax, currentgraph->data.xmax + (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR); /* set the new x hi value */ currentgraph->data.xmax += (currentgraph->data.xmax - currentgraph->data.xmin) * XFACTOR; if (currentgraph->data.xmax > stop) { currentgraph->data.xmax = stop; break; } } /* checking for all y values */ for (v = pl->pl_dvecs; v; v = v->v_next) { if (!(v->v_flags & VF_PLOT)) continue; dy = (isreal(v) ? v->v_realdata[len - 1] : realpart(v->v_compdata[len - 1])); if (ft_grdb) fprintf(cp_err, "y = %G\n", dy); /* checking for y lo */ while (dy < currentgraph->data.ymin) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: ylo %G -> %G\n", currentgraph->data.ymin, currentgraph->data.ymin - (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR); /* set the new y lo value */ currentgraph->data.ymin -= (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR; /* currentgraph->data.ymin += (dy - currentgraph->data.ymin) * YFACTOR;*/ /* currentgraph->data.ymin = dy; currentgraph->data.ymin *= (1 + YFACTOR); */ } if (currentgraph->data.ymax < currentgraph->data.ymin) currentgraph->data.ymax = currentgraph->data.ymin; /* checking for y hi */ while (dy > currentgraph->data.ymax) { changed = TRUE; if (ft_grdb) fprintf(cp_err, "resize: yhi %G -> %G\n", currentgraph->data.ymax, currentgraph->data.ymax + (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR); /* set the new y hi value */ currentgraph->data.ymax += (currentgraph->data.ymax - currentgraph->data.ymin) * YFACTOR; /* currentgraph->data.ymax += (dy - currentgraph->data.ymax) * YFACTOR;*/ /* currentgraph->data.ymax = dy; currentgraph->data.ymax *= (1 + YFACTOR); */ } } if (changed) { /* Redraw everything. */ gr_pmsg("Resizing screen"); gr_resize(currentgraph); #ifndef X_DISPLAY_MISSING gr_redraw(currentgraph); #endif } else { /* Just connect the last two points. This won't be done * with curve interpolation, so it might look funny. */ for (v = pl->pl_dvecs; v; v = v->v_next) if (v->v_flags & VF_PLOT) { gr_point(v, (isreal(xs) ? xs->v_realdata[len - 1] : realpart(xs->v_compdata[len - 1])), (isreal(v) ? v->v_realdata[len - 1] : realpart(v->v_compdata[len - 1])), (isreal(xs) ? xs->v_realdata[len - 2] : realpart(xs->v_compdata[len - 2])), (isreal(v) ? v->v_realdata[len - 2] : realpart(v->v_compdata[len - 2])), len - 1); } } } DevUpdate(); return (inited); }
void ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs) { FILE *file, *file_data; struct dvec *v, *scale = NULL; double xval, yval, extrange; int i, numVecs, linewidth, err, terminal_type; bool xlog, ylog, nogrid, markers; char buf[BSIZE_SP], pointstyle[BSIZE_SP], *text, plotstyle[BSIZE_SP], terminal[BSIZE_SP]; char filename_data[128]; char filename_plt[128]; sprintf(filename_data, "%s.data", filename); sprintf(filename_plt, "%s.plt", filename); /* Sanity checking. */ for (v = vecs, numVecs = 0; v; v = v->v_link2) numVecs++; if (numVecs == 0) { return; } else if (numVecs > GP_MAXVECTORS) { fprintf(cp_err, "Error: too many vectors for gnuplot.\n"); return; } if (fabs((ylims[1]-ylims[0])/ylims[0]) < 1.0e-6) { fprintf(cp_err, "Error: range min ... max too small for using gnuplot.\n"); fprintf(cp_err, " Consider plotting with offset %g.\n", ylims[0]); return; } extrange = 0.05 * (ylims[1] - ylims[0]); if (!cp_getvar("gnuplot_terminal", CP_STRING, terminal)) { terminal_type = 1; } else { terminal_type = 1; if (cieq(terminal,"png")) terminal_type = 2; } if (!cp_getvar("xbrushwidth", CP_NUM, &linewidth)) linewidth = 1; if (linewidth < 1) linewidth = 1; if (!cp_getvar("pointstyle", CP_STRING, pointstyle)) { markers = FALSE; } else { if (cieq(pointstyle,"markers")) markers = TRUE; else markers = FALSE; } /* Make sure the gridtype is supported. */ switch (gridtype) { case GRID_LIN: nogrid = xlog = ylog = FALSE; break; case GRID_XLOG: xlog = TRUE; nogrid = ylog = FALSE; break; case GRID_YLOG: ylog = TRUE; nogrid = xlog = FALSE; break; case GRID_LOGLOG: xlog = ylog = TRUE; nogrid = FALSE; break; case GRID_NONE: nogrid = TRUE; xlog = ylog = FALSE; break; default: fprintf(cp_err, "Error: grid type unsupported by gnuplot.\n"); return; } /* Open the output gnuplot file. */ if ((file = fopen(filename_plt, "w")) == NULL) { perror(filename); return; } /* Set up the file header. */ #if !defined(__MINGW__) && !defined(_MSC_VER) fprintf(file, "set terminal X11\n"); #endif if (title) { text = cp_unquote(title); fprintf(file, "set title \"%s\"\n", text); tfree(text); } if (xlabel) { text = cp_unquote(xlabel); fprintf(file, "set xlabel \"%s\"\n", text); tfree(text); } if (ylabel) { text = cp_unquote(ylabel); fprintf(file, "set ylabel \"%s\"\n", text); tfree(text); } if (!nogrid) { if (linewidth > 1) fprintf(file, "set grid lw %d \n" , linewidth); else fprintf(file, "set grid\n"); } if (xlog) { fprintf(file, "set logscale x\n"); if (xlims) fprintf(file, "set xrange [%1.0e:%1.0e]\n", pow(10, floor(log10(xlims[0]))), pow(10, ceil(log10(xlims[1])))); fprintf(file, "set xrange [%e:%e]\n", xlims[0], xlims[1]); fprintf(file, "set mxtics 10\n"); fprintf(file, "set grid mxtics\n"); } else { fprintf(file, "unset logscale x \n"); if (xlims) fprintf(file, "set xrange [%e:%e]\n", xlims[0], xlims[1]); } if (ylog) { fprintf(file, "set logscale y \n"); if (ylims) fprintf(file, "set yrange [%1.0e:%1.0e]\n", pow(10, floor(log10(ylims[0]))), pow(10, ceil(log10(ylims[1])))); fprintf(file, "set mytics 10\n"); fprintf(file, "set grid mytics\n"); } else { fprintf(file, "unset logscale y \n"); if (ylims) fprintf(file, "set yrange [%e:%e]\n", ylims[0] - extrange, ylims[1] + extrange); } fprintf(file, "#set xtics 1\n"); fprintf(file, "#set x2tics 1\n"); fprintf(file, "#set ytics 1\n"); fprintf(file, "#set y2tics 1\n"); if (linewidth > 1) fprintf(file, "set border lw %d\n", linewidth); if (plottype == PLOT_COMB) { strcpy(plotstyle, "boxes"); } else if (plottype == PLOT_POINT) { if (markers) { // fprintf(file, "Markers: True\n"); } else { // fprintf(file, "LargePixels: True\n"); } strcpy(plotstyle, "points"); } else { strcpy(plotstyle, "lines"); } /* Open the output gnuplot data file. */ if ((file_data = fopen(filename_data, "w")) == NULL) { perror(filename); return; } fprintf(file, "set format y \"%%g\"\n"); fprintf(file, "set format x \"%%g\"\n"); fprintf(file, "plot "); i = 0; /* Write out the gnuplot command */ for (v = vecs; v; v = v->v_link2) { scale = v->v_scale; if (v->v_name) { i = i + 2; if (i > 2) fprintf(file, ",\\\n"); fprintf(file, "\'%s\' using %d:%d with %s lw %d title \"%s\" ", filename_data, i-1, i, plotstyle, linewidth, v->v_name); } } fprintf(file, "\n"); fprintf(file, "set terminal push\n"); if (terminal_type == 1) { fprintf(file, "set terminal postscript eps color\n"); fprintf(file, "set out \'%s.eps\'\n", filename); } else { fprintf(file, "set terminal png\n"); fprintf(file, "set out \'%s.png\'\n", filename); } fprintf(file, "replot\n"); fprintf(file, "set term pop\n"); fprintf(file, "replot\n"); (void) fclose(file); /* Write out the data and setup arrays */ for (i = 0; i < scale->v_length; i++) { for (v = vecs; v; v = v->v_link2) { scale = v->v_scale; xval = isreal(scale) ? scale->v_realdata[i] : realpart(scale->v_compdata[i]); yval = isreal(v) ? v->v_realdata[i] : realpart(v->v_compdata[i]); fprintf(file_data, "%e %e ", xval, yval); } fprintf(file_data, "\n"); } (void) fclose(file_data); #if defined(__MINGW32__) || defined(_MSC_VER) /* for external fcn system() */ // (void) sprintf(buf, "start /B wgnuplot %s -" , filename_plt); (void) sprintf(buf, "start /B wgnuplot -persist %s " , filename_plt); _flushall(); #else /* for external fcn system() from LINUX environment */ (void) sprintf(buf, "xterm -e gnuplot %s - &", filename_plt); #endif err = system(buf); }
int ft_cktcoms(bool terse) { wordlist *coms, *command, all; char *plottype, *s; struct dvec *v; static wordlist twl = { "col", NULL, NULL }; struct plot *pl; int i, found; char numbuf[BSIZE_SP]; /* For printnum*/ all.wl_next = NULL; all.wl_word = "all"; if (!ft_curckt) return 1; plot_cur = setcplot("op"); if (!ft_curckt->ci_commands && !plot_cur) goto nocmds; coms = ft_curckt->ci_commands; cp_interactive = FALSE; /* Listing */ if (ft_listprint) { if (terse) fprintf(cp_err, ".options: no listing, rawfile was generated.\n"); else inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options, LS_DECK); } /* If there was a .op line, then we have to do the .op output. */ plot_cur = setcplot("op"); if (plot_cur != NULL) { assert(plot_cur->pl_dvecs != NULL); if (plot_cur->pl_dvecs->v_realdata != NULL) { if (terse) { fprintf(cp_out, "OP information in rawfile.\n"); } else { fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage"); fprintf(cp_out, "\t%-30s%15s\n", "----", "-------"); fprintf(cp_out, "\t----\t-------\n"); for (v = plot_cur->pl_dvecs; v; v = v->v_next) { if (!isreal(v)) { fprintf(cp_err, "Internal error: op vector %s not real\n", v->v_name); continue; } if ((v->v_type == SV_VOLTAGE) && (*(v->v_name) != '@')) { printnum(numbuf, v->v_realdata[0]); fprintf(cp_out, "\t%-30s%15s\n", v->v_name, numbuf); } } fprintf(cp_out, "\n\tSource\tCurrent\n"); fprintf(cp_out, "\t------\t-------\n\n"); for (v = plot_cur->pl_dvecs; v; v = v->v_next) if (v->v_type == SV_CURRENT) { printnum(numbuf, v->v_realdata[0]); fprintf(cp_out, "\t%-30s%15s\n", v->v_name, numbuf); } fprintf(cp_out, "\n"); if (!ft_nomod) com_showmod(&all); com_show(&all); } } } for (pl = plot_list; pl; pl = pl->pl_next) if (ciprefix("tf", pl->pl_typename)) { if (terse) { fprintf(cp_out, "TF information in rawfile.\n"); break; } plot_cur = pl; fprintf(cp_out, "Transfer function information:\n"); com_print(&all); fprintf(cp_out, "\n"); } /* Now all the '.' lines */ while (coms) { command = cp_lexer(coms->wl_word); if (!command) goto bad; if (eq(command->wl_word, ".width")) { do command = command->wl_next; while (command && !ciprefix("out", command->wl_word)); if (command) { s = strchr(command->wl_word, '='); if (!s || !s[1]) { fprintf(cp_err, "Error: bad line %s\n", coms->wl_word); coms = coms->wl_next; continue; } i = atoi(++s); cp_vset("width", CP_NUM, &i); } } else if (eq(command->wl_word, ".print")) { if (terse) { fprintf(cp_out, ".print line ignored since rawfile was produced.\n"); } else { command = command->wl_next; if (!command) { fprintf(cp_err, "Error: bad line %s\n", coms->wl_word); coms = coms->wl_next; continue; } plottype = command->wl_word; command = command->wl_next; fixdotprint(command); twl.wl_next = command; found = 0; for (pl = plot_list; pl; pl = pl->pl_next) if (ciprefix(plottype, pl->pl_typename)) { plot_cur = pl; com_print(&twl); fprintf(cp_out, "\n"); found = 1; } if (!found) fprintf(cp_err, "Error: .print: no %s analysis found.\n", plottype); } } else if (eq(command->wl_word, ".plot")) { if (terse) { fprintf(cp_out, ".plot line ignored since rawfile was produced.\n"); } else { command = command->wl_next; if (!command) { fprintf(cp_err, "Error: bad line %s\n", coms->wl_word); coms = coms->wl_next; continue; } plottype = command->wl_word; command = command->wl_next; fixdotplot(command); found = 0; for (pl = plot_list; pl; pl = pl->pl_next) if (ciprefix(plottype, pl->pl_typename)) { plot_cur = pl; com_asciiplot(command); fprintf(cp_out, "\n"); found = 1; } if (!found) fprintf(cp_err, "Error: .plot: no %s analysis found.\n", plottype); } } else if (ciprefix(".four", command->wl_word)) { if (terse) { fprintf(cp_out, ".fourier line ignored since rawfile was produced.\n"); } else { int err; plot_cur = setcplot("tran"); err = fourier(command->wl_next, plot_cur); if (!err) fprintf(cp_out, "\n\n"); else fprintf(cp_err, "No transient data available for " "fourier analysis"); } } else if (!eq(command->wl_word, ".save") && !eq(command->wl_word, ".op") && // !eq(command->wl_word, ".measure") && !ciprefix(".meas", command->wl_word) && !eq(command->wl_word, ".tf")) { goto bad; } coms = coms->wl_next; } nocmds: /* Now the node table if (ft_nodesprint) ; */ /* The options */ if (ft_optsprint) { fprintf(cp_out, "Options:\n\n"); cp_vprint(); (void) putc('\n', cp_out); } /* And finally the accounting info. */ if (ft_acctprint) { static wordlist ww = { "everything", NULL, NULL }; com_rusage(&ww); } else if ((!ft_noacctprint) && (!ft_acctprint)) { com_rusage(NULL); } /* absolutely no accounting if noacct is given */ putc('\n', cp_out); return 0; bad: fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n"); return 1; }
void polydiv (header *hd) { header *st=hd,*hd1,*result,*rest; int c1,c2,i,r,j; double *m1,*m2,*mr,*mh,x,l; complex *mc1,*mc2,*mcr,*mch,xc,lc,hc; interval *mi1,*mi2,*mir,*mih,xi,li,hi; hd1=next_param(st); equal_params_2(&hd,&hd1); if (error) return; getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg(); getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg(); if (c1<c2) { result=new_real(0.0,""); rest=(header *)newram; moveresult(rest,hd1); } else if (iscomplex(hd)) { mc1=(complex *)m1; mc2=(complex *)m2; result=new_cmatrix(1,c1-c2+1,""); if (error) return; mcr=(complex *)matrixof(result); rest=new_cmatrix(1,c2,""); if (error) return; mch=(complex *)newram; if (!freeram(c1*sizeof(complex))) { output("Out of memory!\n"); error=190; return; } memmove((char *)mch,(char *)mc1,c1*sizeof(complex)); c_copy(lc,mc2[c2-1]); if (lc[0]==0.0 && lc[1]==0.0) wrong_arg(); for (i=c1-c2; i>=0; i--) { c_div(mch[c2+i-1],lc,xc); c_copy(mcr[i],xc); for(j=0; j<c2; j++) { c_mult(mc2[j],xc,hc); c_sub(mch[i+j],hc,mch[i+j]); } } memmove((char *)matrixof(rest),(char *)mch,c2*sizeof(complex)); } else if (isinterval(hd)) { mi1=(interval *)m1; mi2=(interval *)m2; result=new_imatrix(1,c1-c2+1,""); if (error) return; mir=(interval *)matrixof(result); rest=new_imatrix(1,c2,""); if (error) return; mih=(complex *)newram; if (!freeram(c1*sizeof(complex))) { output("Out of memory!\n"); error=190; return; } memmove((char *)mih,(char *)mi1,c1*sizeof(interval)); i_copy(li,mi2[c2-1]); if (li[0]<=0.0 && li[1]>=0.0) wrong_arg(); for (i=c1-c2; i>=0; i--) { i_div(mih[c2+i-1],li,xi); c_copy(mir[i],xi); for(j=0; j<c2; j++) { i_mult(mi2[j],xi,hi); i_sub(mih[i+j],hi,mih[i+j]); } } memmove((char *)matrixof(rest),(char *)mih,c2*sizeof(interval)); } else if (isreal(hd)) { result=new_matrix(1,c1-c2+1,""); if (error) return; mr=matrixof(result); rest=new_matrix(1,c2,""); if (error) return; mh=(double *)newram; if (!freeram(c1*sizeof(double))) { output("Out of memory!\n"); error=190; return; } memmove((char *)mh,(char *)m1,c1*sizeof(double)); l=m2[c2-1]; if (l==0.0) wrong_arg(); for (i=c1-c2; i>=0; i--) { x=mh[c2+i-1]/l; mr[i]=x; for(j=0; j<c2; j++) mh[i+j]-=m2[j]*x; } memmove((char *)matrixof(rest),(char *)mh,c2*sizeof(double)); } else wrong_arg(); moveresult(st,result); moveresult(nextof(st),rest); }
void com_print(wordlist *wl) { struct dvec *v, *lv = NULL, *bv, *nv, *vecs = NULL; int i, j, ll, width = DEF_WIDTH, height = DEF_HEIGHT, npoints, lineno; struct pnode *pn, *names; struct plot *p; bool col = TRUE, nobreak = FALSE, noprintscale, plotnames = FALSE; bool optgiven = FALSE; char *s, *buf, *buf2; /*, buf[BSIZE_SP], buf2[BSIZE_SP];*/ char numbuf[BSIZE_SP], numbuf2[BSIZE_SP]; /* Printnum buffers */ int ngood; if (wl == NULL) return; buf = TMALLOC(char, BSIZE_SP); buf2 = TMALLOC(char, BSIZE_SP); if (eq(wl->wl_word, "col")) { col = TRUE; optgiven = TRUE; wl = wl->wl_next; } else if (eq(wl->wl_word, "line")) { col = FALSE; optgiven = TRUE; wl = wl->wl_next; } ngood = 0; names = ft_getpnames(wl, TRUE); for (pn = names; pn; pn = pn->pn_next) { if ((v = ft_evaluate(pn)) == NULL) continue; if (!vecs) vecs = lv = v; else lv->v_link2 = v; for (lv = v; lv->v_link2; lv = lv->v_link2) ; ngood += 1; } if (!ngood) goto done; /* See whether we really have to print plot names. */ for (v = vecs; v; v = v->v_link2) if (vecs->v_plot != v->v_plot) { plotnames = TRUE; break; } if (!optgiven) { /* Figure out whether col or line should be used... */ col = FALSE; for (v = vecs; v; v = v->v_link2) if (v->v_length > 1) { col = TRUE; /* Improvement made to print cases @[sin] = (0 12 13 100K) */ if ((v->v_plot->pl_scale && v->v_length != v->v_plot->pl_scale->v_length) && (*(v->v_name) == '@')) { col = FALSE; } break; } /* With this I have found that the vector has less elements than the SCALE vector * in the linked PLOT. But now I must make sure in case of a print @vin[sin] or * @vin[pulse] * for it appear that the v->v_name begins with '@' * And then be in this case. */ } out_init(); if (!col) { if (cp_getvar("width", CP_NUM, &i)) width = i; if (width < 60) width = 60; if (width > BSIZE_SP - 2) buf = TREALLOC(char, buf, width + 1); for (v = vecs; v; v = v->v_link2) { char *basename = vec_basename(v); if (plotnames) (void) sprintf(buf, "%s.%s", v->v_plot->pl_typename, basename); else (void) strcpy(buf, basename); tfree(basename); for (s = buf; *s; s++) ; s--; while (isspace(*s)) { *s = '\0'; s--; } ll = 10; /* v->v_rlength = 1 when it comes to make a print @ M1 and does not want to come out on screen * Multiplier factor [m]=1 * @M1 = 0,00e+00 * In any other case rlength not used for anything and only applies in the copy of the vectors. */ if (v->v_rlength == 0) { if (v->v_length == 1) { if (isreal(v)) { printnum(numbuf, *v->v_realdata); out_printf("%s = %s\n", buf, numbuf); } else { printnum(numbuf, realpart(v->v_compdata[0])); printnum(numbuf2, imagpart(v->v_compdata[0])); out_printf("%s = %s,%s\n", buf, numbuf, numbuf2); } } else { out_printf("%s = ( ", buf); for (i = 0; i < v->v_length; i++) if (isreal(v)) { printnum(numbuf, v->v_realdata[i]); (void) strcpy(buf, numbuf); out_send(buf); ll += (int) strlen(buf); ll = (ll + 7) / 8; ll = ll * 8 + 1; if (ll > width) { out_send("\n\t"); ll = 9; } else { out_send("\t"); } } else { /*DG*/ printnum(numbuf, realpart(v->v_compdata[i])); printnum(numbuf2, imagpart(v->v_compdata[i])); (void) sprintf(buf, "%s,%s", numbuf, numbuf2); out_send(buf); ll += (int) strlen(buf); ll = (ll + 7) / 8; ll = ll * 8 + 1; if (ll > width) { out_send("\n\t"); ll = 9; } else { out_send("\t"); } } out_send(")\n"); } //end if (v->v_length == 1) } //end if (v->v_rlength == 1) } // end for loop } else { /* Print in columns. */ if (cp_getvar("width", CP_NUM, &i))
void ft_xgraph(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs) { FILE *file; struct dvec *v, *scale; double xval, yval; int i, numVecs, linewidth; bool xlog, ylog, nogrid, markers; char buf[BSIZE_SP], pointstyle[BSIZE_SP], *text; /* Sanity checking. */ for (v = vecs, numVecs = 0; v; v = v->v_link2) numVecs++; if (numVecs == 0) { return; } else if (numVecs > XG_MAXVECTORS) { fprintf(cp_err, "Error: too many vectors for Xgraph.\n"); return; } if (!cp_getvar("xbrushwidth", CP_NUM, &linewidth)) linewidth = 1; if (linewidth < 1) linewidth = 1; if (!cp_getvar("pointstyle", CP_STRING, pointstyle)) { markers = FALSE; } else { if (cieq(pointstyle, "markers")) markers = TRUE; else markers = FALSE; } /* Make sure the gridtype is supported. */ switch (gridtype) { case GRID_LIN: nogrid = xlog = ylog = FALSE; break; case GRID_XLOG: xlog = TRUE; nogrid = ylog = FALSE; break; case GRID_YLOG: ylog = TRUE; nogrid = xlog = FALSE; break; case GRID_LOGLOG: xlog = ylog = TRUE; nogrid = FALSE; break; case GRID_NONE: nogrid = TRUE; xlog = ylog = FALSE; break; default: fprintf(cp_err, "Error: grid type unsupported by Xgraph.\n"); return; } /* Open the output file. */ if ((file = fopen(filename, "w")) == NULL) { perror(filename); return; } /* Set up the file header. */ if (title) { text = cp_unquote(title); fprintf(file, "TitleText: %s\n", text); tfree(text); } if (xlabel) { text = cp_unquote(xlabel); fprintf(file, "XUnitText: %s\n", text); tfree(text); } if (ylabel) { text = cp_unquote(ylabel); fprintf(file, "YUnitText: %s\n", text); tfree(text); } if (nogrid) { fprintf(file, "Ticks: True\n"); } if (xlog) { fprintf(file, "LogX: True\n"); if (xlims) { fprintf(file, "XLowLimit: % e\n", log10(xlims[0])); fprintf(file, "XHighLimit: % e\n", log10(xlims[1])); } } else { if (xlims) { fprintf(file, "XLowLimit: % e\n", xlims[0]); fprintf(file, "XHighLimit: % e\n", xlims[1]); } } if (ylog) { fprintf(file, "LogY: True\n"); if (ylims) { fprintf(file, "YLowLimit: % e\n", log10(ylims[0])); fprintf(file, "YHighLimit: % e\n", log10(ylims[1])); } } else { if (ylims) { fprintf(file, "YLowLimit: % e\n", ylims[0]); fprintf(file, "YHighLimit: % e\n", ylims[1]); } } fprintf(file, "LineWidth: %d\n", linewidth); fprintf(file, "BoundBox: True\n"); if (plottype == PLOT_COMB) { fprintf(file, "BarGraph: True\n"); fprintf(file, "NoLines: True\n"); } else if (plottype == PLOT_POINT) { if (markers) fprintf(file, "Markers: True\n"); else fprintf(file, "LargePixels: True\n"); fprintf(file, "NoLines: True\n"); } /* Write out the data. */ for (v = vecs; v; v = v->v_link2) { scale = v->v_scale; if (v->v_name) fprintf(file, "\"%s\"\n", v->v_name); for (i = 0; i < scale->v_length; i++) { xval = isreal(scale) ? scale->v_realdata[i] : realpart(scale->v_compdata[i]); yval = isreal(v) ? v->v_realdata[i] : realpart(v->v_compdata[i]); fprintf(file, "% e % e\n", xval, yval); } fprintf(file, "\n"); } (void) fclose(file); (void) sprintf(buf, "xgraph %s &", filename); (void) system(buf); }
static void oldwrite(char *name, bool app, struct plot *pl) { short four = 4, k; struct dvec *v; float f1, f2, zero = 0.0; char buf[80]; int i, j, tp = VF_REAL, numpts = 0, numvecs = 0; FILE *fp; if (!(fp = fopen(name, app ? "a" : "w"))) { perror(name); return; } for (v = pl->pl_dvecs; v; v = v->v_next) { if (v->v_length > numpts) numpts = v->v_length; numvecs++; if (iscomplex(v)) tp = VF_COMPLEX; } /* This may not be a good idea... */ if (tp == VF_COMPLEX) pl->pl_scale->v_type = SV_FREQUENCY; for (i = 0; i < 80; i++) buf[i] = ' '; for (i = 0; i < 80; i++) if (pl->pl_title[i] == '\0') break; else buf[i] = pl->pl_title[i]; tfwrite(buf, 1, 80, fp); for (i = 0; i < 80; i++) buf[i] = ' '; for (i = 0; i < 16; i++) if (pl->pl_date[i] == '\0') break; else buf[i] = pl->pl_date[i]; tfwrite(buf, 1, 16, fp); tfwrite(&numvecs, sizeof (short), 1, fp); tfwrite(&four, sizeof (short), 1, fp); for (v = pl->pl_dvecs; v; v = v->v_next) { for (j = 0; j < 80; j++) buf[j] = ' '; for (j = 0; j < 8; j++) if (v->v_name[j] == '\0') break; else buf[j] = v->v_name[j]; tfwrite(buf, 1, 8, fp); } for (v = pl->pl_dvecs; v; v = v->v_next) { j = (short) v->v_type; tfwrite(&j, sizeof (short), 1, fp); } for (k = 1; k < numvecs + 1; k++) tfwrite(&k, sizeof (short), 1, fp); for (j = 0; j < 80; j++) buf[j] = ' '; for (j = 0; j < 24; j++) if (pl->pl_name[j] == '\0') break; else buf[j] = pl->pl_name[j]; tfwrite(buf, 1, 24, fp); for (i = 0; i < numpts; i++) { for (v = pl->pl_dvecs; v; v = v->v_next) { if ((tp == VF_REAL) && isreal(v)) { if (i < v->v_length) { tfwrite(&v->v_realdata[i], sizeof (double), 1, fp); } else { tfwrite(&v->v_realdata[v->v_length - 1], sizeof (double), 1, fp); } } else if ((tp == VF_REAL) && iscomplex(v)) { fprintf(cp_err, "internal error, everything real, yet complex ...\n"); exit(1); } else if ((tp == VF_COMPLEX) && isreal(v)) { if (i < v->v_length) f1 = (float) v->v_realdata[i]; else f1 = (float) v->v_realdata[v->v_length - 1]; tfwrite(&f1, sizeof (float), 1, fp); tfwrite(&zero, sizeof (float), 1, fp); } else if ((tp == VF_COMPLEX) && iscomplex(v)) { if (i < v->v_length) { f1 = (float) realpart(v->v_compdata[i]); f2 = (float) imagpart(v->v_compdata[i]); } else { f1 = (float) realpart(v->v_compdata[v-> v_length - 1]); f2 = (float) imagpart(v->v_compdata[v-> v_length - 1]); } tfwrite(&f1, sizeof (float), 1, fp); tfwrite(&f2, sizeof (float), 1, fp); } } } (void) fclose(fp); return; }