-
Notifications
You must be signed in to change notification settings - Fork 895
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compiler: implement complex division
This is hard to do correctly, so copy the relevant files from the Go compiler itself. For related discussions: * golang/go#14644 * golang/go#29846
- Loading branch information
Showing
6 changed files
with
138 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright 2010 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package runtime | ||
|
||
// inf2one returns a signed 1 if f is an infinity and a signed 0 otherwise. | ||
// The sign of the result is the sign of f. | ||
func inf2one(f float64) float64 { | ||
g := 0.0 | ||
if isInf(f) { | ||
g = 1.0 | ||
} | ||
return copysign(g, f) | ||
} | ||
|
||
func complex64div(n complex64, m complex64) complex64 { | ||
return complex64(complex128div(complex128(n), complex128(m))) | ||
} | ||
|
||
func complex128div(n complex128, m complex128) complex128 { | ||
var e, f float64 // complex(e, f) = n/m | ||
|
||
// Algorithm for robust complex division as described in | ||
// Robert L. Smith: Algorithm 116: Complex division. Commun. ACM 5(8): 435 (1962). | ||
if abs(real(m)) >= abs(imag(m)) { | ||
ratio := imag(m) / real(m) | ||
denom := real(m) + ratio*imag(m) | ||
e = (real(n) + imag(n)*ratio) / denom | ||
f = (imag(n) - real(n)*ratio) / denom | ||
} else { | ||
ratio := real(m) / imag(m) | ||
denom := imag(m) + ratio*real(m) | ||
e = (real(n)*ratio + imag(n)) / denom | ||
f = (imag(n)*ratio - real(n)) / denom | ||
} | ||
|
||
if isNaN(e) && isNaN(f) { | ||
// Correct final result to infinities and zeros if applicable. | ||
// Matches C99: ISO/IEC 9899:1999 - G.5.1 Multiplicative operators. | ||
|
||
a, b := real(n), imag(n) | ||
c, d := real(m), imag(m) | ||
|
||
switch { | ||
case m == 0 && (!isNaN(a) || !isNaN(b)): | ||
e = copysign(inf, c) * a | ||
f = copysign(inf, c) * b | ||
|
||
case (isInf(a) || isInf(b)) && isFinite(c) && isFinite(d): | ||
a = inf2one(a) | ||
b = inf2one(b) | ||
e = inf * (a*c + b*d) | ||
f = inf * (b*c - a*d) | ||
|
||
case (isInf(c) || isInf(d)) && isFinite(a) && isFinite(b): | ||
c = inf2one(c) | ||
d = inf2one(d) | ||
e = 0 * (a*c + b*d) | ||
f = 0 * (b*c - a*d) | ||
} | ||
} | ||
|
||
return complex(e, f) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package runtime | ||
|
||
import "unsafe" | ||
|
||
var inf = float64frombits(0x7FF0000000000000) | ||
|
||
// isNaN reports whether f is an IEEE 754 ``not-a-number'' value. | ||
func isNaN(f float64) (is bool) { | ||
// IEEE 754 says that only NaNs satisfy f != f. | ||
return f != f | ||
} | ||
|
||
// isFinite reports whether f is neither NaN nor an infinity. | ||
func isFinite(f float64) bool { | ||
return !isNaN(f - f) | ||
} | ||
|
||
// isInf reports whether f is an infinity. | ||
func isInf(f float64) bool { | ||
return !isNaN(f) && !isFinite(f) | ||
} | ||
|
||
// Abs returns the absolute value of x. | ||
// | ||
// Special cases are: | ||
// Abs(±Inf) = +Inf | ||
// Abs(NaN) = NaN | ||
func abs(x float64) float64 { | ||
const sign = 1 << 63 | ||
return float64frombits(float64bits(x) &^ sign) | ||
} | ||
|
||
// copysign returns a value with the magnitude | ||
// of x and the sign of y. | ||
func copysign(x, y float64) float64 { | ||
const sign = 1 << 63 | ||
return float64frombits(float64bits(x)&^sign | float64bits(y)&sign) | ||
} | ||
|
||
// Float64bits returns the IEEE 754 binary representation of f. | ||
func float64bits(f float64) uint64 { | ||
return *(*uint64)(unsafe.Pointer(&f)) | ||
} | ||
|
||
// Float64frombits returns the floating point number corresponding | ||
// the IEEE 754 binary representation b. | ||
func float64frombits(b uint64) float64 { | ||
return *(*float64)(unsafe.Pointer(&b)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters