111
|
1 // Copyright 2011 The Go Authors. All rights reserved.
|
|
2 // Use of this source code is governed by a BSD-style
|
|
3 // license that can be found in the LICENSE file.
|
|
4
|
|
5 package math
|
|
6
|
|
7 /*
|
|
8 Floating-point tangent.
|
|
9 */
|
|
10
|
|
11 // The original C code, the long comment, and the constants
|
|
12 // below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
|
|
13 // available from http://www.netlib.org/cephes/cmath.tgz.
|
|
14 // The go code is a simplified version of the original C.
|
|
15 //
|
|
16 // tan.c
|
|
17 //
|
|
18 // Circular tangent
|
|
19 //
|
|
20 // SYNOPSIS:
|
|
21 //
|
|
22 // double x, y, tan();
|
|
23 // y = tan( x );
|
|
24 //
|
|
25 // DESCRIPTION:
|
|
26 //
|
|
27 // Returns the circular tangent of the radian argument x.
|
|
28 //
|
|
29 // Range reduction is modulo pi/4. A rational function
|
|
30 // x + x**3 P(x**2)/Q(x**2)
|
|
31 // is employed in the basic interval [0, pi/4].
|
|
32 //
|
|
33 // ACCURACY:
|
|
34 // Relative error:
|
|
35 // arithmetic domain # trials peak rms
|
|
36 // DEC +-1.07e9 44000 4.1e-17 1.0e-17
|
|
37 // IEEE +-1.07e9 30000 2.9e-16 8.1e-17
|
|
38 //
|
|
39 // Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
|
|
40 // is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
|
|
41 // be meaningless for x > 2**49 = 5.6e14.
|
|
42 // [Accuracy loss statement from sin.go comments.]
|
|
43 //
|
|
44 // Cephes Math Library Release 2.8: June, 2000
|
|
45 // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
|
|
46 //
|
|
47 // The readme file at http://netlib.sandia.gov/cephes/ says:
|
|
48 // Some software in this archive may be from the book _Methods and
|
|
49 // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
|
50 // International, 1989) or from the Cephes Mathematical Library, a
|
|
51 // commercial product. In either event, it is copyrighted by the author.
|
|
52 // What you see here may be used freely but it comes with no support or
|
|
53 // guarantee.
|
|
54 //
|
|
55 // The two known misprints in the book are repaired here in the
|
|
56 // source listings for the gamma function and the incomplete beta
|
|
57 // integral.
|
|
58 //
|
|
59 // Stephen L. Moshier
|
|
60 // moshier@na-net.ornl.gov
|
|
61
|
|
62 // tan coefficients
|
|
63 var _tanP = [...]float64{
|
145
|
64 -1.30936939181383777646e4, // 0xc0c992d8d24f3f38
|
|
65 1.15351664838587416140e6, // 0x413199eca5fc9ddd
|
|
66 -1.79565251976484877988e7, // 0xc1711fead3299176
|
111
|
67 }
|
|
68 var _tanQ = [...]float64{
|
145
|
69 1.00000000000000000000e0,
|
|
70 1.36812963470692954678e4, //0x40cab8a5eeb36572
|
|
71 -1.32089234440210967447e6, //0xc13427bc582abc96
|
|
72 2.50083801823357915839e7, //0x4177d98fc2ead8ef
|
|
73 -5.38695755929454629881e7, //0xc189afe03cbe5a31
|
111
|
74 }
|
|
75
|
|
76 // Tan returns the tangent of the radian argument x.
|
|
77 //
|
|
78 // Special cases are:
|
|
79 // Tan(±0) = ±0
|
|
80 // Tan(±Inf) = NaN
|
|
81 // Tan(NaN) = NaN
|
|
82
|
|
83 //extern tan
|
|
84 func libc_tan(float64) float64
|
|
85
|
|
86 func Tan(x float64) float64 {
|
|
87 return libc_tan(x)
|
|
88 }
|
|
89
|
|
90 func tan(x float64) float64 {
|
|
91 const (
|
145
|
92 PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
|
|
93 PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
|
|
94 PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
|
111
|
95 )
|
|
96 // special cases
|
|
97 switch {
|
|
98 case x == 0 || IsNaN(x):
|
|
99 return x // return ±0 || NaN()
|
|
100 case IsInf(x, 0):
|
|
101 return NaN()
|
|
102 }
|
|
103
|
|
104 // make argument positive but save the sign
|
|
105 sign := false
|
|
106 if x < 0 {
|
|
107 x = -x
|
|
108 sign = true
|
|
109 }
|
145
|
110 var j uint64
|
|
111 var y, z float64
|
|
112 if x >= reduceThreshold {
|
|
113 j, z = trigReduce(x)
|
|
114 } else {
|
|
115 j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
|
|
116 y = float64(j) // integer part of x/(Pi/4), as float
|
111
|
117
|
145
|
118 /* map zeros and singularities to origin */
|
|
119 if j&1 == 1 {
|
|
120 j++
|
|
121 y++
|
|
122 }
|
|
123
|
|
124 z = ((x - y*PI4A) - y*PI4B) - y*PI4C
|
111
|
125 }
|
|
126 zz := z * z
|
|
127
|
|
128 if zz > 1e-14 {
|
|
129 y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4]))
|
|
130 } else {
|
|
131 y = z
|
|
132 }
|
|
133 if j&2 == 2 {
|
|
134 y = -1 / y
|
|
135 }
|
|
136 if sign {
|
|
137 y = -y
|
|
138 }
|
|
139 return y
|
|
140 }
|