* commands.c: Use fourier.h.

* dotcards.c: Update to prevent segfault.

	* fourier.c, fourier.h: com_fourier is now calling fourier(), a
	function with more parameters.

	* dotcards.c: Added assertions to guard a double indirection, now
	ngspice will bomb out on an assertion instead of a segfault.
This commit is contained in:
arno 2000-09-09 13:24:30 +00:00
parent 7a3a17a5b9
commit 508fee7d4b
5 changed files with 142 additions and 108 deletions

View File

@ -1,5 +1,12 @@
2000-09-09 Arno W. Peters <A.W.Peters@ieee.org> 2000-09-09 Arno W. Peters <A.W.Peters@ieee.org>
* commands.c: Use fourier.h.
* dotcards.c: Update to prevent segfault.
* fourier.c, fourier.h: com_fourier is now calling fourier(), a
function with more parameters.
* dotcards.c: Added assertions to guard a double indirection, now * dotcards.c: Added assertions to guard a double indirection, now
ngspice will bomb out on an assertion instead of a segfault. ngspice will bomb out on an assertion instead of a segfault.

View File

@ -47,7 +47,7 @@
#include "com_plot.h" #include "com_plot.h"
#include "com_setscale.h" #include "com_setscale.h"
#include "com_xgraph.h" #include "com_xgraph.h"
#include "fourier.h"
/* FIXME: Integrate spcp_coms and nutcp_coms into one variable. */ /* FIXME: Integrate spcp_coms and nutcp_coms into one variable. */

View File

