aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/math/tan.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/math/tan.go')
-rw-r--r--libgo/go/math/tan.go140
1 files changed, 103 insertions, 37 deletions
diff --git a/libgo/go/math/tan.go b/libgo/go/math/tan.go
index 6d7a60b..739ee80 100644
--- a/libgo/go/math/tan.go
+++ b/libgo/go/math/tan.go
@@ -1,64 +1,130 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2011 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 math
/*
- Floating point tangent.
+ Floating-point tangent.
*/
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+// tan.c
+//
+// Circular tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tan();
+// y = tan( x );
+//
+// DESCRIPTION:
+//
+// Returns the circular tangent of the radian argument x.
+//
+// Range reduction is modulo pi/4. A rational function
+// x + x**3 P(x**2)/Q(x**2)
+// is employed in the basic interval [0, pi/4].
+//
+// ACCURACY:
+// Relative error:
+// arithmetic domain # trials peak rms
+// DEC +-1.07e9 44000 4.1e-17 1.0e-17
+// IEEE +-1.07e9 30000 2.9e-16 8.1e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
+// be meaningless for x > 2**49 = 5.6e14.
+// [Accuracy loss statement from sin.go comments.]
+//
+// 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
+
+// tan coefficients
+var _tanP = [...]float64{
+ -1.30936939181383777646E4, // 0xc0c992d8d24f3f38
+ 1.15351664838587416140E6, // 0x413199eca5fc9ddd
+ -1.79565251976484877988E7, // 0xc1711fead3299176
+}
+var _tanQ = [...]float64{
+ 1.00000000000000000000E0,
+ 1.36812963470692954678E4, //0x40cab8a5eeb36572
+ -1.32089234440210967447E6, //0xc13427bc582abc96
+ 2.50083801823357915839E7, //0x4177d98fc2ead8ef
+ -5.38695755929454629881E7, //0xc189afe03cbe5a31
+}
+
// Tan returns the tangent of x.
+//
+// Special conditions are:
+// Tan(±0) = ±0
+// Tan(±Inf) = NaN
+// Tan(NaN) = NaN
func Tan(x float64) float64 {
- // Coefficients are #4285 from Hart & Cheney. (19.74D)
const (
- P0 = -.1306820264754825668269611177e+5
- P1 = .1055970901714953193602353981e+4
- P2 = -.1550685653483266376941705728e+2
- P3 = .3422554387241003435328470489e-1
- P4 = .3386638642677172096076369e-4
- Q0 = -.1663895238947119001851464661e+5
- Q1 = .4765751362916483698926655581e+4
- Q2 = -.1555033164031709966900124574e+3
+ PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts
+ PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000,
+ PI4C = 2.69515142907905952645E-15 // 0x3ce8469898cc5170,
+ M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
)
+ // TODO(rsc): Remove manual inlining of IsNaN, IsInf
+ // when compiler does it for us
+ // special cases
+ switch {
+ case x == 0 || x != x: // x == 0 || IsNaN():
+ return x // return ±0 || NaN()
+ case x < -MaxFloat64 || x > MaxFloat64: // IsInf(x, 0):
+ return NaN()
+ }
- flag := false
+ // make argument positive but save the sign
sign := false
if x < 0 {
x = -x
sign = true
}
- x = x * (4 / Pi) /* overflow? */
- var e float64
- e, x = Modf(x)
- i := int32(e)
-
- switch i & 3 {
- case 1:
- x = 1 - x
- flag = true
- case 2:
- sign = !sign
- flag = true
+ j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+ y := float64(j) // integer part of x/(Pi/4), as float
- case 3:
- x = 1 - x
- sign = !sign
+ /* map zeros and singularities to origin */
+ if j&1 == 1 {
+ j += 1
+ y += 1
}
- xsq := x * x
- temp := ((((P4*xsq+P3)*xsq+P2)*xsq+P1)*xsq + P0) * x
- temp = temp / (((xsq+Q2)*xsq+Q1)*xsq + Q0)
+ z := ((x - y*PI4A) - y*PI4B) - y*PI4C
+ zz := z * z
- if flag {
- if temp == 0 {
- return NaN()
- }
- temp = 1 / temp
+ if zz > 1e-14 {
+ y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4]))
+ } else {
+ y = z
+ }
+ if j&2 == 2 {
+ y = -1 / y
}
if sign {
- temp = -temp
+ y = -y
}
- return temp
+ return y
}