authorgravatar for hi@viri.moeviri <hi@viri.moe> 2022-04-07 03:08:42-06:00
committergravatar for hi@viri.moeviri <hi@viri.moe> 2022-04-07 05:04:03-06:00
log5d6a5a123676ada3ccd229f31dc8855aabaf8057
tree1064010b011c3ff2422e167f7186f8e0d85dba82
parentc5c62605341143b19accc00f28af1c46c0a416be
signaturelock-open Commit is signed but in an unrecognized format.

std.math.is*Inf: make generic, support f80


1 files changed, 34 insertions(+), 105 deletions(-)

lib/std/math/isinf.zig+34-105
......@@ -1,131 +1,60 @@
11const std = @import("../std.zig");
22const math = std.math;
33const expect = std.testing.expect;
4const maxInt = std.math.maxInt;
54
65/// Returns whether x is an infinity, ignoring sign.
76pub fn isInf(x: anytype) bool {
87 const T = @TypeOf(x);
9 switch (T) {
10 f16 => {
11 const bits = @bitCast(u16, x);
12 return bits & 0x7FFF == 0x7C00;
13 },
14 f32 => {
15 const bits = @bitCast(u32, x);
16 return bits & 0x7FFFFFFF == 0x7F800000;
17 },
18 f64 => {
19 const bits = @bitCast(u64, x);
20 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);
21 },
22 f128 => {
23 const bits = @bitCast(u128, x);
24 return bits & (maxInt(u128) >> 1) == (0x7FFF << 112);
25 },
26 else => {
27 @compileError("isInf not implemented for " ++ @typeName(T));
28 },
8 const TBits = std.meta.Int(.unsigned, @bitSizeOf(T));
9 if (@typeInfo(T) != .Float) {
10 @compileError("isInf not implemented for " ++ @typeName(T));
2911 }
12 const remove_sign = ~@as(TBits, 0) >> 1;
13 return @bitCast(TBits, x) & remove_sign == @bitCast(TBits, math.inf(T));
3014}
3115
3216/// Returns whether x is an infinity with a positive sign.
3317pub fn isPositiveInf(x: anytype) bool {
34 const T = @TypeOf(x);
35 switch (T) {
36 f16 => {
37 return @bitCast(u16, x) == 0x7C00;
38 },
39 f32 => {
40 return @bitCast(u32, x) == 0x7F800000;
41 },
42 f64 => {
43 return @bitCast(u64, x) == 0x7FF << 52;
44 },
45 f128 => {
46 return @bitCast(u128, x) == 0x7FFF << 112;
47 },
48 else => {
49 @compileError("isPositiveInf not implemented for " ++ @typeName(T));
50 },
51 }
18 return x == math.inf(@TypeOf(x));
5219}
5320
5421/// Returns whether x is an infinity with a negative sign.
5522pub fn isNegativeInf(x: anytype) bool {
56 const T = @TypeOf(x);
57 switch (T) {
58 f16 => {
59 return @bitCast(u16, x) == 0xFC00;
60 },
61 f32 => {
62 return @bitCast(u32, x) == 0xFF800000;
63 },
64 f64 => {
65 return @bitCast(u64, x) == 0xFFF << 52;
66 },
67 f128 => {
68 return @bitCast(u128, x) == 0xFFFF << 112;
69 },
70 else => {
71 @compileError("isNegativeInf not implemented for " ++ @typeName(T));
72 },
73 }
23 return x == -math.inf(@TypeOf(x));
7424}
7525
7626test "math.isInf" {
77 try expect(!isInf(@as(f16, 0.0)));
78 try expect(!isInf(@as(f16, -0.0)));
79 try expect(!isInf(@as(f32, 0.0)));
80 try expect(!isInf(@as(f32, -0.0)));
81 try expect(!isInf(@as(f64, 0.0)));
82 try expect(!isInf(@as(f64, -0.0)));
83 try expect(!isInf(@as(f128, 0.0)));
84 try expect(!isInf(@as(f128, -0.0)));
85 try expect(isInf(math.inf(f16)));
86 try expect(isInf(-math.inf(f16)));
87 try expect(isInf(math.inf(f32)));
88 try expect(isInf(-math.inf(f32)));
89 try expect(isInf(math.inf(f64)));
90 try expect(isInf(-math.inf(f64)));
91 try expect(isInf(math.inf(f128)));
92 try expect(isInf(-math.inf(f128)));
27 // TODO remove when #11391 is resolved
28 if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest;
29
30 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
31 try expect(!isInf(@as(T, 0.0)));
32 try expect(!isInf(@as(T, -0.0)));
33 try expect(isInf(math.inf(T)));
34 try expect(isInf(-math.inf(T)));
35 }
9336}
9437
9538test "math.isPositiveInf" {
96 try expect(!isPositiveInf(@as(f16, 0.0)));
97 try expect(!isPositiveInf(@as(f16, -0.0)));
98 try expect(!isPositiveInf(@as(f32, 0.0)));
99 try expect(!isPositiveInf(@as(f32, -0.0)));
100 try expect(!isPositiveInf(@as(f64, 0.0)));
101 try expect(!isPositiveInf(@as(f64, -0.0)));
102 try expect(!isPositiveInf(@as(f128, 0.0)));
103 try expect(!isPositiveInf(@as(f128, -0.0)));
104 try expect(isPositiveInf(math.inf(f16)));
105 try expect(!isPositiveInf(-math.inf(f16)));
106 try expect(isPositiveInf(math.inf(f32)));
107 try expect(!isPositiveInf(-math.inf(f32)));
108 try expect(isPositiveInf(math.inf(f64)));
109 try expect(!isPositiveInf(-math.inf(f64)));
110 try expect(isPositiveInf(math.inf(f128)));
111 try expect(!isPositiveInf(-math.inf(f128)));
39 // TODO remove when #11391 is resolved
40 if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest;
41
42 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
43 try expect(!isPositiveInf(@as(T, 0.0)));
44 try expect(!isPositiveInf(@as(T, -0.0)));
45 try expect(isPositiveInf(math.inf(T)));
46 try expect(!isPositiveInf(-math.inf(T)));
47 }
11248}
11349
11450test "math.isNegativeInf" {
115 try expect(!isNegativeInf(@as(f16, 0.0)));
116 try expect(!isNegativeInf(@as(f16, -0.0)));
117 try expect(!isNegativeInf(@as(f32, 0.0)));
118 try expect(!isNegativeInf(@as(f32, -0.0)));
119 try expect(!isNegativeInf(@as(f64, 0.0)));
120 try expect(!isNegativeInf(@as(f64, -0.0)));
121 try expect(!isNegativeInf(@as(f128, 0.0)));
122 try expect(!isNegativeInf(@as(f128, -0.0)));
123 try expect(!isNegativeInf(math.inf(f16)));
124 try expect(isNegativeInf(-math.inf(f16)));
125 try expect(!isNegativeInf(math.inf(f32)));
126 try expect(isNegativeInf(-math.inf(f32)));
127 try expect(!isNegativeInf(math.inf(f64)));
128 try expect(isNegativeInf(-math.inf(f64)));
129 try expect(!isNegativeInf(math.inf(f128)));
130 try expect(isNegativeInf(-math.inf(f128)));
51 // TODO remove when #11391 is resolved
52 if (@import("builtin").os.tag == .freebsd) return error.SkipZigTest;
53
54 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
55 try expect(!isNegativeInf(@as(T, 0.0)));
56 try expect(!isNegativeInf(@as(T, -0.0)));
57 try expect(!isNegativeInf(math.inf(T)));
58 try expect(isNegativeInf(-math.inf(T)));
59 }
13160}