Browse Source

Improvements in vector derivative computation and new functions to


			
			
				pre-master-46
			
			
		
pnenzi 17 years ago
parent
commit
f543aa8c06
  1. 17
      ChangeLog
  2. 4
      src/frontend/cpitf.c
  3. 4
      src/frontend/evaluate.c
  4. 2
      src/frontend/parse.c
  5. 62
      src/frontend/postcoms.c
  6. 2
      src/frontend/spiceif.c
  7. 3
      src/frontend/vectors.c
  8. 3
      src/include/fteext.h
  9. 45
      src/maths/cmaths/cmath2.c
  10. 234
      src/maths/cmaths/cmath4.c
  11. 2
      src/maths/cmaths/cmath4.h

17
ChangeLog

@ -1,3 +1,20 @@
2009-01-15 Paolo Nenzi
* src/frontend/vectors.c:
57: Fixed I(vx), before the if I(*) (upper case) was not recognized as the
function to plot the current of vx. A. Roldan - Espice
* src/frontend/postcoms.c:
7: Fixed plot number after "destroy all" command. A. Roldan - Espice
* src/include/fteext.h
* src/frontend/evaluate.c, src/frontend/cpitf.c, src/frontend/parse.c
* src/maths/cmaths/cmath2.c, src/cmaths/cmath4.c, src/cmaths/cmath4.h:
16: New function to compute the group delay has been implemented.
Group delay is defined as -(dphase/dfrequency) and can be printed or
plotted by writing vg(x), where x is a complex vector. A. Roldan - Espice
15: Fixed existing problems in this function due to the complex nature of
the frequency vector. To get the data from frequency[i], the real part
must be accessed. A. Roldan - Espice
14: New function to compute the moving average. A. Roldan - Espice
2009-01-15 Paolo Nenzi
* src/frontend/{spiceif.c, spiceif.h, vectors.c}, src/include/fteext.h,
* src/main.c:

4
src/frontend/cpitf.c

@ -55,7 +55,9 @@ ft_cpinit(void)
"vi(x,y)", "im(v(x) - v(y))",
"vm(x)", "mag(v(x))",
"vm(x,y)", "mag(v(x) - v(y))",
"vp(x)", "ph(v(x))",
"vg(x)", "group_delay(v(x))", //A.Rroldan 10/06/05 group delay new function
"gd(x)", "group_delay(v(x))", //A.Rroldan 10/06/05 group delay new function
"vp(x)", "ph(v(x))",
"vp(x,y)", "ph(v(x) - v(y))",
"vr(x)", "re(v(x))",
"vr(x,y)", "re(v(x) - v(y))"

4
src/frontend/evaluate.c

