v / vlib / math / sin.v
186 lines · 179 sloc · 4.44 KB · 008aaad99981918c51194d7aaaaaccb4c258f244
Raw
1module math
2
3import math.internal
4
5const sin_data = [
6 -0.3295190160663511504173,
7 0.0025374284671667991990,
8 0.0006261928782647355874,
9 -4.6495547521854042157541e-06,
10 -5.6917531549379706526677e-07,
11 3.7283335140973803627866e-09,
12 3.0267376484747473727186e-10,
13 -1.7400875016436622322022e-12,
14 -1.0554678305790849834462e-13,
15 5.3701981409132410797062e-16,
16 2.5984137983099020336115e-17,
17 -1.1821555255364833468288e-19,
18]
19const sin_cs = ChebSeries{
20 c: sin_data
21 order: 11
22 a: -1
23 b: 1
24}
25const cos_data = [
26 0.165391825637921473505668118136,
27 -0.00084852883845000173671196530195,
28 -0.000210086507222940730213625768083,
29 1.16582269619760204299639757584e-6,
30 1.43319375856259870334412701165e-7,
31 -7.4770883429007141617951330184e-10,
32 -6.0969994944584252706997438007e-11,
33 2.90748249201909353949854872638e-13,
34 1.77126739876261435667156490461e-14,
35 -7.6896421502815579078577263149e-17,
36 -3.7363121133079412079201377318e-18,
37]
38const cos_cs = ChebSeries{
39 c: cos_data
40 order: 10
41 a: -1
42 b: 1
43}
44
45// sin calculates the sine of the angle in radians
46pub fn sin(x f64) f64 {
47 p1 := 7.85398125648498535156e-1
48 p2 := 3.77489470793079817668e-8
49 p3 := 2.69515142907905952645e-15
50 sgn_x := if x < 0 { -1 } else { 1 }
51 abs_x := abs(x)
52 if abs_x < internal.root4_f64_epsilon {
53 x2 := x * x
54 return x * (1.0 - x2 / 6.0)
55 } else {
56 mut sgn_result := sgn_x
57 mut y := floor(abs_x / (0.25 * pi))
58 mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3))
59 if (octant & 1) == 1 {
60 octant++
61 octant &= 7
62 y += 1.0
63 }
64 if octant > 3 {
65 octant -= 4
66 sgn_result = -sgn_result
67 }
68 z := ((abs_x - y * p1) - y * p2) - y * p3
69 mut result := 0.0
70 if octant == 0 {
71 t := 8.0 * abs(z) / pi - 1.0
72 sin_cs_val, _ := sin_cs.eval_e(t)
73 result = z * (1.0 + z * z * sin_cs_val)
74 } else {
75 t := 8.0 * abs(z) / pi - 1.0
76 cos_cs_val, _ := cos_cs.eval_e(t)
77 result = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val)
78 }
79 result *= sgn_result
80 return result
81 }
82}
83
84// cos calculates the cosine of the angle in radians
85pub fn cos(x f64) f64 {
86 p1 := 7.85398125648498535156e-1
87 p2 := 3.77489470793079817668e-8
88 p3 := 2.69515142907905952645e-15
89 abs_x := abs(x)
90 if abs_x < internal.root4_f64_epsilon {
91 x2 := x * x
92 return 1.0 - 0.5 * x2
93 } else {
94 mut sgn_result := 1
95 mut y := floor(abs_x / (0.25 * pi))
96 mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3))
97 if (octant & 1) == 1 {
98 octant++
99 octant &= 7
100 y += 1.0
101 }
102 if octant > 3 {
103 octant -= 4
104 sgn_result = -sgn_result
105 }
106 if octant > 1 {
107 sgn_result = -sgn_result
108 }
109 z := ((abs_x - y * p1) - y * p2) - y * p3
110 mut result := 0.0
111 if octant == 0 {
112 t := 8.0 * abs(z) / pi - 1.0
113 cos_cs_val, _ := cos_cs.eval_e(t)
114 result = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val)
115 } else {
116 t := 8.0 * abs(z) / pi - 1.0
117 sin_cs_val, _ := sin_cs.eval_e(t)
118 result = z * (1.0 + z * z * sin_cs_val)
119 }
120 result *= sgn_result
121 return result
122 }
123}
124
125// cosf calculates cosine in radians (float32).
126@[inline]
127pub fn cosf(a f32) f32 {
128 return f32(cos(a))
129}
130
131// sinf calculates sine in radians (float32)
132@[inline]
133pub fn sinf(a f32) f32 {
134 return f32(sin(a))
135}
136
137// sincos calculates the sine and cosine of the angle in radians
138pub fn sincos(x f64) (f64, f64) {
139 if is_nan(x) {
140 return x, x
141 }
142 p1 := 7.85398125648498535156e-1
143 p2 := 3.77489470793079817668e-8
144 p3 := 2.69515142907905952645e-15
145 sgn_x := if x < 0 { -1 } else { 1 }
146 abs_x := abs(x)
147 if is_inf(x, sgn_x) {
148 return nan(), nan()
149 }
150 if abs_x < internal.root4_f64_epsilon {
151 x2 := x * x
152 return x * (1.0 - x2 / 6.0), 1.0 - 0.5 * x2
153 } else {
154 mut sgn_result_sin := sgn_x
155 mut sgn_result_cos := 1
156 mut y := floor(abs_x / (0.25 * pi))
157 mut octant := int(y - ldexp(floor(ldexp(y, -3)), 3))
158 if (octant & 1) == 1 {
159 octant++
160 octant &= 7
161 y += 1.0
162 }
163 if octant > 3 {
164 octant -= 4
165 sgn_result_sin = -sgn_result_sin
166 sgn_result_cos = -sgn_result_cos
167 }
168 sgn_result_cos = if octant > 1 { -sgn_result_cos } else { sgn_result_cos }
169 z := ((abs_x - y * p1) - y * p2) - y * p3
170 t := 8.0 * abs(z) / pi - 1.0
171 sin_cs_val, _ := sin_cs.eval_e(t)
172 cos_cs_val, _ := cos_cs.eval_e(t)
173 mut result_sin := 0.0
174 mut result_cos := 0.0
175 if octant == 0 {
176 result_sin = z * (1.0 + z * z * sin_cs_val)
177 result_cos = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val)
178 } else {
179 result_sin = 1.0 - 0.5 * z * z * (1.0 - z * z * cos_cs_val)
180 result_cos = z * (1.0 + z * z * sin_cs_val)
181 }
182 result_sin *= sgn_result_sin
183 result_cos *= sgn_result_cos
184 return result_sin, result_cos
185 }
186}
187