1 | module math |
2 | |
3 | import math.internal |
4 | |
5 | const ( |
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 |
48 | pub 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 |
87 | pub 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] |
129 | pub fn cosf(a f32) f32 { |
130 | return f32(cos(a)) |
131 | } |
132 | |
133 | // sinf calculates sine in radians (float32) |
134 | [inline] |
135 | pub fn sinf(a f32) f32 { |
136 | return f32(sin(a)) |
137 | } |
138 | |
139 | // sincos calculates the sine and cosine of the angle in radians |
140 | pub 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 | } |