diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-05-24 16:48:22 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-05-25 21:57:14 +0200 |
commit | 31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch) | |
tree | 16e789c7d68608831b498f41f54d9482b82a711a /source/math.c |
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'source/math.c')
-rw-r--r-- | source/math.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/source/math.c b/source/math.c new file mode 100644 index 0000000..c8eafee --- /dev/null +++ b/source/math.c @@ -0,0 +1,135 @@ +#include "compat.h" +#include "math.h" + + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + asm volatile ("int $0"); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} + +/* slightly modified version from + * https://code.google.com/p/embox/source/browse/trunk/embox/src/lib/gcc + * _thx_ + */ + +UINT64 __udivdi3(UINT64 num, UINT64 den) +{ + UINT64 result = 0; + int steps; + + if (den == 0) + { + return 0; + } + + steps = 0; + result = 0; + + while (!(den & 0x8000000000000000)) + { + den <<= 1; + ++steps; + } + + do + { + result <<= 1; + if (num >= den) + { + result |= 1; + num -= den; + } + den >>= 1; + } + while (steps--); + + return result; +} + +INT64 __divdi3(INT64 num, INT64 den) +{ + INT64 quot; + int neg; + + num = num < 0 ? (neg = 1, -num) : (neg = 0, num); + den = den < 0 ? (neg ^= 1, -den) : den; + + quot = __udivdi3(num, den); + + return neg ? -quot : quot; +} + +INT64 __moddi3(INT64 num, INT64 den) +{ + INT64 rem; + int neg; + + num = num < 0 ? (neg = 1, -num) : (neg = 0, num); + den = den < 0 ? (neg ^= 1, -den) : den; + + rem = __umoddi3(num, den); + + return neg ? -rem : rem; +} + +UINT64 __umoddi3(UINT64 num, UINT64 den) +{ + int steps; + + if (den == 0) + { + return 0; + } + + steps = 0; + + while (!(den & 0x8000000000000000)) + { + den <<= 1; + ++steps; + } + + do + { + if (num >= den) + { + num -= den; + } + den >>= 1; + } + while (steps--); + + return num; +} + +size_t __pow(size_t x, size_t n) +{ + if (n > 0) { + return x*__pow(x, n-1); + } else return 1; +} |