From d0b39c7f2b95522c262a92b97bf5654721ace1c7 Mon Sep 17 00:00:00 2001 From: Pivok Date: Thu, 5 Feb 2026 21:57:32 +0100 Subject: [PATCH] libzigc: hypot (#31104) First time contribution. Implements hypot for libzigc #30978. Commands i run: ``` $ stage3/bin/zig build -p stage4 -Denable-llvm -Dno-lib $ stage4/bin/zig build test-libc -Dlibc-test-path=../../libc-test -Dtest-filter=hypot --summary line -fqemu -fwasmtime Build Summary: 725/737 steps succeeded (12 skipped) ``` I also changed std.math.hypot becuase some libc-tests raised fp exceptions. Example: ``` ../../libc-test/src/math/special/hypot.h:8: bad fp exception: RN hypot(0x1p-1074,0x0p+0)=0x1p-1074, want 0 got INEXACT|UNDERFLOW ../../libc-test/src/math/special/hypot.h:9: bad fp exception: RN hypot(0x1p-1074,-0x0p+0)=0x1p-1074, want 0 got INEXACT|UNDERFLOW ``` I also run this command as a quick sanity check: ``` $ stage4/bin/zig build test-std -Dtest-filter=hypot -Dtest-target-filter=x86_64-linux-musl --summary line Build Summary: 5/5 steps succeeded; 136/136 tests passed ``` Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31104 Reviewed-by: Andrew Kelley Co-authored-by: Pivok Co-committed-by: Pivok --- lib/c/math.zig | 5 +++ lib/libc/musl/src/math/hypot.c | 67 ----------------------------- lib/libc/musl/src/math/i386/hypot.s | 45 ------------------- lib/std/math/hypot.zig | 8 ++-- src/libs/musl.zig | 2 - src/libs/wasi_libc.zig | 1 - 6 files changed, 9 insertions(+), 119 deletions(-) delete mode 100644 lib/libc/musl/src/math/hypot.c delete mode 100644 lib/libc/musl/src/math/i386/hypot.s diff --git a/lib/c/math.zig b/lib/c/math.zig index 8fc7c03228..403e8f9d47 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -41,6 +41,7 @@ comptime { @export(&atanl, .{ .name = "atanl", .linkage = common.linkage, .visibility = common.visibility }); @export(&cbrt, .{ .name = "cbrt", .linkage = common.linkage, .visibility = common.visibility }); @export(&cbrtf, .{ .name = "cbrtf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&hypot, .{ .name = "hypot", .linkage = common.linkage, .visibility = common.visibility }); @export(&pow, .{ .name = "pow", .linkage = common.linkage, .visibility = common.visibility }); } @@ -118,6 +119,10 @@ fn cbrtf(x: f32) callconv(.c) f32 { return math.cbrt(x); } +fn hypot(x: f64, y: f64) callconv(.c) f64 { + return math.hypot(x, y); +} + fn pow(x: f64, y: f64) callconv(.c) f64 { return math.pow(f64, x, y); } diff --git a/lib/libc/musl/src/math/hypot.c b/lib/libc/musl/src/math/hypot.c deleted file mode 100644 index 6071bf1e28..0000000000 --- a/lib/libc/musl/src/math/hypot.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include - -#if FLT_EVAL_METHOD > 1U && LDBL_MANT_DIG == 64 -#define SPLIT (0x1p32 + 1) -#else -#define SPLIT (0x1p27 + 1) -#endif - -static void sq(double_t *hi, double_t *lo, double x) -{ - double_t xh, xl, xc; - - xc = (double_t)x*SPLIT; - xh = x - xc + xc; - xl = x - xh; - *hi = (double_t)x*x; - *lo = xh*xh - *hi + 2*xh*xl + xl*xl; -} - -double hypot(double x, double y) -{ - union {double f; uint64_t i;} ux = {x}, uy = {y}, ut; - int ex, ey; - double_t hx, lx, hy, ly, z; - - /* arrange |x| >= |y| */ - ux.i &= -1ULL>>1; - uy.i &= -1ULL>>1; - if (ux.i < uy.i) { - ut = ux; - ux = uy; - uy = ut; - } - - /* special cases */ - ex = ux.i>>52; - ey = uy.i>>52; - x = ux.f; - y = uy.f; - /* note: hypot(inf,nan) == inf */ - if (ey == 0x7ff) - return y; - if (ex == 0x7ff || uy.i == 0) - return x; - /* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */ - /* 64 difference is enough for ld80 double_t */ - if (ex - ey > 64) - return x + y; - - /* precise sqrt argument in nearest rounding mode without overflow */ - /* xh*xh must not overflow and xl*xl must not underflow in sq */ - z = 1; - if (ex > 0x3ff+510) { - z = 0x1p700; - x *= 0x1p-700; - y *= 0x1p-700; - } else if (ey < 0x3ff-450) { - z = 0x1p-700; - x *= 0x1p700; - y *= 0x1p700; - } - sq(&hx, &lx, x); - sq(&hy, &ly, y); - return z*sqrt(ly+lx+hy+hx); -} diff --git a/lib/libc/musl/src/math/i386/hypot.s b/lib/libc/musl/src/math/i386/hypot.s deleted file mode 100644 index 299c2e186c..0000000000 --- a/lib/libc/musl/src/math/i386/hypot.s +++ /dev/null @@ -1,45 +0,0 @@ -.global hypot -.type hypot,@function -hypot: - mov 8(%esp),%eax - mov 16(%esp),%ecx - add %eax,%eax - add %ecx,%ecx - and %eax,%ecx - cmp $0xffe00000,%ecx - jae 2f - or 4(%esp),%eax - jnz 1f - fldl 12(%esp) - fabs - ret -1: mov 16(%esp),%eax - add %eax,%eax - or 12(%esp),%eax - jnz 1f - fldl 4(%esp) - fabs - ret -1: fldl 4(%esp) - fld %st(0) - fmulp - fldl 12(%esp) - fld %st(0) - fmulp - faddp - fsqrt - ret -2: sub $0xffe00000,%eax - or 4(%esp),%eax - jnz 1f - fldl 4(%esp) - fabs - ret -1: mov 16(%esp),%eax - add %eax,%eax - sub $0xffe00000,%eax - or 12(%esp),%eax - fldl 12(%esp) - jnz 1f - fabs -1: ret diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig index f95c3c0bd4..40a9518cf4 100644 --- a/lib/std/math/hypot.zig +++ b/lib/std/math/hypot.zig @@ -6,10 +6,10 @@ const isNan = math.isNan; const isInf = math.isInf; const inf = math.inf; const nan = math.nan; -const floatEpsAt = math.floatEpsAt; const floatEps = math.floatEps; const floatMin = math.floatMin; const floatMax = math.floatMax; +const floatTrueMin = math.floatTrueMin; /// Returns sqrt(x * x + y * y), avoiding unnecessary overflow and underflow. /// @@ -30,8 +30,7 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { } const lower = @sqrt(floatMin(T)); const upper = @sqrt(floatMax(T) / 2); - const incre = @sqrt(floatEps(T) / 2); - const scale = floatEpsAt(T, incre); + const scale = floatTrueMin(T) * upper; const hypfn = if (emulateFma(T)) hypotUnfused else hypotFused; var major: T = x; var minor: T = y; @@ -46,7 +45,8 @@ pub fn hypot(x: anytype, y: anytype) @TypeOf(x, y) { major = minor; minor = tempo; } - if (major * incre >= minor) return major; + if (minor == 0.0) return major; + if (major - minor == major) return major; if (major > upper) return hypfn(T, major * scale, minor * scale) / scale; if (minor < lower) return hypfn(T, major / scale, minor / scale) * scale; return hypfn(T, major, minor); diff --git a/src/libs/musl.zig b/src/libs/musl.zig index ebbd285665..8fd59eb36f 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -874,7 +874,6 @@ const src_files = [_][]const u8{ "musl/src/math/frexp.c", "musl/src/math/frexpf.c", "musl/src/math/frexpl.c", - "musl/src/math/hypot.c", "musl/src/math/hypotf.c", "musl/src/math/hypotl.c", "musl/src/math/i386/acosf.s", @@ -890,7 +889,6 @@ const src_files = [_][]const u8{ "musl/src/math/i386/expl.s", "musl/src/math/i386/expm1l.s", "musl/src/math/i386/hypotf.s", - "musl/src/math/i386/hypot.s", "musl/src/math/i386/__invtrigl.s", "musl/src/math/i386/ldexpf.s", "musl/src/math/i386/ldexpl.s", diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig index 24a0ead598..350a4184bf 100644 --- a/src/libs/wasi_libc.zig +++ b/src/libs/wasi_libc.zig @@ -730,7 +730,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/frexp.c", "musl/src/math/frexpf.c", "musl/src/math/frexpl.c", - "musl/src/math/hypot.c", "musl/src/math/hypotf.c", "musl/src/math/hypotl.c", "musl/src/math/ilogb.c",