diff options
| author | Russ Cox <rsc@golang.org> | 2010-06-18 15:46:00 -0700 | 
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2010-06-18 15:46:00 -0700 | 
| commit | e8bbf1946bbdf4923b0ac66bda8339f49fec7ab3 (patch) | |
| tree | 856ce616828c0b3474d915b46ce5f07aba23fe51 /src/pkg/runtime/complex.c | |
| parent | a4cc6162ab466f051c80ffb7ea06eb25517f365f (diff) | |
| download | golang-e8bbf1946bbdf4923b0ac66bda8339f49fec7ab3.tar.gz | |
complex divide: match C99 implementation
R=iant, ken2, r, r2, ken3
CC=golang-dev
http://codereview.appspot.com/1686044
Diffstat (limited to 'src/pkg/runtime/complex.c')
| -rw-r--r-- | src/pkg/runtime/complex.c | 70 | 
1 files changed, 47 insertions, 23 deletions
| diff --git a/src/pkg/runtime/complex.c b/src/pkg/runtime/complex.c index ca6ed79ba..2240d9fb8 100644 --- a/src/pkg/runtime/complex.c +++ b/src/pkg/runtime/complex.c @@ -4,33 +4,57 @@  #include "runtime.h" -// complex128div(num, den complex128) (quo complex128) +typedef struct Complex128 Complex128; +  void -·complex128div(float64 numreal, float64 numimag, -	float64 denreal, float64 denimag, -	float64 quoreal, float64 quoimag) +·complex128div(Complex128 n, Complex128 d, Complex128 q)  { +	int32 ninf, dinf, nnan, dnan;  	float64 a, b, ratio, denom; -	a = denreal; -	if(a < 0) -		a = -a; -	b = denimag; -	if(b < 0) -		b = -b; -	if(a <= b) { -		if(b == 0) -			panicstring("complex divide by zero"); -		ratio = denreal/denimag; -		denom = denreal*ratio + denimag; -		quoreal = (numreal*ratio + numimag) / denom; -		quoimag = (numimag*ratio - numreal) / denom; +	// Special cases as in C99. +	ninf = isInf(n.real, 0) || isInf(n.imag, 0); +	dinf = isInf(d.real, 0) || isInf(d.imag, 0); + +	nnan = !ninf && (isNaN(n.real) || isNaN(n.imag)); +	dnan = !dinf && (isNaN(d.real) || isNaN(d.imag)); + +	if(nnan || dnan) { +		q.real = NaN(); +		q.imag = NaN(); +	} else if(ninf && !dinf && !dnan) { +		q.real = Inf(0); +		q.imag = Inf(0); +	} else if(!ninf && !nnan && dinf) { +		q.real = 0; +		q.imag = 0; +	} else if(d.real == 0 && d.imag == 0) { +		if(n.real == 0 && n.imag == 0) { +			q.real = NaN(); +			q.imag = NaN(); +		} else { +			q.real = Inf(0); +			q.imag = Inf(0); +		}  	} else { -		ratio = denimag/denreal; -		denom = denimag*ratio + denreal; -		quoreal = (numimag*ratio + numreal) / denom; -		quoimag = (numimag - numreal*ratio) / denom; +		// Standard complex arithmetic, factored to avoid unnecessary overflow. +		a = d.real; +		if(a < 0) +			a = -a; +		b = d.imag; +		if(b < 0) +			b = -b; +		if(a <= b) { +			ratio = d.real/d.imag; +			denom = d.real*ratio + d.imag; +			q.real = (n.real*ratio + n.imag) / denom; +			q.imag = (n.imag*ratio - n.real) / denom; +		} else { +			ratio = d.imag/d.real; +			denom = d.imag*ratio + d.real; +			q.real = (n.imag*ratio + n.real) / denom; +			q.imag = (n.imag - n.real*ratio) / denom; +		}  	} -	FLUSH(&quoreal); -	FLUSH(&quoimag); +	FLUSH(&q);  } | 
