diff --git a/ChangeLog b/ChangeLog index 093de3773..59b35da6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-18 Holger Vogt + * cmath1.c, cmath1.h, cmath2.c, cmath2.h, parse.c, fteext.h: + new complex functions sinh, cosh, tanh + 2011-07-10 Holger Vogt * main.c, ivars.c, /xspice/icm/analog/file_source/cfunc.mod: environmental variable NGSPICE_INPUT_DIR diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c index fe67cf0e8..80cb2a40f 100644 --- a/src/frontend/evaluate.c +++ b/src/frontend/evaluate.c @@ -16,7 +16,6 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include #include "evaluate.h" -#include "../maths/cmaths/cmath2.h" #include "sim.h" /* To get SV_VOLTAGE definition */ diff --git a/src/frontend/parse.c b/src/frontend/parse.c index 5308556b6..8648ad508 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -18,8 +18,6 @@ $Id$ #include "evaluate.h" #include "parse.h" -#include "../maths/cmaths/cmath2.h" - /* static declarations */ static bool checkvalid(struct pnode *pn); static struct pnode * mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2); @@ -160,6 +158,9 @@ struct func ft_funcs[] = { { "sin", cx_sin } , { "cos", cx_cos } , { "tan", cx_tan } , + { "sinh", cx_sinh } , + { "cosh", cx_cosh } , + { "tanh", cx_tanh } , { "atan", cx_atan } , { "norm", cx_norm } , { "rnd", cx_rnd } , diff --git a/src/include/fteext.h b/src/include/fteext.h index 4a3fe3011..4230fb593 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -64,7 +64,35 @@ extern void *cx_ln(void *, short int , int , int *, short int *); extern void *cx_exp(void *, short int , int , int *, short int *); extern void *cx_sqrt(void *, short int , int , int *, short int *); extern void *cx_sin(void *, short int , int , int *, short int *); +extern void *cx_sinh(void *, short int , int , int *, short int *); extern void *cx_cos(void *, short int , int , int *, short int *); +extern void *cx_cosh(void *, short int , int , int *, short int *); +extern void * cx_tan(void *, short int , int , int *, short int *); +extern void * cx_tanh(void *, short int , int , int *, short int *); +extern void * cx_atan(void *, short int , int , int *, short int *); + +/* cmath2.c */ + +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_sunif(void *, short int , int , int *, short int *); +extern void * cx_sgauss(void *, short int , int , int *, short int *); +extern void * cx_poisson(void *, short int , int , int *, short int *); +extern void * cx_exponential(void *, short int , int , int *, short int *); +extern void * cx_mean(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 *); +extern void * cx_plus(void *, void *, short int , short int , int ); +extern void * cx_minus(void *, void *, short int , short int , int ); +extern void * cx_times(void *, void *, short int , short int , int ); +extern void * cx_mod(void *, void *, short int , short int , int ); +extern void * cx_max(void *, short int , int , int *, short int *); +extern void * cx_min(void *, short int , int , int *, short int *); +extern void * cx_d(void *, short int , int , int *, short int *); +extern void *cx_avg(void *, short int , int , int *, short int *); + /* cmath3.c */ diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index efaaa29d1..31c206b1f 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -427,6 +427,40 @@ cx_sin(void *data, short int type, int length, int *newlength, short int *newtyp } } +void * +cx_sinh(void *data, short int type, int length, int *newlength, short int *newtype) +{ + *newlength = length; + if (type == VF_COMPLEX) { + ngcomplex_t *c; + ngcomplex_t *cc = (ngcomplex_t *) data; + int i; + double u, v; + c = alloc_c(length); + + *newtype = VF_COMPLEX; + for (i = 0; i < length; i++) { + /* sinh(x+iy) = sinh(x)*cos(y) + i * cosh(x)*sin(y) */ + u = degtorad(realpart(&cc[i])); + v = degtorad(imagpart(&cc[i])); + realpart(&c[i]) = sinh(u)*cos(v); + imagpart(&c[i]) = cosh(u)*sin(v); + } + return ((void *) c); + } else { + double *d; + double *dd = (double *) data; + int i; + + d = alloc_d(length); + *newtype = VF_REAL; + for (i = 0; i < length; i++) + d[i] = sinh(degtorad(dd[i])); + return ((void *) d); + } +} + + void * cx_cos(void *data, short int type, int length, int *newlength, short int *newtype) { @@ -458,3 +492,174 @@ cx_cos(void *data, short int type, int length, int *newlength, short int *newtyp } } + +void * +cx_cosh(void *data, short int type, int length, int *newlength, short int *newtype) +{ + *newlength = length; + if (type == VF_COMPLEX) { + ngcomplex_t *c; + ngcomplex_t *cc = (ngcomplex_t *) data; + int i; + double u, v; + + c = alloc_c(length); + + *newtype = VF_COMPLEX; + for (i = 0; i < length; i++) { + /* cosh(x+iy) = cosh(x)*cos(y) + i * sinh(x)*sin(y) */ + u = degtorad(realpart(&cc[i])); + v = degtorad(imagpart(&cc[i])); + realpart(&c[i]) = cosh(u)*cos(v); + imagpart(&c[i]) = sinh(u)*sin(v); + } + return ((void *) c); + } else { + double *d; + double *dd = (double *) data; + int i; + + d = alloc_d(length); + *newtype = VF_REAL; + for (i = 0; i < length; i++) + d[i] = cosh(degtorad(dd[i])); + return ((void *) d); + } +} + +static double * +d_tan(double *dd, int length) +{ + double *d; + int i; + + d = alloc_d(length); + for (i = 0; i < length; i++) { + rcheck(cos(degtorad(dd[i])) != 0, "tan"); + d[i] = sin(degtorad(dd[i])) / cos(degtorad(dd[i])); + } + return d; +} + +static double * +d_tanh(double *dd, int length) +{ + double *d; + int i; + + d = alloc_d(length); + for (i = 0; i < length; i++) { + rcheck(cosh(degtorad(dd[i])) != 0, "tanh"); + d[i] = sinh(degtorad(dd[i])) / cosh(degtorad(dd[i])); + } + return d; +} + +static ngcomplex_t * +c_tan(ngcomplex_t *cc, int length) +{ + ngcomplex_t *c; + int i; + + c = alloc_c(length); + for (i = 0; i < length; i++) { + double u, v; + + rcheck(cos(degtorad(realpart(&cc[i]))) * + cosh(degtorad(imagpart(&cc[i]))), "tan"); + rcheck(sin(degtorad(realpart(&cc[i]))) * + sinh(degtorad(imagpart(&cc[i]))), "tan"); + u = degtorad(realpart(&cc[i])); + v = degtorad(imagpart(&cc[i])); + /* The Lattice C compiler won't take multi-line macros, and + * CMS won't take >80 column lines.... + */ +#define xx1 sin(u) * cosh(v) +#define xx2 cos(u) * sinh(v) +#define xx3 cos(u) * cosh(v) +#define xx4 -sin(u) * sinh(v) + cdiv(xx1, xx2, xx3, xx4, realpart(&c[i]), imagpart(&c[i])); + } + return c; +} + +/* complex tanh function, uses tanh(z) = -i * tan (i * z) */ +static ngcomplex_t * +c_tanh(ngcomplex_t *cc, int length) +{ + ngcomplex_t *c, *s, *t; + int i; + + c = alloc_c(length); + s = alloc_c(1); + t = alloc_c(1); + + for (i = 0; i < length; i++) { + /* multiply by i */ + t[0].cx_real = -1. * imagpart(&cc[i]); + t[0].cx_imag = realpart(&cc[i]); + /* get complex tangent */ + s = c_tan(t, 1); + /* if check in c_tan fails */ + if (s == NULL) { + tfree(t); + return (NULL); + } + /* multiply by -i */ + realpart(&c[i]) = imagpart(&s[0]); + imagpart(&c[i]) = -1. * realpart(&s[0]); + } + tfree(s); + tfree(t); + return c; +} + +void * +cx_tan(void *data, short int type, int length, int *newlength, short int *newtype) +{ + *newlength = length; + if (type == VF_REAL) { + *newtype = VF_REAL; + return (void *) d_tan((double *) data, length); + } else { + *newtype = VF_COMPLEX; + return (void *) c_tan((ngcomplex_t *) data, length); + } +} + +void * +cx_tanh(void *data, short int type, int length, int *newlength, short int *newtype) +{ + *newlength = length; + if (type == VF_REAL) { + *newtype = VF_REAL; + return (void *) d_tanh((double *) data, length); + } else { + *newtype = VF_COMPLEX; + return (void *) c_tanh((ngcomplex_t *) data, length); + } +} + +void * +cx_atan(void *data, short int type, int length, int *newlength, short int *newtype) +{ + double *d; + + d = alloc_d(length); + *newtype = VF_REAL; + *newlength = length; + if (type == VF_COMPLEX) { + ngcomplex_t *cc = (ngcomplex_t *) data; + int i; + + for (i = 0; i < length; i++) + d[i] = radtodeg(atan(realpart(&cc[i]))); + } else { + double *dd = (double *) data; + int i; + + for (i = 0; i < length; i++) + d[i] = radtodeg(atan(dd[i])); + } + return ((void *) d); +} diff --git a/src/maths/cmaths/cmath1.h b/src/maths/cmaths/cmath1.h index 777a60bae..21f35121f 100644 --- a/src/maths/cmaths/cmath1.h +++ b/src/maths/cmaths/cmath1.h @@ -19,8 +19,12 @@ void * cx_ln(void *data, short int type, int length, int *newlength, short int * void * cx_exp(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_sqrt(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_sin(void *data, short int type, int length, int *newlength, short int *newtype); +void * cx_sinh(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_cos(void *data, short int type, int length, int *newlength, short int *newtype); - +void * cx_cosh(void *data, short int type, int length, int *newlength, short int *newtype); +void * cx_tan(void *data, short int type, int length, int *newlength, short int *newtype); +void * cx_tanh(void *data, short int type, int length, int *newlength, short int *newtype); +void * cx_atan(void *data, short int type, int length, int *newlength, short int *newtype); #endif diff --git a/src/maths/cmaths/cmath2.c b/src/maths/cmaths/cmath2.c index fc9e25d1d..1607903ca 100644 --- a/src/maths/cmaths/cmath2.c +++ b/src/maths/cmaths/cmath2.c @@ -36,87 +36,6 @@ extern double gauss0(void); /* from randnumb.c */ extern int poisson(double); /* from randnumb.c */ extern double exprand(double); /* from randnumb.c */ -static double * -d_tan(double *dd, int length) -{ - double *d; - int i; - - d = alloc_d(length); - for (i = 0; i < length; i++) { - rcheck(cos(degtorad(dd[i])) != 0, "tan"); - d[i] = sin(degtorad(dd[i])) / cos(degtorad(dd[i])); - } - return d; -} - -static ngcomplex_t * -c_tan(ngcomplex_t *cc, int length) -{ - ngcomplex_t *c; - int i; - - c = alloc_c(length); - for (i = 0; i < length; i++) { - double u, v; - - rcheck(cos(degtorad(realpart(&cc[i]))) * - cosh(degtorad(imagpart(&cc[i]))), "tan"); - rcheck(sin(degtorad(realpart(&cc[i]))) * - sinh(degtorad(imagpart(&cc[i]))), "tan"); - u = degtorad(realpart(&cc[i])); - v = degtorad(imagpart(&cc[i])); - /* The Lattice C compiler won't take multi-line macros, and - * CMS won't take >80 column lines.... - */ -#define xx1 sin(u) * cosh(v) -#define xx2 cos(u) * sinh(v) -#define xx3 cos(u) * cosh(v) -#define xx4 sin(u) * sinh(v) - cdiv(xx1, xx2, xx3, xx4, realpart(&c[i]), imagpart(&c[i])); - } - return c; -} - -void * -cx_tan(void *data, short int type, int length, int *newlength, short int *newtype) -{ - *newlength = length; - if (type == VF_REAL) { - *newtype = VF_REAL; - return (void *) d_tan((double *) data, length); - } else { - *newtype = VF_COMPLEX; - return (void *) c_tan((ngcomplex_t *) data, length); - } -} - - - -void * -cx_atan(void *data, short int type, int length, int *newlength, short int *newtype) -{ - double *d; - - d = alloc_d(length); - *newtype = VF_REAL; - *newlength = length; - if (type == VF_COMPLEX) { - ngcomplex_t *cc = (ngcomplex_t *) data; - int i; - - for (i = 0; i < length; i++) - d[i] = radtodeg(atan(realpart(&cc[i]))); - } else { - double *dd = (double *) data; - int i; - - for (i = 0; i < length; i++) - d[i] = radtodeg(atan(dd[i])); - } - return ((void *) d); -} - static double cx_max_local(void *data, short int type, int length) diff --git a/src/maths/cmaths/cmath2.h b/src/maths/cmaths/cmath2.h index cabe6a0e6..f34b69f3e 100644 --- a/src/maths/cmaths/cmath2.h +++ b/src/maths/cmaths/cmath2.h @@ -7,8 +7,7 @@ #define CMATH2_H_INCLUDED -void * cx_tan(void *data, short int type, int length, int *newlength, short int *newtype); -void * cx_atan(void *data, short int type, int length, int *newlength, short int *newtype); + void * cx_norm(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_uminus(void *data, short int type, int length, int *newlength, short int *newtype); void * cx_rnd(void *data, short int type, int length, int *newlength, short int *newtype);