GCC Code Coverage Report


Directory: src/gate/
File: src/gate/mathematics.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 135 211 64.0%
Functions: 55 75 73.3%
Branches: 86 112 76.8%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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 470 gate_bool_t gate_math_iszero(gate_real64_t num)
160 {
161
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 450 times.
470 if (num < 0.0)
162 {
163 20 return (-num < DBL_EPSILON) ? true : false;
164 }
165 else
166 {
167 450 return (num < DBL_EPSILON) ? true : false;
168 }
169 }
170 2214 gate_bool_t gate_math_iszerof(gate_real32_t num)
171 {
172
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2210 times.
2214 if (num < 0.0f)
173 {
174 4 return (-num < FLT_EPSILON) ? true : false;
175 }
176 else
177 {
178 2210 return (num < FLT_EPSILON) ? true : false;
179 }
180 }
181
182 360 gate_bool_t gate_math_isnan(gate_real64_t num)
183 {
184 360 volatile gate_real64_t tmp = num;
185 360 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 360 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 359 times.
360 if (num > DBL_MAX)
197 {
198 1 return 1;
199 }
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
359 else if (num < -DBL_MAX)
201 {
202 return -1;
203 }
204 359 return 0;
205 #else
206 #define gate_math_infinite_pos (1.0 / 0.0)
207 #define 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 819 gate_int16_t gate_math_abs_i16(gate_int16_t num)
278 {
279 819 return num < 0 ? -num : num;
280 }
281 166 gate_int32_t gate_math_abs_i32(gate_int32_t num)
282 {
283 166 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 273 gate_int16_t gate_math_max_i16(gate_size_t count, ...)
361 {
362
5/6
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 304 times.
✓ Branch 6 taken 546 times.
✓ Branch 7 taken 273 times.
819 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 7 gate_uint8_t gate_math_decimal_length(gate_real64_t value)
381 {
382 7 gate_uint8_t len = 0;
383 7 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 7 times.
7 if (value < 0.0)
388 {
389 value = -value;
390 }
391
392
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 while (len < 20)
393 {
394 30 test_value = value * factor;
395 30 diff = (test_value - ((gate_real64_t)(gate_int64_t)test_value));
396
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 23 times.
30 if (gate_math_iszero(diff))
397 {
398 7 break;
399 }
400 23 factor *= 10.0;
401 23 ++len;
402 }
403 7 return len;
404 }
405
406 21 gate_real64_t gate_math_deg2rad(gate_real64_t value)
407 {
408 21 return value * GATE_MATH_CONST_PI / 180.0;
409 }
410 11 gate_real64_t gate_math_rad2deg(gate_real64_t value)
411 {
412 11 return value * 180.0 / GATE_MATH_CONST_PI;
413 }
414
415 1 gate_int64_t gate_math_pow_i64(gate_int64_t base, gate_uint16_t exp)
416 {
417 gate_uint8_t n;
418 1 gate_int64_t ret = 1;
419
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 1 times.
20 for (n = 0; n != exp; ++n)
420 {
421 19 ret *= base;
422 }
423 1 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 40 gate_real64_t gate_math_cos(gate_real64_t value)
461 {
462 40 return cos(value);
463 }
464 9 gate_real64_t gate_math_sin(gate_real64_t value)
465 {
466 9 return sin(value);
467 }
468 9 gate_real64_t gate_math_tan(gate_real64_t value)
469 {
470 9 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 12 gate_real64_t gate_math_atan(gate_real64_t value)
481 {
482 12 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 9 gate_real64_t gate_math_exp(gate_real64_t value)
502 {
503 9 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 24 gate_real64_t gate_math_log(gate_real64_t value)
514 {
515 24 return log(value);
516 }
517 2 gate_real64_t gate_math_log2(gate_real64_t value)
518 {
519 static const gate_real64_t log2inverse = 1.4426950408889634;
520 2 return log(value) * log2inverse;
521 }
522 6 gate_real64_t gate_math_log10(gate_real64_t value)
523 {
524 6 return log10(value);
525 }
526 2 gate_real64_t gate_math_modf(gate_real64_t value, double* intpart)
527 {
528 2 return modf(value, intpart);
529 }
530
531 2 gate_real64_t gate_math_pow(gate_real64_t base, gate_real64_t exp)
532 {
533 2 return pow(base, exp);
534 }
535 21 gate_real64_t gate_math_sqrt(gate_real64_t value)
536 {
537 21 return sqrt(value);
538 }
539
540 7 gate_real64_t gate_math_ceil(gate_real64_t value)
541 {
542 7 return ceil(value);
543 }
544 9 gate_real64_t gate_math_floor(gate_real64_t value)
545 {
546 9 return floor(value);
547 }
548
549
550 #endif /* GATE_CORE_MATH_STD_IMPL */
551
552
553
554 #if defined(GATE_CORE_MATH_EFI_IMPL)
555
556 static gate_real64_t normalize_angle(gate_real64_t angle)
557 {
558 while (angle <= -GATE_MATH_CONST_PI)
559 {
560 angle += GATE_MATH_CONST_PI;
561 }
562 while (angle > GATE_MATH_CONST_PI)
563 {
564 angle -= GATE_MATH_CONST_PI;
565 }
566 return angle;
567 }
568
569 gate_real64_t gate_math_cos(gate_real64_t value)
570 {
571 static gate_real64_t const n2 = 2.0;
572 static gate_real64_t const n4 = 24.0;
573 static gate_real64_t const n6 = 720.0;
574 static gate_real64_t const n8 = 40320.0;
575 static gate_real64_t const n10 = 3628800.0;
576 static gate_real64_t const n12 = 479001600.0;
577 gate_real64_t const x = normalize_angle(value);
578 gate_real64_t const x2 = x * x;
579 gate_real64_t const x4 = x2 * x * x;
580 gate_real64_t const x6 = x4 * x * x;
581 gate_real64_t const x8 = x6 * x * x;
582 gate_real64_t const x10 = x8 * x * x;
583 gate_real64_t const x12 = x10 * x * x;
584
585 return 1 - x2 / n2 + x4 / n4 - x6 / n6 + x8 / n8 - x10 / n10 + x12 / n12;
586 }
587
588
589
590 gate_real64_t gate_math_sin(gate_real64_t value)
591 {
592 static gate_real64_t const n3 = 6.0;
593 static gate_real64_t const n5 = 120.0;
594 static gate_real64_t const n7 = 5040.0;
595 static gate_real64_t const n9 = 362880.0;
596 static gate_real64_t const n11 = 39916800.0;
597 static gate_real64_t const n13 = 6227020800.0;
598 gate_real64_t const x = normalize_angle(value);
599 gate_real64_t const x3 = x * x * x;
600 gate_real64_t const x5 = x3 * x * x;
601 gate_real64_t const x7 = x5 * x * x;
602 gate_real64_t const x9 = x7 * x * x;
603 gate_real64_t const x11 = x9 * x * x;
604 gate_real64_t const x13 = x11 * x * x;
605
606 return x - x3 / n3 + x5 / n5 - x7 / n7 + x9 / n9 - x11 / n11 + x13 / n13;
607 }
608 gate_real64_t gate_math_tan(gate_real64_t value)
609 {
610 return gate_math_sin(value) / gate_math_cos(value);
611 }
612
613 gate_real64_t gate_math_asin(gate_real64_t value)
614 {
615 /* https://de.wikipedia.org/wiki/Arkussinus_und_Arkuskosinus#Reihenentwicklungen */
616
617 static double const ret_0_96 = 1.2870022176;
618 /*static double const ret_1_00 = GATE_MATH_CONST_PI * 0.5;*/
619 static double const diff_1_00 = GATE_MATH_CONST_PI * 0.5 - 1.2870022176;
620 double ret = value;
621
622 if (value > 0.96)
623 {
624 /* iterative solution becomes unstable for value > 0.96
625 just apply a quick and dirty linear patch */
626 double factor = (value - 0.96) / (1.00 - 0.96);
627 ret = ret_0_96 + diff_1_00 * factor;
628 }
629 else
630 {
631 static unsigned const n_max = 107; /* quite OK up to 0.96 */
632 unsigned n;
633 double x = value;
634 double a = 1;
635 double b = 1;
636 for (n = 3; n != n_max; n += 2)
637 {
638 x *= value * value;
639 a *= ((double)n - 2.0);
640 b *= ((double)n - 1.0);
641 ret += a * x / (b * (double)n);
642 }
643 }
644
645 return ret;
646 }
647 gate_real64_t gate_math_acos(gate_real64_t value)
648 {
649 /* https://stackoverflow.com/questions/3380628/fast-arc-cos-algorithm/20914630 */
650 /* return (-0.69813170079773212 * value * value - 0.87266462599716477) * value + 1.5707963267948966; */
651 return GATE_MATH_CONST_PI * 0.5 - gate_math_asin(value);
652 }
653 gate_real64_t gate_math_atan(gate_real64_t value)
654 {
655 gate_real64_t ret;
656 ret = gate_math_asin(value / gate_math_sqrt(1 + value * value));
657 return ret;
658 }
659 gate_real64_t gate_math_atan2(gate_real64_t y, gate_real64_t x)
660 {
661 /* TODO */
662 return 0.0;
663 }
664 gate_real64_t gate_math_sinh(gate_real64_t value)
665 {
666 return 0.5 * (gate_math_exp(value) - gate_math_exp(-value));
667 }
668 gate_real64_t gate_math_cosh(gate_real64_t value)
669 {
670 return 0.5 * (gate_math_exp(value) + gate_math_exp(-value));
671 }
672 gate_real64_t gate_math_tanh(gate_real64_t value)
673 {
674 return gate_math_sinh(value) / gate_math_cosh(value);
675 }
676
677 gate_real64_t gate_math_exp(gate_real64_t value)
678 {
679 /* https://www.pseudorandom.com/implementing-exp */
680 gate_real64_t x0, tn;
681 gate_int64_t i, n;
682
683 if (gate_math_iszero(value))
684 {
685 return 1.0;
686 }
687 x0 = gate_math_abs_r64(value);
688 tn = 1.0;
689 n = 12;
690 n *= (gate_int64_t)gate_math_ceil(x0 * GATE_MATH_CONST_E);
691 for (i = n; i > 0; i--)
692 {
693 tn = tn * (x0 / i) + 1.0;
694 }
695
696 if (value < 0.0)
697 {
698 tn = 1.0 / tn;
699 }
700 return tn;
701 }
702 gate_real64_t gate_math_frexp(gate_real64_t value, int* exp)
703 {
704 /* TODO */
705 return 0.0;
706 }
707 gate_real64_t gate_math_ldexp(gate_real64_t value, int exp)
708 {
709 /* TODO */
710 return 0.0;
711 }
712
713 static unsigned msb(unsigned v)
714 {
715 unsigned ret = 0;
716 while (v >>= 1)
717 {
718 ret++;
719 }
720 return ret;
721 }
722
723 static float log_n(float value)
724 {
725 /* https://stackoverflow.com/questions/9799041/efficient-implementation-of-natural-logarithm-ln-and-exponentiation */
726 int log2;
727 float divisor, x, result;
728
729 log2 = msb((int)value); // See: https://stackoverflow.com/a/4970859/6630230
730 divisor = (float)(1 << log2);
731 x = value / divisor;
732 result = -1.7417939f + (2.8212026f + (-1.4699568f + (0.44717955f - 0.056570851f * x) * x) * x) * x;
733 result += ((float)log2) * 0.69314718f;
734
735 return result;
736 }
737
738
739 gate_real64_t gate_math_log(gate_real64_t value)
740 {
741 return (gate_real64_t)log_n((float)value);
742 }
743 gate_real64_t gate_math_log10(gate_real64_t value)
744 {
745 return gate_math_log(value) / gate_math_log(10.0);
746 }
747 gate_real64_t gate_math_modf(gate_real64_t value, gate_real64_t* intpart)
748 {
749 gate_real64_t ret;
750 gate_uint64_t ui;
751 if (value < 0.0)
752 {
753 ui = (gate_uint64_t)-value;
754 ret = -value - (gate_real64_t)ui;
755 if (intpart)
756 {
757 *intpart = -((gate_real64_t)ui);
758 }
759 }
760 else
761 {
762 ui = (gate_uint64_t)value;
763 ret = value - (gate_real64_t)ui;
764 if (intpart)
765 {
766 *intpart = (gate_real64_t)ui;
767 }
768 }
769 return ret;
770 }
771
772 gate_real64_t gate_math_pow(gate_real64_t base, gate_real64_t exp)
773 {
774 if (exp < 0.0)
775 {
776 return 1.0 / gate_math_pow_iexp(base, (gate_uint16_t)-exp);
777 }
778 else
779 {
780 return gate_math_pow_iexp(base, (gate_uint16_t)exp);
781 }
782 return 0.0;
783 }
784
785 union f_rsqrt_helper
786 {
787 float f;
788 gate_uint32_t i;
789 };
790
791
792 union d_rsqrt_helper
793 {
794 double d;
795 gate_uint64_t i;
796 };
797
798 /* https://en.wikipedia.org/wiki/Fast_inverse_square_root */
799 /* https://stackoverflow.com/questions/11644441/fast-inverse-square-root-on-x64/11644533 */
800 static float f_rsqrt(float number)
801 {
802 static const float threehalfs = 1.5F;
803 const float x2 = number * 0.5F;
804
805 union f_rsqrt_helper conv;
806 conv.f = number;
807 conv.i = 0x5f3759df - (conv.i >> 1);
808 conv.f *= threehalfs - (x2 * conv.f * conv.f);
809 return conv.f;
810 }
811
812 static double d_rsqrt(double number)
813 {
814 double y = number;
815 double x2 = y * 0.5;
816
817 union d_rsqrt_helper conv;
818 conv.d = y;
819 conv.i = 0x5fe6eb50c7b537a9 - (conv.i >> 1);
820 y = conv.d;
821 y = y * (1.5 - (x2 * y * y));
822 y = y * (1.5 - (x2 * y * y));
823 return y;
824 }
825
826
827 gate_real64_t gate_math_sqrt(gate_real64_t value)
828 {
829 double num = gate_math_abs_r64((double)value);
830 return (gate_real64_t)(1.0 / d_rsqrt(num));
831 }
832
833 gate_real64_t gate_math_ceil(gate_real64_t value)
834 {
835 gate_int64_t i = (gate_int64_t)value;
836 gate_real64_t diff = value - (gate_real64_t)i;
837 if (!gate_math_iszero(diff))
838 {
839 if (value >= 0.0)
840 {
841 i = (gate_int64_t)(value + 1.0);
842 }
843 else
844 {
845 i = -(gate_int64_t)(-value);
846 }
847 }
848 return (gate_real64_t)i;
849 }
850 gate_real64_t gate_math_floor(gate_real64_t value)
851 {
852 gate_int64_t i = (gate_int64_t)value;
853 gate_real64_t diff = value - (gate_real64_t)i;
854 if (!gate_math_iszero(diff))
855 {
856 if (value >= 0.0)
857 {
858 i = (gate_int64_t)(value);
859 }
860 else
861 {
862 i = -(gate_int64_t)(-value + 1.0);
863 }
864 }
865 return (gate_real64_t)i;
866 }
867
868 #endif /* GATE_CORE_MATH_EFI_IMPL */
869
870