|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include "map.h" | 
|  |  | 
|  | /*complex divide, defensive against overflow from | 
|  | *	* and /, but not from + and - | 
|  | *	assumes underflow yields 0.0 | 
|  | *	uses identities: | 
|  | *	(a + bi)/(c + di) = ((a + bd/c) + (b - ad/c)i)/(c + dd/c) | 
|  | *	(a + bi)/(c + di) = (b - ai)/(d - ci) | 
|  | */ | 
|  | void | 
|  | cdiv(double a, double b, double c, double d, double *u, double *v) | 
|  | { | 
|  | double r,t; | 
|  | if(fabs(c)<fabs(d)) { | 
|  | t = -c; c = d; d = t; | 
|  | t = -a; a = b; b = t; | 
|  | } | 
|  | r = d/c; | 
|  | t = c + r*d; | 
|  | *u = (a + r*b)/t; | 
|  | *v = (b - r*a)/t; | 
|  | } | 
|  |  | 
|  | void | 
|  | cmul(double c1, double c2, double d1, double d2, double *e1, double *e2) | 
|  | { | 
|  | *e1 = c1*d1 - c2*d2; | 
|  | *e2 = c1*d2 + c2*d1; | 
|  | } | 
|  |  | 
|  | void | 
|  | csq(double c1, double c2, double *e1, double *e2) | 
|  | { | 
|  | *e1 = c1*c1 - c2*c2; | 
|  | *e2 = c1*c2*2; | 
|  | } | 
|  |  | 
|  | /* complex square root | 
|  | *	assumes underflow yields 0.0 | 
|  | *	uses these identities: | 
|  | *	sqrt(x+_iy) = sqrt(r(cos(t)+_isin(t)) | 
|  | *	           = sqrt(r)(cos(t/2)+_isin(t/2)) | 
|  | *	cos(t/2) = sin(t)/2sin(t/2) = sqrt((1+cos(t)/2) | 
|  | *	sin(t/2) = sin(t)/2cos(t/2) = sqrt((1-cos(t)/2) | 
|  | */ | 
|  | void | 
|  | csqrt(double c1, double c2, double *e1, double *e2) | 
|  | { | 
|  | double r,s; | 
|  | double x,y; | 
|  | x = fabs(c1); | 
|  | y = fabs(c2); | 
|  | if(x>=y) { | 
|  | if(x==0) { | 
|  | *e1 = *e2 = 0; | 
|  | return; | 
|  | } | 
|  | r = x; | 
|  | s = y/x; | 
|  | } else { | 
|  | r = y; | 
|  | s = x/y; | 
|  | } | 
|  | r *= sqrt(1+ s*s); | 
|  | if(c1>0) { | 
|  | *e1 = sqrt((r+c1)/2); | 
|  | *e2 = c2/(2* *e1); | 
|  | } else { | 
|  | *e2 = sqrt((r-c1)/2); | 
|  | if(c2<0) | 
|  | *e2 = -*e2; | 
|  | *e1 = c2/(2* *e2); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | void cpow(double c1, double c2, double *d1, double *d2, double pwr) | 
|  | { | 
|  | double theta = pwr*atan2(c2,c1); | 
|  | double r = pow(hypot(c1,c2), pwr); | 
|  | *d1 = r*cos(theta); | 
|  | *d2 = r*sin(theta); | 
|  | } |