From 5d6a5a123676ada3ccd229f31dc8855aabaf8057 Mon Sep 17 00:00:00 2001 From: viri Date: Thu, 7 Apr 2022 03:08:42 -0600 Subject: [PATCH] std.math.is*Inf: make generic, support f80 --- lib/std/math/isinf.zig | 139 ++++++++++------------------------------- 1 file changed, 34 insertions(+), 105 deletions(-) diff --git a/lib/std/math/isinf.zig b/lib/std/math/isinf.zig index cadaa8d937..2524354207 100644 --- a/lib/std/math/isinf.zig +++ b/lib/std/math/isinf.zig @@ -1,131 +1,60 @@ const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; -const maxInt = std.math.maxInt; /// Returns whether x is an infinity, ignoring sign. pub fn isInf(x: anytype) bool { const T = @TypeOf(x); - switch (T) { - f16 => { - const bits = @bitCast(u16, x); - return bits & 0x7FFF == 0x7C00; - }, - f32 => { - const bits = @bitCast(u32, x); - return bits & 0x7FFFFFFF == 0x7F800000; - }, - f64 => { - const bits = @bitCast(u64, x); - return bits & (maxInt(u64) >> 1) == (0x7FF << 52); - }, - f128 => { - const bits = @bitCast(u128, x); - return bits & (maxInt(u128) >> 1) == (0x7FFF << 112); - }, - else => { - @compileError("isInf not implemented for " ++ @typeName(T)); - }, + const TBits = std.meta.Int(.unsigned, @bitSizeOf(T)); + if (@typeInfo(T) != .Float) { + @compileError("isInf not implemented for " ++ @typeName(T)); } + const remove_sign = ~@as(TBits, 0) >> 1; + return @bitCast(TBits, x) & remove_sign == @bitCast(TBits, math.inf(T)); } /// Returns whether x is an infinity with a positive sign. pub fn isPositiveInf(x: anytype) bool { - const T = @TypeOf(x); - switch (T) { - f16 => { - return @bitCast(u16, x) == 0x7C00; - }, - f32 => { - return @bitCast(u32, x) == 0x7F800000; - }, - f64 => { - return @bitCast(u64, x) == 0x7FF << 52; - }, - f128 => { - return @bitCast(u128, x) == 0x7FFF << 112; - }, - else => { - @compileError("isPositiveInf not implemented for " ++ @typeName(T)); - }, - } + return x == math.inf(@TypeOf(x)); } /// Returns whether x is an infinity with a negative sign. pub fn isNegativeInf(x: anytype) bool { - const T = @TypeOf(x); - switch (T) { - f16 => { - return @bitCast(u16, x) == 0xFC00; - }, - f32 => { - return @bitCast(u32, x) == 0xFF800000; - }, - f64 => { - return @bitCast(u64, x) == 0xFFF << 52; - }, - f128 => { - return @bitCast(u128, x) == 0xFFFF << 112; - }, - else => { - @compileError("isNegativeInf not implemented for " ++ @typeName(T)); - }, - } + return x == -math.inf(@TypeOf(x)); } test "math.isInf" { - try expect(!isInf(@as(f16, 0.0))); - try expect(!isInf(@as(f16, -0.0))); - try expect(!isInf(@as(f32, 0.0))); - try expect(!isInf(@as(f32, -0.0))); - try expect(!isInf(@as(f64, 0.0))); - try expect(!isInf(@as(f64, -0.0))); - try expect(!isInf(@as(f128, 0.0))); - try expect(!isInf(@as(f128, -0.0))); - try expect(isInf(math.inf(f16))); - try expect(isInf(-math.inf(f16))); - try expect(isInf(math.inf(f32))); - try expect(isInf(-math.inf(f32))); - try expect(isInf(math.inf(f64))); - try expect(isInf(-math.inf(f64))); - try expect(isInf(math.inf(f128))); - try expect(isInf(-math.inf(f128))); + // TODO remove when #11391 is resolved + if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest; + + inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { + try expect(!isInf(@as(T, 0.0))); + try expect(!isInf(@as(T, -0.0))); + try expect(isInf(math.inf(T))); + try expect(isInf(-math.inf(T))); + } } test "math.isPositiveInf" { - try expect(!isPositiveInf(@as(f16, 0.0))); - try expect(!isPositiveInf(@as(f16, -0.0))); - try expect(!isPositiveInf(@as(f32, 0.0))); - try expect(!isPositiveInf(@as(f32, -0.0))); - try expect(!isPositiveInf(@as(f64, 0.0))); - try expect(!isPositiveInf(@as(f64, -0.0))); - try expect(!isPositiveInf(@as(f128, 0.0))); - try expect(!isPositiveInf(@as(f128, -0.0))); - try expect(isPositiveInf(math.inf(f16))); - try expect(!isPositiveInf(-math.inf(f16))); - try expect(isPositiveInf(math.inf(f32))); - try expect(!isPositiveInf(-math.inf(f32))); - try expect(isPositiveInf(math.inf(f64))); - try expect(!isPositiveInf(-math.inf(f64))); - try expect(isPositiveInf(math.inf(f128))); - try expect(!isPositiveInf(-math.inf(f128))); + // TODO remove when #11391 is resolved + if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest; + + inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { + try expect(!isPositiveInf(@as(T, 0.0))); + try expect(!isPositiveInf(@as(T, -0.0))); + try expect(isPositiveInf(math.inf(T))); + try expect(!isPositiveInf(-math.inf(T))); + } } test "math.isNegativeInf" { - try expect(!isNegativeInf(@as(f16, 0.0))); - try expect(!isNegativeInf(@as(f16, -0.0))); - try expect(!isNegativeInf(@as(f32, 0.0))); - try expect(!isNegativeInf(@as(f32, -0.0))); - try expect(!isNegativeInf(@as(f64, 0.0))); - try expect(!isNegativeInf(@as(f64, -0.0))); - try expect(!isNegativeInf(@as(f128, 0.0))); - try expect(!isNegativeInf(@as(f128, -0.0))); - try expect(!isNegativeInf(math.inf(f16))); - try expect(isNegativeInf(-math.inf(f16))); - try expect(!isNegativeInf(math.inf(f32))); - try expect(isNegativeInf(-math.inf(f32))); - try expect(!isNegativeInf(math.inf(f64))); - try expect(isNegativeInf(-math.inf(f64))); - try expect(!isNegativeInf(math.inf(f128))); - try expect(isNegativeInf(-math.inf(f128))); + // TODO remove when #11391 is resolved + if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest; + + inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { + try expect(!isNegativeInf(@as(T, 0.0))); + try expect(!isNegativeInf(@as(T, -0.0))); + try expect(!isNegativeInf(math.inf(T))); + try expect(isNegativeInf(-math.inf(T))); + } }