zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

fmax.zig (2867B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const math = std.math;
      4 const arch = builtin.cpu.arch;
      5 const common = @import("common.zig");
      6 
      7 pub const panic = common.panic;
      8 
      9 comptime {
     10     @export(&__fmaxh, .{ .name = "__fmaxh", .linkage = common.linkage, .visibility = common.visibility });
     11     @export(&fmaxf, .{ .name = "fmaxf", .linkage = common.linkage, .visibility = common.visibility });
     12     @export(&fmax, .{ .name = "fmax", .linkage = common.linkage, .visibility = common.visibility });
     13     @export(&__fmaxx, .{ .name = "__fmaxx", .linkage = common.linkage, .visibility = common.visibility });
     14     if (common.want_ppc_abi) {
     15         @export(&fmaxq, .{ .name = "fmaxf128", .linkage = common.linkage, .visibility = common.visibility });
     16     }
     17     @export(&fmaxq, .{ .name = "fmaxq", .linkage = common.linkage, .visibility = common.visibility });
     18     @export(&fmaxl, .{ .name = "fmaxl", .linkage = common.linkage, .visibility = common.visibility });
     19 }
     20 
     21 pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 {
     22     return generic_fmax(f16, x, y);
     23 }
     24 
     25 pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 {
     26     return generic_fmax(f32, x, y);
     27 }
     28 
     29 pub fn fmax(x: f64, y: f64) callconv(.c) f64 {
     30     return generic_fmax(f64, x, y);
     31 }
     32 
     33 pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 {
     34     return generic_fmax(f80, x, y);
     35 }
     36 
     37 pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 {
     38     return generic_fmax(f128, x, y);
     39 }
     40 
     41 pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble {
     42     switch (@typeInfo(c_longdouble).float.bits) {
     43         16 => return __fmaxh(x, y),
     44         32 => return fmaxf(x, y),
     45         64 => return fmax(x, y),
     46         80 => return __fmaxx(x, y),
     47         128 => return fmaxq(x, y),
     48         else => @compileError("unreachable"),
     49     }
     50 }
     51 
     52 inline fn generic_fmax(comptime T: type, x: T, y: T) T {
     53     if (math.isNan(x))
     54         return y;
     55     if (math.isNan(y))
     56         return x;
     57     if (math.signbit(x) != math.signbit(y))
     58         return if (math.signbit(x)) y else x;
     59     return if (x < y) y else x;
     60 }
     61 
     62 test "generic_fmax" {
     63     inline for ([_]type{ f32, f64, c_longdouble, f80, f128 }) |T| {
     64         const nan_val = math.nan(T);
     65         const Int = std.meta.Int(.unsigned, @bitSizeOf(T));
     66 
     67         try std.testing.expect(math.isNan(generic_fmax(T, nan_val, nan_val)));
     68         try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, nan_val, 1.0));
     69         try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, nan_val));
     70 
     71         try std.testing.expectEqual(@as(T, 10.0), generic_fmax(T, 1.0, 10.0));
     72         try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, -1.0));
     73 
     74         try std.testing.expectEqual(@as(Int, @bitCast(@as(T, 0.0))), @as(Int, @bitCast(generic_fmax(T, 0.0, -0.0))));
     75         try std.testing.expectEqual(@as(Int, @bitCast(@as(T, 0.0))), @as(Int, @bitCast(generic_fmax(T, -0.0, 0.0))));
     76     }
     77 }