v / vlib / math / tan.v
111 lines · 107 sloc · 2.38 KB · 390efe46a1f46f302ae98c803b8ffbbb333fdb28
Raw
1module math
2
3const tan_p = [
4 -1.30936939181383777646e+4,
5 1.15351664838587416140e+6,
6 -1.79565251976484877988e+7,
7]
8const tan_q = [
9 1.00000000000000000000e+0,
10 1.36812963470692954678e+4,
11 -1.32089234440210967447e+6,
12 2.50083801823357915839e+7,
13 -5.38695755929454629881e+7,
14]
15const tan_dp1 = 7.853981554508209228515625e-1
16const tan_dp2 = 7.94662735614792836714e-9
17const tan_dp3 = 3.06161699786838294307e-17
18const tan_lossth = 1.073741824e+9
19
20// tan calculates tangent of a number
21pub fn tan(a f64) f64 {
22 mut x := a
23 if x == 0.0 || is_nan(x) {
24 return x
25 }
26 if is_inf(x, 0) {
27 return nan()
28 }
29 mut sgn := 1 // make argument positive but save the sign
30 if x < 0 {
31 x = -x
32 sgn = -1
33 }
34 if x > tan_lossth {
35 return 0.0
36 }
37 // compute x mod pi_4
38 mut y := floor(x * 4.0 / pi) // strip high bits of integer part
39 mut z := ldexp(y, -3)
40 z = floor(z) // integer part of y/8
41 z = y - ldexp(z, 3) // y - 16 * (y/16) // integer and fractional part modulo one octant
42 mut octant := int(z) // map zeros and singularities to origin
43 if (octant & 1) == 1 {
44 octant++
45 y += 1.0
46 }
47 z = ((x - y * tan_dp1) - y * tan_dp2) - y * tan_dp3
48 zz := z * z
49 if zz > 1.0e-14 {
50 y = z + z * (zz * (((tan_p[0] * zz) + tan_p[1]) * zz + tan_p[2]) / ((((zz + tan_q[1]) * zz +
51 tan_q[2]) * zz + tan_q[3]) * zz + tan_q[4]))
52 } else {
53 y = z
54 }
55 if (octant & 2) == 2 {
56 y = -1.0 / y
57 }
58 if sgn < 0 {
59 y = -y
60 }
61 return y
62}
63
64// tanf calculates tangent. (float32)
65@[inline]
66pub fn tanf(a f32) f32 {
67 return f32(tan(a))
68}
69
70// tan calculates cotangent of a number
71pub fn cot(a f64) f64 {
72 mut x := a
73 if x == 0.0 {
74 return inf(1)
75 }
76 mut sgn := 1 // make argument positive but save the sign
77 if x < 0 {
78 x = -x
79 sgn = -1
80 }
81 if x > tan_lossth {
82 return 0.0
83 }
84 // compute x mod pi_4
85 mut y := floor(x * 4.0 / pi) // strip high bits of integer part
86 mut z := ldexp(y, -3)
87 z = floor(z) // integer part of y/8
88 z = y - ldexp(z, 3) // y - 16 * (y/16) // integer and fractional part modulo one octant
89 mut octant := int(z) // map zeros and singularities to origin
90 if (octant & 1) == 1 {
91 octant++
92 y += 1.0
93 }
94 z = ((x - y * tan_dp1) - y * tan_dp2) - y * tan_dp3
95 zz := z * z
96 if zz > 1.0e-14 {
97 y = z + z * (zz * (((tan_p[0] * zz) + tan_p[1]) * zz + tan_p[2]) / ((((zz + tan_q[1]) * zz +
98 tan_q[2]) * zz + tan_q[3]) * zz + tan_q[4]))
99 } else {
100 y = z
101 }
102 if (octant & 2) == 2 {
103 y = -y
104 } else {
105 y = 1.0 / y
106 }
107 if sgn < 0 {
108 y = -y
109 }
110 return y
111}
112