GCC Code Coverage Report


Directory: src/gate/
File: src/gate/mathematics.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 128 209 61.2%
Functions: 53 74 71.6%
Branches: 84 112 75.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
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 are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/mathematics.h"
30
31 #if defined(GATE_SYS_EFI)
32 //# define GATE_CORE_MATH_EFI_IMPL 1
33 # define GATE_CORE_MATH_STD_IMPL 1
34 #else
35 # define GATE_CORE_MATH_STD_IMPL 1
36 #endif
37
38 /*****************************
39 * Generic implementations *
40 *****************************/
41
42 #include <stdarg.h>
43 #include <float.h>
44
45 void gate_decimal_init(gate_decimal_t* deci, gate_int32_t int_num, gate_uint32_t micro_num)
46 {
47 deci->value = (gate_decimal_primitive_t)(int_num * GATE_DECIMAL_FACTOR);
48 deci->value += (gate_decimal_primitive_t)(micro_num % GATE_DECIMAL_FACTOR);
49 }
50 gate_int32_t gate_decimal_get_int(gate_decimal_t const* deci)
51 {
52 return (gate_int32_t)(deci->value / GATE_DECIMAL_FACTOR);
53 }
54 gate_uint32_t gate_decimal_get_micro(gate_decimal_t const* deci)
55 {
56 if (deci->value < 0)
57 {
58 return (gate_uint32_t)((-deci->value) % GATE_DECIMAL_FACTOR);
59 }
60 else
61 {
62 return (gate_uint32_t)(deci->value % GATE_DECIMAL_FACTOR);
63 }
64 }
65 gate_real32_t gate_decimal_get_float(gate_decimal_t const* micro)
66 {
67 return (gate_real32_t)micro->value / (gate_real32_t)GATE_DECIMAL_FACTOR;
68 }
69
70 int gate_decimal_compare(gate_decimal_t const* a, gate_decimal_t const* b)
71 {
72 if (a->value < b->value)
73 {
74 return -1;
75 }
76 else if (a->value > b->value)
77 {
78 return 1;
79 }
80 return 0;
81 }
82
83
84 void gate_decimal_add_int(gate_decimal_t* deci, gate_int32_t value)
85 {
86 deci->value += (gate_decimal_primitive_t)value * GATE_DECIMAL_FACTOR;
87 }
88 void gate_decimal_sub_int(gate_decimal_t* deci, gate_int32_t value)
89 {
90 deci->value -= (gate_decimal_primitive_t)value * GATE_DECIMAL_FACTOR;
91 }
92 void gate_decimal_mul_int(gate_decimal_t* deci, gate_int32_t value)
93 {
94 deci->value *= (gate_decimal_primitive_t)value;
95 }
96 void gate_decimal_div_int(gate_decimal_t* deci, gate_int32_t value)
97 {
98 deci->value /= (gate_decimal_primitive_t)value;
99 }
100
101 void gate_decimal_add_dec(gate_decimal_t* deci, gate_decimal_t const* ptr_value)
102 {
103 deci->value += ptr_value->value;
104 }
105 void gate_decimal_sub_dec(gate_decimal_t* deci, gate_decimal_t const* ptr_value)
106 {
107 deci->value -= ptr_value->value;
108 }
109 void gate_decimal_mul_dec(gate_decimal_t* deci, gate_decimal_t const* ptr_value)
110 {
111 deci->value *= ptr_value->value;
112 deci->value /= (gate_decimal_primitive_t)GATE_DECIMAL_FACTOR;
113 }
114 void gate_decimal_div_dec(gate_decimal_t* deci, gate_decimal_t const* ptr_value)
115 {
116 gate_int64_t r = deci->value % ptr_value->value;
117 deci->value /= ptr_value->value;
118 deci->value *= (gate_decimal_primitive_t)GATE_DECIMAL_FACTOR;
119 deci->value += (gate_decimal_primitive_t)(r * GATE_DECIMAL_FACTOR / ptr_value->value);
120 }
121
122 void gate_decimal_add_flt(gate_decimal_t* deci, gate_real32_t value)
123 {
124 deci->value += (gate_decimal_primitive_t)(value * (gate_real32_t)GATE_DECIMAL_FACTOR);
125 }
126 void gate_decimal_sub_flt(gate_decimal_t* deci, gate_real32_t value)
127 {
128 deci->value -= (gate_decimal_primitive_t)(value * (gate_real32_t)GATE_DECIMAL_FACTOR);
129 }
130 void gate_decimal_mul_flt(gate_decimal_t* deci, gate_real32_t value)
131 {
132 deci->value = (gate_decimal_primitive_t)((gate_real32_t)deci->value * value);
133 }
134 void gate_decimal_div_flt(gate_decimal_t* deci, gate_real32_t value)
135 {
136 deci->value = (gate_decimal_primitive_t)((gate_real32_t)deci->value / value);
137 }
138 void gate_decimal_sqrt(gate_decimal_t* deci)
139 {
140 static gate_decimal_t n2 = GATE_DECIMAL_INIT(2, 0);
141 gate_decimal_t a = GATE_DECIMAL_INIT(1255, 0);
142 gate_decimal_t b;
143 unsigned n;
144
145 if (gate_decimal_compare(deci, &n2) < 0)
146 {
147 return;
148 }
149
150 for (n = 0; n < 8; ++n)
151 {
152 b.value = (deci->value / a.value) * GATE_DECIMAL_FACTOR;
153 a.value = (a.value + b.value) / 2;
154 }
155 deci->value = a.value;
156 }
157
158
159 528 gate_bool_t gate_math_iszero(gate_real64_t num)
160 {
161
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 517 times.
528 if (num < 0.0)
162 {
163 11 return (-num < DBL_EPSILON) ? true : false;
164 }
165 else
166 {
167 517 return (num < DBL_EPSILON) ? true : false;
168 }
169 }
170 40 gate_bool_t gate_math_iszerof(gate_real32_t num)
171 {
172
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 if (num < 0.0f)
173 {
174 4 return (-num < FLT_EPSILON) ? true : false;
175 }
176 else
177 {
178 36 return (num < FLT_EPSILON) ? true : false;
179 }
180 }
181
182 31 gate_bool_t gate_math_isnan(gate_real64_t num)
183 {
184 31 volatile gate_real64_t tmp = num;
185 31 return (tmp != num) ? true : false;
186 }
187 3 gate_bool_t gate_math_isnanf(gate_real32_t num)
188 {
189 3 volatile gate_real32_t tmp = num;
190 3 return (tmp != num) ? true : false;
191 }
192
193 31 int gate_math_isinfinite(gate_real64_t num)
194 {
195 #if defined(DBL_MAX)
196
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (num > DBL_MAX)
197 {
198 1 return 1;
199 }
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 else if (num < -DBL_MAX)
201 {
202 return -1;
203 }
204 30 return 0;
205 #else
206 static gate_real64_t const gate_math_infinite_pos = 1.0 / 0.0;
207 static gate_real64_t const gate_math_infinite_neg = -1.0 / 0.0;
208 if (num == gate_math_infinite_pos)
209 {
210 return 1;
211 }
212 else if (num == gate_math_infinite_neg)
213 {
214 return -1;
215 }
216 return 0;
217 #endif
218 }
219 3 int gate_math_isinfinitef(gate_real32_t num)
220 {
221 #if defined(FLT_MAX)
222
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (num > FLT_MAX)
223 {
224 1 return 1;
225 }
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (num < -FLT_MAX)
227 {
228 return -1;
229 }
230 2 return 0;
231 #else
232 static gate_real32_t const gate_math_infinite_pos = 1.0f / 0.0f;
233 static gate_real32_t const gate_math_infinite_neg = -1.0f / 0.0f;
234 if (num == gate_math_infinite_pos)
235 {
236 return 1;
237 }
238 else if (num == gate_math_infinite_neg)
239 {
240 return -1;
241 }
242 return 0;
243 #endif
244
245 }
246
247 4 int gate_math_signum_i8(gate_int8_t num)
248 {
249
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 return (num < 0) ? -1 : ((num == 0) ? 0 : 1);
250 }
251 4 int gate_math_signum_i16(gate_int16_t num)
252 {
253
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 return (num < 0) ? -1 : ((num == 0) ? 0 : 1);
254 }
255 4 int gate_math_signum_i32(gate_int32_t num)
256 {
257
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 return (num < 0) ? -1 : ((num == 0) ? 0 : 1);
258 }
259 4 int gate_math_signum_i64(gate_int64_t num)
260 {
261
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 return (num < 0) ? -1 : ((num == 0) ? 0 : 1);
262 }
263 4 int gate_math_signum_r32(gate_real32_t num)
264 {
265
4/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
4 return gate_math_iszerof(num) ? 0 : ((num < 0.0f) ? -1 : 1);
266 }
267 4 int gate_math_signum_r64(gate_real64_t num)
268 {
269
4/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
4 return gate_math_iszero(num) ? 0 : ((num < 0.0) ? -1 : 1);
270 }
271
272
273 3 gate_int8_t gate_math_abs_i8(gate_int8_t num)
274 {
275 3 return num < 0 ? -num : num;
276 }
277 3 gate_int16_t gate_math_abs_i16(gate_int16_t num)
278 {
279 3 return num < 0 ? -num : num;
280 }
281 41 gate_int32_t gate_math_abs_i32(gate_int32_t num)
282 {
283 41 return num < 0 ? -num : num;
284 }
285 3 gate_int64_t gate_math_abs_i64(gate_int64_t num)
286 {
287 3 return num < 0 ? -num : num;
288 }
289 6 gate_real32_t gate_math_abs_r32(gate_real32_t num)
290 {
291
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 return num < 0.0f ? -num : num;
292 }
293 7 gate_real64_t gate_math_abs_r64(gate_real64_t num)
294 {
295
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 return num < 0.0 ? -num : num;
296 }
297
298 #define gate_math_min_type(type, va_type, count) \
299 type ret = 0; \
300 type tmp; \
301 va_list vl; \
302 if(count != 0) \
303 { \
304 va_start(vl, count); \
305 ret = (type)va_arg(vl, va_type); \
306 while(--count) \
307 { \
308 tmp = (type)va_arg(vl, va_type); \
309 if(tmp < ret) \
310 { \
311 ret = tmp; \
312 } \
313 } \
314 va_end(vl); \
315 } \
316 return ret
317
318 #define gate_math_max_type(type, va_type, count) \
319 type ret = 0; \
320 type tmp; \
321 va_list vl; \
322 if(count != 0) \
323 { \
324 va_start(vl, count); \
325 ret = (type)va_arg(vl, va_type); \
326 while(--count) \
327 { \
328 tmp = (type)va_arg(vl, va_type); \
329 if(tmp > ret) \
330 { \
331 ret = tmp; \
332 } \
333 } \
334 va_end(vl); \
335 } \
336 return ret
337
338
339 1 gate_int16_t gate_math_min_i16(gate_size_t count, ...)
340 {
341
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_min_type(gate_int16_t, int, count);
342 }
343 1 gate_int32_t gate_math_min_i32(gate_size_t count, ...)
344 {
345
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_min_type(gate_int32_t, gate_int32_t, count);
346 }
347 1 gate_int64_t gate_math_min_i64(gate_size_t count, ...)
348 {
349
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_min_type(gate_int64_t, gate_int64_t, count);
350 }
351 1 gate_real32_t gate_math_min_r32(gate_size_t count, ...)
352 {
353
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_min_type(gate_real32_t, gate_real64_t, count);
354 }
355 1 gate_real64_t gate_math_min_r64(gate_size_t count, ...)
356 {
357
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_min_type(gate_real64_t, gate_real64_t, count);
358 }
359
360 1 gate_int16_t gate_math_max_i16(gate_size_t count, ...)
361 {
362
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_max_type(gate_int16_t, int, count);
363 }
364 1 gate_int32_t gate_math_max_i32(gate_size_t count, ...)
365 {
366
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_max_type(gate_int32_t, gate_int32_t, count);
367 }
368 1 gate_int64_t gate_math_max_i64(gate_size_t count, ...)
369 {
370
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_max_type(gate_int64_t, gate_int64_t, count);
371 }
372 1 gate_real32_t gate_math_max_r32(gate_size_t count, ...)
373 {
374
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_max_type(gate_real32_t, gate_real64_t, count);
375 }
376 1 gate_real64_t gate_math_max_r64(gate_size_t count, ...)
377 {
378
5/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
3 gate_math_max_type(gate_real64_t, gate_real64_t, count);
379 }
380 3 gate_uint8_t gate_math_decimal_length(gate_real64_t value)
381 {
382 3 gate_uint8_t len = 0;
383 3 gate_real64_t factor = 1.0;
384 gate_real64_t test_value;
385 gate_real64_t diff;
386
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (value < 0.0)
388 {
389 value = -value;
390 }
391
392
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 while (len < 20)
393 {
394 15 test_value = value * factor;
395 15 diff = (test_value - ((gate_real64_t)(gate_int64_t)test_value));
396
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 12 times.
15 if (gate_math_iszero(diff))
397 {
398 3 break;
399 }
400 12 factor *= 10.0;
401 12 ++len;
402 }
403 3 return len;
404 }
405
406 19 gate_real64_t gate_math_deg2rad(gate_real64_t value)
407 {
408 19 return value * GATE_MATH_CONST_PI / 180.0;
409 }
410 7 gate_real64_t gate_math_rad2deg(gate_real64_t value)
411 {
412 7 return value * 180.0 / GATE_MATH_CONST_PI;
413 }
414
415 gate_int64_t gate_math_pow_i64(gate_int64_t base, gate_uint16_t exp)
416 {
417 gate_uint8_t n;
418 gate_int64_t ret = 1;
419 for (n = 0; n != exp; ++n)
420 {
421 ret *= base;
422 }
423 return ret;
424 }
425
426 gate_real64_t gate_math_pow_iexp(gate_real64_t base, gate_uint16_t exp)
427 {
428 gate_uint16_t n;
429 gate_real64_t ret = 1.0;
430 for (n = 0; n != exp; ++n)
431 {
432 ret *= base;
433 }
434 return ret;
435 }
436
437 5 gate_real64_t gate_math_acosh(gate_real64_t value)
438 {
439 5 return gate_math_log(value + gate_math_sqrt(value * value - 1.0));
440 }
441 6 gate_real64_t gate_math_asinh(gate_real64_t value)
442 {
443 6 return gate_math_log(value + gate_math_sqrt(value * value + 1.0));
444 }
445 6 gate_real64_t gate_math_atanh(gate_real64_t value)
446 {
447 6 return gate_math_log((1.0 + value) / (1.0 - value)) / 2.0;
448 }
449
450
451
452
453
454
455
456 #if defined(GATE_CORE_MATH_STD_IMPL)
457
458 #include <math.h>
459
460 45 gate_real64_t gate_math_cos(gate_real64_t value)
461 {
462 45 return cos(value);
463 }
464 9 gate_real64_t gate_math_sin(gate_real64_t value)
465 {
466 9 return sin(value);
467 }
468 7 gate_real64_t gate_math_tan(gate_real64_t value)
469 {
470 7 return tan(value);
471 }
472 6 gate_real64_t gate_math_acos(gate_real64_t value)
473 {
474 6 return acos(value);
475 }
476 9 gate_real64_t gate_math_asin(gate_real64_t value)
477 {
478 9 return asin(value);
479 }
480 10 gate_real64_t gate_math_atan(gate_real64_t value)
481 {
482 10 return atan(value);
483 }
484 2 gate_real64_t gate_math_atan2(gate_real64_t y, gate_real64_t x)
485 {
486 2 return atan2(y, x);
487 }
488 6 gate_real64_t gate_math_cosh(gate_real64_t value)
489 {
490 6 return cosh(value);
491 }
492 6 gate_real64_t gate_math_sinh(gate_real64_t value)
493 {
494 6 return sinh(value);
495 }
496 6 gate_real64_t gate_math_tanh(gate_real64_t value)
497 {
498 6 return tanh(value);
499 }
500
501 7 gate_real64_t gate_math_exp(gate_real64_t value)
502 {
503 7 return exp(value);
504 }
505 2 gate_real64_t gate_math_frexp(gate_real64_t value, int* exp)
506 {
507 2 return frexp(value, exp);
508 }
509 gate_real64_t gate_math_ldexp(gate_real64_t value, int exp)
510 {
511 return ldexp(value, exp);
512 }
513 23 gate_real64_t gate_math_log(gate_real64_t value)
514 {
515 23 return log(value);
516 }
517 6 gate_real64_t gate_math_log10(gate_real64_t value)
518 {
519 6 return log10(value);
520 }
521 2 gate_real64_t gate_math_modf(gate_real64_t value, double* intpart)
522 {
523 2 return modf(value, intpart);
524 }
525
526 2 gate_real64_t gate_math_pow(gate_real64_t base, gate_real64_t exp)
527 {
528 2 return pow(base, exp);
529 }
530 21 gate_real64_t gate_math_sqrt(gate_real64_t value)
531 {
532 21 return sqrt(value);
533 }
534
535 7 gate_real64_t gate_math_ceil(gate_real64_t value)
536 {
537 7 return ceil(value);
538 }
539 7 gate_real64_t gate_math_floor(gate_real64_t value)
540 {
541 7 return floor(value);
542 }
543
544
545 #endif /* GATE_CORE_MATH_STD_IMPL */
546
547
548
549 #if defined(GATE_CORE_MATH_EFI_IMPL)
550
551 static gate_real64_t normalize_angle(gate_real64_t angle)
552 {
553 while (angle <= -GATE_MATH_CONST_PI)
554 {
555 angle += GATE_MATH_CONST_PI;
556 }
557 while (angle > GATE_MATH_CONST_PI)
558 {
559 angle -= GATE_MATH_CONST_PI;
560 }
561 return angle;
562 }
563
564 gate_real64_t gate_math_cos(gate_real64_t value)
565 {
566 static gate_real64_t const n2 = 2.0;
567 static gate_real64_t const n4 = 24.0;
568 static gate_real64_t const n6 = 720.0;
569 static gate_real64_t const n8 = 40320.0;
570 static gate_real64_t const n10 = 3628800.0;
571 static gate_real64_t const n12 = 479001600.0;
572 gate_real64_t const x = normalize_angle(value);
573 gate_real64_t const x2 = x * x;
574 gate_real64_t const x4 = x2 * x * x;
575 gate_real64_t const x6 = x4 * x * x;
576 gate_real64_t const x8 = x6 * x * x;
577 gate_real64_t const x10 = x8 * x * x;
578 gate_real64_t const x12 = x10 * x * x;
579
580 return 1 - x2 / n2 + x4 / n4 - x6 / n6 + x8 / n8 - x10 / n10 + x12 / n12;
581 }
582
583
584
585 gate_real64_t gate_math_sin(gate_real64_t value)
586 {
587 static gate_real64_t const n3 = 6.0;
588 static gate_real64_t const n5 = 120.0;
589 static gate_real64_t const n7 = 5040.0;
590 static gate_real64_t const n9 = 362880.0;
591 static gate_real64_t const n11 = 39916800.0;
592 static gate_real64_t const n13 = 6227020800.0;
593 gate_real64_t const x = normalize_angle(value);
594 gate_real64_t const x3 = x * x * x;
595 gate_real64_t const x5 = x3 * x * x;
596 gate_real64_t const x7 = x5 * x * x;
597 gate_real64_t const x9 = x7 * x * x;
598 gate_real64_t const x11 = x9 * x * x;
599 gate_real64_t const x13 = x11 * x * x;
600
601 return x - x3 / n3 + x5 / n5 - x7 / n7 + x9 / n9 - x11 / n11 + x13 / n13;
602 }
603 gate_real64_t gate_math_tan(gate_real64_t value)
604 {
605 return gate_math_sin(value) / gate_math_cos(value);
606 }
607
608 gate_real64_t gate_math_asin(gate_real64_t value)
609 {
610 /* https://de.wikipedia.org/wiki/Arkussinus_und_Arkuskosinus#Reihenentwicklungen */
611
612 static double const ret_0_96 = 1.2870022176;
613 /*static double const ret_1_00 = GATE_MATH_CONST_PI * 0.5;*/
614 static double const diff_1_00 = GATE_MATH_CONST_PI * 0.5 - 1.2870022176;
615
616 static unsigned const n_max = 107; /* quite OK up to 0.96 */
617 double factor;
618 unsigned n;
619
620 double x = value;
621 double ret = x;
622 double a = 1;
623 double b = 1;
624
625 if (value > 0.96)
626 {
627 /* iterative solution becomes unstable for value > 0.96
628 just apply a quick and dirty linear patch */
629 factor = (value - 0.96) / (1.00 - 0.96);
630 ret = ret_0_96 + diff_1_00 * factor;
631 }
632 else
633 {
634 for (n = 3; n != n_max; n += 2)
635 {
636 x *= value * value;
637 a *= ((double)n - 2.0);
638 b *= ((double)n - 1.0);
639 ret += a * x / (b * (double)n);
640 }
641 }
642
643 return ret;
644 }
645 gate_real64_t gate_math_acos(gate_real64_t value)
646 {
647 /* https://stackoverflow.com/questions/3380628/fast-arc-cos-algorithm/20914630 */
648 /* return (-0.69813170079773212 * value * value - 0.87266462599716477) * value + 1.5707963267948966; */
649 return GATE_MATH_CONST_PI * 0.5 - gate_math_asin(value);
650 }
651 gate_real64_t gate_math_atan(gate_real64_t value)
652 {
653 gate_real64_t ret;
654 ret = gate_math_asin(value / gate_math_sqrt(1 + value * value));
655 return ret;
656 }
657 gate_real64_t gate_math_atan2(gate_real64_t y, gate_real64_t x)
658 {
659 /* TODO */
660 return 0.0;
661 }
662 gate_real64_t gate_math_sinh(gate_real64_t value)
663 {
664 return 0.5 * (gate_math_exp(value) - gate_math_exp(-value));
665 }
666 gate_real64_t gate_math_cosh(gate_real64_t value)
667 {
668 return 0.5 * (gate_math_exp(value) + gate_math_exp(-value));
669 }
670 gate_real64_t gate_math_tanh(gate_real64_t value)
671 {
672 return gate_math_sinh(value) / gate_math_cosh(value);
673 }
674
675 gate_real64_t gate_math_exp(gate_real64_t value)
676 {
677 /* https://www.pseudorandom.com/implementing-exp */
678 gate_real64_t x0, tn;
679 gate_int64_t i, n;
680
681 if (gate_math_iszero(value))
682 {
683 return 1.0;
684 }
685 x0 = gate_math_abs_r64(value);
686 tn = 1.0;
687 n = 12;
688 n *= (gate_int64_t)gate_math_ceil(x0 * GATE_MATH_CONST_E);
689 for (i = n; i > 0; i--)
690 {
691 tn = tn * (x0 / i) + 1.0;
692 }
693
694 if (value < 0.0)
695 {
696 tn = 1.0 / tn;
697 }
698 return tn;
699 }
700 gate_real64_t gate_math_frexp(gate_real64_t value, int* exp)
701 {
702 /* TODO */
703 return 0.0;
704 }
705 gate_real64_t gate_math_ldexp(gate_real64_t value, int exp)
706 {
707 /* TODO */
708 return 0.0;
709 }
710
711 static unsigned msb(unsigned v)
712 {
713 unsigned ret = 0;
714 while (v >>= 1)
715 {
716 ret++;
717 }
718 return ret;
719 }
720
721 static float log_n(float value)
722 {
723 /* https://stackoverflow.com/questions/9799041/efficient-implementation-of-natural-logarithm-ln-and-exponentiation */
724 int log2;
725 float divisor, x, result;
726
727 log2 = msb((int)value); // See: https://stackoverflow.com/a/4970859/6630230
728 divisor = (float)(1 << log2);
729 x = value / divisor;
730 result = -1.7417939f + (2.8212026f + (-1.4699568f + (0.44717955f - 0.056570851f * x) * x) * x) * x;
731 result += ((float)log2) * 0.69314718f;
732
733 return result;
734 }
735
736
737 gate_real64_t gate_math_log(gate_real64_t value)
738 {
739 return (gate_real64_t)log_n((float)value);
740 }
741 gate_real64_t gate_math_log10(gate_real64_t value)
742 {
743 return gate_math_log(value) / gate_math_log(10.0);
744 }
745 gate_real64_t gate_math_modf(gate_real64_t value, gate_real64_t* intpart)
746 {
747 gate_real64_t ret;
748 gate_uint64_t ui;
749 if (value < 0.0)
750 {
751 ui = (gate_uint64_t)-value;
752 ret = -value - (gate_real64_t)ui;
753 if (intpart)
754 {
755 *intpart = -((gate_real64_t)ui);
756 }
757 }
758 else
759 {
760 ui = (gate_uint64_t)value;
761 ret = value - (gate_real64_t)ui;
762 if (intpart)
763 {
764 *intpart = (gate_real64_t)ui;
765 }
766 }
767 return ret;
768 }
769
770 gate_real64_t gate_math_pow(gate_real64_t base, gate_real64_t exp)
771 {
772 if (exp < 0.0)
773 {
774 return 1.0 / gate_math_pow_iexp(base, (gate_uint16_t)-exp);
775 }
776 else
777 {
778 return gate_math_pow_iexp(base, (gate_uint16_t)exp);
779 }
780 return 0.0;
781 }
782
783 union f_rsqrt_helper
784 {
785 float f;
786 gate_uint32_t i;
787 };
788
789
790 union d_rsqrt_helper
791 {
792 double d;
793 gate_uint64_t i;
794 };
795
796 /* https://en.wikipedia.org/wiki/Fast_inverse_square_root */
797 /* https://stackoverflow.com/questions/11644441/fast-inverse-square-root-on-x64/11644533 */
798 static float f_rsqrt(float number)
799 {
800 static const float threehalfs = 1.5F;
801 const float x2 = number * 0.5F;
802
803 union f_rsqrt_helper conv;
804 conv.f = number;
805 conv.i = 0x5f3759df - (conv.i >> 1);
806 conv.f *= threehalfs - (x2 * conv.f * conv.f);
807 return conv.f;
808 }
809
810 static double d_rsqrt(double number)
811 {
812 double y = number;
813 double x2 = y * 0.5;
814
815 union d_rsqrt_helper conv;
816 conv.d = y;
817 conv.i = 0x5fe6eb50c7b537a9 - (conv.i >> 1);
818 y = conv.d;
819 y = y * (1.5 - (x2 * y * y));
820 y = y * (1.5 - (x2 * y * y));
821 return y;
822 }
823
824
825 gate_real64_t gate_math_sqrt(gate_real64_t value)
826 {
827 double num = gate_math_abs_r64((double)value);
828 return (gate_real64_t)(1.0 / d_rsqrt(num));
829 }
830
831 gate_real64_t gate_math_ceil(gate_real64_t value)
832 {
833 gate_int64_t i = (gate_int64_t)value;
834 gate_real64_t diff = value - (gate_real64_t)i;
835 if (!gate_math_iszero(diff))
836 {
837 if (value >= 0.0)
838 {
839 i = (gate_int64_t)(value + 1.0);
840 }
841 else
842 {
843 i = -(gate_int64_t)(-value);
844 }
845 }
846 return (gate_real64_t)i;
847 }
848 gate_real64_t gate_math_floor(gate_real64_t value)
849 {
850 gate_int64_t i = (gate_int64_t)value;
851 gate_real64_t diff = value - (gate_real64_t)i;
852 if (!gate_math_iszero(diff))
853 {
854 if (value >= 0.0)
855 {
856 i = (gate_int64_t)(value);
857 }
858 else
859 {
860 i = -(gate_int64_t)(-value + 1.0);
861 }
862 }
863 return (gate_real64_t)i;
864 }
865
866 #endif /* GATE_CORE_MATH_EFI_IMPL */
867
868