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