123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669 |
- /* clogf.c
- *
- * Complex natural logarithm
- *
- *
- *
- * SYNOPSIS:
- *
- * void clogf();
- * cmplxf z, w;
- *
- * clogf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns complex logarithm to the base e (2.718...) of
- * the complex argument x.
- *
- * If z = x + iy, r = sqrt( x**2 + y**2 ),
- * then
- * w = log(r) + i arctan(y/x).
- *
- * The arctangent ranges from -PI to +PI.
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 1.9e-6 6.2e-8
- *
- * Larger relative error can be observed for z near 1 +i0.
- * In IEEE arithmetic the peak absolute error is 3.1e-7.
- *
- */
- #include <math.h>
- extern float MAXNUMF, MACHEPF, PIF, PIO2F;
- #ifdef ANSIC
- float cabsf(cmplxf *), sqrtf(float), logf(float), atan2f(float, float);
- float expf(float), sinf(float), cosf(float);
- float coshf(float), sinhf(float), asinf(float);
- float ctansf(cmplxf *), redupif(float);
- void cchshf( float, float *, float * );
- void caddf( cmplxf *, cmplxf *, cmplxf * );
- void csqrtf( cmplxf *, cmplxf * );
- #else
- float cabsf(), sqrtf(), logf(), atan2f();
- float expf(), sinf(), cosf();
- float coshf(), sinhf(), asinf();
- float ctansf(), redupif();
- void cchshf(), csqrtf(), caddf();
- #endif
- #define fabsf(x) ( (x) < 0 ? -(x) : (x) )
- void clogf( z, w )
- register cmplxf *z, *w;
- {
- float p, rr;
- /*rr = sqrtf( z->r * z->r + z->i * z->i );*/
- rr = cabsf(z);
- p = logf(rr);
- #if ANSIC
- rr = atan2f( z->i, z->r );
- #else
- rr = atan2f( z->r, z->i );
- if( rr > PIF )
- rr -= PIF + PIF;
- #endif
- w->i = rr;
- w->r = p;
- }
- /* cexpf()
- *
- * Complex exponential function
- *
- *
- *
- * SYNOPSIS:
- *
- * void cexpf();
- * cmplxf z, w;
- *
- * cexpf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns the exponential of the complex argument z
- * into the complex result w.
- *
- * If
- * z = x + iy,
- * r = exp(x),
- *
- * then
- *
- * w = r cos y + i r sin y.
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 1.4e-7 4.5e-8
- *
- */
- void cexpf( z, w )
- register cmplxf *z, *w;
- {
- float r;
- r = expf( z->r );
- w->r = r * cosf( z->i );
- w->i = r * sinf( z->i );
- }
- /* csinf()
- *
- * Complex circular sine
- *
- *
- *
- * SYNOPSIS:
- *
- * void csinf();
- * cmplxf z, w;
- *
- * csinf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * If
- * z = x + iy,
- *
- * then
- *
- * w = sin x cosh y + i cos x sinh y.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 1.9e-7 5.5e-8
- *
- */
- void csinf( z, w )
- register cmplxf *z, *w;
- {
- float ch, sh;
- cchshf( z->i, &ch, &sh );
- w->r = sinf( z->r ) * ch;
- w->i = cosf( z->r ) * sh;
- }
- /* calculate cosh and sinh */
- void cchshf( float xx, float *c, float *s )
- {
- float x, e, ei;
- x = xx;
- if( fabsf(x) <= 0.5f )
- {
- *c = coshf(x);
- *s = sinhf(x);
- }
- else
- {
- e = expf(x);
- ei = 0.5f/e;
- e = 0.5f * e;
- *s = e - ei;
- *c = e + ei;
- }
- }
- /* ccosf()
- *
- * Complex circular cosine
- *
- *
- *
- * SYNOPSIS:
- *
- * void ccosf();
- * cmplxf z, w;
- *
- * ccosf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * If
- * z = x + iy,
- *
- * then
- *
- * w = cos x cosh y - i sin x sinh y.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 1.8e-7 5.5e-8
- */
- void ccosf( z, w )
- register cmplxf *z, *w;
- {
- float ch, sh;
- cchshf( z->i, &ch, &sh );
- w->r = cosf( z->r ) * ch;
- w->i = -sinf( z->r ) * sh;
- }
- /* ctanf()
- *
- * Complex circular tangent
- *
- *
- *
- * SYNOPSIS:
- *
- * void ctanf();
- * cmplxf z, w;
- *
- * ctanf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * If
- * z = x + iy,
- *
- * then
- *
- * sin 2x + i sinh 2y
- * w = --------------------.
- * cos 2x + cosh 2y
- *
- * On the real axis the denominator is zero at odd multiples
- * of PI/2. The denominator is evaluated by its Taylor
- * series near these points.
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 3.3e-7 5.1e-8
- */
- void ctanf( z, w )
- register cmplxf *z, *w;
- {
- float d;
- d = cosf( 2.0f * z->r ) + coshf( 2.0f * z->i );
- if( fabsf(d) < 0.25f )
- d = ctansf(z);
- if( d == 0.0f )
- {
- mtherr( "ctanf", OVERFLOW );
- w->r = MAXNUMF;
- w->i = MAXNUMF;
- return;
- }
- w->r = sinf( 2.0f * z->r ) / d;
- w->i = sinhf( 2.0f * z->i ) / d;
- }
- /* ccotf()
- *
- * Complex circular cotangent
- *
- *
- *
- * SYNOPSIS:
- *
- * void ccotf();
- * cmplxf z, w;
- *
- * ccotf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * If
- * z = x + iy,
- *
- * then
- *
- * sin 2x - i sinh 2y
- * w = --------------------.
- * cosh 2y - cos 2x
- *
- * On the real axis, the denominator has zeros at even
- * multiples of PI/2. Near these points it is evaluated
- * by a Taylor series.
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 3.6e-7 5.7e-8
- * Also tested by ctan * ccot = 1 + i0.
- */
- void ccotf( z, w )
- register cmplxf *z, *w;
- {
- float d;
- d = coshf(2.0f * z->i) - cosf(2.0f * z->r);
- if( fabsf(d) < 0.25f )
- d = ctansf(z);
- if( d == 0.0f )
- {
- mtherr( "ccotf", OVERFLOW );
- w->r = MAXNUMF;
- w->i = MAXNUMF;
- return;
- }
- d = 1.0f/d;
- w->r = sinf( 2.0f * z->r ) * d;
- w->i = -sinhf( 2.0f * z->i ) * d;
- }
- /* Program to subtract nearest integer multiple of PI */
- /* extended precision value of PI: */
- static float DP1 = 3.140625;
- static float DP2 = 9.67502593994140625E-4;
- static float DP3 = 1.509957990978376432E-7;
- float redupif(float xx)
- {
- float x, t;
- long i;
- x = xx;
- t = x/PIF;
- if( t >= 0.0f )
- t += 0.5f;
- else
- t -= 0.5f;
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return(t);
- }
- /* Taylor series expansion for cosh(2y) - cos(2x) */
- float ctansf(z)
- cmplxf *z;
- {
- float f, x, x2, y, y2, rn, t, d;
- x = fabsf( 2.0f * z->r );
- y = fabsf( 2.0f * z->i );
- x = redupif(x);
- x = x * x;
- y = y * y;
- x2 = 1.0f;
- y2 = 1.0f;
- f = 1.0f;
- rn = 0.0f;
- d = 0.0f;
- do
- {
- rn += 1.0f;
- f *= rn;
- rn += 1.0f;
- f *= rn;
- x2 *= x;
- y2 *= y;
- t = y2 + x2;
- t /= f;
- d += t;
- rn += 1.0f;
- f *= rn;
- rn += 1.0f;
- f *= rn;
- x2 *= x;
- y2 *= y;
- t = y2 - x2;
- t /= f;
- d += t;
- }
- while( fabsf(t/d) > MACHEPF );
- return(d);
- }
- /* casinf()
- *
- * Complex circular arc sine
- *
- *
- *
- * SYNOPSIS:
- *
- * void casinf();
- * cmplxf z, w;
- *
- * casinf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * Inverse complex sine:
- *
- * 2
- * w = -i clog( iz + csqrt( 1 - z ) ).
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 1.1e-5 1.5e-6
- * Larger relative error can be observed for z near zero.
- *
- */
- void casinf( z, w )
- cmplxf *z, *w;
- {
- float x, y;
- static cmplxf ca, ct, zz, z2;
- /*
- float cn, n;
- static float a, b, s, t, u, v, y2;
- static cmplxf sum;
- */
- x = z->r;
- y = z->i;
- if( y == 0.0f )
- {
- if( fabsf(x) > 1.0f )
- {
- w->r = PIO2F;
- w->i = 0.0f;
- mtherr( "casinf", DOMAIN );
- }
- else
- {
- w->r = asinf(x);
- w->i = 0.0f;
- }
- return;
- }
- /* Power series expansion */
- /*
- b = cabsf(z);
- if( b < 0.125 )
- {
- z2.r = (x - y) * (x + y);
- z2.i = 2.0 * x * y;
- cn = 1.0;
- n = 1.0;
- ca.r = x;
- ca.i = y;
- sum.r = x;
- sum.i = y;
- do
- {
- ct.r = z2.r * ca.r - z2.i * ca.i;
- ct.i = z2.r * ca.i + z2.i * ca.r;
- ca.r = ct.r;
- ca.i = ct.i;
- cn *= n;
- n += 1.0;
- cn /= n;
- n += 1.0;
- b = cn/n;
- ct.r *= b;
- ct.i *= b;
- sum.r += ct.r;
- sum.i += ct.i;
- b = fabsf(ct.r) + fabsf(ct.i);
- }
- while( b > MACHEPF );
- w->r = sum.r;
- w->i = sum.i;
- return;
- }
- */
- ca.r = x;
- ca.i = y;
- ct.r = -ca.i; /* iz */
- ct.i = ca.r;
- /* sqrt( 1 - z*z) */
- /* cmul( &ca, &ca, &zz ) */
- zz.r = (ca.r - ca.i) * (ca.r + ca.i); /*x * x - y * y */
- zz.i = 2.0f * ca.r * ca.i;
- zz.r = 1.0f - zz.r;
- zz.i = -zz.i;
- csqrtf( &zz, &z2 );
- caddf( &z2, &ct, &zz );
- clogf( &zz, &zz );
- w->r = zz.i; /* mult by 1/i = -i */
- w->i = -zz.r;
- return;
- }
- /* cacosf()
- *
- * Complex circular arc cosine
- *
- *
- *
- * SYNOPSIS:
- *
- * void cacosf();
- * cmplxf z, w;
- *
- * cacosf( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- *
- * w = arccos z = PI/2 - arcsin z.
- *
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 9.2e-6 1.2e-6
- *
- */
- void cacosf( z, w )
- cmplxf *z, *w;
- {
- casinf( z, w );
- w->r = PIO2F - w->r;
- w->i = -w->i;
- }
- /* catan()
- *
- * Complex circular arc tangent
- *
- *
- *
- * SYNOPSIS:
- *
- * void catan();
- * cmplxf z, w;
- *
- * catan( &z, &w );
- *
- *
- *
- * DESCRIPTION:
- *
- * If
- * z = x + iy,
- *
- * then
- * 1 ( 2x )
- * Re w = - arctan(-----------) + k PI
- * 2 ( 2 2)
- * (1 - x - y )
- *
- * ( 2 2)
- * 1 (x + (y+1) )
- * Im w = - log(------------)
- * 4 ( 2 2)
- * (x + (y-1) )
- *
- * Where k is an arbitrary integer.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * IEEE -10,+10 30000 2.3e-6 5.2e-8
- *
- */
- void catanf( z, w )
- cmplxf *z, *w;
- {
- float a, t, x, x2, y;
- x = z->r;
- y = z->i;
- if( (x == 0.0f) && (y > 1.0f) )
- goto ovrf;
- x2 = x * x;
- a = 1.0f - x2 - (y * y);
- if( a == 0.0f )
- goto ovrf;
- #if ANSIC
- t = 0.5f * atan2f( 2.0f * x, a );
- #else
- t = 0.5f * atan2f( a, 2.0f * x );
- #endif
- w->r = redupif( t );
- t = y - 1.0f;
- a = x2 + (t * t);
- if( a == 0.0f )
- goto ovrf;
- t = y + 1.0f;
- a = (x2 + (t * t))/a;
- w->i = 0.25f*logf(a);
- return;
- ovrf:
- mtherr( "catanf", OVERFLOW );
- w->r = MAXNUMF;
- w->i = MAXNUMF;
- }
|