xref: /plan9/sys/src/cmd/map/libmap/complex.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier #include <u.h>
2*59cc4ca5SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include "map.h"
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier /*complex divide, defensive against overflow from
63e12c5d1SDavid du Colombier  *	* and /, but not from + and -
73e12c5d1SDavid du Colombier  *	assumes underflow yields 0.0
83e12c5d1SDavid du Colombier  *	uses identities:
93e12c5d1SDavid du Colombier  *	(a + bi)/(c + di) = ((a + bd/c) + (b - ad/c)i)/(c + dd/c)
103e12c5d1SDavid du Colombier  *	(a + bi)/(c + di) = (b - ai)/(d - ci)
113e12c5d1SDavid du Colombier */
123e12c5d1SDavid du Colombier void
cdiv(double a,double b,double c,double d,double * u,double * v)133e12c5d1SDavid du Colombier cdiv(double a, double b, double c, double d, double *u, double *v)
143e12c5d1SDavid du Colombier {
153e12c5d1SDavid du Colombier 	double r,t;
163e12c5d1SDavid du Colombier 	if(fabs(c)<fabs(d)) {
173e12c5d1SDavid du Colombier 		t = -c; c = d; d = t;
183e12c5d1SDavid du Colombier 		t = -a; a = b; b = t;
193e12c5d1SDavid du Colombier 	}
203e12c5d1SDavid du Colombier 	r = d/c;
213e12c5d1SDavid du Colombier 	t = c + r*d;
223e12c5d1SDavid du Colombier 	*u = (a + r*b)/t;
233e12c5d1SDavid du Colombier 	*v = (b - r*a)/t;
243e12c5d1SDavid du Colombier }
253e12c5d1SDavid du Colombier 
263e12c5d1SDavid du Colombier void
cmul(double c1,double c2,double d1,double d2,double * e1,double * e2)273e12c5d1SDavid du Colombier cmul(double c1, double c2, double d1, double d2, double *e1, double *e2)
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier 	*e1 = c1*d1 - c2*d2;
303e12c5d1SDavid du Colombier 	*e2 = c1*d2 + c2*d1;
313e12c5d1SDavid du Colombier }
323e12c5d1SDavid du Colombier 
333e12c5d1SDavid du Colombier void
csq(double c1,double c2,double * e1,double * e2)343e12c5d1SDavid du Colombier csq(double c1, double c2, double *e1, double *e2)
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier 	*e1 = c1*c1 - c2*c2;
373e12c5d1SDavid du Colombier 	*e2 = c1*c2*2;
383e12c5d1SDavid du Colombier }
393e12c5d1SDavid du Colombier 
403e12c5d1SDavid du Colombier /* complex square root
413e12c5d1SDavid du Colombier  *	assumes underflow yields 0.0
423e12c5d1SDavid du Colombier  *	uses these identities:
433e12c5d1SDavid du Colombier  *	sqrt(x+_iy) = sqrt(r(cos(t)+_isin(t))
443e12c5d1SDavid du Colombier  *	           = sqrt(r)(cos(t/2)+_isin(t/2))
453e12c5d1SDavid du Colombier  *	cos(t/2) = sin(t)/2sin(t/2) = sqrt((1+cos(t)/2)
463e12c5d1SDavid du Colombier  *	sin(t/2) = sin(t)/2cos(t/2) = sqrt((1-cos(t)/2)
473e12c5d1SDavid du Colombier */
483e12c5d1SDavid du Colombier void
csqrt(double c1,double c2,double * e1,double * e2)493e12c5d1SDavid du Colombier csqrt(double c1, double c2, double *e1, double *e2)
503e12c5d1SDavid du Colombier {
513e12c5d1SDavid du Colombier 	double r,s;
523e12c5d1SDavid du Colombier 	double x,y;
533e12c5d1SDavid du Colombier 	x = fabs(c1);
543e12c5d1SDavid du Colombier 	y = fabs(c2);
553e12c5d1SDavid du Colombier 	if(x>=y) {
563e12c5d1SDavid du Colombier 		if(x==0) {
573e12c5d1SDavid du Colombier 			*e1 = *e2 = 0;
583e12c5d1SDavid du Colombier 			return;
593e12c5d1SDavid du Colombier 		}
603e12c5d1SDavid du Colombier 		r = x;
613e12c5d1SDavid du Colombier 		s = y/x;
623e12c5d1SDavid du Colombier 	} else {
633e12c5d1SDavid du Colombier 		r = y;
643e12c5d1SDavid du Colombier 		s = x/y;
653e12c5d1SDavid du Colombier 	}
663e12c5d1SDavid du Colombier 	r *= sqrt(1+ s*s);
673e12c5d1SDavid du Colombier 	if(c1>0) {
683e12c5d1SDavid du Colombier 		*e1 = sqrt((r+c1)/2);
693e12c5d1SDavid du Colombier 		*e2 = c2/(2* *e1);
703e12c5d1SDavid du Colombier 	} else {
713e12c5d1SDavid du Colombier 		*e2 = sqrt((r-c1)/2);
723e12c5d1SDavid du Colombier 		if(c2<0)
733e12c5d1SDavid du Colombier 			*e2 = -*e2;
743e12c5d1SDavid du Colombier 		*e1 = c2/(2* *e2);
753e12c5d1SDavid du Colombier 	}
763e12c5d1SDavid du Colombier }
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier 
cpow(double c1,double c2,double * d1,double * d2,double pwr)797dd7cddfSDavid du Colombier void cpow(double c1, double c2, double *d1, double *d2, double pwr)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier 	double theta = pwr*atan2(c2,c1);
827dd7cddfSDavid du Colombier 	double r = pow(hypot(c1,c2), pwr);
837dd7cddfSDavid du Colombier 	*d1 = r*cos(theta);
847dd7cddfSDavid du Colombier 	*d2 = r*sin(theta);
857dd7cddfSDavid du Colombier }
86