aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/map/libmap/complex.c
blob: b3099fd4ef2fe8ed5159c792d416ae830f50455d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#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);
}