authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-02 16:03:25-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-07-02 16:03:25-04:00
logbd282d6cca226c0b02af193f9c3cf0da5f6ea46d
tree5286470c43ef6c7f6530bf8518b0356e44a6ca3a
parent22b7312460c89f8fc9dad9674776d4ca3b40acd7
parent30cfc0ab2c56ad73dca9b9935731d10010c93b32
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1176 from bnoordhuis/f16-std

improve std.math f16 support

14 files changed, 191 insertions(+), 2 deletions(-)

std/math/copysign.zig+18
...@@ -4,12 +4,22 @@ const assert = std.debug.assert;...@@ -4,12 +4,22 @@ const assert = std.debug.assert;
44
5pub fn copysign(comptime T: type, x: T, y: T) T {5pub fn copysign(comptime T: type, x: T, y: T) T {
6 return switch (T) {6 return switch (T) {
7 f16 => copysign16(x, y),
7 f32 => copysign32(x, y),8 f32 => copysign32(x, y),
8 f64 => copysign64(x, y),9 f64 => copysign64(x, y),
9 else => @compileError("copysign not implemented for " ++ @typeName(T)),10 else => @compileError("copysign not implemented for " ++ @typeName(T)),
10 };11 };
11}12}
1213
14fn copysign16(x: f16, y: f16) f16 {
15 const ux = @bitCast(u16, x);
16 const uy = @bitCast(u16, y);
17
18 const h1 = ux & (@maxValue(u16) / 2);
19 const h2 = uy & (u16(1) << 15);
20 return @bitCast(f16, h1 | h2);
21}
22
13fn copysign32(x: f32, y: f32) f32 {23fn copysign32(x: f32, y: f32) f32 {
14 const ux = @bitCast(u32, x);24 const ux = @bitCast(u32, x);
15 const uy = @bitCast(u32, y);25 const uy = @bitCast(u32, y);
...@@ -29,10 +39,18 @@ fn copysign64(x: f64, y: f64) f64 {...@@ -29,10 +39,18 @@ fn copysign64(x: f64, y: f64) f64 {
29}39}
3040
31test "math.copysign" {41test "math.copysign" {
42 assert(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
32 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));43 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
33 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));44 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
34}45}
3546
47test "math.copysign16" {
48 assert(copysign16(5.0, 1.0) == 5.0);
49 assert(copysign16(5.0, -1.0) == -5.0);
50 assert(copysign16(-5.0, -1.0) == -5.0);
51 assert(copysign16(-5.0, 1.0) == 5.0);
52}
53
36test "math.copysign32" {54test "math.copysign32" {
37 assert(copysign32(5.0, 1.0) == 5.0);55 assert(copysign32(5.0, 1.0) == 5.0);
38 assert(copysign32(5.0, -1.0) == -5.0);56 assert(copysign32(5.0, -1.0) == -5.0);
std/math/fabs.zig+19
...@@ -10,12 +10,19 @@ const assert = std.debug.assert;...@@ -10,12 +10,19 @@ const assert = std.debug.assert;
10pub fn fabs(x: var) @typeOf(x) {10pub fn fabs(x: var) @typeOf(x) {
11 const T = @typeOf(x);11 const T = @typeOf(x);
12 return switch (T) {12 return switch (T) {
13 f16 => fabs16(x),
13 f32 => fabs32(x),14 f32 => fabs32(x),
14 f64 => fabs64(x),15 f64 => fabs64(x),
15 else => @compileError("fabs not implemented for " ++ @typeName(T)),16 else => @compileError("fabs not implemented for " ++ @typeName(T)),
16 };17 };
17}18}
1819
20fn fabs16(x: f16) f16 {
21 var u = @bitCast(u16, x);
22 u &= 0x7FFF;
23 return @bitCast(f16, u);
24}
25
19fn fabs32(x: f32) f32 {26fn fabs32(x: f32) f32 {
20 var u = @bitCast(u32, x);27 var u = @bitCast(u32, x);
21 u &= 0x7FFFFFFF;28 u &= 0x7FFFFFFF;
...@@ -29,10 +36,16 @@ fn fabs64(x: f64) f64 {...@@ -29,10 +36,16 @@ fn fabs64(x: f64) f64 {
29}36}
3037
31test "math.fabs" {38test "math.fabs" {
39 assert(fabs(f16(1.0)) == fabs16(1.0));
32 assert(fabs(f32(1.0)) == fabs32(1.0));40 assert(fabs(f32(1.0)) == fabs32(1.0));
33 assert(fabs(f64(1.0)) == fabs64(1.0));41 assert(fabs(f64(1.0)) == fabs64(1.0));
34}42}
3543
44test "math.fabs16" {
45 assert(fabs16(1.0) == 1.0);
46 assert(fabs16(-1.0) == 1.0);
47}
48
36test "math.fabs32" {49test "math.fabs32" {
37 assert(fabs32(1.0) == 1.0);50 assert(fabs32(1.0) == 1.0);
38 assert(fabs32(-1.0) == 1.0);51 assert(fabs32(-1.0) == 1.0);
...@@ -43,6 +56,12 @@ test "math.fabs64" {...@@ -43,6 +56,12 @@ test "math.fabs64" {
43 assert(fabs64(-1.0) == 1.0);56 assert(fabs64(-1.0) == 1.0);
44}57}
4558
59test "math.fabs16.special" {
60 assert(math.isPositiveInf(fabs(math.inf(f16))));
61 assert(math.isPositiveInf(fabs(-math.inf(f16))));
62 assert(math.isNan(fabs(math.nan(f16))));
63}
64
46test "math.fabs32.special" {65test "math.fabs32.special" {
47 assert(math.isPositiveInf(fabs(math.inf(f32))));66 assert(math.isPositiveInf(fabs(math.inf(f32))));
48 assert(math.isPositiveInf(fabs(-math.inf(f32))));67 assert(math.isPositiveInf(fabs(-math.inf(f32))));
std/math/floor.zig+50
...@@ -12,12 +12,47 @@ const math = std.math;...@@ -12,12 +12,47 @@ const math = std.math;
12pub fn floor(x: var) @typeOf(x) {12pub fn floor(x: var) @typeOf(x) {
13 const T = @typeOf(x);13 const T = @typeOf(x);
14 return switch (T) {14 return switch (T) {
15 f16 => floor16(x),
15 f32 => floor32(x),16 f32 => floor32(x),
16 f64 => floor64(x),17 f64 => floor64(x),
17 else => @compileError("floor not implemented for " ++ @typeName(T)),18 else => @compileError("floor not implemented for " ++ @typeName(T)),
18 };19 };
19}20}
2021
22fn floor16(x: f16) f16 {
23 var u = @bitCast(u16, x);
24 const e = @intCast(i16, (u >> 10) & 31) - 15;
25 var m: u16 = undefined;
26
27 // TODO: Shouldn't need this explicit check.
28 if (x == 0.0) {
29 return x;
30 }
31
32 if (e >= 10) {
33 return x;
34 }
35
36 if (e >= 0) {
37 m = u16(1023) >> @intCast(u4, e);
38 if (u & m == 0) {
39 return x;
40 }
41 math.forceEval(x + 0x1.0p120);
42 if (u >> 15 != 0) {
43 u += m;
44 }
45 return @bitCast(f16, u & ~m);
46 } else {
47 math.forceEval(x + 0x1.0p120);
48 if (u >> 15 == 0) {
49 return 0.0;
50 } else {
51 return -1.0;
52 }
53 }
54}
55
21fn floor32(x: f32) f32 {56fn floor32(x: f32) f32 {
22 var u = @bitCast(u32, x);57 var u = @bitCast(u32, x);
23 const e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;58 const e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
...@@ -84,10 +119,17 @@ fn floor64(x: f64) f64 {...@@ -84,10 +119,17 @@ fn floor64(x: f64) f64 {
84}119}
85120
86test "math.floor" {121test "math.floor" {
122 assert(floor(f16(1.3)) == floor16(1.3));
87 assert(floor(f32(1.3)) == floor32(1.3));123 assert(floor(f32(1.3)) == floor32(1.3));
88 assert(floor(f64(1.3)) == floor64(1.3));124 assert(floor(f64(1.3)) == floor64(1.3));
89}125}
90126
127test "math.floor16" {
128 assert(floor16(1.3) == 1.0);
129 assert(floor16(-1.3) == -2.0);
130 assert(floor16(0.2) == 0.0);
131}
132
91test "math.floor32" {133test "math.floor32" {
92 assert(floor32(1.3) == 1.0);134 assert(floor32(1.3) == 1.0);
93 assert(floor32(-1.3) == -2.0);135 assert(floor32(-1.3) == -2.0);
...@@ -100,6 +142,14 @@ test "math.floor64" {...@@ -100,6 +142,14 @@ test "math.floor64" {
100 assert(floor64(0.2) == 0.0);142 assert(floor64(0.2) == 0.0);
101}143}
102144
145test "math.floor16.special" {
146 assert(floor16(0.0) == 0.0);
147 assert(floor16(-0.0) == -0.0);
148 assert(math.isPositiveInf(floor16(math.inf(f16))));
149 assert(math.isNegativeInf(floor16(-math.inf(f16))));
150 assert(math.isNan(floor16(math.nan(f16))));
151}
152
103test "math.floor32.special" {153test "math.floor32.special" {
104 assert(floor32(0.0) == 0.0);154 assert(floor32(0.0) == 0.0);
105 assert(floor32(-0.0) == -0.0);155 assert(floor32(-0.0) == -0.0);
std/math/index.zig+17
...@@ -19,6 +19,18 @@ pub const f32_max = 3.40282346638528859812e+38;...@@ -19,6 +19,18 @@ pub const f32_max = 3.40282346638528859812e+38;
19pub const f32_epsilon = 1.1920928955078125e-07;19pub const f32_epsilon = 1.1920928955078125e-07;
20pub const f32_toint = 1.0 / f32_epsilon;20pub const f32_toint = 1.0 / f32_epsilon;
2121
22pub const f16_true_min = 0.000000059604644775390625; // 2**-24
23pub const f16_min = 0.00006103515625; // 2**-14
24pub const f16_max = 65504;
25pub const f16_epsilon = 0.0009765625; // 2**-10
26pub const f16_toint = 1.0 / f16_epsilon;
27
28pub const nan_u16 = u16(0x7C01);
29pub const nan_f16 = @bitCast(f16, nan_u16);
30
31pub const inf_u16 = u16(0x7C00);
32pub const inf_f16 = @bitCast(f16, inf_u16);
33
22pub const nan_u32 = u32(0x7F800001);34pub const nan_u32 = u32(0x7F800001);
23pub const nan_f32 = @bitCast(f32, nan_u32);35pub const nan_f32 = @bitCast(f32, nan_u32);
2436
...@@ -44,6 +56,11 @@ pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool {...@@ -44,6 +56,11 @@ pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool {
44pub fn forceEval(value: var) void {56pub fn forceEval(value: var) void {
45 const T = @typeOf(value);57 const T = @typeOf(value);
46 switch (T) {58 switch (T) {
59 f16 => {
60 var x: f16 = undefined;
61 const p = @ptrCast(*volatile f16, &x);
62 p.* = x;
63 },
47 f32 => {64 f32 => {
48 var x: f32 = undefined;65 var x: f32 = undefined;
49 const p = @ptrCast(*volatile f32, &x);66 const p = @ptrCast(*volatile f32, &x);
std/math/inf.zig+1-1
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;
43
5pub fn inf(comptime T: type) T {4pub fn inf(comptime T: type) T {
6 return switch (T) {5 return switch (T) {
6 f16 => @bitCast(f16, math.inf_u16),
7 f32 => @bitCast(f32, math.inf_u32),7 f32 => @bitCast(f32, math.inf_u32),
8 f64 => @bitCast(f64, math.inf_u64),8 f64 => @bitCast(f64, math.inf_u64),
9 else => @compileError("inf not implemented for " ++ @typeName(T)),9 else => @compileError("inf not implemented for " ++ @typeName(T)),
std/math/isfinite.zig+8
...@@ -5,6 +5,10 @@ const assert = std.debug.assert;...@@ -5,6 +5,10 @@ const assert = std.debug.assert;
5pub fn isFinite(x: var) bool {5pub fn isFinite(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
7 switch (T) {7 switch (T) {
8 f16 => {
9 const bits = @bitCast(u16, x);
10 return bits & 0x7FFF < 0x7C00;
11 },
8 f32 => {12 f32 => {
9 const bits = @bitCast(u32, x);13 const bits = @bitCast(u32, x);
10 return bits & 0x7FFFFFFF < 0x7F800000;14 return bits & 0x7FFFFFFF < 0x7F800000;
...@@ -20,10 +24,14 @@ pub fn isFinite(x: var) bool {...@@ -20,10 +24,14 @@ pub fn isFinite(x: var) bool {
20}24}
2125
22test "math.isFinite" {26test "math.isFinite" {
27 assert(isFinite(f16(0.0)));
28 assert(isFinite(f16(-0.0)));
23 assert(isFinite(f32(0.0)));29 assert(isFinite(f32(0.0)));
24 assert(isFinite(f32(-0.0)));30 assert(isFinite(f32(-0.0)));
25 assert(isFinite(f64(0.0)));31 assert(isFinite(f64(0.0)));
26 assert(isFinite(f64(-0.0)));32 assert(isFinite(f64(-0.0)));
33 assert(!isFinite(math.inf(f16)));
34 assert(!isFinite(-math.inf(f16)));
27 assert(!isFinite(math.inf(f32)));35 assert(!isFinite(math.inf(f32)));
28 assert(!isFinite(-math.inf(f32)));36 assert(!isFinite(-math.inf(f32)));
29 assert(!isFinite(math.inf(f64)));37 assert(!isFinite(math.inf(f64)));
std/math/isinf.zig+22
...@@ -5,6 +5,10 @@ const assert = std.debug.assert;...@@ -5,6 +5,10 @@ const assert = std.debug.assert;
5pub fn isInf(x: var) bool {5pub fn isInf(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
7 switch (T) {7 switch (T) {
8 f16 => {
9 const bits = @bitCast(u16, x);
10 return bits & 0x7FFF == 0x7C00;
11 },
8 f32 => {12 f32 => {
9 const bits = @bitCast(u32, x);13 const bits = @bitCast(u32, x);
10 return bits & 0x7FFFFFFF == 0x7F800000;14 return bits & 0x7FFFFFFF == 0x7F800000;
...@@ -22,6 +26,9 @@ pub fn isInf(x: var) bool {...@@ -22,6 +26,9 @@ pub fn isInf(x: var) bool {
22pub fn isPositiveInf(x: var) bool {26pub fn isPositiveInf(x: var) bool {
23 const T = @typeOf(x);27 const T = @typeOf(x);
24 switch (T) {28 switch (T) {
29 f16 => {
30 return @bitCast(u16, x) == 0x7C00;
31 },
25 f32 => {32 f32 => {
26 return @bitCast(u32, x) == 0x7F800000;33 return @bitCast(u32, x) == 0x7F800000;
27 },34 },
...@@ -37,6 +44,9 @@ pub fn isPositiveInf(x: var) bool {...@@ -37,6 +44,9 @@ pub fn isPositiveInf(x: var) bool {
37pub fn isNegativeInf(x: var) bool {44pub fn isNegativeInf(x: var) bool {
38 const T = @typeOf(x);45 const T = @typeOf(x);
39 switch (T) {46 switch (T) {
47 f16 => {
48 return @bitCast(u16, x) == 0xFC00;
49 },
40 f32 => {50 f32 => {
41 return @bitCast(u32, x) == 0xFF800000;51 return @bitCast(u32, x) == 0xFF800000;
42 },52 },
...@@ -50,10 +60,14 @@ pub fn isNegativeInf(x: var) bool {...@@ -50,10 +60,14 @@ pub fn isNegativeInf(x: var) bool {
50}60}
5161
52test "math.isInf" {62test "math.isInf" {
63 assert(!isInf(f16(0.0)));
64 assert(!isInf(f16(-0.0)));
53 assert(!isInf(f32(0.0)));65 assert(!isInf(f32(0.0)));
54 assert(!isInf(f32(-0.0)));66 assert(!isInf(f32(-0.0)));
55 assert(!isInf(f64(0.0)));67 assert(!isInf(f64(0.0)));
56 assert(!isInf(f64(-0.0)));68 assert(!isInf(f64(-0.0)));
69 assert(isInf(math.inf(f16)));
70 assert(isInf(-math.inf(f16)));
57 assert(isInf(math.inf(f32)));71 assert(isInf(math.inf(f32)));
58 assert(isInf(-math.inf(f32)));72 assert(isInf(-math.inf(f32)));
59 assert(isInf(math.inf(f64)));73 assert(isInf(math.inf(f64)));
...@@ -61,10 +75,14 @@ test "math.isInf" {...@@ -61,10 +75,14 @@ test "math.isInf" {
61}75}
6276
63test "math.isPositiveInf" {77test "math.isPositiveInf" {
78 assert(!isPositiveInf(f16(0.0)));
79 assert(!isPositiveInf(f16(-0.0)));
64 assert(!isPositiveInf(f32(0.0)));80 assert(!isPositiveInf(f32(0.0)));
65 assert(!isPositiveInf(f32(-0.0)));81 assert(!isPositiveInf(f32(-0.0)));
66 assert(!isPositiveInf(f64(0.0)));82 assert(!isPositiveInf(f64(0.0)));
67 assert(!isPositiveInf(f64(-0.0)));83 assert(!isPositiveInf(f64(-0.0)));
84 assert(isPositiveInf(math.inf(f16)));
85 assert(!isPositiveInf(-math.inf(f16)));
68 assert(isPositiveInf(math.inf(f32)));86 assert(isPositiveInf(math.inf(f32)));
69 assert(!isPositiveInf(-math.inf(f32)));87 assert(!isPositiveInf(-math.inf(f32)));
70 assert(isPositiveInf(math.inf(f64)));88 assert(isPositiveInf(math.inf(f64)));
...@@ -72,10 +90,14 @@ test "math.isPositiveInf" {...@@ -72,10 +90,14 @@ test "math.isPositiveInf" {
72}90}
7391
74test "math.isNegativeInf" {92test "math.isNegativeInf" {
93 assert(!isNegativeInf(f16(0.0)));
94 assert(!isNegativeInf(f16(-0.0)));
75 assert(!isNegativeInf(f32(0.0)));95 assert(!isNegativeInf(f32(0.0)));
76 assert(!isNegativeInf(f32(-0.0)));96 assert(!isNegativeInf(f32(-0.0)));
77 assert(!isNegativeInf(f64(0.0)));97 assert(!isNegativeInf(f64(0.0)));
78 assert(!isNegativeInf(f64(-0.0)));98 assert(!isNegativeInf(f64(-0.0)));
99 assert(!isNegativeInf(math.inf(f16)));
100 assert(isNegativeInf(-math.inf(f16)));
79 assert(!isNegativeInf(math.inf(f32)));101 assert(!isNegativeInf(math.inf(f32)));
80 assert(isNegativeInf(-math.inf(f32)));102 assert(isNegativeInf(-math.inf(f32)));
81 assert(!isNegativeInf(math.inf(f64)));103 assert(!isNegativeInf(math.inf(f64)));
std/math/isnan.zig+6
...@@ -5,6 +5,10 @@ const assert = std.debug.assert;...@@ -5,6 +5,10 @@ const assert = std.debug.assert;
5pub fn isNan(x: var) bool {5pub fn isNan(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
7 switch (T) {7 switch (T) {
8 f16 => {
9 const bits = @bitCast(u16, x);
10 return (bits & 0x7fff) > 0x7c00;
11 },
8 f32 => {12 f32 => {
9 const bits = @bitCast(u32, x);13 const bits = @bitCast(u32, x);
10 return bits & 0x7FFFFFFF > 0x7F800000;14 return bits & 0x7FFFFFFF > 0x7F800000;
...@@ -26,8 +30,10 @@ pub fn isSignalNan(x: var) bool {...@@ -26,8 +30,10 @@ pub fn isSignalNan(x: var) bool {
26}30}
2731
28test "math.isNan" {32test "math.isNan" {
33 assert(isNan(math.nan(f16)));
29 assert(isNan(math.nan(f32)));34 assert(isNan(math.nan(f32)));
30 assert(isNan(math.nan(f64)));35 assert(isNan(math.nan(f64)));
36 assert(!isNan(f16(1.0)));
31 assert(!isNan(f32(1.0)));37 assert(!isNan(f32(1.0)));
32 assert(!isNan(f64(1.0)));38 assert(!isNan(f64(1.0)));
33}39}
std/math/isnormal.zig+9
...@@ -5,6 +5,10 @@ const assert = std.debug.assert;...@@ -5,6 +5,10 @@ const assert = std.debug.assert;
5pub fn isNormal(x: var) bool {5pub fn isNormal(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
7 switch (T) {7 switch (T) {
8 f16 => {
9 const bits = @bitCast(u16, x);
10 return (bits + 1024) & 0x7FFF >= 2048;
11 },
8 f32 => {12 f32 => {
9 const bits = @bitCast(u32, x);13 const bits = @bitCast(u32, x);
10 return (bits + 0x00800000) & 0x7FFFFFFF >= 0x01000000;14 return (bits + 0x00800000) & 0x7FFFFFFF >= 0x01000000;
...@@ -20,8 +24,13 @@ pub fn isNormal(x: var) bool {...@@ -20,8 +24,13 @@ pub fn isNormal(x: var) bool {
20}24}
2125
22test "math.isNormal" {26test "math.isNormal" {
27 assert(!isNormal(math.nan(f16)));
23 assert(!isNormal(math.nan(f32)));28 assert(!isNormal(math.nan(f32)));
24 assert(!isNormal(math.nan(f64)));29 assert(!isNormal(math.nan(f64)));
30 assert(!isNormal(f16(0)));
31 assert(!isNormal(f32(0)));
32 assert(!isNormal(f64(0)));
33 assert(isNormal(f16(1.0)));
25 assert(isNormal(f32(1.0)));34 assert(isNormal(f32(1.0)));
26 assert(isNormal(f64(1.0)));35 assert(isNormal(f64(1.0)));
27}36}
std/math/nan.zig+2
...@@ -2,6 +2,7 @@ const math = @import("index.zig");...@@ -2,6 +2,7 @@ const math = @import("index.zig");
22
3pub fn nan(comptime T: type) T {3pub fn nan(comptime T: type) T {
4 return switch (T) {4 return switch (T) {
5 f16 => @bitCast(f16, math.nan_u16),
5 f32 => @bitCast(f32, math.nan_u32),6 f32 => @bitCast(f32, math.nan_u32),
6 f64 => @bitCast(f64, math.nan_u64),7 f64 => @bitCast(f64, math.nan_u64),
7 else => @compileError("nan not implemented for " ++ @typeName(T)),8 else => @compileError("nan not implemented for " ++ @typeName(T)),
...@@ -12,6 +13,7 @@ pub fn nan(comptime T: type) T {...@@ -12,6 +13,7 @@ pub fn nan(comptime T: type) T {
12// representation in the future when required.13// representation in the future when required.
13pub fn snan(comptime T: type) T {14pub fn snan(comptime T: type) T {
14 return switch (T) {15 return switch (T) {
16 f16 => @bitCast(f16, math.nan_u16),
15 f32 => @bitCast(f32, math.nan_u32),17 f32 => @bitCast(f32, math.nan_u32),
16 f64 => @bitCast(f64, math.nan_u64),18 f64 => @bitCast(f64, math.nan_u64),
17 else => @compileError("snan not implemented for " ++ @typeName(T)),19 else => @compileError("snan not implemented for " ++ @typeName(T)),
std/math/signbit.zig+12
...@@ -5,12 +5,18 @@ const assert = std.debug.assert;...@@ -5,12 +5,18 @@ const assert = std.debug.assert;
5pub fn signbit(x: var) bool {5pub fn signbit(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
7 return switch (T) {7 return switch (T) {
8 f16 => signbit16(x),
8 f32 => signbit32(x),9 f32 => signbit32(x),
9 f64 => signbit64(x),10 f64 => signbit64(x),
10 else => @compileError("signbit not implemented for " ++ @typeName(T)),11 else => @compileError("signbit not implemented for " ++ @typeName(T)),
11 };12 };
12}13}
1314
15fn signbit16(x: f16) bool {
16 const bits = @bitCast(u16, x);
17 return bits >> 15 != 0;
18}
19
14fn signbit32(x: f32) bool {20fn signbit32(x: f32) bool {
15 const bits = @bitCast(u32, x);21 const bits = @bitCast(u32, x);
16 return bits >> 31 != 0;22 return bits >> 31 != 0;
...@@ -22,10 +28,16 @@ fn signbit64(x: f64) bool {...@@ -22,10 +28,16 @@ fn signbit64(x: f64) bool {
22}28}
2329
24test "math.signbit" {30test "math.signbit" {
31 assert(signbit(f16(4.0)) == signbit16(4.0));
25 assert(signbit(f32(4.0)) == signbit32(4.0));32 assert(signbit(f32(4.0)) == signbit32(4.0));
26 assert(signbit(f64(4.0)) == signbit64(4.0));33 assert(signbit(f64(4.0)) == signbit64(4.0));
27}34}
2835
36test "math.signbit16" {
37 assert(!signbit16(4.0));
38 assert(signbit16(-3.0));
39}
40
29test "math.signbit32" {41test "math.signbit32" {
30 assert(!signbit32(4.0));42 assert(!signbit32(4.0));
31 assert(signbit32(-3.0));43 assert(signbit32(-3.0));
std/math/sqrt.zig+23
...@@ -31,10 +31,25 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ...@@ -31,10 +31,25 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ
31}31}
3232
33test "math.sqrt" {33test "math.sqrt" {
34 assert(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
34 assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0));35 assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
35 assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0));36 assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
36}37}
3738
39test "math.sqrt16" {
40 const epsilon = 0.000001;
41
42 assert(@sqrt(f16, 0.0) == 0.0);
43 assert(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
44 assert(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
45 assert(@sqrt(f16, 4.0) == 2.0);
46 assert(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
47 assert(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
48 assert(@sqrt(f16, 64.0) == 8.0);
49 assert(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
50 assert(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
51}
52
38test "math.sqrt32" {53test "math.sqrt32" {
39 const epsilon = 0.000001;54 const epsilon = 0.000001;
4055
...@@ -63,6 +78,14 @@ test "math.sqrt64" {...@@ -63,6 +78,14 @@ test "math.sqrt64" {
63 assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));78 assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
64}79}
6580
81test "math.sqrt16.special" {
82 assert(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
83 assert(@sqrt(f16, 0.0) == 0.0);
84 assert(@sqrt(f16, -0.0) == -0.0);
85 assert(math.isNan(@sqrt(f16, -1.0)));
86 assert(math.isNan(@sqrt(f16, math.nan(f16))));
87}
88
66test "math.sqrt32.special" {89test "math.sqrt32.special" {
67 assert(math.isPositiveInf(@sqrt(f32, math.inf(f32))));90 assert(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
68 assert(@sqrt(f32, 0.0) == 0.0);91 assert(@sqrt(f32, 0.0) == 0.0);
std/special/builtin.zig+3-1
...@@ -210,7 +210,9 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {...@@ -210,7 +210,9 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
210}210}
211211
212fn isNan(comptime T: type, bits: T) bool {212fn isNan(comptime T: type, bits: T) bool {
213 if (T == u32) {213 if (T == u16) {
214 return (bits & 0x7fff) > 0x7c00;
215 } else if (T == u32) {
214 return (bits & 0x7fffffff) > 0x7f800000;216 return (bits & 0x7fffffff) > 0x7f800000;
215 } else if (T == u64) {217 } else if (T == u64) {
216 return (bits & (@maxValue(u64) >> 1)) > (u64(0x7ff) << 52);218 return (bits & (@maxValue(u64) >> 1)) > (u64(0x7ff) << 52);
std/special/compiler_rt/extendXfYf2_test.zig+1
...@@ -88,6 +88,7 @@ test "extenddftf2" {...@@ -88,6 +88,7 @@ test "extenddftf2" {
88test "extendhfsf2" {88test "extendhfsf2" {
89 test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN89 test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN
90 test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN90 test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
91 test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
9192
92 test__extendhfsf2(0, 0); // 093 test__extendhfsf2(0, 0); // 0
93 test__extendhfsf2(0x8000, 0x80000000); // -094 test__extendhfsf2(0x8000, 0x80000000); // -0