@ -20,19 +20,35 @@ Modified: 2000 AlansFixes
#include "circuits.h" #include "circuits.h"
#include "dotcards.h" #include "dotcards.h"
#include "variable.h" #include "variable.h"
#include "fourier.h"
/* Extract all the .save lines */ /* Extract all the .save lines */
static void fixdotplot(wordlist *wl); static void fixdotplot(wordlist *wl);
static void fixdotprint(wordlist *wl); static void fixdotprint(wordlist *wl);
static char * fixem(char *string); static char * fixem(char *string);
static bool setcplot(char *name);
static wordlist * gettoks(char *s); static wordlist * gettoks(char *s);
extern void com_save2 (wordlist *wl, char *name); extern void com_save2 (wordlist *wl, char *name);
static struct plot *
setcplot(char *name)
{
struct plot *pl;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix(name, pl->pl_typename)) {
return pl;
}
}
return NULL;
}
void void
ft_dotsaves(void) ft_dotsaves(void)
{ {
@ -157,7 +173,9 @@ ft_cktcoms(bool terse)
if (!ft_curckt) if (!ft_curckt)
return 1; return 1;
if (!ft_curckt->ci_commands && !setcplot("op"))
plot_cur = setcplot("op");
if (!ft_curckt->ci_commands && !plot_cur)
goto nocmds; goto nocmds;
coms = ft_curckt->ci_commands; coms = ft_curckt->ci_commands;
cp_interactive = FALSE; cp_interactive = FALSE;
@ -172,9 +190,10 @@ ft_cktcoms(bool terse)
} }
/* If there was a .op line, then we have to do the .op output. */ /* If there was a .op line, then we have to do the .op output. */
assert(plot_cur != NULL); plot_cur = setcplot("op");
if (plot_cur != NULL) {
assert(plot_cur->pl_dvecs != NULL); assert(plot_cur->pl_dvecs != NULL);
if (setcplot("op") && (plot_cur->pl_dvecs->v_realdata!=NULL)) { if (plot_cur->pl_dvecs->v_realdata!=NULL) {
if (terse) { if (terse) {
fprintf(cp_out, "OP information in rawfile.\n"); fprintf(cp_out, "OP information in rawfile.\n");
} else { } else {
@ -205,6 +224,7 @@ ft_cktcoms(bool terse)
com_show(&all); com_show(&all);
} }
} }
}
for (pl = plot_list; pl; pl = pl->pl_next) { for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix("tf", pl->pl_typename)) { if (ciprefix("tf", pl->pl_typename)) {
@ -298,12 +318,17 @@ ft_cktcoms(bool terse)
if (terse) { if (terse) {
fprintf(cp_out, fprintf(cp_out,
".fourier line ignored since rawfile was produced.\n"); ".fourier line ignored since rawfile was produced.\n");
} else if (setcplot("tran")) { } else {
com_fourier(command->wl_next); int err;
plot_cur = setcplot("tran");
err = fourier(command->wl_next, plot_cur);
if (!err)
fprintf(cp_out, "\n\n"); fprintf(cp_out, "\n\n");
} else else
fprintf(cp_err, fprintf(cp_err, "No transient data available for "
"No transient data available for fourier analysis"); "fourier analysis");
}
} else if (!eq(command->wl_word, ".save") } else if (!eq(command->wl_word, ".save")
&& !eq(command->wl_word, ".op") && !eq(command->wl_word, ".op")
&& !eq(command->wl_word, ".tf")) && !eq(command->wl_word, ".tf"))
@ -313,7 +338,7 @@ ft_cktcoms(bool terse)
coms = coms->wl_next; coms = coms->wl_next;
} }
nocmds: nocmds:
/* Now the node table */ /* Now the node table */
if (ft_nodesprint) if (ft_nodesprint)
; ;
@ -335,7 +360,7 @@ nocmds:
putc('\n', cp_out); putc('\n', cp_out);
return 0; return 0;
bad: bad:
fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n"); fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n");
return 1; return 1;
} }
@ -473,22 +498,6 @@ fixem(char *string)
return (string); return (string);
} }
/* Don't bother with ccom strangeness here. */
static bool
setcplot(char *name)
{
struct plot *pl;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (ciprefix(name, pl->pl_typename)) {
plot_cur = pl;
return (TRUE);
}
}
return (FALSE);
}
static wordlist * static wordlist *
gettoks(char *s) gettoks(char *s)
{ {

View File

@ -31,12 +31,15 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va
#define DEF_FOURGRIDSIZE 200 #define DEF_FOURGRIDSIZE 200
/* CKTfour(ndata,numFreq,thd,Time,Value,FundFreq,Freq,Mag,Phase,nMag,nPhase) /* CKTfour(ndata,numFreq,thd,Time,Value,FundFreq,Freq,Mag,Phase,nMag,nPhase)
* len 10 ? inp inp inp out out out out out * len 10 ? inp inp inp out out out out out
*/ */
void /* FIXME: This function leaks memory due to non local exit bypassing
com_fourier(wordlist *wl) freeing of memory at the end of the function. */
int
fourier(wordlist *wl, struct plot *current_plot)
{ {
struct dvec *time, *vec; struct dvec *time, *vec;
struct pnode *names, *first_name; struct pnode *names, *first_name;
@ -49,11 +52,14 @@ com_fourier(wordlist *wl)
char xbuf[20]; char xbuf[20];
int shift; int shift;
if (!current_plot)
return 1;
sprintf(xbuf, "%1.1e", 0.0); sprintf(xbuf, "%1.1e", 0.0);
shift = strlen(xbuf) - 7; shift = strlen(xbuf) - 7;
if (!plot_cur || !plot_cur->pl_scale) { if (!current_plot || !current_plot->pl_scale) {
fprintf(cp_err, "Error: no vectors loaded.\n"); fprintf(cp_err, "Error: no vectors loaded.\n");
return; return 1;
} }
if ((!cp_getvar("nfreqs", VT_NUM, (char *) &nfreqs)) || (nfreqs < 1)) if ((!cp_getvar("nfreqs", VT_NUM, (char *) &nfreqs)) || (nfreqs < 1))
@ -65,15 +71,15 @@ com_fourier(wordlist *wl)
(fourgridsize < 1)) (fourgridsize < 1))
fourgridsize = DEF_FOURGRIDSIZE; fourgridsize = DEF_FOURGRIDSIZE;
time = plot_cur->pl_scale; time = current_plot->pl_scale;
if (!isreal(time)) { if (!isreal(time)) {
fprintf(cp_err, "Error: fourier needs real time scale\n"); fprintf(cp_err, "Error: fourier needs real time scale\n");
return; return 1;
} }
s = wl->wl_word; s = wl->wl_word;
if (!(ff = ft_numparse(&s, FALSE)) || (*ff <= 0.0)) { if (!(ff = ft_numparse(&s, FALSE)) || (*ff <= 0.0)) {
fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word); fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word);
return; return 1;
} }
fundfreq = *ff; fundfreq = *ff;
@ -115,7 +121,7 @@ com_fourier(wordlist *wl)
if (dp[1] - dp[0] < d) { if (dp[1] - dp[0] < d) {
fprintf(cp_err, fprintf(cp_err,
"Error: wavelength longer than time span\n"); "Error: wavelength longer than time span\n");
return; return 1;
} else if (dp[1] - dp[0] > d) { } else if (dp[1] - dp[0] > d) {
dp[0] = dp[1] - d; dp[0] = dp[1] - d;
} }
@ -131,7 +137,7 @@ com_fourier(wordlist *wl)
polydegree)) { polydegree)) {
fprintf(cp_err, fprintf(cp_err,
"Error: can't interpolate\n"); "Error: can't interpolate\n");
return; return 1;
} }
timescale = grid; timescale = grid;
} else { } else {
@ -145,7 +151,7 @@ com_fourier(wordlist *wl)
nphase); nphase);
if (err != OK) { if (err != OK) {
ft_sperror(err, "fourier"); ft_sperror(err, "fourier");
return; return 1;
} }
fprintf(cp_out, "Fourier analysis for %s:\n", fprintf(cp_out, "Fourier analysis for %s:\n",
@ -185,9 +191,18 @@ com_fourier(wordlist *wl)
tfree(phase); tfree(phase);
tfree(nmag); tfree(nmag);
tfree(nphase); tfree(nphase);
return; return 0;
} }
void
com_fourier(wordlist *wl)
{
fourier(wl, plot_cur);
}
static char * static char *
pn(double num) pn(double num)
{ {
@ -198,50 +213,54 @@ pn(double num)
i = 6; i = 6;
if (num < 0.0) if (num < 0.0)
(void) sprintf(buf, "%.*g", i - 1, num); sprintf(buf, "%.*g", i - 1, num);
else else
(void) sprintf(buf, "%.*g", i, num); sprintf(buf, "%.*g", i, num);
return (copy(buf)); return (copy(buf));
} }
/*
* CKTfour() - perform fourier analysis of an output vector. /* CKTfour() - perform fourier analysis of an output vector.
* Due to the construction of the program which places all the
* output data in the post-processor, the fourier analysis can not
* be done directly. This function allows the post processor to
* hand back vectors of time and data values to have the fourier analysis
* performed on them.
* *
*/ * Due to the construction of the program which places all the output
* data in the post-processor, the fourier analysis can not be done
* directly. This function allows the post processor to hand back
* vectors of time and data values to have the fourier analysis
* performed on them. */
static int static int
CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value, double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag, double *nPhase) CKTfour(int ndata, /* number of entries in the Time and
/* number of entries in the Time and Value arrays */ Value arrays */
/* number of harmonics to calculate */ int numFreq, /* number of harmonics to calculate */
/* total harmonic distortion (percent) to be returned */ double *thd, /* total harmonic distortion (percent)
/* times at which the voltage/current values were measured*/ to be returned */
/* voltage or current vector whose transform is desired */ double *Time, /* times at which the voltage/current
/* the fundamental frequency of the analysis */ values were measured*/
/* the frequency value of the various harmonics */ double *Value, /* voltage or current vector whose
/* the Magnitude of the fourier transform */ transform is desired */
/* the Phase of the fourier transform */ double FundFreq, /* the fundamental frequency of the
/* the normalized magnitude of the transform: nMag(fund)=1*/ analysis */
/* the normalized phase of the transform: Nphase(fund)=0 */ double *Freq, /* the frequency value of the various
/* note we can consider these as a set of arrays: The sizes are: harmonics */
* Time[ndata], Value[ndata] double *Mag, /* the Magnitude of the fourier
* Freq[numFreq],Mag[numfreq],Phase[numfreq],nMag[numfreq],nPhase[numfreq] transform */
double *Phase, /* the Phase of the fourier transform */
double *nMag, /* the normalized magnitude of the
transform: nMag(fund)=1*/
double *nPhase) /* the normalized phase of the
transform: Nphase(fund)=0 */
{
/* Note: we can consider these as a set of arrays. The sizes are:
* Time[ndata], Value[ndata], Freq[numFreq], Mag[numfreq],
* Phase[numfreq], nMag[numfreq], nPhase[numfreq]
*
* The arrays must all be allocated by the caller. * The arrays must all be allocated by the caller.
* The Time and Value array must be reasonably distributed over at * The Time and Value array must be reasonably distributed over at
* least one full period of the fundamental Frequency for the * least one full period of the fundamental Frequency for the
* fourier transform to be useful. The function will take the * fourier transform to be useful. The function will take the
* last period of the frequency as data for the transform. * last period of the frequency as data for the transform.
*/ *
* We are assuming that the caller has provided exactly one period
{ * of the fundamental frequency. */
/* we are assuming that the caller has provided exactly one period
* of the fundamental frequency.
*/
int i; int i;
int j; int j;
double tmp; double tmp;

View File

@ -7,7 +7,6 @@
#define FOURIER_H_INCLUDED #define FOURIER_H_INCLUDED
void com_fourier(wordlist *wl); void com_fourier(wordlist *wl);
int fourier(wordlist *wl, struct plot *current);
#endif #endif