Skip to content

Commit 4209a9f

Browse files
bmkesslergriesemer
authored andcommitted
math/cmplx: handle special cases
Implement special case handling and testing to ensure conformance with the C99 standard annex G.6 Complex arithmetic. Fixes #29320 Change-Id: Id72eb4c5a35d5a54b4b8690d2f7176ab11028f1b Reviewed-on: https://go-review.googlesource.com/c/go/+/220689 Reviewed-by: Robert Griesemer <[email protected]>
1 parent da382a3 commit 4209a9f

File tree

8 files changed

+923
-152
lines changed

8 files changed

+923
-152
lines changed

src/math/cmplx/abs.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
// license that can be found in the LICENSE file.
44

55
// Package cmplx provides basic constants and mathematical functions for
6-
// complex numbers.
6+
// complex numbers. Special case handling conforms to the C99 standard
7+
// Annex G IEC 60559-compatible complex arithmetic.
78
package cmplx
89

910
import "math"

src/math/cmplx/asin.go

+66-4
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,31 @@ import "math"
4949

5050
// Asin returns the inverse sine of x.
5151
func Asin(x complex128) complex128 {
52-
if imag(x) == 0 && math.Abs(real(x)) <= 1 {
53-
return complex(math.Asin(real(x)), imag(x))
52+
switch re, im := real(x), imag(x); {
53+
case im == 0 && math.Abs(re) <= 1:
54+
return complex(math.Asin(re), im)
55+
case re == 0 && math.Abs(im) <= 1:
56+
return complex(re, math.Asinh(im))
57+
case math.IsNaN(im):
58+
switch {
59+
case re == 0:
60+
return complex(re, math.NaN())
61+
case math.IsInf(re, 0):
62+
return complex(math.NaN(), re)
63+
default:
64+
return NaN()
65+
}
66+
case math.IsInf(im, 0):
67+
switch {
68+
case math.IsNaN(re):
69+
return x
70+
case math.IsInf(re, 0):
71+
return complex(math.Copysign(math.Pi/4, re), im)
72+
default:
73+
return complex(math.Copysign(0, re), im)
74+
}
75+
case math.IsInf(re, 0):
76+
return complex(math.Copysign(math.Pi/2, re), math.Copysign(re, im))
5477
}
5578
ct := complex(-imag(x), real(x)) // i * x
5679
xx := x * x
@@ -62,8 +85,31 @@ func Asin(x complex128) complex128 {
6285

6386
// Asinh returns the inverse hyperbolic sine of x.
6487
func Asinh(x complex128) complex128 {
65-
if imag(x) == 0 && math.Abs(real(x)) <= 1 {
66-
return complex(math.Asinh(real(x)), imag(x))
88+
switch re, im := real(x), imag(x); {
89+
case im == 0 && math.Abs(re) <= 1:
90+
return complex(math.Asinh(re), im)
91+
case re == 0 && math.Abs(im) <= 1:
92+
return complex(re, math.Asin(im))
93+
case math.IsInf(re, 0):
94+
switch {
95+
case math.IsInf(im, 0):
96+
return complex(re, math.Copysign(math.Pi/4, im))
97+
case math.IsNaN(im):
98+
return x
99+
default:
100+
return complex(re, math.Copysign(0.0, im))
101+
}
102+
case math.IsNaN(re):
103+
switch {
104+
case im == 0:
105+
return x
106+
case math.IsInf(im, 0):
107+
return complex(im, re)
108+
default:
109+
return NaN()
110+
}
111+
case math.IsInf(im, 0):
112+
return complex(math.Copysign(im, re), math.Copysign(math.Pi/2, im))
67113
}
68114
xx := x * x
69115
x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
@@ -91,6 +137,9 @@ func Acos(x complex128) complex128 {
91137

92138
// Acosh returns the inverse hyperbolic cosine of x.
93139
func Acosh(x complex128) complex128 {
140+
if x == 0 {
141+
return complex(0, math.Copysign(math.Pi/2, imag(x)))
142+
}
94143
w := Acos(x)
95144
if imag(w) <= 0 {
96145
return complex(-imag(w), real(w)) // i * w
@@ -133,6 +182,19 @@ func Acosh(x complex128) complex128 {
133182

134183
// Atan returns the inverse tangent of x.
135184
func Atan(x complex128) complex128 {
185+
switch re, im := real(x), imag(x); {
186+
case im == 0:
187+
return complex(math.Atan(re), im)
188+
case re == 0 && math.Abs(im) <= 1:
189+
return complex(re, math.Atanh(im))
190+
case math.IsInf(im, 0) || math.IsInf(re, 0):
191+
if math.IsNaN(re) {
192+
return complex(math.NaN(), math.Copysign(0, im))
193+
}
194+
return complex(math.Copysign(math.Pi/2, re), math.Copysign(0, im))
195+
case math.IsNaN(re) || math.IsNaN(im):
196+
return NaN()
197+
}
136198
x2 := real(x) * real(x)
137199
a := 1 - x2 - imag(x)*imag(x)
138200
if a == 0 {

0 commit comments

Comments
 (0)