From 1025e978bc33fd7dbb8580a21f57b31cbc5a4998 Mon Sep 17 00:00:00 2001 From: arno Date: Sat, 3 Jun 2000 12:08:35 +0000 Subject: [PATCH] * src/include/complex.h, src/include/macros.h, src/include/memory.h, src/maths/sparse/spdefs.h: Moved definitions of complex into complex.h. There are three different ways to declare a complex number in Spice. We need further work to reduce this to only one. * src/maths/cmaths/Makefile.am, src/maths/cmaths/.cvsignore, src/maths/cmaths/test_cx_ph.c: Added a new test and updated the corresponding support files. --- ChangeLog | 12 ++ src/include/complex.h | 284 +++++++++++++++++++++++++++++++++- src/include/macros.h | 80 +++------- src/include/memory.h | 8 + src/maths/cmaths/.cvsignore | 4 + src/maths/cmaths/Makefile.am | 11 +- src/maths/cmaths/test_cx_ph.c | 34 ++++ src/maths/sparse/spdefs.h | 43 +---- 8 files changed, 369 insertions(+), 107 deletions(-) create mode 100644 src/include/memory.h create mode 100644 src/maths/cmaths/test_cx_ph.c diff --git a/ChangeLog b/ChangeLog index 3d6f649a8..bbc9f2366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2000-06-03 Arno W. Peters + + * src/include/complex.h, src/include/macros.h, + src/include/memory.h, src/maths/sparse/spdefs.h: Moved definitions + of complex into complex.h. There are three different ways to + declare a complex number in Spice. We need further work to reduce + this to only one. + + * src/maths/cmaths/Makefile.am, src/maths/cmaths/.cvsignore, + src/maths/cmaths/test_cx_ph.c: Added a new test and updated the + corresponding support files. + 2000-06-02 Arno W. Peters * src/circuit/inp2dot.c: Refactoring introduced a bug in the line diff --git a/src/include/complex.h b/src/include/complex.h index daacb5333..c9c76b482 100644 --- a/src/include/complex.h +++ b/src/include/complex.h @@ -1,6 +1,6 @@ /* * Copyright (c) 1985 Thomas L. Quarles - * Modified: Paolo Nenzi 1999, Arno W. Peters 2000 + * Modified: 1999 Paolo Nenzi, 2000 Arno W. Peters */ #ifndef _COMPLEX_H #define _COMPLEX_H @@ -18,8 +18,7 @@ typedef struct _complex complex; #define imagpart(cval) ((struct _complex *) (cval))->cx_imag -/* header file containing definitions for complex functions - * +/* * Each expects two arguments for each complex number - a real and an * imaginary part. */ @@ -28,6 +27,61 @@ typedef struct { double imag; } SPcomplex; +/* + * COMPLEX NUMBER DATA STRUCTURE + * + * >>> Structure fields: + * Real (RealNumber) + * The real portion of the number. Real must be the first + * field in this structure. + * Imag (RealNumber) + * The imaginary portion of the number. This field must follow + * immediately after Real. + */ + +#define spREAL double + +/* Begin `RealNumber'. */ +typedef spREAL RealNumber, *RealVector; + +/* Begin `ComplexNumber'. */ +typedef struct +{ RealNumber Real; + RealNumber Imag; +} ComplexNumber, *ComplexVector; + + +/* Some defines used mainly in cmath.c. */ +#define alloc_c(len) ((complex *) tmalloc((len) * sizeof (complex))) +#define alloc_d(len) ((double *) tmalloc((len) * sizeof (double))) +#define FTEcabs(d) (((d) < 0.0) ? - (d) : (d)) +#define cph(c) (atan2(imagpart(c), (realpart(c)))) +#define cmag(c) (sqrt(imagpart(c) * imagpart(c) + realpart(c) * realpart(c))) +#define radtodeg(c) (cx_degrees ? ((c) / 3.14159265358979323846 * 180) : (c)) +#define degtorad(c) (cx_degrees ? ((c) * 3.14159265358979323846 / 180) : (c)) +#define rcheck(cond, name) if (!(cond)) { \ + fprintf(cp_err, "Error: argument out of range for %s\n", name); \ + return (NULL); } + + +#define cdiv(r1, i1, r2, i2, r3, i3) \ +{ \ + double r, s; \ + if (FTEcabs(r2) > FTEcabs(i2)) { \ + r = (i2) / (r2); \ + s = (r2) + r * (i2); \ + (r3) = ((r1) + r * (i1)) / s; \ + (i3) = ((i1) - r * (r1)) / s; \ + } else { \ + r = (r2) / (i2); \ + s = (i2) + r * (r2); \ + (r3) = (r * (r1) + (i1)) / s; \ + (i3) = (r * (i1) - (r1)) / s; \ + } \ +} + + + #define DC_ABS(a,b) (fabs(a) + fabs(b)) @@ -215,6 +269,228 @@ typedef struct { (A).imag = (B.imag) - (C.imag); \ } +/* Macro function that returns the approx absolute value of a complex number. */ +#if spCOMPLEX +#define ELEMENT_MAG(ptr) (ABS((ptr)->Real) + ABS((ptr)->Imag)) +#else +#define ELEMENT_MAG(ptr) ((ptr)->Real < 0.0 ? -(ptr)->Real : (ptr)->Real) +#endif + +/* Complex assignment statements. */ +#define CMPLX_ASSIGN(to,from) \ +{ (to).Real = (from).Real; \ + (to).Imag = (from).Imag; \ +} +#define CMPLX_CONJ_ASSIGN(to,from) \ +{ (to).Real = (from).Real; \ + (to).Imag = -(from).Imag; \ +} +#define CMPLX_NEGATE_ASSIGN(to,from) \ +{ (to).Real = -(from).Real; \ + (to).Imag = -(from).Imag; \ +} +#define CMPLX_CONJ_NEGATE_ASSIGN(to,from) \ +{ (to).Real = -(from).Real; \ + (to).Imag = (from).Imag; \ +} +#define CMPLX_CONJ(a) (a).Imag = -(a).Imag +#define CMPLX_NEGATE(a) \ +{ (a).Real = -(a).Real; \ + (a).Imag = -(a).Imag; \ +} + +/* Macro that returns the approx magnitude (L-1 norm) of a complex number. */ +#define CMPLX_1_NORM(a) (ABS((a).Real) + ABS((a).Imag)) + +/* Macro that returns the approx magnitude (L-infinity norm) of a complex. */ +#define CMPLX_INF_NORM(a) (MAX (ABS((a).Real),ABS((a).Imag))) + +/* Macro function that returns the magnitude (L-2 norm) of a complex number. */ +#define CMPLX_2_NORM(a) (sqrt((a).Real*(a).Real + (a).Imag*(a).Imag)) + +/* Macro function that performs complex addition. */ +#define CMPLX_ADD(to,from_a,from_b) \ +{ (to).Real = (from_a).Real + (from_b).Real; \ + (to).Imag = (from_a).Imag + (from_b).Imag; \ +} + +/* Macro function that performs complex subtraction. */ +#define CMPLX_SUBT(to,from_a,from_b) \ +{ (to).Real = (from_a).Real - (from_b).Real; \ + (to).Imag = (from_a).Imag - (from_b).Imag; \ +} + +/* Macro function that is equivalent to += operator for complex numbers. */ +#define CMPLX_ADD_ASSIGN(to,from) \ +{ (to).Real += (from).Real; \ + (to).Imag += (from).Imag; \ +} + +/* Macro function that is equivalent to -= operator for complex numbers. */ +#define CMPLX_SUBT_ASSIGN(to,from) \ +{ (to).Real -= (from).Real; \ + (to).Imag -= (from).Imag; \ +} + +/* Macro function that multiplies a complex number by a scalar. */ +#define SCLR_MULT(to,sclr,cmplx) \ +{ (to).Real = (sclr) * (cmplx).Real; \ + (to).Imag = (sclr) * (cmplx).Imag; \ +} + +/* Macro function that multiply-assigns a complex number by a scalar. */ +#define SCLR_MULT_ASSIGN(to,sclr) \ +{ (to).Real *= (sclr); \ + (to).Imag *= (sclr); \ +} + +/* Macro function that multiplies two complex numbers. */ +#define CMPLX_MULT(to,from_a,from_b) \ +{ (to).Real = (from_a).Real * (from_b).Real - \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag = (from_a).Real * (from_b).Imag + \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that implements to *= from for complex numbers. */ +#define CMPLX_MULT_ASSIGN(to,from) \ +{ RealNumber to_real_ = (to).Real; \ + (to).Real = to_real_ * (from).Real - \ + (to).Imag * (from).Imag; \ + (to).Imag = to_real_ * (from).Imag + \ + (to).Imag * (from).Real; \ +} + +/* Macro function that multiplies two complex numbers, the first of which is + * conjugated. */ +#define CMPLX_CONJ_MULT(to,from_a,from_b) \ +{ (to).Real = (from_a).Real * (from_b).Real + \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag = (from_a).Real * (from_b).Imag - \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that multiplies two complex numbers and then adds them + * to another. to = add + mult_a * mult_b */ +#define CMPLX_MULT_ADD(to,mult_a,mult_b,add) \ +{ (to).Real = (mult_a).Real * (mult_b).Real - \ + (mult_a).Imag * (mult_b).Imag + (add).Real; \ + (to).Imag = (mult_a).Real * (mult_b).Imag + \ + (mult_a).Imag * (mult_b).Real + (add).Imag; \ +} + +/* Macro function that subtracts the product of two complex numbers from + * another. to = subt - mult_a * mult_b */ +#define CMPLX_MULT_SUBT(to,mult_a,mult_b,subt) \ +{ (to).Real = (subt).Real - (mult_a).Real * (mult_b).Real + \ + (mult_a).Imag * (mult_b).Imag; \ + (to).Imag = (subt).Imag - (mult_a).Real * (mult_b).Imag - \ + (mult_a).Imag * (mult_b).Real; \ +} + +/* Macro function that multiplies two complex numbers and then adds them + * to another. to = add + mult_a* * mult_b where mult_a* represents mult_a + * conjugate. */ +#define CMPLX_CONJ_MULT_ADD(to,mult_a,mult_b,add) \ +{ (to).Real = (mult_a).Real * (mult_b).Real + \ + (mult_a).Imag * (mult_b).Imag + (add).Real; \ + (to).Imag = (mult_a).Real * (mult_b).Imag - \ + (mult_a).Imag * (mult_b).Real + (add).Imag; \ +} + +/* Macro function that multiplies two complex numbers and then adds them + * to another. to += mult_a * mult_b */ +#define CMPLX_MULT_ADD_ASSIGN(to,from_a,from_b) \ +{ (to).Real += (from_a).Real * (from_b).Real - \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag += (from_a).Real * (from_b).Imag + \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that multiplies two complex numbers and then subtracts them + * from another. */ +#define CMPLX_MULT_SUBT_ASSIGN(to,from_a,from_b) \ +{ (to).Real -= (from_a).Real * (from_b).Real - \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag -= (from_a).Real * (from_b).Imag + \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that multiplies two complex numbers and then adds them + * to the destination. to += from_a* * from_b where from_a* represents from_a + * conjugate. */ +#define CMPLX_CONJ_MULT_ADD_ASSIGN(to,from_a,from_b) \ +{ (to).Real += (from_a).Real * (from_b).Real + \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag += (from_a).Real * (from_b).Imag - \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that multiplies two complex numbers and then subtracts them + * from the destination. to -= from_a* * from_b where from_a* represents from_a + * conjugate. */ +#define CMPLX_CONJ_MULT_SUBT_ASSIGN(to,from_a,from_b) \ +{ (to).Real -= (from_a).Real * (from_b).Real + \ + (from_a).Imag * (from_b).Imag; \ + (to).Imag -= (from_a).Real * (from_b).Imag - \ + (from_a).Imag * (from_b).Real; \ +} + +/* + * Macro functions that provide complex division. + */ + +/* Complex division: to = num / den */ +#define CMPLX_DIV(to,num,den) \ +{ RealNumber r_, s_; \ + if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \ + ((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \ + { r_ = (den).Imag / (den).Real; \ + s_ = (den).Real + r_*(den).Imag; \ + (to).Real = ((num).Real + r_*(num).Imag)/s_; \ + (to).Imag = ((num).Imag - r_*(num).Real)/s_; \ + } \ + else \ + { r_ = (den).Real / (den).Imag; \ + s_ = (den).Imag + r_*(den).Real; \ + (to).Real = (r_*(num).Real + (num).Imag)/s_; \ + (to).Imag = (r_*(num).Imag - (num).Real)/s_; \ + } \ +} + +/* Complex division and assignment: num /= den */ +#define CMPLX_DIV_ASSIGN(num,den) \ +{ RealNumber r_, s_, t_; \ + if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \ + ((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \ + { r_ = (den).Imag / (den).Real; \ + s_ = (den).Real + r_*(den).Imag; \ + t_ = ((num).Real + r_*(num).Imag)/s_; \ + (num).Imag = ((num).Imag - r_*(num).Real)/s_; \ + (num).Real = t_; \ + } \ + else \ + { r_ = (den).Real / (den).Imag; \ + s_ = (den).Imag + r_*(den).Real; \ + t_ = (r_*(num).Real + (num).Imag)/s_; \ + (num).Imag = (r_*(num).Imag - (num).Real)/s_; \ + (num).Real = t_; \ + } \ +} + +/* Complex reciprocation: to = 1.0 / den */ +#define CMPLX_RECIPROCAL(to,den) \ +{ RealNumber r_; \ + if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \ + ((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \ + { r_ = (den).Imag / (den).Real; \ + (to).Imag = -r_*((to).Real = 1.0/((den).Real + r_*(den).Imag)); \ + } \ + else \ + { r_ = (den).Real / (den).Imag; \ + (to).Real = -r_*((to).Imag = -1.0/((den).Imag + r_*(den).Real));\ + } \ +} -#endif /*CMPLX*/ +#endif /*_COMPLEX_H */ diff --git a/src/include/macros.h b/src/include/macros.h index b9377eeab..52a210b2f 100644 --- a/src/include/macros.h +++ b/src/include/macros.h @@ -14,46 +14,6 @@ #define NUMELEMS(ARRAY) (sizeof(ARRAY)/sizeof(*ARRAY)) -/* - * Macros for complex mathematical functions. - */ - -/* Some defines used mainly in cmath.c. */ -#define alloc_c(len) ((complex *) tmalloc((len) * sizeof (complex))) -#define alloc_d(len) ((double *) tmalloc((len) * sizeof (double))) -#define FTEcabs(d) (((d) < 0.0) ? - (d) : (d)) -#define cph(c) (atan2(imagpart(c), (realpart(c)))) -#define cmag(c) (sqrt(imagpart(c) * imagpart(c) + realpart(c) * realpart(c))) -#define radtodeg(c) (cx_degrees ? ((c) / 3.14159265358979323846 * 180) : (c)) -#define degtorad(c) (cx_degrees ? ((c) * 3.14159265358979323846 / 180) : (c)) -#define rcheck(cond, name) if (!(cond)) { \ - fprintf(cp_err, "Error: argument out of range for %s\n", name); \ - return (NULL); } - - -#define cdiv(r1, i1, r2, i2, r3, i3) \ -{ \ - double r, s; \ - if (FTEcabs(r2) > FTEcabs(i2)) { \ - r = (i2) / (r2); \ - s = (r2) + r * (i2); \ - (r3) = ((r1) + r * (i1)) / s; \ - (i3) = ((i1) - r * (r1)) / s; \ - } else { \ - r = (r2) / (i2); \ - s = (i2) + r * (r2); \ - (r3) = (r * (r1) + (i1)) / s; \ - (i3) = (r * (i1) - (r1)) / s; \ - } \ -} - - - - -#define tfree(x) (txfree(x), x = 0) -#define alloc(TYPE) ((TYPE *) tmalloc(sizeof(TYPE))) - - #define eq(a,b) (!strcmp((a), (b))) #define eqc(a,b) (cieq((a), (b))) #define isalphanum(c) (isalpha(c) || isdigit(c)) @@ -61,6 +21,8 @@ 'a') && ((c) <= 'f')) ? ((c) - 'a' + 10) : ((((c) >= 'A') && \ ((c) <= 'F')) ? ((c) - 'A' + 10) : 0))) +#define tfree(x) (txfree(x), x = 0) +#define alloc(TYPE) ((TYPE *) tmalloc(sizeof(TYPE))) #define MALLOC(x) tmalloc((unsigned)(x)) #define FREE(x) {if (x) {free((char *)(x));(x) = 0;}} #define REALLOC(x,y) trealloc((char *)(x),(unsigned)(y)) @@ -73,29 +35,29 @@ #define ABORT() fflush(stderr);fflush(stdout);abort(); -#define ERROR(CODE,MESSAGE) { \ - errMsg = MALLOC(strlen(MESSAGE) + 1); \ - strcpy(errMsg, (MESSAGE)); \ - return (CODE); \ +#define ERROR(CODE,MESSAGE) { \ + errMsg = (char *) tmalloc(strlen(MESSAGE) + 1); \ + strcpy(errMsg, (MESSAGE)); \ + return (CODE); \ } -#define NEW(TYPE) ((TYPE *) MALLOC(sizeof(TYPE))) -#define NEWN(TYPE,COUNT) ((TYPE *) MALLOC(sizeof(TYPE) * (COUNT))) +#define NEW(TYPE) ((TYPE *) tmalloc(sizeof(TYPE))) +#define NEWN(TYPE,COUNT) ((TYPE *) tmalloc(sizeof(TYPE) * (COUNT))) -#define R_NORM(A,B) { \ - if ((A) == 0.0) { \ - (B) = 0; \ - } else { \ - while (fabs(A) > 1.0) { \ - (B) += 1; \ - (A) /= 2.0; \ - } \ - while (fabs(A) < 0.5) { \ - (B) -= 1; \ - (A) *= 2.0; \ - } \ - } \ +#define R_NORM(A,B) { \ + if ((A) == 0.0) { \ + (B) = 0; \ + } else { \ + while (fabs(A) > 1.0) { \ + (B) += 1; \ + (A) /= 2.0; \ + } \ + while (fabs(A) < 0.5) { \ + (B) -= 1; \ + (A) *= 2.0; \ + } \ + } \ } diff --git a/src/include/memory.h b/src/include/memory.h new file mode 100644 index 000000000..349aca18f --- /dev/null +++ b/src/include/memory.h @@ -0,0 +1,8 @@ +#ifndef _MEMORY_H +#define _MEMORY_H + +extern void *tmalloc(size_t num); +extern void *trealloc(void *str, size_t num); +extern void txfree(void *ptr); + +#endif diff --git a/src/maths/cmaths/.cvsignore b/src/maths/cmaths/.cvsignore index e440fafda..d1e3a9641 100644 --- a/src/maths/cmaths/.cvsignore +++ b/src/maths/cmaths/.cvsignore @@ -1,3 +1,7 @@ Makefile.in Makefile .deps +.libs +test_cx_mag +test_cx_j +test_cx_ph diff --git a/src/maths/cmaths/Makefile.am b/src/maths/cmaths/Makefile.am index 8b4be8474..bcc34d2cd 100644 --- a/src/maths/cmaths/Makefile.am +++ b/src/maths/cmaths/Makefile.am @@ -12,7 +12,14 @@ libcmaths_a_SOURCES = \ cmath4.c \ cmath4.h -bin_PROGRAMS = test_cx_mag test_cx_j +bin_PROGRAMS = test_cx_mag test_cx_j test_cx_ph + +test_cx_ph_SOURCES = \ + test_cx_ph.c + +test_cx_ph_LDADD = \ + libcmaths.a \ + ../../misc/libmisc.a test_cx_mag_SOURCES = \ test_cx_mag.c @@ -28,7 +35,7 @@ test_cx_j_LDADD = \ libcmaths.a \ ../../misc/libmisc.a -TESTS = test_cx_mag test_cx_j +TESTS = test_cx_mag test_cx_j test_cx_ph INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/maths/poly diff --git a/src/maths/cmaths/test_cx_ph.c b/src/maths/cmaths/test_cx_ph.c new file mode 100644 index 000000000..95bd1e050 --- /dev/null +++ b/src/maths/cmaths/test_cx_ph.c @@ -0,0 +1,34 @@ +#include +#include + +#include +#include +#include + +#include "cmath1.h" + +FILE *cp_err; + +int +main(void) +{ + complex *c = NULL; + double *d = NULL; + short int t1; + short int t2; + int n1; + int n2; + double eps = DBL_EPSILON; + + cp_err = stderr; + n1 = 1; + t1 = VF_COMPLEX; + c = alloc_c(n1); + realpart(&c[0]) = .0; + imagpart(&c[0]) = 1.0; + d = (double *) cx_ph((void *) c, t1, n1, &n2, &t2); + if (M_PI/2 - eps < d[0] && d[0] < M_PI/2 + eps) + return 0; + else + return 1; +} diff --git a/src/maths/sparse/spdefs.h b/src/maths/sparse/spdefs.h index faefba48a..333f32277 100644 --- a/src/maths/sparse/spdefs.h +++ b/src/maths/sparse/spdefs.h @@ -440,48 +440,7 @@ } - - - - - -/* - * REAL NUMBER - */ - -/* Begin `RealNumber'. */ - -typedef spREAL RealNumber, *RealVector; - - - - - - - - -/* - * COMPLEX NUMBER DATA STRUCTURE - * - * >>> Structure fields: - * Real (RealNumber) - * The real portion of the number. Real must be the first - * field in this structure. - * Imag (RealNumber) - * The imaginary portion of the number. This field must follow - * immediately after Real. - */ - -/* Begin `ComplexNumber'. */ - -typedef struct -{ RealNumber Real; - RealNumber Imag; -} ComplexNumber, *ComplexVector; - - - - +#include "complex.h"