From fcfe25710bcc7c3c8ccd23bbad32c02ae6df7c40 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 20 Apr 2021 15:43:46 +0200 Subject: [PATCH] c: Implement fmin and fminf --- lib/std/special/c.zig | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 5112e76dfb..bea172b81d 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -880,6 +880,35 @@ test "fmod, fmodf" { } } +fn generic_fmin(comptime T: type, x: T, y: T) T { + if (isNan(x)) + return y; + if (isNan(y)) + return x; + return if (x < y) x else y; +} + +export fn fminf(x: f32, y: f32) callconv(.C) f32 { + return generic_fmin(f32, x, y); +} + +export fn fmin(x: f64, y: f64) callconv(.C) f64 { + return generic_fmin(f64, x, y); +} + +test "fmin, fminf" { + inline for ([_]type{ f32, f64 }) |T| { + const nan_val = math.nan(T); + + std.testing.expect(isNan(generic_fmin(T, nan_val, nan_val))); + std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, nan_val, 1.0)); + std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, nan_val)); + + std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, 10.0)); + std.testing.expectEqual(@as(T, -1.0), generic_fmin(T, 1.0, -1.0)); + } +} + // NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound // behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are // potentially some edge cases remaining that are not handled in the same way.