From f3afec61bb4127439701adbc99ccbf18c13dd08e Mon Sep 17 00:00:00 2001 From: Adversing Date: Thu, 23 Jan 2025 04:34:27 +0100 Subject: [PATCH] Added fmodf function #1875 --- lib/std/math/math_nolibc/__fmod.c3 | 78 +++++++++++++++++++++++++++++- releasenotes.md | 1 + 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/lib/std/math/math_nolibc/__fmod.c3 b/lib/std/math/math_nolibc/__fmod.c3 index 1bc304b31..432bd0cf9 100644 --- a/lib/std/math/math_nolibc/__fmod.c3 +++ b/lib/std/math/math_nolibc/__fmod.c3 @@ -6,6 +6,12 @@ union DoubleInternal ulong i; } +union FloatInternal +{ + float f; + uint i; +} + // Based on the musl implementation fn double fmod(double x, double y) @extern("fmod") @weak @nostrip { @@ -75,4 +81,74 @@ fn double fmod(double x, double y) @extern("fmod") @weak @nostrip uxi |= (ulong)sx << 63; ux.i = uxi; return ux.f; -} \ No newline at end of file +} + +fn float fmodf(float x, float y) @extern("fmodf") @weak @nostrip +{ + FloatInternal ux = { .f = x }; + FloatInternal uy = { .f = y }; + int ex = (int)((ux.i >> 23) & 0xff); + int ey = (int)((uy.i >> 23) & 0xff); + int sx = (int)(ux.i >> 31); + uint uxi = ux.i; + if (uy.i << 1 == 0 || math::is_nan(y) || ex == 0xff) return (x * y)/(x * y); + if (uxi << 1 <= uy.i << 1) + { + if (uxi << 1 == uy.i << 1) return 0 * x; + return x; + } + + if (!ex) + { + for (uint i = uxi << 9; i >> 31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } + else + { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) + { + for (uint i = uy.i << 9; i >> 31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } + else + { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; + } + + /* x mod y */ + for (; ex > ey; ex--) + { + uint i = uxi - uy.i; + if (i >> 31 == 0) + { + if (i == 0) return 0 * x; + uxi = i; + } + uxi <<= 1; + } + uint i = uxi - uy.i; + if (i >> 31 == 0) + { + if (i == 0) return 0*x; + uxi = i; + } + for (; uxi>>23 == 0; uxi <<= 1, ex--); + + /* scale result */ + if (ex > 0) + { + uxi -= 1U << 23; + uxi |= (uint)ex << 23; + } + else + { + uxi >>= -ex + 1; + } + uxi |= (uint)sx << 31; + ux.i = uxi; + return ux.f; +} diff --git a/releasenotes.md b/releasenotes.md index bb3e78e7c..1c20b63ce 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -45,6 +45,7 @@ - Added channels for threads. - New `std::core::test` module for unit testing machinery. - New unit test default runner. +- Added weakly linked `fmodf`. ## 0.6.6 Change list