diff --git a/lib/c/math.zig b/lib/c/math.zig index 5b191c3e93..8fe93716db 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -60,6 +60,7 @@ comptime { symbol(&exp10, "exp10"); symbol(&exp10f, "exp10f"); symbol(&fdim, "fdim"); + symbol(&frexp, "frexp"); symbol(&hypot, "hypot"); symbol(&modf, "modf"); symbol(&pow, "pow"); @@ -161,6 +162,25 @@ fn fdim(x: f64, y: f64) callconv(.c) f64 { return 0; } +fn frexp(x: f64, e: *c_int) callconv(.c) f64 { + // libc expects `*e` to be unspecified in this case; an unspecified C value + // should be a valid value of the relevant type, yet Zig's std + // implementation sets it to `undefined` -- which can even be nonsense + // according to the type (int). Therefore, we're setting it to a valid + // int value in Zig -- a zero. + // + // This mirrors the handling of infinities, where libc also expects + // unspecified for the value `*e` and Zig std sets it to a zero. + if (math.isNan(x)) { + e.* = 0; + return x; + } + + const r = math.frexp(x); + e.* = r.exponent; + return r.significand; +} + fn hypot(x: f64, y: f64) callconv(.c) f64 { return math.hypot(x, y); } diff --git a/lib/libc/musl/src/math/frexp.c b/lib/libc/musl/src/math/frexp.c deleted file mode 100644 index 27b6266ed0..0000000000 --- a/lib/libc/musl/src/math/frexp.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -double frexp(double x, int *e) -{ - union { double d; uint64_t i; } y = { x }; - int ee = y.i>>52 & 0x7ff; - - if (!ee) { - if (x) { - x = frexp(x*0x1p64, e); - *e -= 64; - } else *e = 0; - return x; - } else if (ee == 0x7ff) { - return x; - } - - *e = ee - 0x3fe; - y.i &= 0x800fffffffffffffull; - y.i |= 0x3fe0000000000000ull; - return y.d; -} diff --git a/src/libs/musl.zig b/src/libs/musl.zig index a3806437d7..e90a08f92c 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -839,7 +839,6 @@ const src_files = [_][]const u8{ "musl/src/math/__fpclassify.c", "musl/src/math/__fpclassifyf.c", "musl/src/math/__fpclassifyl.c", - "musl/src/math/frexp.c", "musl/src/math/frexpf.c", "musl/src/math/frexpl.c", "musl/src/math/i386/acosl.s", diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig index aaf8968060..d694a0381e 100644 --- a/src/libs/wasi_libc.zig +++ b/src/libs/wasi_libc.zig @@ -701,7 +701,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/finitef.c", "musl/src/math/fma.c", "musl/src/math/fmaf.c", - "musl/src/math/frexp.c", "musl/src/math/frexpf.c", "musl/src/math/frexpl.c", "musl/src/math/ilogb.c",