mirror of
https://github.com/golang/go
synced 2024-11-07 00:36:15 -07:00
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: Ieb0527191dd7fdea5b1aecb42b9e23aae3f74260 Reviewed-on: https://go-review.googlesource.com/c/go/+/169501 Run-TryBot: Brian Kessler <brian.m.kessler@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
3c47eada3f
commit
68dce4296e
@ -3,7 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package cmplx provides basic constants and mathematical functions for
|
// Package cmplx provides basic constants and mathematical functions for
|
||||||
// complex numbers.
|
// complex numbers. Special case handling conforms to the C99 standard
|
||||||
|
// Annex G IEC 60559-compatible complex arithmetic.
|
||||||
package cmplx
|
package cmplx
|
||||||
|
|
||||||
import "math"
|
import "math"
|
||||||
|
@ -49,8 +49,31 @@ import "math"
|
|||||||
|
|
||||||
// Asin returns the inverse sine of x.
|
// Asin returns the inverse sine of x.
|
||||||
func Asin(x complex128) complex128 {
|
func Asin(x complex128) complex128 {
|
||||||
if imag(x) == 0 && math.Abs(real(x)) <= 1 {
|
switch re, im := real(x), imag(x); {
|
||||||
return complex(math.Asin(real(x)), imag(x))
|
case im == 0 && math.Abs(re) <= 1:
|
||||||
|
return complex(math.Asin(re), im)
|
||||||
|
case re == 0 && math.Abs(im) <= 1:
|
||||||
|
return complex(re, math.Asinh(im))
|
||||||
|
case math.IsNaN(im):
|
||||||
|
switch {
|
||||||
|
case re == 0:
|
||||||
|
return complex(re, math.NaN())
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
return complex(math.NaN(), re)
|
||||||
|
default:
|
||||||
|
return NaN()
|
||||||
|
}
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
switch {
|
||||||
|
case math.IsNaN(re):
|
||||||
|
return x
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
return complex(math.Copysign(math.Pi/4, re), im)
|
||||||
|
default:
|
||||||
|
return complex(math.Copysign(0, re), im)
|
||||||
|
}
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
return complex(math.Copysign(math.Pi/2, re), math.Copysign(re, im))
|
||||||
}
|
}
|
||||||
ct := complex(-imag(x), real(x)) // i * x
|
ct := complex(-imag(x), real(x)) // i * x
|
||||||
xx := x * x
|
xx := x * x
|
||||||
@ -62,8 +85,31 @@ func Asin(x complex128) complex128 {
|
|||||||
|
|
||||||
// Asinh returns the inverse hyperbolic sine of x.
|
// Asinh returns the inverse hyperbolic sine of x.
|
||||||
func Asinh(x complex128) complex128 {
|
func Asinh(x complex128) complex128 {
|
||||||
if imag(x) == 0 && math.Abs(real(x)) <= 1 {
|
switch re, im := real(x), imag(x); {
|
||||||
return complex(math.Asinh(real(x)), imag(x))
|
case im == 0 && math.Abs(re) <= 1:
|
||||||
|
return complex(math.Asinh(re), im)
|
||||||
|
case re == 0 && math.Abs(im) <= 1:
|
||||||
|
return complex(re, math.Asin(im))
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
switch {
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
return complex(re, math.Copysign(math.Pi/4, im))
|
||||||
|
case math.IsNaN(im):
|
||||||
|
return x
|
||||||
|
default:
|
||||||
|
return complex(re, math.Copysign(0.0, im))
|
||||||
|
}
|
||||||
|
case math.IsNaN(re):
|
||||||
|
switch {
|
||||||
|
case im == 0:
|
||||||
|
return x
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
return complex(im, re)
|
||||||
|
default:
|
||||||
|
return NaN()
|
||||||
|
}
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
return complex(math.Copysign(im, re), math.Copysign(math.Pi/2, im))
|
||||||
}
|
}
|
||||||
xx := x * x
|
xx := x * x
|
||||||
x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
|
x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
|
||||||
@ -91,6 +137,9 @@ func Acos(x complex128) complex128 {
|
|||||||
|
|
||||||
// Acosh returns the inverse hyperbolic cosine of x.
|
// Acosh returns the inverse hyperbolic cosine of x.
|
||||||
func Acosh(x complex128) complex128 {
|
func Acosh(x complex128) complex128 {
|
||||||
|
if x == 0 {
|
||||||
|
return complex(0, math.Copysign(math.Pi/2, imag(x)))
|
||||||
|
}
|
||||||
w := Acos(x)
|
w := Acos(x)
|
||||||
if imag(w) <= 0 {
|
if imag(w) <= 0 {
|
||||||
return complex(-imag(w), real(w)) // i * w
|
return complex(-imag(w), real(w)) // i * w
|
||||||
@ -133,6 +182,17 @@ func Acosh(x complex128) complex128 {
|
|||||||
|
|
||||||
// Atan returns the inverse tangent of x.
|
// Atan returns the inverse tangent of x.
|
||||||
func Atan(x complex128) complex128 {
|
func Atan(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case im == 0:
|
||||||
|
return complex(math.Atan(re), im)
|
||||||
|
case re == 0 && math.Abs(im) <= 1:
|
||||||
|
return complex(re, math.Atanh(im))
|
||||||
|
case math.IsInf(im, 0) || math.IsInf(re, 0):
|
||||||
|
if math.IsNaN(re) {
|
||||||
|
return complex(math.NaN(), math.Copysign(0, im))
|
||||||
|
}
|
||||||
|
return complex(math.Copysign(math.Pi/2, re), math.Copysign(0, im))
|
||||||
|
}
|
||||||
x2 := real(x) * real(x)
|
x2 := real(x) * real(x)
|
||||||
a := 1 - x2 - imag(x)*imag(x)
|
a := 1 - x2 - imag(x)*imag(x)
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
|
@ -291,48 +291,190 @@ var tanh = []complex128{
|
|||||||
(-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i),
|
(-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i),
|
||||||
}
|
}
|
||||||
|
|
||||||
// special cases
|
// special cases conform to C99 standard appendix G.6 Complex arithmetic
|
||||||
|
var inf, nan = math.Inf(1), math.NaN()
|
||||||
|
|
||||||
var vcAbsSC = []complex128{
|
var vcAbsSC = []complex128{
|
||||||
NaN(),
|
NaN(),
|
||||||
}
|
}
|
||||||
var absSC = []float64{
|
var absSC = []float64{
|
||||||
math.NaN(),
|
math.NaN(),
|
||||||
}
|
}
|
||||||
var vcAcosSC = []complex128{
|
var acosSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.1.1
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(math.Pi/2, -zero)},
|
||||||
|
{complex(-zero, zero),
|
||||||
|
complex(math.Pi/2, -zero)},
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(math.Pi/2, nan)},
|
||||||
|
{complex(-zero, nan),
|
||||||
|
complex(math.Pi/2, nan)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(math.Pi/2, -inf)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(math.Pi, -inf)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(0.0, -inf)},
|
||||||
|
{complex(-inf, inf),
|
||||||
|
complex(3*math.Pi/4, -inf)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(math.Pi/4, -inf)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(nan, -inf)}, // imaginary sign unspecified
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(nan, inf)}, // imaginary sign unspecified
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(nan, -inf)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var acosSC = []complex128{
|
var acoshSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.2.1
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, math.Pi/2)},
|
||||||
|
{complex(-zero, zero),
|
||||||
|
complex(zero, math.Pi/2)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, math.Pi/2)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(inf, math.Pi)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(-inf, inf),
|
||||||
|
complex(inf, 3*math.Pi/4)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, math.Pi/4)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcAcoshSC = []complex128{
|
var asinSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// Derived from Asin(z) = -i * Asinh(i * z), G.6 #7
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(0, inf)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, 1),
|
||||||
|
complex(math.Pi/2, inf)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(math.Pi/4, inf)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(nan, inf)}, // imaginary sign unspecified
|
||||||
|
{complex(nan, zero),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, 1),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(nan, inf)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var acoshSC = []complex128{
|
var asinhSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.2.2
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, math.Pi/2)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, math.Pi/4)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, nan)}, // sign of real part unspecified
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcAsinSC = []complex128{
|
var atanSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// Derived from Atan(z) = -i * Atanh(i * z), G.6 #7
|
||||||
|
{complex(0, zero),
|
||||||
|
complex(0, zero)},
|
||||||
|
{complex(0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(1.0, zero),
|
||||||
|
complex(math.Pi/4, zero)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(math.Pi/2, zero)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, 1),
|
||||||
|
complex(math.Pi/2, zero)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(math.Pi/2, zero)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(math.Pi/2, zero)},
|
||||||
|
{complex(nan, 1),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var asinSC = []complex128{
|
var atanhSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
}
|
want complex128
|
||||||
var vcAsinhSC = []complex128{
|
}{
|
||||||
NaN(),
|
// G.6.2.3
|
||||||
}
|
{complex(zero, zero),
|
||||||
var asinhSC = []complex128{
|
complex(zero, zero)},
|
||||||
NaN(),
|
{complex(zero, nan),
|
||||||
}
|
complex(zero, nan)},
|
||||||
var vcAtanSC = []complex128{
|
{complex(1.0, zero),
|
||||||
NaN(),
|
complex(inf, zero)},
|
||||||
}
|
{complex(1.0, inf),
|
||||||
var atanSC = []complex128{
|
complex(0, math.Pi/2)},
|
||||||
NaN(),
|
{complex(1.0, nan),
|
||||||
}
|
NaN()},
|
||||||
var vcAtanhSC = []complex128{
|
{complex(inf, 1.0),
|
||||||
NaN(),
|
complex(zero, math.Pi/2)},
|
||||||
}
|
{complex(inf, inf),
|
||||||
var atanhSC = []complex128{
|
complex(zero, math.Pi/2)},
|
||||||
NaN(),
|
{complex(inf, nan),
|
||||||
|
complex(0, nan)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(zero, math.Pi/2)}, // sign of real part not specified.
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcConjSC = []complex128{
|
var vcConjSC = []complex128{
|
||||||
NaN(),
|
NaN(),
|
||||||
@ -340,23 +482,105 @@ var vcConjSC = []complex128{
|
|||||||
var conjSC = []complex128{
|
var conjSC = []complex128{
|
||||||
NaN(),
|
NaN(),
|
||||||
}
|
}
|
||||||
var vcCosSC = []complex128{
|
var cosSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// Derived from Cos(z) = Cosh(i * z), G.6 #7
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(1.0, -zero)},
|
||||||
|
{complex(zero, inf),
|
||||||
|
complex(inf, -zero)},
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(nan, zero)}, // imaginary sign unspecified
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, -inf)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, zero),
|
||||||
|
complex(nan, -zero)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(inf, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, -zero)}, // imaginary sign unspecified
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var cosSC = []complex128{
|
var coshSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.2.4
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(1.0, zero)},
|
||||||
|
{complex(zero, inf),
|
||||||
|
complex(nan, zero)}, // imaginary sign unspecified
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(nan, zero)}, // imaginary sign unspecified
|
||||||
|
{complex(1.0, inf),
|
||||||
|
NaN()},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, zero),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf*math.Cos(1.0), inf*math.Sin(1.0))}, // +inf cis(y)
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)}, // imaginary sign unspecified
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
NaN()},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcCoshSC = []complex128{
|
var expSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
}
|
want complex128
|
||||||
var coshSC = []complex128{
|
}{
|
||||||
NaN(),
|
// G.6.3.1
|
||||||
}
|
{complex(zero, zero),
|
||||||
var vcExpSC = []complex128{
|
complex(1.0, zero)},
|
||||||
NaN(),
|
{complex(-zero, zero),
|
||||||
}
|
complex(1.0, zero)},
|
||||||
var expSC = []complex128{
|
{complex(1.0, inf),
|
||||||
NaN(),
|
NaN()},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, zero),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(math.Copysign(0.0, math.Cos(1.0)), math.Copysign(0.0, math.Sin(1.0)))}, // +0 cis(y)
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf*math.Cos(1.0), inf*math.Sin(1.0))}, // +inf cis(y)
|
||||||
|
{complex(-inf, inf),
|
||||||
|
complex(zero, zero)}, // real and imaginary sign unspecified
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(zero, zero)}, // real and imaginary sign unspecified
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
NaN()},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcIsNaNSC = []complex128{
|
var vcIsNaNSC = []complex128{
|
||||||
complex(math.Inf(-1), math.Inf(-1)),
|
complex(math.Inf(-1), math.Inf(-1)),
|
||||||
@ -380,17 +604,70 @@ var isNaNSC = []bool{
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
}
|
}
|
||||||
var vcLogSC = []complex128{
|
|
||||||
NaN(),
|
var logSC = []struct {
|
||||||
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.3.2
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(-inf, zero)},
|
||||||
|
{complex(-zero, zero),
|
||||||
|
complex(-inf, math.Pi)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, math.Pi/2)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(inf, math.Pi)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf, 0.0)},
|
||||||
|
{complex(-inf, inf),
|
||||||
|
complex(inf, 3*math.Pi/4)},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, math.Pi/4)},
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var logSC = []complex128{
|
var log10SC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
}
|
want complex128
|
||||||
var vcLog10SC = []complex128{
|
}{
|
||||||
NaN(),
|
// derived from Log special cases via Log10(x) = math.Log10E*Log(x)
|
||||||
}
|
{complex(zero, zero),
|
||||||
var log10SC = []complex128{
|
complex(-inf, zero)},
|
||||||
NaN(),
|
{complex(-zero, zero),
|
||||||
|
complex(-inf, float64(math.Log10E)*float64(math.Pi))},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, float64(math.Log10E)*float64(math.Pi/2))},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(inf, float64(math.Log10E)*float64(math.Pi))},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf, 0.0)},
|
||||||
|
{complex(-inf, inf),
|
||||||
|
complex(inf, float64(math.Log10E)*float64(3*math.Pi/4))},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, float64(math.Log10E)*float64(math.Pi/4))},
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcPolarSC = []complex128{
|
var vcPolarSC = []complex128{
|
||||||
NaN(),
|
NaN(),
|
||||||
@ -406,35 +683,153 @@ var powSC = []complex128{
|
|||||||
NaN(),
|
NaN(),
|
||||||
NaN(),
|
NaN(),
|
||||||
}
|
}
|
||||||
var vcSinSC = []complex128{
|
var sinSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// Derived from Sin(z) = -i * Sinh(i * z), G.6 #7
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(zero, inf),
|
||||||
|
complex(zero, inf)},
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(zero, nan)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, inf)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(nan, inf)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(nan, inf)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var sinSC = []complex128{
|
|
||||||
NaN(),
|
var sinhSC = []struct {
|
||||||
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.2.5
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(zero, inf),
|
||||||
|
complex(zero, nan)}, // real sign unspecified
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(zero, nan)}, // real sign unspecified
|
||||||
|
{complex(1.0, inf),
|
||||||
|
NaN()},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, zero),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf*math.Cos(1.0), inf*math.Sin(1.0))}, // +inf cis(y)
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)}, // real sign unspecified
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
NaN()},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcSinhSC = []complex128{
|
|
||||||
NaN(),
|
var sqrtSC = []struct {
|
||||||
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// G.6.4.2
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(-zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(inf, inf)},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(inf, inf)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(-inf, 1.0),
|
||||||
|
complex(zero, inf)},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
complex(inf, zero)},
|
||||||
|
{complex(-inf, nan),
|
||||||
|
complex(nan, inf)}, // imaginary sign unspecified
|
||||||
|
{complex(inf, nan),
|
||||||
|
complex(inf, nan)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var sinhSC = []complex128{
|
var tanSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
|
want complex128
|
||||||
|
}{
|
||||||
|
// Derived from Tan(z) = -i * Tanh(i * z), G.6 #7
|
||||||
|
{complex(zero, zero),
|
||||||
|
complex(zero, zero)},
|
||||||
|
{complex(zero, nan),
|
||||||
|
complex(zero, nan)},
|
||||||
|
{complex(1.0, inf),
|
||||||
|
complex(zero, 1.0)},
|
||||||
|
{complex(1.0, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(inf, inf),
|
||||||
|
complex(zero, 1.0)},
|
||||||
|
{complex(inf, nan),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, zero),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
complex(zero, 1.0)},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
var vcSqrtSC = []complex128{
|
var tanhSC = []struct {
|
||||||
NaN(),
|
in,
|
||||||
}
|
want complex128
|
||||||
var sqrtSC = []complex128{
|
}{
|
||||||
NaN(),
|
// G.6.2.6
|
||||||
}
|
{complex(zero, zero),
|
||||||
var vcTanSC = []complex128{
|
complex(zero, zero)},
|
||||||
NaN(),
|
{complex(1.0, inf),
|
||||||
}
|
NaN()},
|
||||||
var tanSC = []complex128{
|
{complex(1.0, nan),
|
||||||
NaN(),
|
NaN()},
|
||||||
}
|
{complex(inf, 1.0),
|
||||||
var vcTanhSC = []complex128{
|
complex(1.0, math.Copysign(0.0, math.Sin(2*1.0)))}, // 1 + i 0 sin(2y)
|
||||||
NaN(),
|
{complex(inf, inf),
|
||||||
}
|
complex(1.0, zero)}, // imaginary sign unspecified
|
||||||
var tanhSC = []complex128{
|
{complex(inf, nan),
|
||||||
NaN(),
|
complex(1.0, zero)}, // imaginary sign unspecified
|
||||||
|
{complex(nan, zero),
|
||||||
|
complex(nan, zero)},
|
||||||
|
{complex(nan, 1.0),
|
||||||
|
NaN()},
|
||||||
|
{complex(nan, inf),
|
||||||
|
NaN()},
|
||||||
|
{NaN(),
|
||||||
|
NaN()},
|
||||||
}
|
}
|
||||||
|
|
||||||
// branch cut continuity checks
|
// branch cut continuity checks
|
||||||
@ -496,13 +891,7 @@ func cTolerance(a, b complex128, e float64) bool {
|
|||||||
func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) }
|
func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) }
|
||||||
func cVeryclose(a, b complex128) bool { return cTolerance(a, b, 4e-16) }
|
func cVeryclose(a, b complex128) bool { return cTolerance(a, b, 4e-16) }
|
||||||
func cAlike(a, b complex128) bool {
|
func cAlike(a, b complex128) bool {
|
||||||
switch {
|
return alike(real(a), real(b)) && alike(imag(a), imag(b))
|
||||||
case IsNaN(a) && IsNaN(b):
|
|
||||||
return true
|
|
||||||
case a == b:
|
|
||||||
return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b))
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAbs(t *testing.T) {
|
func TestAbs(t *testing.T) {
|
||||||
@ -523,9 +912,13 @@ func TestAcos(t *testing.T) {
|
|||||||
t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i])
|
t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAcosSC); i++ {
|
for _, v := range acosSC {
|
||||||
if f := Acos(vcAcosSC[i]); !cAlike(acosSC[i], f) {
|
if f := Acos(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Acos(%g) = %g, want %g", vcAcosSC[i], f, acosSC[i])
|
t.Errorf("Acos(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
// Acos(Conj(z)) == Conj(Acos(z))
|
||||||
|
if f := Acos(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Acos(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -540,10 +933,15 @@ func TestAcosh(t *testing.T) {
|
|||||||
t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i])
|
t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAcoshSC); i++ {
|
for _, v := range acoshSC {
|
||||||
if f := Acosh(vcAcoshSC[i]); !cAlike(acoshSC[i], f) {
|
if f := Acosh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Acosh(%g) = %g, want %g", vcAcoshSC[i], f, acoshSC[i])
|
t.Errorf("Acosh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
}
|
}
|
||||||
|
// Acosh(Conj(z)) == Conj(Acosh(z))
|
||||||
|
if f := Acosh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Acosh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
if f0, f1 := Acosh(pt[0]), Acosh(pt[1]); !cVeryclose(f0, f1) {
|
if f0, f1 := Acosh(pt[0]), Acosh(pt[1]); !cVeryclose(f0, f1) {
|
||||||
@ -557,9 +955,21 @@ func TestAsin(t *testing.T) {
|
|||||||
t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i])
|
t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAsinSC); i++ {
|
for _, v := range asinSC {
|
||||||
if f := Asin(vcAsinSC[i]); !cAlike(asinSC[i], f) {
|
if f := Asin(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Asin(%g) = %g, want %g", vcAsinSC[i], f, asinSC[i])
|
t.Errorf("Asin(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Asin(Conj(z)) == Asin(Sinh(z))
|
||||||
|
if f := Asin(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Asin(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Asin(-z) == -Asin(z)
|
||||||
|
if f := Asin(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Asin(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -574,9 +984,21 @@ func TestAsinh(t *testing.T) {
|
|||||||
t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i])
|
t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAsinhSC); i++ {
|
for _, v := range asinhSC {
|
||||||
if f := Asinh(vcAsinhSC[i]); !cAlike(asinhSC[i], f) {
|
if f := Asinh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Asinh(%g) = %g, want %g", vcAsinhSC[i], f, asinhSC[i])
|
t.Errorf("Asinh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Asinh(Conj(z)) == Asinh(Sinh(z))
|
||||||
|
if f := Asinh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Asinh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Asinh(-z) == -Asinh(z)
|
||||||
|
if f := Asinh(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Asinh(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -591,9 +1013,21 @@ func TestAtan(t *testing.T) {
|
|||||||
t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i])
|
t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAtanSC); i++ {
|
for _, v := range atanSC {
|
||||||
if f := Atan(vcAtanSC[i]); !cAlike(atanSC[i], f) {
|
if f := Atan(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Atan(%g) = %g, want %g", vcAtanSC[i], f, atanSC[i])
|
t.Errorf("Atan(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Atan(Conj(z)) == Conj(Atan(z))
|
||||||
|
if f := Atan(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Atan(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Atan(-z) == -Atan(z)
|
||||||
|
if f := Atan(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Atan(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -608,9 +1042,21 @@ func TestAtanh(t *testing.T) {
|
|||||||
t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i])
|
t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcAtanhSC); i++ {
|
for _, v := range atanhSC {
|
||||||
if f := Atanh(vcAtanhSC[i]); !cAlike(atanhSC[i], f) {
|
if f := Atanh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Atanh(%g) = %g, want %g", vcAtanhSC[i], f, atanhSC[i])
|
t.Errorf("Atanh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Atanh(Conj(z)) == Conj(Atanh(z))
|
||||||
|
if f := Atanh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Atanh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Atanh(-z) == -Atanh(z)
|
||||||
|
if f := Atanh(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Atanh(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -637,9 +1083,21 @@ func TestCos(t *testing.T) {
|
|||||||
t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i])
|
t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcCosSC); i++ {
|
for _, v := range cosSC {
|
||||||
if f := Cos(vcCosSC[i]); !cAlike(cosSC[i], f) {
|
if f := Cos(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Cos(%g) = %g, want %g", vcCosSC[i], f, cosSC[i])
|
t.Errorf("Cos(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Cos(Conj(z)) == Cos(Cosh(z))
|
||||||
|
if f := Cos(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Cos(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Cos(-z) == Cos(z)
|
||||||
|
if f := Cos(-v.in); !cAlike(v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Cos(%g) = %g, want %g", -v.in, f, v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,9 +1107,21 @@ func TestCosh(t *testing.T) {
|
|||||||
t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i])
|
t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcCoshSC); i++ {
|
for _, v := range coshSC {
|
||||||
if f := Cosh(vcCoshSC[i]); !cAlike(coshSC[i], f) {
|
if f := Cosh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Cosh(%g) = %g, want %g", vcCoshSC[i], f, coshSC[i])
|
t.Errorf("Cosh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Cosh(Conj(z)) == Conj(Cosh(z))
|
||||||
|
if f := Cosh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Cosh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Cosh(-z) == Cosh(z)
|
||||||
|
if f := Cosh(-v.in); !cAlike(v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Cosh(%g) = %g, want %g", -v.in, f, v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -661,9 +1131,13 @@ func TestExp(t *testing.T) {
|
|||||||
t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i])
|
t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcExpSC); i++ {
|
for _, v := range expSC {
|
||||||
if f := Exp(vcExpSC[i]); !cAlike(expSC[i], f) {
|
if f := Exp(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Exp(%g) = %g, want %g", vcExpSC[i], f, expSC[i])
|
t.Errorf("Exp(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
// Exp(Conj(z)) == Exp(Cosh(z))
|
||||||
|
if f := Exp(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Exp(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,9 +1154,13 @@ func TestLog(t *testing.T) {
|
|||||||
t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i])
|
t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcLogSC); i++ {
|
for _, v := range logSC {
|
||||||
if f := Log(vcLogSC[i]); !cAlike(logSC[i], f) {
|
if f := Log(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Log(%g) = %g, want %g", vcLogSC[i], f, logSC[i])
|
t.Errorf("Log(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
// Log(Conj(z)) == Conj(Log(z))
|
||||||
|
if f := Log(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Log(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -697,9 +1175,13 @@ func TestLog10(t *testing.T) {
|
|||||||
t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i])
|
t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcLog10SC); i++ {
|
for _, v := range log10SC {
|
||||||
if f := Log10(vcLog10SC[i]); !cAlike(log10SC[i], f) {
|
if f := Log10(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Log10(%g) = %g, want %g", vcLog10SC[i], f, log10SC[i])
|
t.Errorf("Log10(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
// Log10(Conj(z)) == Conj(Log10(z))
|
||||||
|
if f := Log10(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Log10(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -764,9 +1246,22 @@ func TestSin(t *testing.T) {
|
|||||||
t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i])
|
t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcSinSC); i++ {
|
for _, v := range sinSC {
|
||||||
if f := Sin(vcSinSC[i]); !cAlike(sinSC[i], f) {
|
if f := Sin(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Sin(%g) = %g, want %g", vcSinSC[i], f, sinSC[i])
|
t.Errorf("Sin(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Sin(Conj(z)) == Conj(Sin(z))
|
||||||
|
if f := Sin(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Sinh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Sin(-z) == -Sin(z)
|
||||||
|
if f := Sin(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Sinh(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -776,9 +1271,21 @@ func TestSinh(t *testing.T) {
|
|||||||
t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i])
|
t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcSinhSC); i++ {
|
for _, v := range sinhSC {
|
||||||
if f := Sinh(vcSinhSC[i]); !cAlike(sinhSC[i], f) {
|
if f := Sinh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Sinh(%g) = %g, want %g", vcSinhSC[i], f, sinhSC[i])
|
t.Errorf("Sinh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Sinh(Conj(z)) == Conj(Sinh(z))
|
||||||
|
if f := Sinh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Sinh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Sinh(-z) == -Sinh(z)
|
||||||
|
if f := Sinh(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Sinh(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -788,9 +1295,13 @@ func TestSqrt(t *testing.T) {
|
|||||||
t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i])
|
t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcSqrtSC); i++ {
|
for _, v := range sqrtSC {
|
||||||
if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) {
|
if f := Sqrt(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i])
|
t.Errorf("Sqrt(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
// Sqrt(Conj(z)) == Conj(Sqrt(z))
|
||||||
|
if f := Sqrt(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Sqrt(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pt := range branchPoints {
|
for _, pt := range branchPoints {
|
||||||
@ -805,9 +1316,21 @@ func TestTan(t *testing.T) {
|
|||||||
t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i])
|
t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcTanSC); i++ {
|
for _, v := range tanSC {
|
||||||
if f := Tan(vcTanSC[i]); !cAlike(tanSC[i], f) {
|
if f := Tan(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Tan(%g) = %g, want %g", vcTanSC[i], f, tanSC[i])
|
t.Errorf("Tan(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Tan(Conj(z)) == Conj(Tan(z))
|
||||||
|
if f := Tan(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Tan(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Tan(-z) == -Tan(z)
|
||||||
|
if f := Tan(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Tan(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,9 +1340,21 @@ func TestTanh(t *testing.T) {
|
|||||||
t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i])
|
t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(vcTanhSC); i++ {
|
for _, v := range tanhSC {
|
||||||
if f := Tanh(vcTanhSC[i]); !cAlike(tanhSC[i], f) {
|
if f := Tanh(v.in); !cAlike(v.want, f) {
|
||||||
t.Errorf("Tanh(%g) = %g, want %g", vcTanhSC[i], f, tanhSC[i])
|
t.Errorf("Tanh(%g) = %g, want %g", v.in, f, v.want)
|
||||||
|
}
|
||||||
|
if cAlike(-v.in, Conj(v.in)) && !cAlike(-v.want, Conj(v.want)) {
|
||||||
|
// The following conditions can't simultaneously be satisfied for this input.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Tanh(Conj(z)) == Conj(Tanh(z))
|
||||||
|
if f := Tanh(Conj(v.in)); !cAlike(Conj(v.want), f) && !cAlike(v.in, Conj(v.in)) {
|
||||||
|
t.Errorf("Tanh(%g) = %g, want %g", Conj(v.in), f, Conj(v.want))
|
||||||
|
}
|
||||||
|
// Tanh(-z) == -Tanh(z)
|
||||||
|
if f := Tanh(-v.in); !cAlike(-v.want, f) && !cAlike(v.in, -v.in) {
|
||||||
|
t.Errorf("Tanh(%g) = %g, want %g", -v.in, f, -v.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,23 @@ import "math"
|
|||||||
|
|
||||||
// Exp returns e**x, the base-e exponential of x.
|
// Exp returns e**x, the base-e exponential of x.
|
||||||
func Exp(x complex128) complex128 {
|
func Exp(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
switch {
|
||||||
|
case re > 0 && im == 0:
|
||||||
|
return x
|
||||||
|
case math.IsInf(im, 0) || math.IsNaN(im):
|
||||||
|
if re < 0 {
|
||||||
|
return complex(0, math.Copysign(0, im))
|
||||||
|
} else {
|
||||||
|
return complex(math.Inf(1.0), math.NaN())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case math.IsNaN(re):
|
||||||
|
if im == 0 {
|
||||||
|
return complex(math.NaN(), im)
|
||||||
|
}
|
||||||
|
}
|
||||||
r := math.Exp(real(x))
|
r := math.Exp(real(x))
|
||||||
s, c := math.Sincos(imag(x))
|
s, c := math.Sincos(imag(x))
|
||||||
return complex(r*c, r*s)
|
return complex(r*c, r*s)
|
||||||
|
@ -60,5 +60,6 @@ func Log(x complex128) complex128 {
|
|||||||
|
|
||||||
// Log10 returns the decimal logarithm of x.
|
// Log10 returns the decimal logarithm of x.
|
||||||
func Log10(x complex128) complex128 {
|
func Log10(x complex128) complex128 {
|
||||||
return math.Log10E * Log(x)
|
z := Log(x)
|
||||||
|
return complex(math.Log10E*real(z), math.Log10E*imag(z))
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,19 @@ import "math"
|
|||||||
|
|
||||||
// Sin returns the sine of x.
|
// Sin returns the sine of x.
|
||||||
func Sin(x complex128) complex128 {
|
func Sin(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
|
||||||
|
return complex(math.NaN(), im)
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
switch {
|
||||||
|
case re == 0:
|
||||||
|
return x
|
||||||
|
case math.IsInf(re, 0) || math.IsNaN(re):
|
||||||
|
return complex(math.NaN(), im)
|
||||||
|
}
|
||||||
|
case re == 0 && math.IsNaN(im):
|
||||||
|
return x
|
||||||
|
}
|
||||||
s, c := math.Sincos(real(x))
|
s, c := math.Sincos(real(x))
|
||||||
sh, ch := sinhcosh(imag(x))
|
sh, ch := sinhcosh(imag(x))
|
||||||
return complex(s*ch, c*sh)
|
return complex(s*ch, c*sh)
|
||||||
@ -71,6 +84,19 @@ func Sin(x complex128) complex128 {
|
|||||||
|
|
||||||
// Sinh returns the hyperbolic sine of x.
|
// Sinh returns the hyperbolic sine of x.
|
||||||
func Sinh(x complex128) complex128 {
|
func Sinh(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case re == 0 && (math.IsInf(im, 0) || math.IsNaN(im)):
|
||||||
|
return complex(re, math.NaN())
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
switch {
|
||||||
|
case im == 0:
|
||||||
|
return complex(re, im)
|
||||||
|
case math.IsInf(im, 0) || math.IsNaN(im):
|
||||||
|
return complex(re, math.NaN())
|
||||||
|
}
|
||||||
|
case im == 0 && math.IsNaN(re):
|
||||||
|
return complex(math.NaN(), im)
|
||||||
|
}
|
||||||
s, c := math.Sincos(imag(x))
|
s, c := math.Sincos(imag(x))
|
||||||
sh, ch := sinhcosh(real(x))
|
sh, ch := sinhcosh(real(x))
|
||||||
return complex(c*sh, s*ch)
|
return complex(c*sh, s*ch)
|
||||||
@ -96,6 +122,19 @@ func Sinh(x complex128) complex128 {
|
|||||||
|
|
||||||
// Cos returns the cosine of x.
|
// Cos returns the cosine of x.
|
||||||
func Cos(x complex128) complex128 {
|
func Cos(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
|
||||||
|
return complex(math.NaN(), -im*math.Copysign(0, re))
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
switch {
|
||||||
|
case re == 0:
|
||||||
|
return complex(math.Inf(1), -re*math.Copysign(0, im))
|
||||||
|
case math.IsInf(re, 0) || math.IsNaN(re):
|
||||||
|
return complex(math.Inf(1), math.NaN())
|
||||||
|
}
|
||||||
|
case re == 0 && math.IsNaN(im):
|
||||||
|
return complex(math.NaN(), 0)
|
||||||
|
}
|
||||||
s, c := math.Sincos(real(x))
|
s, c := math.Sincos(real(x))
|
||||||
sh, ch := sinhcosh(imag(x))
|
sh, ch := sinhcosh(imag(x))
|
||||||
return complex(c*ch, -s*sh)
|
return complex(c*ch, -s*sh)
|
||||||
@ -115,6 +154,19 @@ func Cos(x complex128) complex128 {
|
|||||||
|
|
||||||
// Cosh returns the hyperbolic cosine of x.
|
// Cosh returns the hyperbolic cosine of x.
|
||||||
func Cosh(x complex128) complex128 {
|
func Cosh(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case re == 0 && (math.IsInf(im, 0) || math.IsNaN(im)):
|
||||||
|
return complex(math.NaN(), re*math.Copysign(0, im))
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
switch {
|
||||||
|
case im == 0:
|
||||||
|
return complex(math.Inf(1), im*math.Copysign(0, re))
|
||||||
|
case math.IsInf(im, 0) || math.IsNaN(im):
|
||||||
|
return complex(math.Inf(1), math.NaN())
|
||||||
|
}
|
||||||
|
case im == 0 && math.IsNaN(re):
|
||||||
|
return complex(math.NaN(), im)
|
||||||
|
}
|
||||||
s, c := math.Sincos(imag(x))
|
s, c := math.Sincos(imag(x))
|
||||||
sh, ch := sinhcosh(real(x))
|
sh, ch := sinhcosh(real(x))
|
||||||
return complex(c*ch, s*sh)
|
return complex(c*ch, s*sh)
|
||||||
|
@ -65,6 +65,8 @@ func Sqrt(x complex128) complex128 {
|
|||||||
return complex(0, math.Copysign(math.Sqrt(-real(x)), imag(x)))
|
return complex(0, math.Copysign(math.Sqrt(-real(x)), imag(x)))
|
||||||
}
|
}
|
||||||
return complex(math.Sqrt(real(x)), imag(x))
|
return complex(math.Sqrt(real(x)), imag(x))
|
||||||
|
} else if math.IsInf(imag(x), 0) {
|
||||||
|
return complex(math.Inf(1.0), imag(x))
|
||||||
}
|
}
|
||||||
if real(x) == 0 {
|
if real(x) == 0 {
|
||||||
if imag(x) < 0 {
|
if imag(x) < 0 {
|
||||||
|
@ -57,6 +57,16 @@ import "math"
|
|||||||
|
|
||||||
// Tan returns the tangent of x.
|
// Tan returns the tangent of x.
|
||||||
func Tan(x complex128) complex128 {
|
func Tan(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case math.IsInf(im, 0):
|
||||||
|
switch {
|
||||||
|
case math.IsInf(re, 0) || math.IsNaN(re):
|
||||||
|
return complex(math.Copysign(0, re), math.Copysign(1, im))
|
||||||
|
}
|
||||||
|
return complex(math.Copysign(0, math.Sin(2*re)), math.Copysign(1, im))
|
||||||
|
case re == 0 && math.IsNaN(im):
|
||||||
|
return x
|
||||||
|
}
|
||||||
d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
|
d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
|
||||||
if math.Abs(d) < 0.25 {
|
if math.Abs(d) < 0.25 {
|
||||||
d = tanSeries(x)
|
d = tanSeries(x)
|
||||||
@ -81,6 +91,16 @@ func Tan(x complex128) complex128 {
|
|||||||
|
|
||||||
// Tanh returns the hyperbolic tangent of x.
|
// Tanh returns the hyperbolic tangent of x.
|
||||||
func Tanh(x complex128) complex128 {
|
func Tanh(x complex128) complex128 {
|
||||||
|
switch re, im := real(x), imag(x); {
|
||||||
|
case math.IsInf(re, 0):
|
||||||
|
switch {
|
||||||
|
case math.IsInf(im, 0) || math.IsNaN(im):
|
||||||
|
return complex(math.Copysign(1, re), math.Copysign(0, im))
|
||||||
|
}
|
||||||
|
return complex(math.Copysign(1, re), math.Copysign(0, math.Sin(2*im)))
|
||||||
|
case im == 0 && math.IsNaN(re):
|
||||||
|
return x
|
||||||
|
}
|
||||||
d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))
|
d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))
|
||||||
if d == 0 {
|
if d == 0 {
|
||||||
return Inf()
|
return Inf()
|
||||||
|
Loading…
Reference in New Issue
Block a user