@ -707,8 +707,8 @@ apply_func(struct func *func, struct pnode *arg)
}
(void) signal(SIGILL, (SIGNAL_FUNCTION) sig_matherr);
if (eq(func->fu_name, "interpolate")
|| eq(func->fu_name, "deriv")) /* Ack */
/* Modified for passing necessary parameters to the derive function - A.Roldan */
if (eq(func->fu_name, "interpolate") || eq(func->fu_name, "deriv") || eq(func->fu_name, "group_delay")) /* Ack */
{
void *(*f)(void *data, short int type, int length,
int *newlength, short int *newtype, ...)=func->fu_func;

2
src/frontend/parse.c

@ -698,6 +698,8 @@ struct func ft_funcs[] = {
{ "rnd", cx_rnd } ,
{ "pos", cx_pos } ,
{ "mean", cx_mean } ,
{ "avg", cx_avg } , //A.Rroldan 03/06/05 incremental average new function
{ "group_delay", cx_group_delay } , //A.Rroldan 10/06/05 group delay new function
{ "vector", cx_vector } ,
{ "unitvec", cx_unitvec } ,
{ "length", cx_length } ,

62
src/frontend/postcoms.c

@ -260,7 +260,22 @@ nextpage:
if (isreal(v))
(void) sprintf(buf2, "%-16.15s", v->v_name);
else
(void) sprintf(buf2, "%-32.31s", v->v_name);
{
/* The frequency vector is complex but often with imaginary part = 0,
* this prevents to print two columns.
*/
if(eq(v->v_name, "frequency"))
{
if(imagpart(&v->v_compdata[0])==0.0)
{
(void) sprintf(buf2, "%-16.15s", v->v_name);
}
else
(void) sprintf(buf2, "%-32.31s", v->v_name);
}
else
(void) sprintf(buf2, "%-32.31s", v->v_name);
}
(void) strcat(buf, buf2);
}
lineno = 3;
@ -290,14 +305,34 @@ loop:
else
out_send("\t\t\t\t");
} else {
if (isreal(v)) {
sprintf(out_pbuf, "%e\t",
v->v_realdata[j]);
if (isreal(v))
{
printnum(numbuf, v->v_realdata[j]);
//sprintf(out_pbuf, "%e\t",v->v_realdata[j]);
(void) sprintf(out_pbuf, "%s\t",numbuf);
out_send(out_pbuf);
} else {
sprintf(out_pbuf, "%e,\t%e\t",
realpart(&v->v_compdata[j]),
imagpart(&v->v_compdata[j]));
}
else
{
/* In case of a single frequency and have a real part avoids print imaginary part equals 0. */
if(eq(v->v_name, "frequency"))
{
if(imagpart(&v->v_compdata[j])==0.0)
{
printnum(numbuf, realpart(&v->v_compdata[j]));
(void) sprintf(out_pbuf, "%s\t",numbuf);
}
}
else
{
printnum(numbuf, realpart(&v->v_compdata[j]));
printnum(numbuf2, imagpart(&v->v_compdata[j]));
(void) sprintf(out_pbuf, "%s,\t%s\t",numbuf,numbuf2);
/* sprintf(out_pbuf, "%e,\t%e\t",
* realpart(&v->v_compdata[j]),
* imagpart(&v->v_compdata[j]));
*/
}
out_send(out_pbuf);
}
}
@ -582,7 +617,13 @@ com_destroy(wordlist *wl)
for (pl = plot_list; pl; pl = npl) {
npl = pl->pl_next;
if (!eq(pl->pl_typename, "const"))
killplot(pl);
{
killplot(pl);
}
else
{
plot_num=1;
}
}
} else {
while (wl) {
@ -590,7 +631,10 @@ com_destroy(wordlist *wl)
if (eq(pl->pl_typename, wl->wl_word))
break;
if (pl)
{
killplot(pl);
plot_num--;
}
else
fprintf(cp_err, "Error: no such plot %s\n",
wl->wl_word);

2
src/frontend/spiceif.c

@ -675,7 +675,7 @@ spif_getparam_special(void *ckt,char **name,char *param,int ind,int do_model)
* 2. Copy the type of variable of IFparm into a variable (thus parm-to-var)
* vv->va_type = opt->dataType
* The long description of the parameter:
* IFparm MOS_SGTmPTable[] = { /* model parameters */
* IFparm MOS_SGTmPTable[] = { // model parameters //
* OP("type", MOS_SGT_MOD_TYPE, IF_STRING, "N-channel or P-channel MOS")
* goes into tv->va_name to put braces around the parameter of the model
* tv->va_name += device->modelParms[i].keyword;

3
src/frontend/vectors.c

@ -275,7 +275,8 @@ vec_fromplot(char *word, struct plot *plot)
/* ( */ ((s =strrchr(buf, ')')) != NULL) &&
(*(s + 1) == '\0')) {
*s = '\0';
if (prefix("i(", /* ) */ word)) {
if (prefix("i(", /* ) */ word) || prefix("I(", /* ) */ word))
{
/* Spice dependency... */
(void) sprintf(buf2, "%s#branch", buf);
(void) strcpy(buf, buf2);

3
src/include/fteext.h

@ -100,6 +100,7 @@ extern void *cx_norm(void *, short int , int , int *, short int *, ...);
extern void *cx_uminus(void *, short int , int , int *, short int *, ...);
extern void *cx_rnd(void *, short int , int , int *, short int *, ...);
extern void *cx_mean(void *, short int , int , int *, short int *, ...);
extern void *cx_avg(void *, short int , int , int *, short int *, ...);
extern void *cx_length(void *, short int , int , int *, short int *, ...);
extern void *cx_vector(void *, short int , int , int *, short int *, ...);
extern void *cx_unitvec(void *, short int , int , int *, short int *, ...);
@ -133,6 +134,8 @@ extern void *cx_or(void *, void *, short int , short int , int, ...);
extern void *cx_not(void *, short int , int , int *, short int * , ...);
extern void *cx_interpolate(void *, short int , int , int *, short int *, ...); /* struct plot *, struct plot *, int ); */
extern void *cx_deriv(void *, short int , int , int *, short int *, ...); /*struct plot *, struct plot *, int );*/
extern void *cx_group_delay(void *, short int , int , int *, short int *, ...); /*struct plot *, struct plot *, int );*/
/* cmdtab.c */

45
src/maths/cmaths/cmath2.c

@ -244,6 +244,51 @@ cx_rnd(void *data, short int type, int length, int *newlength, short int *newtyp
}
}
/* Compute the avg of a vector.
Created by A.M.Roldan 2005-05-21 */
void
*cx_avg(void *data, short int type, int length, int *newlength, short int *newtype, ...)
{
complex *c;
double *d, sum_real = 0.0,sum_imag = 0.0;
complex *cc = (complex *) data;
double *dd = (double *) data;
int i;
if (type == VF_REAL) {
d = alloc_d(length);
*newtype = VF_REAL;
} else {
c = alloc_c(length);
*newtype = VF_COMPLEX;
}
*newlength = length;
if (type == VF_COMPLEX)
{
for (i = 0; i < length; i++)
{
sum_real= sum_real + realpart(&cc[i]);
realpart(&c[i]) = sum_real / (double)(i+1);
sum_imag = sum_imag + imagpart(&cc[i]);
imagpart(&c[i]) = sum_imag / (double)(i+1);
}
return ((char *) c);
}
else
{ //VF_REAL
for (i = 0; i < length; i++)
{
sum_real= sum_real + dd[i];
d[i] = sum_real / (double)(i+1);
}
return ((char *) d);
}
}
/* Compute the mean of a vector. */
void *

234
src/maths/cmaths/cmath4.c

@ -28,7 +28,10 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "cmath.h"
#include "cmath4.h"
#include "sim.h" /* To get SV_TIME */
#include "../../frontend/variable.h" /* for VT_NUM in cx_interpolate */
extern bool cx_degrees;
void *
cx_and(void *data1, void *data2, short int datatype1, short int datatype2, int length)
@ -262,67 +265,75 @@ cx_deriv(void *data, short int type, int length, int *newlength, short int *newt
scale = alloc_d(length); /* XXX */
if (pl->pl_scale->v_type == VF_COMPLEX)
/* Not ideal */
for (i = 0; i < length; i++)
scale[i] = realpart(&pl->pl_scale->v_compdata[i]);
else
for (i = 0; i < length; i++)
scale[i] = realpart(&pl->pl_scale->v_compdata[i]);
else
for (i = 0; i < length; i++)
scale[i] = pl->pl_scale->v_realdata[i];
for (base = 0; base < length; base += grouping) {
scale[i] = pl->pl_scale->v_realdata[i];
for (base = 0; base < length; base += grouping)
{
k = 0;
for (i = degree; i < grouping; i += 1) {
for (i = degree; i < grouping; i += 1)
{
/* real */
for (j = 0; j < n; j++)
/* real */
for (j = 0; j < n; j++)
spare[j] = c_indata[j + i + base].cx_real;
if (!ft_polyfit(scale + i + base - degree,
if (!ft_polyfit(scale + i + base - degree,
spare, r_coefs, degree, scratch))
{
{
fprintf(stderr, "ft_polyfit @ %d failed\n", i);
}
ft_polyderiv(r_coefs, degree);
}
ft_polyderiv(r_coefs, degree);
/* for loop gets the beginning part */
for (j = k; j <= i - degree / 2; j++) {
/* for loop gets the beginning part */
for (j = k; j <= i + degree / 2; j++)
{
x = scale[j + base];
c_outdata[j + base].cx_real =
ft_peval(x, r_coefs, degree - 1);
}
}
/* imag */
for (j = 0; j < n; j++)
/* imag */
for (j = 0; j < n; j++)
spare[j] = c_indata[j + i + base].cx_imag;
if (!ft_polyfit(scale + i - degree + base,
if (!ft_polyfit(scale + i - degree + base,
spare, i_coefs, degree, scratch))
{
{
fprintf(stderr, "ft_polyfit @ %d failed\n", i);
}
ft_polyderiv(i_coefs, degree);
}
ft_polyderiv(i_coefs, degree);
/* for loop gets the beginning part */
for (j = k; j <= i - degree / 2; j++) {
/* for loop gets the beginning part */
for (j = k; j <= i - degree / 2; j++)
{
x = scale[j + base];
c_outdata[j + base].cx_imag =
ft_peval(x, i_coefs, degree - 1);
}
k = j;
}
ft_peval(x, i_coefs, degree - 1);
}
k = j;
}
/* get the tail */
for (j = k; j < length; j++) {
x = scale[j + base];
/* real */
c_outdata[j + base].cx_real = ft_peval(x, r_coefs, degree - 1);
/* imag */
c_outdata[j + base].cx_imag = ft_peval(x, i_coefs, degree - 1);
for (j = k; j < length; j++)
{
x = scale[j + base];
/* real */
c_outdata[j + base].cx_real = ft_peval(x, r_coefs, degree - 1);
/* imag */
c_outdata[j + base].cx_imag = ft_peval(x, i_coefs, degree - 1);
}
}
}
tfree(r_coefs);
tfree(i_coefs);
tfree(scale);
return (void *) c_outdata;
} else {
}
else
{
/* all-real case */
double *coefs;
@ -333,36 +344,155 @@ cx_deriv(void *data, short int type, int length, int *newlength, short int *newt
indata = (double *) data;
outdata = alloc_d(length);
scale = alloc_d(length); /* XXX */
for (i = 0; i < length; i++)
scale[i] = pl->pl_scale->v_realdata[i];
for (base = 0; base < length; base += grouping) {
/* Here I encountered a problem because when we issue an instruction like this:
* plot -deriv(vp(3)) to calculate something similar to the group delay, the code
* detects that vector vp(3) is real and it is believed that the frequency is also
* real. The frequency is COMPLEX and the program aborts so I'm going to put the
* check that the frequency is complex vector not to abort.
*/
/* Original problematic code
* for (i = 0; i < length; i++)
* scale[i] = pl->pl_scale->v_realdata[i];
*/
/* Modified to deal with complex frequency vector */
if (pl->pl_scale->v_type == VF_COMPLEX)
for (i = 0; i < length; i++)
scale[i] = realpart(&pl->pl_scale->v_compdata[i]);
else
for (i = 0; i < length; i++)
scale[i] = pl->pl_scale->v_realdata[i];
for (base = 0; base < length; base += grouping)
{
k = 0;
for (i = degree; i < grouping; i += 1) {
if (!ft_polyfit(scale + i - degree + base,
for (i = degree; i < grouping; i += 1)
{
if (!ft_polyfit(scale + i - degree + base,
indata + i - degree + base, coefs, degree, scratch))
{
{
fprintf(stderr, "ft_polyfit @ %d failed\n", i + base);
}
ft_polyderiv(coefs, degree);
}
ft_polyderiv(coefs, degree);
/* for loop gets the beginning part */
for (j = k; j <= i - degree / 2; j++)
{
/* Seems the same problem because the frequency vector is complex
* and the real part of the complex should be accessed because if we
* run x = pl-> pl_scale-> v_realdata [base + j]; the execution will
* abort.
*/
if (pl->pl_scale->v_type == VF_COMPLEX)
x = realpart(&pl->pl_scale->v_compdata[j+base]); /* For complex scale vector */
else
x = pl->pl_scale->v_realdata[j + base]; /* For real scale vector */
/* for loop gets the beginning part */
for (j = k; j <= i - degree / 2; j++) {
x = pl->pl_scale->v_realdata[j + base];
outdata[j + base] = ft_peval(x, coefs, degree - 1);
}
k = j;
}
k = j;
}
for (j = k; j < length; j++) {
x = pl->pl_scale->v_realdata[j + base];
for (j = k; j < length; j++)
{
/* Again the same error */
/* x = pl->pl_scale->v_realdata[j + base]; */
if (pl->pl_scale->v_type == VF_COMPLEX)
x = realpart(&pl->pl_scale->v_compdata[j+base]); /* For complex scale vector */
else
x = pl->pl_scale->v_realdata[j + base]; /* For real scale vector */
outdata[j + base] = ft_peval(x, coefs, degree - 1);
}
}
}
tfree(coefs);
tfree(scale); /* XXX */
return (void *) outdata;
return (char *) outdata;
}
}
void *
cx_group_delay(void *data, short int type, int length, int *newlength, short int *newtype, struct plot *pl, struct plot *newpl, int grouping)
{
complex *cc = (complex *) data;
double *v_phase = alloc_d(length);
double *datos,adjust_final;
double *group_delay = alloc_d(length);
int i;
/* char *datos_aux; */
/* Check to see if we have the frequency vector for the derivative */
if (!eq(pl->pl_scale->v_name, "frequency"))
{
fprintf(cp_err, "Internal error: cx_group_delay: need frequency based complex vector.\n");
return (NULL);
}
if (type == VF_COMPLEX)
for (i = 0; i < length; i++)
{
v_phase[i] = radtodeg(cph(&cc[i]));
}
else
{
fprintf(cp_err, "Signal must be complex to calculate group delay\n");
return (NULL);
}
type = VF_REAL;
/* datos_aux = (char *)cx_deriv((char *)v_phase, type, length, newlength, newtype, pl, newpl, grouping);
* datos = (double *) datos_aux;
*/
datos = (double *)cx_deriv((char *)v_phase, type, length, newlength, newtype, pl, newpl, grouping);
/* With this global variable I will change how to obtain the group delay because
* it is defined as:
*
* gd()=-dphase[rad]/dw[rad/s]
*
* if you have degrees in phase and frequency in Hz, must be taken into account
*
* gd()=-dphase[deg]/df[Hz]/360
* gd()=-dphase[rad]/df[Hz]/(2*pi)
*/
if(cx_degrees)
{
adjust_final=1.0/360;
}
else
{
adjust_final=1.0/(2*M_PI);
}
for (i = 0; i < length; i++)
{
group_delay[i] = -datos[i]*adjust_final;
}
/* Adjust to Real because the result is Real */
*newtype = VF_REAL;
/* Set the type of Vector to "Time" because the speed of group units' s'
* The different types of vectors are INCLUDE \ Fte_cons.h
*/
pl->pl_dvecs->v_type= SV_TIME;
return ((char *) group_delay);
}

2
src/maths/cmaths/cmath4.h

@ -13,6 +13,8 @@ void * cx_interpolate(void *data, short int type, int length, int *newlength,
short int *newtype, struct plot *pl, struct plot *newpl, int grouping);
void * cx_deriv(void *data, short int type, int length, int *newlength, short int *newtype,
struct plot *pl, struct plot *newpl, int grouping);
void * cx_group_delay(void *data, short int type, int length, int *newlength, short int *newtype,
struct plot *pl, struct plot *newpl, int grouping);
#endif
Loading…
Cancel
Save