source: mainline/uspace/lib/math/generic/trig.c@ bbe5e34

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bbe5e34 was 516e780, checked in by GitHub <noreply@…>, 7 years ago

Strip down libmath. (#45)

libmath is mostly unused (except for trunc(), sin() and cos()), and most functions in it are either very imprecise or downright broken. Additionally, it is implemented in manner that conflicts with C standard. Instead of trying to fix all the shortcomings while maintaining unused functionality, I'm opting to simply remove most of it and only keep the parts that are currently necessary.

Later readdition of the removed functions is possible, but there needs to be a reliable way to evaluate their quality first.

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * Copyright (c) 2014 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libmath
31 * @{
32 */
33/** @file
34 */
35
36#include <math.h>
37
38#define TAYLOR_DEGREE_32 13
39#define TAYLOR_DEGREE_64 21
40
41/** Precomputed values for factorial (starting from 1!) */
42static double factorials[TAYLOR_DEGREE_64] = {
43 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800,
44 479001600, 6227020800.0L, 87178291200.0L, 1307674368000.0L,
45 20922789888000.0L, 355687428096000.0L, 6402373705728000.0L,
46 121645100408832000.0L, 2432902008176640000.0L, 51090942171709440000.0L
47};
48
49/** Sine approximation by Taylor series (32-bit floating point)
50 *
51 * Compute the approximation of sine by a Taylor
52 * series (using the first TAYLOR_DEGREE terms).
53 * The approximation is reasonably accurate for
54 * arguments within the interval [-pi/4, pi/4].
55 *
56 * @param arg Sine argument.
57 *
58 * @return Sine value approximation.
59 *
60 */
61static float taylor_sin_32(float arg)
62{
63 float ret = 0;
64 float nom = 1;
65
66 for (unsigned int i = 0; i < TAYLOR_DEGREE_32; i++) {
67 nom *= arg;
68
69 if ((i % 4) == 0)
70 ret += nom / factorials[i];
71 else if ((i % 4) == 2)
72 ret -= nom / factorials[i];
73 }
74
75 return ret;
76}
77
78/** Sine approximation by Taylor series (64-bit floating point)
79 *
80 * Compute the approximation of sine by a Taylor
81 * series (using the first TAYLOR_DEGREE terms).
82 * The approximation is reasonably accurate for
83 * arguments within the interval [-pi/4, pi/4].
84 *
85 * @param arg Sine argument.
86 *
87 * @return Sine value approximation.
88 *
89 */
90static double taylor_sin_64(double arg)
91{
92 double ret = 0;
93 double nom = 1;
94
95 for (unsigned int i = 0; i < TAYLOR_DEGREE_64; i++) {
96 nom *= arg;
97
98 if ((i % 4) == 0)
99 ret += nom / factorials[i];
100 else if ((i % 4) == 2)
101 ret -= nom / factorials[i];
102 }
103
104 return ret;
105}
106
107/** Cosine approximation by Taylor series (32-bit floating point)
108 *
109 * Compute the approximation of cosine by a Taylor
110 * series (using the first TAYLOR_DEGREE terms).
111 * The approximation is reasonably accurate for
112 * arguments within the interval [-pi/4, pi/4].
113 *
114 * @param arg Cosine argument.
115 *
116 * @return Cosine value approximation.
117 *
118 */
119static float taylor_cos_32(float arg)
120{
121 float ret = 1;
122 float nom = 1;
123
124 for (unsigned int i = 0; i < TAYLOR_DEGREE_32; i++) {
125 nom *= arg;
126
127 if ((i % 4) == 1)
128 ret -= nom / factorials[i];
129 else if ((i % 4) == 3)
130 ret += nom / factorials[i];
131 }
132
133 return ret;
134}
135
136/** Cosine approximation by Taylor series (64-bit floating point)
137 *
138 * Compute the approximation of cosine by a Taylor
139 * series (using the first TAYLOR_DEGREE terms).
140 * The approximation is reasonably accurate for
141 * arguments within the interval [-pi/4, pi/4].
142 *
143 * @param arg Cosine argument.
144 *
145 * @return Cosine value approximation.
146 *
147 */
148static double taylor_cos_64(double arg)
149{
150 double ret = 1;
151 double nom = 1;
152
153 for (unsigned int i = 0; i < TAYLOR_DEGREE_64; i++) {
154 nom *= arg;
155
156 if ((i % 4) == 1)
157 ret -= nom / factorials[i];
158 else if ((i % 4) == 3)
159 ret += nom / factorials[i];
160 }
161
162 return ret;
163}
164
165/** Sine value for values within base period (32-bit floating point)
166 *
167 * Compute the value of sine for arguments within
168 * the base period [0, 2pi]. For arguments outside
169 * the base period the returned values can be
170 * very inaccurate or even completely wrong.
171 *
172 * @param arg Sine argument.
173 *
174 * @return Sine value.
175 *
176 */
177static float base_sin_32(float arg)
178{
179 unsigned int period = arg / (M_PI / 4);
180
181 switch (period) {
182 case 0:
183 return taylor_sin_32(arg);
184 case 1:
185 case 2:
186 return taylor_cos_32(arg - M_PI / 2);
187 case 3:
188 case 4:
189 return -taylor_sin_32(arg - M_PI);
190 case 5:
191 case 6:
192 return -taylor_cos_32(arg - 3 * M_PI / 2);
193 default:
194 return taylor_sin_32(arg - 2 * M_PI);
195 }
196}
197
198/** Sine value for values within base period (64-bit floating point)
199 *
200 * Compute the value of sine for arguments within
201 * the base period [0, 2pi]. For arguments outside
202 * the base period the returned values can be
203 * very inaccurate or even completely wrong.
204 *
205 * @param arg Sine argument.
206 *
207 * @return Sine value.
208 *
209 */
210static double base_sin_64(double arg)
211{
212 unsigned int period = arg / (M_PI / 4);
213
214 switch (period) {
215 case 0:
216 return taylor_sin_64(arg);
217 case 1:
218 case 2:
219 return taylor_cos_64(arg - M_PI / 2);
220 case 3:
221 case 4:
222 return -taylor_sin_64(arg - M_PI);
223 case 5:
224 case 6:
225 return -taylor_cos_64(arg - 3 * M_PI / 2);
226 default:
227 return taylor_sin_64(arg - 2 * M_PI);
228 }
229}
230
231/** Cosine value for values within base period (32-bit floating point)
232 *
233 * Compute the value of cosine for arguments within
234 * the base period [0, 2pi]. For arguments outside
235 * the base period the returned values can be
236 * very inaccurate or even completely wrong.
237 *
238 * @param arg Cosine argument.
239 *
240 * @return Cosine value.
241 *
242 */
243static float base_cos_32(float arg)
244{
245 unsigned int period = arg / (M_PI / 4);
246
247 switch (period) {
248 case 0:
249 return taylor_cos_32(arg);
250 case 1:
251 case 2:
252 return -taylor_sin_32(arg - M_PI / 2);
253 case 3:
254 case 4:
255 return -taylor_cos_32(arg - M_PI);
256 case 5:
257 case 6:
258 return taylor_sin_32(arg - 3 * M_PI / 2);
259 default:
260 return taylor_cos_32(arg - 2 * M_PI);
261 }
262}
263
264/** Cosine value for values within base period (64-bit floating point)
265 *
266 * Compute the value of cosine for arguments within
267 * the base period [0, 2pi]. For arguments outside
268 * the base period the returned values can be
269 * very inaccurate or even completely wrong.
270 *
271 * @param arg Cosine argument.
272 *
273 * @return Cosine value.
274 *
275 */
276static double base_cos_64(double arg)
277{
278 unsigned int period = arg / (M_PI / 4);
279
280 switch (period) {
281 case 0:
282 return taylor_cos_64(arg);
283 case 1:
284 case 2:
285 return -taylor_sin_64(arg - M_PI / 2);
286 case 3:
287 case 4:
288 return -taylor_cos_64(arg - M_PI);
289 case 5:
290 case 6:
291 return taylor_sin_64(arg - 3 * M_PI / 2);
292 default:
293 return taylor_cos_64(arg - 2 * M_PI);
294 }
295}
296
297/** Sine (32-bit floating point)
298 *
299 * Compute sine value.
300 *
301 * @param arg Sine argument.
302 *
303 * @return Sine value.
304 *
305 */
306float sinf(float arg)
307{
308 float base_arg = fmodf(arg, 2 * M_PI);
309
310 if (base_arg < 0)
311 return -base_sin_32(-base_arg);
312
313 return base_sin_32(base_arg);
314}
315
316/** Sine (64-bit floating point)
317 *
318 * Compute sine value.
319 *
320 * @param arg Sine argument.
321 *
322 * @return Sine value.
323 *
324 */
325double sin(double arg)
326{
327 double base_arg = fmod(arg, 2 * M_PI);
328
329 if (base_arg < 0)
330 return -base_sin_64(-base_arg);
331
332 return base_sin_64(base_arg);
333}
334
335/** Cosine (32-bit floating point)
336 *
337 * Compute cosine value.
338 *
339 * @param arg Cosine argument.
340 *
341 * @return Cosine value.
342 *
343 */
344float cosf(float arg)
345{
346 float base_arg = fmodf(arg, 2 * M_PI);
347
348 if (base_arg < 0)
349 return base_cos_32(-base_arg);
350
351 return base_cos_32(base_arg);
352}
353
354/** Cosine (64-bit floating point)
355 *
356 * Compute cosine value.
357 *
358 * @param arg Cosine argument.
359 *
360 * @return Cosine value.
361 *
362 */
363double cos(double arg)
364{
365 double base_arg = fmod(arg, 2 * M_PI);
366
367 if (base_arg < 0)
368 return base_cos_64(-base_arg);
369
370 return base_cos_64(base_arg);
371}
372
373/** @}
374 */
Note: See TracBrowser for help on using the repository browser.