| // 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 cmath |
| |
| import "math" |
| |
| // The original C code, the long comment, and the constants |
| // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. |
| // The go code is a simplified version of the original C. |
| // |
| // Cephes Math Library Release 2.8: June, 2000 |
| // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier |
| // |
| // The readme file at http://netlib.sandia.gov/cephes/ says: |
| // Some software in this archive may be from the book _Methods and |
| // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster |
| // International, 1989) or from the Cephes Mathematical Library, a |
| // commercial product. In either event, it is copyrighted by the author. |
| // What you see here may be used freely but it comes with no support or |
| // guarantee. |
| // |
| // The two known misprints in the book are repaired here in the |
| // source listings for the gamma function and the incomplete beta |
| // integral. |
| // |
| // Stephen L. Moshier |
| // moshier@na-net.ornl.gov |
| |
| // Complex circular tangent |
| // |
| // DESCRIPTION: |
| // |
| // If |
| // z = x + iy, |
| // |
| // then |
| // |
| // sin 2x + i sinh 2y |
| // w = --------------------. |
| // cos 2x + cosh 2y |
| // |
| // On the real axis the denominator is zero at odd multiples |
| // of PI/2. The denominator is evaluated by its Taylor |
| // series near these points. |
| // |
| // ctan(z) = -i ctanh(iz). |
| // |
| // ACCURACY: |
| // |
| // Relative error: |
| // arithmetic domain # trials peak rms |
| // DEC -10,+10 5200 7.1e-17 1.6e-17 |
| // IEEE -10,+10 30000 7.2e-16 1.2e-16 |
| // Also tested by ctan * ccot = 1 and catan(ctan(z)) = z. |
| |
| // Tan returns the tangent of x. |
| func Tan(x complex128) complex128 { |
| d := math.Cos(2*real(x)) + math.Cosh(2*imag(x)) |
| if math.Fabs(d) < 0.25 { |
| d = tanSeries(x) |
| } |
| if d == 0 { |
| return Inf() |
| } |
| return cmplx(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d) |
| } |
| |
| // Complex hyperbolic tangent |
| // |
| // DESCRIPTION: |
| // |
| // tanh z = (sinh 2x + i sin 2y) / (cosh 2x + cos 2y) . |
| // |
| // ACCURACY: |
| // |
| // Relative error: |
| // arithmetic domain # trials peak rms |
| // IEEE -10,+10 30000 1.7e-14 2.4e-16 |
| |
| // Tanh returns the hyperbolic tangent of x. |
| func Tanh(x complex128) complex128 { |
| d := math.Cosh(2*real(x)) + math.Cos(2*imag(x)) |
| if d == 0 { |
| return Inf() |
| } |
| return cmplx(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d) |
| } |
| |
| // Program to subtract nearest integer multiple of PI |
| func reducePi(x float64) float64 { |
| const ( |
| // extended precision value of PI: |
| DP1 = 3.14159265160560607910E0 // ?? 0x400921fb54000000 |
| DP2 = 1.98418714791870343106E-9 // ?? 0x3e210b4610000000 |
| DP3 = 1.14423774522196636802E-17 // ?? 0x3c6a62633145c06e |
| ) |
| t := x / math.Pi |
| if t >= 0 { |
| t += 0.5 |
| } else { |
| t -= 0.5 |
| } |
| t = float64(int64(t)) // int64(t) = the multiple |
| return ((x - t*DP1) - t*DP2) - t*DP3 |
| } |
| |
| // Taylor series expansion for cosh(2y) - cos(2x) |
| func tanSeries(z complex128) float64 { |
| const MACHEP = 1.0 / (1 << 53) |
| x := math.Fabs(2 * real(z)) |
| y := math.Fabs(2 * imag(z)) |
| x = reducePi(x) |
| x = x * x |
| y = y * y |
| x2 := float64(1) |
| y2 := float64(1) |
| f := float64(1) |
| rn := float64(0) |
| d := float64(0) |
| for { |
| rn += 1 |
| f *= rn |
| rn += 1 |
| f *= rn |
| x2 *= x |
| y2 *= y |
| t := y2 + x2 |
| t /= f |
| d += t |
| |
| rn += 1 |
| f *= rn |
| rn += 1 |
| f *= rn |
| x2 *= x |
| y2 *= y |
| t = y2 - x2 |
| t /= f |
| d += t |
| if math.Fabs(t/d) <= MACHEP { |
| break |
| } |
| } |
| return d |
| } |
| |
| // Complex circular cotangent |
| // |
| // DESCRIPTION: |
| // |
| // If |
| // z = x + iy, |
| // |
| // then |
| // |
| // sin 2x - i sinh 2y |
| // w = --------------------. |
| // cosh 2y - cos 2x |
| // |
| // On the real axis, the denominator has zeros at even |
| // multiples of PI/2. Near these points it is evaluated |
| // by a Taylor series. |
| // |
| // ACCURACY: |
| // |
| // Relative error: |
| // arithmetic domain # trials peak rms |
| // DEC -10,+10 3000 6.5e-17 1.6e-17 |
| // IEEE -10,+10 30000 9.2e-16 1.2e-16 |
| // Also tested by ctan * ccot = 1 + i0. |
| |
| // Cot returns the cotangent of x. |
| func Cot(x complex128) complex128 { |
| d := math.Cosh(2*imag(x)) - math.Cos(2*real(x)) |
| if math.Fabs(d) < 0.25 { |
| d = tanSeries(x) |
| } |
| if d == 0 { |
| return Inf() |
| } |
| return cmplx(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d) |
| } |