From e74b98227eee5eef1c3a7cded0f8fff147178864 Mon Sep 17 00:00:00 2001 From: rpkak Date: Tue, 7 Apr 2026 12:10:27 +0200 Subject: [PATCH] zigc: long double: call double function if long double and double are equivalent For some of these functions and most targets this changes nothing, either because long double and double are not equivalent or because llvm did function deduplication. But e.g. on aarch64-windows-gnu, ucrt provides hypot, but not hypotl. Now hypotl calls hypot from ucrt instead of including the std.math.hypot implementation in zigc. Very trivial functions (like nanl) are not changed, because a function call would probably make this function more complex. --- lib/c/math.zig | 45 ++++++++++++++++++++++++++++----------------- lib/std/c.zig | 8 ++++++++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/c/math.zig b/lib/c/math.zig index 18ba8d9e755e4f74a6bc50d3cd178ffb2d1ed686..5eff669a9755975cc7423a203c15ecc6d5a199c6 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -116,13 +116,9 @@ fn atanf(x: f32) callconv(.c) f32 { } fn atanl(x: c_longdouble) callconv(.c) c_longdouble { - return switch (@typeInfo(@TypeOf(x)).float.bits) { - 16 => math.atan(@as(f16, @floatCast(x))), - 32 => math.atan(@as(f32, @floatCast(x))), - 64 => math.atan(@as(f64, @floatCast(x))), - 80 => math.atan(@as(f80, @floatCast(x))), - 128 => math.atan(@as(f128, @floatCast(x))), - else => unreachable, + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.atan(x), + else => math.atan(x), }; } @@ -143,7 +139,10 @@ fn copysignf(x: f32, y: f32) callconv(.c) f32 { } fn copysignl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return math.copysign(x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.copysign(x, y), + else => math.copysign(x, y), + }; } fn cosh(x: f64) callconv(.c) f64 { @@ -183,15 +182,18 @@ fn fdimf(x: f32, y: f32) callconv(.c) f32 { } fn fdiml(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return fdimGeneric(c_longdouble, x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.fdim(x, y), + else => fdimGeneric(c_longdouble, x, y), + }; } fn finite(x: f64) callconv(.c) c_int { - return if (math.isFinite(x)) 1 else 0; + return @intFromBool(math.isFinite(x)); } fn finitef(x: f32) callconv(.c) c_int { - return if (math.isFinite(x)) 1 else 0; + return @intFromBool(math.isFinite(x)); } fn frexpGeneric(comptime T: type, x: T, e: *c_int) T { @@ -222,7 +224,10 @@ fn frexpf(x: f32, e: *c_int) callconv(.c) f32 { } fn frexpl(x: c_longdouble, e: *c_int) callconv(.c) c_longdouble { - return frexpGeneric(c_longdouble, x, e); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.frexp(x, e), + else => frexpGeneric(c_longdouble, x, e), + }; } fn hypot(x: f64, y: f64) callconv(.c) f64 { @@ -234,19 +239,22 @@ fn hypotf(x: f32, y: f32) callconv(.c) f32 { } fn hypotl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { - return math.hypot(x, y); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.hypot(x, y), + else => math.hypot(x, y), + }; } fn isnan(x: f64) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn isnanf(x: f32) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn isnanl(x: c_longdouble) callconv(.c) c_int { - return if (math.isNan(x)) 1 else 0; + return @intFromBool(math.isNan(x)); } fn lrint(x: f64) callconv(.c) c_long { @@ -290,7 +298,10 @@ fn modff(x: f32, iptr: *f32) callconv(.c) f32 { } fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble { - return modfGeneric(c_longdouble, x, iptr); + return switch (@typeInfo(c_longdouble).float.bits) { + 64 => std.c.modf(x, iptr), + else => modfGeneric(c_longdouble, x, iptr), + }; } fn testModf(comptime T: type) !void { diff --git a/lib/std/c.zig b/lib/std/c.zig index f0b03917855a2261fad5352220329c6904f922dc..4e1bc6594339b4597058afbac119ae96c1218acb 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -11102,6 +11102,14 @@ pub const ioctl = switch (native_os) { else => private.ioctl, }; +// Math +pub extern "c" fn atan(x: f64) callconv(.c) f64; +pub extern "c" fn copysign(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn fdim(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn frexp(x: f64, e: *c_int) callconv(.c) f64; +pub extern "c" fn hypot(x: f64, y: f64) callconv(.c) f64; +pub extern "c" fn modf(x: f64, iptr: *f64) callconv(.c) f64; + // OS-specific bits. These are protected from being used on the wrong OS by // comptime assertions inside each OS-specific file. -- 2.54.0