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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 10d65d70 was 83932dc9, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

Split up libmath functions into more files

so that they don't conflict with fdlibm during static linking.

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[ba11ebb]1/*
[9adb61d]2 * Copyright (c) 2015 Jiri Svoboda
[ba11ebb]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>
[83932dc9]37#include "internal.h"
[ba11ebb]38
[992ffa6]39#define TAYLOR_DEGREE_32 13
40#define TAYLOR_DEGREE_64 21
[ba11ebb]41
42/** Precomputed values for factorial (starting from 1!) */
[516e780]43static double factorials[TAYLOR_DEGREE_64] = {
[ba11ebb]44 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800,
[992ffa6]45 479001600, 6227020800.0L, 87178291200.0L, 1307674368000.0L,
46 20922789888000.0L, 355687428096000.0L, 6402373705728000.0L,
47 121645100408832000.0L, 2432902008176640000.0L, 51090942171709440000.0L
[ba11ebb]48};
49
[9adb61d]50/** Sine approximation by Taylor series (32-bit floating point)
[ba11ebb]51 *
52 * Compute the approximation of sine by a Taylor
53 * series (using the first TAYLOR_DEGREE terms).
54 * The approximation is reasonably accurate for
55 * arguments within the interval [-pi/4, pi/4].
56 *
57 * @param arg Sine argument.
58 *
59 * @return Sine value approximation.
60 *
61 */
[516e780]62static float taylor_sin_32(float arg)
[9adb61d]63{
[516e780]64 float ret = 0;
65 float nom = 1;
[a35b458]66
[9adb61d]67 for (unsigned int i = 0; i < TAYLOR_DEGREE_32; i++) {
68 nom *= arg;
[a35b458]69
[9adb61d]70 if ((i % 4) == 0)
71 ret += nom / factorials[i];
72 else if ((i % 4) == 2)
73 ret -= nom / factorials[i];
74 }
[a35b458]75
[9adb61d]76 return ret;
77}
78
79/** Sine approximation by Taylor series (64-bit floating point)
80 *
81 * Compute the approximation of sine by a Taylor
82 * series (using the first TAYLOR_DEGREE terms).
83 * The approximation is reasonably accurate for
84 * arguments within the interval [-pi/4, pi/4].
85 *
86 * @param arg Sine argument.
87 *
88 * @return Sine value approximation.
89 *
90 */
[516e780]91static double taylor_sin_64(double arg)
[ba11ebb]92{
[516e780]93 double ret = 0;
94 double nom = 1;
[a35b458]95
[992ffa6]96 for (unsigned int i = 0; i < TAYLOR_DEGREE_64; i++) {
[ba11ebb]97 nom *= arg;
[a35b458]98
[ba11ebb]99 if ((i % 4) == 0)
100 ret += nom / factorials[i];
101 else if ((i % 4) == 2)
102 ret -= nom / factorials[i];
103 }
[a35b458]104
[ba11ebb]105 return ret;
106}
107
[9adb61d]108/** Cosine approximation by Taylor series (32-bit floating point)
109 *
110 * Compute the approximation of cosine by a Taylor
111 * series (using the first TAYLOR_DEGREE terms).
112 * The approximation is reasonably accurate for
113 * arguments within the interval [-pi/4, pi/4].
114 *
115 * @param arg Cosine argument.
116 *
117 * @return Cosine value approximation.
118 *
119 */
[516e780]120static float taylor_cos_32(float arg)
[9adb61d]121{
[516e780]122 float ret = 1;
123 float nom = 1;
[a35b458]124
[9adb61d]125 for (unsigned int i = 0; i < TAYLOR_DEGREE_32; i++) {
126 nom *= arg;
[a35b458]127
[9adb61d]128 if ((i % 4) == 1)
129 ret -= nom / factorials[i];
130 else if ((i % 4) == 3)
131 ret += nom / factorials[i];
132 }
[a35b458]133
[9adb61d]134 return ret;
135}
136
137/** Cosine approximation by Taylor series (64-bit floating point)
[ba11ebb]138 *
139 * Compute the approximation of cosine by a Taylor
140 * series (using the first TAYLOR_DEGREE terms).
141 * The approximation is reasonably accurate for
142 * arguments within the interval [-pi/4, pi/4].
143 *
144 * @param arg Cosine argument.
145 *
146 * @return Cosine value approximation.
147 *
148 */
[516e780]149static double taylor_cos_64(double arg)
[ba11ebb]150{
[516e780]151 double ret = 1;
152 double nom = 1;
[a35b458]153
[992ffa6]154 for (unsigned int i = 0; i < TAYLOR_DEGREE_64; i++) {
[ba11ebb]155 nom *= arg;
[a35b458]156
[ba11ebb]157 if ((i % 4) == 1)
158 ret -= nom / factorials[i];
159 else if ((i % 4) == 3)
160 ret += nom / factorials[i];
161 }
[a35b458]162
[ba11ebb]163 return ret;
164}
165
[9adb61d]166/** Sine value for values within base period (32-bit floating point)
167 *
168 * Compute the value of sine for arguments within
169 * the base period [0, 2pi]. For arguments outside
170 * the base period the returned values can be
171 * very inaccurate or even completely wrong.
172 *
173 * @param arg Sine argument.
174 *
175 * @return Sine value.
176 *
177 */
[83932dc9]178float __math_base_sin_32(float arg)
[9adb61d]179{
180 unsigned int period = arg / (M_PI / 4);
[a35b458]181
[9adb61d]182 switch (period) {
183 case 0:
184 return taylor_sin_32(arg);
185 case 1:
186 case 2:
187 return taylor_cos_32(arg - M_PI / 2);
188 case 3:
189 case 4:
190 return -taylor_sin_32(arg - M_PI);
191 case 5:
192 case 6:
193 return -taylor_cos_32(arg - 3 * M_PI / 2);
194 default:
195 return taylor_sin_32(arg - 2 * M_PI);
196 }
197}
198
199/** Sine value for values within base period (64-bit floating point)
[ba11ebb]200 *
201 * Compute the value of sine for arguments within
202 * the base period [0, 2pi]. For arguments outside
203 * the base period the returned values can be
204 * very inaccurate or even completely wrong.
205 *
206 * @param arg Sine argument.
207 *
208 * @return Sine value.
209 *
210 */
[83932dc9]211double __math_base_sin_64(double arg)
[9adb61d]212{
213 unsigned int period = arg / (M_PI / 4);
[a35b458]214
[9adb61d]215 switch (period) {
216 case 0:
217 return taylor_sin_64(arg);
218 case 1:
219 case 2:
220 return taylor_cos_64(arg - M_PI / 2);
221 case 3:
222 case 4:
223 return -taylor_sin_64(arg - M_PI);
224 case 5:
225 case 6:
226 return -taylor_cos_64(arg - 3 * M_PI / 2);
227 default:
228 return taylor_sin_64(arg - 2 * M_PI);
229 }
230}
231
232/** Cosine value for values within base period (32-bit floating point)
233 *
234 * Compute the value of cosine for arguments within
235 * the base period [0, 2pi]. For arguments outside
236 * the base period the returned values can be
237 * very inaccurate or even completely wrong.
238 *
239 * @param arg Cosine argument.
240 *
241 * @return Cosine value.
242 *
243 */
[83932dc9]244float __math_base_cos_32(float arg)
[ba11ebb]245{
246 unsigned int period = arg / (M_PI / 4);
[a35b458]247
[ba11ebb]248 switch (period) {
249 case 0:
[9adb61d]250 return taylor_cos_32(arg);
[ba11ebb]251 case 1:
252 case 2:
[9adb61d]253 return -taylor_sin_32(arg - M_PI / 2);
[ba11ebb]254 case 3:
255 case 4:
[9adb61d]256 return -taylor_cos_32(arg - M_PI);
[ba11ebb]257 case 5:
258 case 6:
[9adb61d]259 return taylor_sin_32(arg - 3 * M_PI / 2);
[ba11ebb]260 default:
[9adb61d]261 return taylor_cos_32(arg - 2 * M_PI);
[ba11ebb]262 }
263}
264
[9adb61d]265/** Cosine value for values within base period (64-bit floating point)
[ba11ebb]266 *
267 * Compute the value of cosine for arguments within
268 * the base period [0, 2pi]. For arguments outside
269 * the base period the returned values can be
270 * very inaccurate or even completely wrong.
271 *
272 * @param arg Cosine argument.
273 *
274 * @return Cosine value.
275 *
276 */
[83932dc9]277double __math_base_cos_64(double arg)
[ba11ebb]278{
279 unsigned int period = arg / (M_PI / 4);
[a35b458]280
[ba11ebb]281 switch (period) {
282 case 0:
[9adb61d]283 return taylor_cos_64(arg);
[ba11ebb]284 case 1:
285 case 2:
[9adb61d]286 return -taylor_sin_64(arg - M_PI / 2);
[ba11ebb]287 case 3:
288 case 4:
[9adb61d]289 return -taylor_cos_64(arg - M_PI);
[ba11ebb]290 case 5:
291 case 6:
[9adb61d]292 return taylor_sin_64(arg - 3 * M_PI / 2);
[ba11ebb]293 default:
[9adb61d]294 return taylor_cos_64(arg - 2 * M_PI);
[ba11ebb]295 }
296}
297
298/** @}
299 */
Note: See TracBrowser for help on using the repository browser.