123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- /* cmplx.c
- *
- * Complex number arithmetic
- *
- *
- *
- * SYNOPSIS:
- *
- * typedef struct {
- * double r; real part
- * double i; imaginary part
- * }cmplx;
- *
- * cmplx *a, *b, *c;
- *
- * cadd( a, b, c ); c = b + a
- * csub( a, b, c ); c = b - a
- * cmul( a, b, c ); c = b * a
- * cdiv( a, b, c ); c = b / a
- * cneg( c ); c = -c
- * cmov( b, c ); c = b
- *
- *
- *
- * DESCRIPTION:
- *
- * Addition:
- * c.r = b.r + a.r
- * c.i = b.i + a.i
- *
- * Subtraction:
- * c.r = b.r - a.r
- * c.i = b.i - a.i
- *
- * Multiplication:
- * c.r = b.r * a.r - b.i * a.i
- * c.i = b.r * a.i + b.i * a.r
- *
- * Division:
- * d = a.r * a.r + a.i * a.i
- * c.r = (b.r * a.r + b.i * a.i)/d
- * c.i = (b.i * a.r - b.r * a.i)/d
- * ACCURACY:
- *
- * In DEC arithmetic, the test (1/z) * z = 1 had peak relative
- * error 3.1e-17, rms 1.2e-17. The test (y/z) * (z/y) = 1 had
- * peak relative error 8.3e-17, rms 2.1e-17.
- *
- * Tests in the rectangle {-10,+10}:
- * Relative error:
- * arithmetic function # trials peak rms
- * DEC cadd 10000 1.4e-17 3.4e-18
- * IEEE cadd 100000 1.1e-16 2.7e-17
- * DEC csub 10000 1.4e-17 4.5e-18
- * IEEE csub 100000 1.1e-16 3.4e-17
- * DEC cmul 3000 2.3e-17 8.7e-18
- * IEEE cmul 100000 2.1e-16 6.9e-17
- * DEC cdiv 18000 4.9e-17 1.3e-17
- * IEEE cdiv 100000 3.7e-16 1.1e-16
- */
- /* cmplx.c
- * complex number arithmetic
- */
- /*
- Cephes Math Library Release 2.8: June, 2000
- Copyright 1984, 1995, 2000 by Stephen L. Moshier
- */
- #include <math.h>
- #ifdef ANSIPROT
- extern double fabs ( double );
- extern double cabs ( cmplx * );
- extern double sqrt ( double );
- extern double atan2 ( double, double );
- extern double cos ( double );
- extern double sin ( double );
- extern double sqrt ( double );
- extern double frexp ( double, int * );
- extern double ldexp ( double, int );
- int isnan ( double );
- void cdiv ( cmplx *, cmplx *, cmplx * );
- void cadd ( cmplx *, cmplx *, cmplx * );
- #else
- double fabs(), cabs(), sqrt(), atan2(), cos(), sin();
- double sqrt(), frexp(), ldexp();
- int isnan();
- void cdiv(), cadd();
- #endif
- extern double MAXNUM, MACHEP, PI, PIO2, INFINITY, NAN;
- /*
- typedef struct
- {
- double r;
- double i;
- }cmplx;
- */
- cmplx czero = {0.0, 0.0};
- extern cmplx czero;
- cmplx cone = {1.0, 0.0};
- extern cmplx cone;
- /* c = b + a */
- void cadd( a, b, c )
- register cmplx *a, *b;
- cmplx *c;
- {
- c->r = b->r + a->r;
- c->i = b->i + a->i;
- }
- /* c = b - a */
- void csub( a, b, c )
- register cmplx *a, *b;
- cmplx *c;
- {
- c->r = b->r - a->r;
- c->i = b->i - a->i;
- }
- /* c = b * a */
- void cmul( a, b, c )
- register cmplx *a, *b;
- cmplx *c;
- {
- double y;
- y = b->r * a->r - b->i * a->i;
- c->i = b->r * a->i + b->i * a->r;
- c->r = y;
- }
- /* c = b / a */
- void cdiv( a, b, c )
- register cmplx *a, *b;
- cmplx *c;
- {
- double y, p, q, w;
- y = a->r * a->r + a->i * a->i;
- p = b->r * a->r + b->i * a->i;
- q = b->i * a->r - b->r * a->i;
- if( y < 1.0 )
- {
- w = MAXNUM * y;
- if( (fabs(p) > w) || (fabs(q) > w) || (y == 0.0) )
- {
- c->r = MAXNUM;
- c->i = MAXNUM;
- mtherr( "cdiv", OVERFLOW );
- return;
- }
- }
- c->r = p/y;
- c->i = q/y;
- }
- /* b = a
- Caution, a `short' is assumed to be 16 bits wide. */
- void cmov( a, b )
- void *a, *b;
- {
- register short *pa, *pb;
- int i;
- pa = (short *) a;
- pb = (short *) b;
- i = 8;
- do
- *pb++ = *pa++;
- while( --i );
- }
- void cneg( a )
- register cmplx *a;
- {
- a->r = -a->r;
- a->i = -a->i;
- }
- /* cabs()
- *
- * Complex absolute value
- *
- *
- *
- * SYNOPSIS:
- *
- * double cabs();
- * cmplx z;
- * double a;
- *
- * a = cabs( &z );
- *
- *
- *
- * DESCRIPTION:
- *
- *
- * If z = x + iy
- *
- * then
- *
- * a = sqrt( x**2 + y**2 ).
- *
- * Overflow and underflow are avoided by testing the magnitudes
- * of x and y before squaring. If either is outside half of
- * the floating point full scale range, both are rescaled.
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC -30,+30 30000 3.2e-17 9.2e-18
- * IEEE -10,+10 100000 2.7e-16 6.9e-17
- */
- /*
- Cephes Math Library Release 2.1: January, 1989
- Copyright 1984, 1987, 1989 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
- /*
- typedef struct
- {
- double r;
- double i;
- }cmplx;
- */
- #ifdef UNK
- #define PREC 27
- #define MAXEXP 1024
- #define MINEXP -1077
- #endif
- #ifdef DEC
- #define PREC 29
- #define MAXEXP 128
- #define MINEXP -128
- #endif
- #ifdef IBMPC
- #define PREC 27
- #define MAXEXP 1024
- #define MINEXP -1077
- #endif
- #ifdef MIEEE
- #define PREC 27
- #define MAXEXP 1024
- #define MINEXP -1077
- #endif
- double cabs( z )
- register cmplx *z;
- {
- double x, y, b, re, im;
- int ex, ey, e;
- #ifdef INFINITIES
- /* Note, cabs(INFINITY,NAN) = INFINITY. */
- if( z->r == INFINITY || z->i == INFINITY
- || z->r == -INFINITY || z->i == -INFINITY )
- return( INFINITY );
- #endif
- #ifdef NANS
- if( isnan(z->r) )
- return(z->r);
- if( isnan(z->i) )
- return(z->i);
- #endif
- re = fabs( z->r );
- im = fabs( z->i );
- if( re == 0.0 )
- return( im );
- if( im == 0.0 )
- return( re );
- /* Get the exponents of the numbers */
- x = frexp( re, &ex );
- y = frexp( im, &ey );
- /* Check if one number is tiny compared to the other */
- e = ex - ey;
- if( e > PREC )
- return( re );
- if( e < -PREC )
- return( im );
- /* Find approximate exponent e of the geometric mean. */
- e = (ex + ey) >> 1;
- /* Rescale so mean is about 1 */
- x = ldexp( re, -e );
- y = ldexp( im, -e );
-
- /* Hypotenuse of the right triangle */
- b = sqrt( x * x + y * y );
- /* Compute the exponent of the answer. */
- y = frexp( b, &ey );
- ey = e + ey;
- /* Check it for overflow and underflow. */
- if( ey > MAXEXP )
- {
- mtherr( "cabs", OVERFLOW );
- return( INFINITY );
- }
- if( ey < MINEXP )
- return(0.0);
- /* Undo the scaling */
- b = ldexp( b, e );
- return( b );
- }
- /* csqrt()
- *
- * Complex square root
- *
- *
- *
- * SYNOPSIS:
- *
- * void csqrt();
- * cmplx z, w;
- *
- * csqrt( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- *
- * If z = x + iy, r = |z|, then
- *
- * 1/2
- * Im w = [ (r - x)/2 ] ,
- *
- * Re w = y / 2 Im w.
- *
- *
- * Note that -w is also a square root of z. The root chosen
- * is always in the upper half plane.
- *
- * Because of the potential for cancellation error in r - x,
- * the result is sharpened by doing a Heron iteration
- * (see sqrt.c) in complex arithmetic.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC -10,+10 25000 3.2e-17 9.6e-18
- * IEEE -10,+10 100000 3.2e-16 7.7e-17
- *
- * 2
- * Also tested by csqrt( z ) = z, and tested by arguments
- * close to the real axis.
- */
- void csqrt( z, w )
- cmplx *z, *w;
- {
- cmplx q, s;
- double x, y, r, t;
- x = z->r;
- y = z->i;
- if( y == 0.0 )
- {
- if( x < 0.0 )
- {
- w->r = 0.0;
- w->i = sqrt(-x);
- return;
- }
- else
- {
- w->r = sqrt(x);
- w->i = 0.0;
- return;
- }
- }
- if( x == 0.0 )
- {
- r = fabs(y);
- r = sqrt(0.5*r);
- if( y > 0 )
- w->r = r;
- else
- w->r = -r;
- w->i = r;
- return;
- }
- /* Approximate sqrt(x^2+y^2) - x = y^2/2x - y^4/24x^3 + ... .
- * The relative error in the first term is approximately y^2/12x^2 .
- */
- if( (fabs(y) < 2.e-4 * fabs(x))
- && (x > 0) )
- {
- t = 0.25*y*(y/x);
- }
- else
- {
- r = cabs(z);
- t = 0.5*(r - x);
- }
- r = sqrt(t);
- q.i = r;
- q.r = y/(2.0*r);
- /* Heron iteration in complex arithmetic */
- cdiv( &q, z, &s );
- cadd( &q, &s, w );
- w->r *= 0.5;
- w->i *= 0.5;
- }
- double hypot( x, y )
- double x, y;
- {
- cmplx z;
- z.r = x;
- z.i = y;
- return( cabs(&z) );
- }
|