Commit 387b0ac4f1
Changed files (19)
lib
test
behavior
lib/compiler_rt/divtf3_test.zig
@@ -30,10 +30,8 @@ fn test__divtf3(a: f128, b: f128, expectedHi: u64, expectedLo: u64) !void {
}
test "divtf3" {
- // qNaN / any = qNaN
- try test__divtf3(math.qnan_f128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
// NaN / any = NaN
- try test__divtf3(math.nan_f128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
+ try test__divtf3(math.nan(f128), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
// inf / any(except inf and nan) = inf
try test__divtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0);
// inf / inf = nan
lib/compiler_rt/divxf3_test.zig
@@ -39,10 +39,8 @@ fn test__divxf3(a: f80, b: f80) !void {
}
test "divxf3" {
- // qNaN / any = qNaN
- try expect__divxf3_result(math.qnan_f80, 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
// NaN / any = NaN
- try expect__divxf3_result(math.nan_f80, 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
+ try expect__divxf3_result(math.nan(f80), 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
// inf / any(except inf and nan) = inf
try expect__divxf3_result(math.inf(f80), 0x1.23456789abcdefp+5, 0x7fff8000000000000000);
// inf / inf = nan
lib/compiler_rt/log10.zig
@@ -112,11 +112,11 @@ pub fn log10(x_: f64) callconv(.C) f64 {
if (hx < 0x00100000 or hx >> 31 != 0) {
// log(+-0) = -inf
if (ix << 1 == 0) {
- return -math.inf(f32);
+ return -math.inf(f64);
}
// log(-#) = nan
if (hx >> 31 != 0) {
- return math.nan(f32);
+ return math.nan(f64);
}
// subnormal, scale x
lib/compiler_rt/sqrt.zig
@@ -29,7 +29,7 @@ pub fn sqrtf(x: f32) callconv(.C) f32 {
var ix: i32 = @as(i32, @bitCast(x));
if ((ix & 0x7F800000) == 0x7F800000) {
- return x * x + x; // sqrt(nan) = nan, sqrt(+inf) = +inf, sqrt(-inf) = snan
+ return x * x + x; // sqrt(nan) = nan, sqrt(+inf) = +inf, sqrt(-inf) = nan
}
// zero
@@ -38,7 +38,7 @@ pub fn sqrtf(x: f32) callconv(.C) f32 {
return x; // sqrt (+-0) = +-0
}
if (ix < 0) {
- return math.snan(f32);
+ return math.nan(f32);
}
}
@@ -119,9 +119,9 @@ pub fn sqrt(x: f64) callconv(.C) f64 {
if (x == 0.0) {
return x;
}
- // sqrt(-ve) = snan
+ // sqrt(-ve) = nan
if (ix0 & sign != 0) {
- return math.snan(f64);
+ return math.nan(f64);
}
// normalize x
lib/std/math/acos.zig
@@ -117,7 +117,7 @@ fn acos64(x: f64) f64 {
}
}
- return math.nan(f32);
+ return math.nan(f64);
}
// |x| < 0.5
lib/std/math/acosh.zig
@@ -11,7 +11,7 @@ const expect = std.testing.expect;
/// Returns the hyperbolic arc-cosine of x.
///
/// Special cases:
-/// - acosh(x) = snan if x < 1
+/// - acosh(x) = nan if x < 1
/// - acosh(nan) = nan
pub fn acosh(x: anytype) @TypeOf(x) {
const T = @TypeOf(x);
@@ -84,10 +84,10 @@ test "math.acosh64" {
test "math.acosh32.special" {
try expect(math.isNan(acosh32(math.nan(f32))));
- try expect(math.isSignalNan(acosh32(0.5)));
+ try expect(math.isNan(acosh32(0.5)));
}
test "math.acosh64.special" {
try expect(math.isNan(acosh64(math.nan(f64))));
- try expect(math.isSignalNan(acosh64(0.5)));
+ try expect(math.isNan(acosh64(0.5)));
}
lib/std/math/atanh.zig
@@ -107,15 +107,15 @@ test "math.atanh_64" {
test "math.atanh32.special" {
try expect(math.isPositiveInf(atanh_32(1)));
try expect(math.isNegativeInf(atanh_32(-1)));
- try expect(math.isSignalNan(atanh_32(1.5)));
- try expect(math.isSignalNan(atanh_32(-1.5)));
+ try expect(math.isNan(atanh_32(1.5)));
+ try expect(math.isNan(atanh_32(-1.5)));
try expect(math.isNan(atanh_32(math.nan(f32))));
}
test "math.atanh64.special" {
try expect(math.isPositiveInf(atanh_64(1)));
try expect(math.isNegativeInf(atanh_64(-1)));
- try expect(math.isSignalNan(atanh_64(1.5)));
- try expect(math.isSignalNan(atanh_64(-1.5)));
+ try expect(math.isNan(atanh_64(1.5)));
+ try expect(math.isNan(atanh_64(-1.5)));
try expect(math.isNan(atanh_64(math.nan(f64))));
}
lib/std/math/float.zig
@@ -1,6 +1,8 @@
const std = @import("../std.zig");
+const builtin = @import("builtin");
const assert = std.debug.assert;
const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
/// Creates a raw "1.0" mantissa for floating point type T. Used to dedupe f80 logic.
inline fn mantissaOne(comptime T: type) comptime_int {
@@ -97,6 +99,27 @@ pub inline fn inf(comptime T: type) T {
return reconstructFloat(T, floatExponentMax(T) + 1, mantissaOne(T));
}
+/// Returns the canonical quiet NaN representation for floating point type T.
+pub inline fn nan(comptime T: type) T {
+ return reconstructFloat(
+ T,
+ floatExponentMax(T) + 1,
+ mantissaOne(T) | 1 << (floatFractionalBits(T) - 1),
+ );
+}
+
+/// Returns a signalling NaN representation for floating point type T.
+///
+/// TODO: LLVM is known to miscompile on some architectures to quiet NaN -
+/// this is tracked by https://github.com/ziglang/zig/issues/14366
+pub inline fn snan(comptime T: type) T {
+ return reconstructFloat(
+ T,
+ floatExponentMax(T) + 1,
+ mantissaOne(T) | 1 << (floatFractionalBits(T) - 2),
+ );
+}
+
test "float bits" {
inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
// (1 +) for the sign bit, since it is separate from the other bits
@@ -108,3 +131,45 @@ test "float bits" {
try expect(-floatFractionalBits(T) <= floatExponentMax(T));
}
}
+
+test "math.inf" {
+ const inf_u16: u16 = 0x7C00;
+ const inf_u32: u32 = 0x7F800000;
+ const inf_u64: u64 = 0x7FF0000000000000;
+ const inf_u80: u80 = 0x7FFF8000000000000000;
+ const inf_u128: u128 = 0x7FFF0000000000000000000000000000;
+ try expectEqual(inf_u16, @bitCast(inf(f16)));
+ try expectEqual(inf_u32, @bitCast(inf(f32)));
+ try expectEqual(inf_u64, @bitCast(inf(f64)));
+ try expectEqual(inf_u80, @bitCast(inf(f80)));
+ try expectEqual(inf_u128, @bitCast(inf(f128)));
+}
+
+test "math.nan" {
+ const qnan_u16: u16 = 0x7E00;
+ const qnan_u32: u32 = 0x7FC00000;
+ const qnan_u64: u64 = 0x7FF8000000000000;
+ const qnan_u80: u80 = 0x7FFFC000000000000000;
+ const qnan_u128: u128 = 0x7FFF8000000000000000000000000000;
+ try expectEqual(qnan_u16, @bitCast(nan(f16)));
+ try expectEqual(qnan_u32, @bitCast(nan(f32)));
+ try expectEqual(qnan_u64, @bitCast(nan(f64)));
+ try expectEqual(qnan_u80, @bitCast(nan(f80)));
+ try expectEqual(qnan_u128, @bitCast(nan(f128)));
+}
+
+test "math.snan" {
+ // TODO: https://github.com/ziglang/zig/issues/14366
+ if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
+
+ const snan_u16: u16 = 0x7D00;
+ const snan_u32: u32 = 0x7FA00000;
+ const snan_u64: u64 = 0x7FF4000000000000;
+ const snan_u80: u80 = 0x7FFFA000000000000000;
+ const snan_u128: u128 = 0x7FFF4000000000000000000000000000;
+ try expectEqual(snan_u16, @bitCast(snan(f16)));
+ try expectEqual(snan_u32, @bitCast(snan(f32)));
+ try expectEqual(snan_u64, @bitCast(snan(f64)));
+ try expectEqual(snan_u80, @bitCast(snan(f80)));
+ try expectEqual(snan_u128, @bitCast(snan(f128)));
+}
lib/std/math/isnan.zig
@@ -1,27 +1,40 @@
const std = @import("../std.zig");
+const builtin = @import("builtin");
const math = std.math;
+const meta = std.meta;
const expect = std.testing.expect;
-const maxInt = std.math.maxInt;
-/// Returns whether x is a nan.
pub fn isNan(x: anytype) bool {
return x != x;
}
-/// Returns whether x is a signalling nan.
+/// TODO: LLVM is known to miscompile on some architectures to quiet NaN -
+/// this is tracked by https://github.com/ziglang/zig/issues/14366
pub fn isSignalNan(x: anytype) bool {
- // Note: A signalling nan is identical to a standard nan right now but may have a different bit
- // representation in the future when required.
- return isNan(x);
+ const T = @TypeOf(x);
+ const U = meta.Int(.unsigned, @bitSizeOf(T));
+ const quiet_signal_bit_mask = 1 << (math.floatFractionalBits(T) - 1);
+ return isNan(x) and (@as(U, @bitCast(x)) & quiet_signal_bit_mask == 0);
}
test "math.isNan" {
- try expect(isNan(math.nan(f16)));
- try expect(isNan(math.nan(f32)));
- try expect(isNan(math.nan(f64)));
- try expect(isNan(math.nan(f128)));
- try expect(!isNan(@as(f16, 1.0)));
- try expect(!isNan(@as(f32, 1.0)));
- try expect(!isNan(@as(f64, 1.0)));
- try expect(!isNan(@as(f128, 1.0)));
+ inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
+ try expect(isNan(math.nan(T)));
+ try expect(isNan(-math.nan(T)));
+ try expect(isNan(math.snan(T)));
+ try expect(!isNan(@as(T, 1.0)));
+ try expect(!isNan(@as(T, math.inf(T))));
+ }
+}
+
+test "math.isSignalNan" {
+ inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
+ // TODO: Signalling NaN values get converted to quiet NaN values in
+ // some cases where they shouldn't such that this can fail.
+ // See https://github.com/ziglang/zig/issues/14366
+ // try expect(isSignalNan(math.snan(T)));
+ try expect(!isSignalNan(math.nan(T)));
+ try expect(!isSignalNan(@as(T, 1.0)));
+ try expect(!isSignalNan(math.inf(T)));
+ }
}
lib/std/math/nan.zig
@@ -1,20 +0,0 @@
-const math = @import("../math.zig");
-
-/// Returns the nan representation for type T.
-pub inline fn nan(comptime T: type) T {
- return switch (@typeInfo(T).Float.bits) {
- 16 => math.nan_f16,
- 32 => math.nan_f32,
- 64 => math.nan_f64,
- 80 => math.nan_f80,
- 128 => math.nan_f128,
- else => @compileError("unreachable"),
- };
-}
-
-/// Returns the signalling nan representation for type T.
-/// Note: A signalling nan is identical to a standard right now by may have a different bit
-/// representation in the future when required.
-pub inline fn snan(comptime T: type) T {
- return nan(T);
-}
lib/std/zig/c_builtins.zig
@@ -207,7 +207,7 @@ pub inline fn __builtin_expect(expr: c_long, c: c_long) c_long {
pub inline fn __builtin_nanf(tagp: []const u8) f32 {
const parsed = std.fmt.parseUnsigned(c_ulong, tagp, 0) catch 0;
const bits: u23 = @truncate(parsed); // single-precision float trailing significand is 23 bits
- return @bitCast(@as(u32, bits) | std.math.qnan_u32);
+ return @bitCast(@as(u32, bits) | @as(u32, @bitCast(std.math.nan(f32))));
}
pub inline fn __builtin_huge_valf() f32 {
lib/std/fmt.zig
@@ -2384,22 +2384,22 @@ test "float.scientific.precision" {
}
test "float.special" {
- try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});
+ try expectFmt("f64: nan", "f64: {}", .{math.nan(f64)});
// negative nan is not defined by IEE 754,
// and ARM thus normalizes it to positive nan
if (builtin.target.cpu.arch != .arm) {
- try expectFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
+ try expectFmt("f64: -nan", "f64: {}", .{-math.nan(f64)});
}
try expectFmt("f64: inf", "f64: {}", .{math.inf(f64)});
try expectFmt("f64: -inf", "f64: {}", .{-math.inf(f64)});
}
test "float.hexadecimal.special" {
- try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64});
+ try expectFmt("f64: nan", "f64: {x}", .{math.nan(f64)});
// negative nan is not defined by IEE 754,
// and ARM thus normalizes it to positive nan
if (builtin.target.cpu.arch != .arm) {
- try expectFmt("f64: -nan", "f64: {x}", .{-math.nan_f64});
+ try expectFmt("f64: -nan", "f64: {x}", .{-math.nan(f64)});
}
try expectFmt("f64: inf", "f64: {x}", .{math.inf(f64)});
try expectFmt("f64: -inf", "f64: {x}", .{-math.inf(f64)});
lib/std/math.zig
@@ -47,6 +47,8 @@ pub const floatMin = @import("math/float.zig").floatMin;
pub const floatMax = @import("math/float.zig").floatMax;
pub const floatEps = @import("math/float.zig").floatEps;
pub const inf = @import("math/float.zig").inf;
+pub const nan = @import("math/float.zig").nan;
+pub const snan = @import("math/float.zig").snan;
pub const f16_true_min = @compileError("Deprecated: use `floatTrueMin(f16)` instead");
pub const f32_true_min = @compileError("Deprecated: use `floatTrueMin(f32)` instead");
@@ -73,47 +75,38 @@ pub const f32_toint = @compileError("Deprecated: use `1.0 / floatEps(f32)` inste
pub const f64_toint = @compileError("Deprecated: use `1.0 / floatEps(f64)` instead");
pub const f80_toint = @compileError("Deprecated: use `1.0 / floatEps(f80)` instead");
pub const f128_toint = @compileError("Deprecated: use `1.0 / floatEps(f128)` instead");
-pub const inf_u16 = @compileError("Deprecated: use `@bitCast(u16, inf(f16))` instead");
+pub const inf_u16 = @compileError("Deprecated: use `@as(u16, @bitCast(inf(f16)))` instead");
pub const inf_f16 = @compileError("Deprecated: use `inf(f16)` instead");
-pub const inf_u32 = @compileError("Deprecated: use `@bitCast(u32, inf(f32))` instead");
+pub const inf_u32 = @compileError("Deprecated: use `@as(u32, @bitCast(inf(f32)))` instead");
pub const inf_f32 = @compileError("Deprecated: use `inf(f32)` instead");
-pub const inf_u64 = @compileError("Deprecated: use `@bitCast(u64, inf(f64))` instead");
+pub const inf_u64 = @compileError("Deprecated: use `@as(u64, @bitCast(inf(f64)))` instead");
pub const inf_f64 = @compileError("Deprecated: use `inf(f64)` instead");
+pub const inf_u80 = @compileError("Deprecated: use `@as(u80, @bitCast(inf(f80)))` instead");
pub const inf_f80 = @compileError("Deprecated: use `inf(f80)` instead");
-pub const inf_u128 = @compileError("Deprecated: use `@bitCast(u128, inf(f128))` instead");
+pub const inf_u128 = @compileError("Deprecated: use `@as(u128, @bitCast(inf(f128)))` instead");
pub const inf_f128 = @compileError("Deprecated: use `inf(f128)` instead");
+pub const nan_u16 = @compileError("Deprecated: use `@as(u16, @bitCast(nan(f16)))` instead");
+pub const nan_f16 = @compileError("Deprecated: use `nan(f16)` instead");
+pub const nan_u32 = @compileError("Deprecated: use `@as(u32, @bitCast(nan(f32)))` instead");
+pub const nan_f32 = @compileError("Deprecated: use `nan(f32)` instead");
+pub const nan_u64 = @compileError("Deprecated: use `@as(u64, @bitCast(nan(f64)))` instead");
+pub const nan_f64 = @compileError("Deprecated: use `nan(f64)` instead");
+pub const nan_u80 = @compileError("Deprecated: use `@as(u80, @bitCast(nan(f80)))` instead");
+pub const nan_f80 = @compileError("Deprecated: use `nan(f80)` instead");
+pub const nan_u128 = @compileError("Deprecated: use `@as(u128, @bitCast(nan(f128)))` instead");
+pub const nan_f128 = @compileError("Deprecated: use `nan(f128)` instead");
+pub const qnan_u16 = @compileError("Deprecated: use `@as(u16, @bitCast(nan(f16)))` instead");
+pub const qnan_f16 = @compileError("Deprecated: use `nan(f16)` instead");
+pub const qnan_u32 = @compileError("Deprecated: use `@as(u32, @bitCast(nan(f32)))` instead");
+pub const qnan_f32 = @compileError("Deprecated: use `nan(f32)` instead");
+pub const qnan_u64 = @compileError("Deprecated: use `@as(u64, @bitCast(nan(f64)))` instead");
+pub const qnan_f64 = @compileError("Deprecated: use `nan(f64)` instead");
+pub const qnan_u80 = @compileError("Deprecated: use `@as(u80, @bitCast(nan(f80)))` instead");
+pub const qnan_f80 = @compileError("Deprecated: use `nan(f80)` instead");
+pub const qnan_u128 = @compileError("Deprecated: use `@as(u128, @bitCast(nan(f128)))` instead");
+pub const qnan_f128 = @compileError("Deprecated: use `nan(f128)` instead");
pub const epsilon = @compileError("Deprecated: use `floatEps` instead");
-pub const nan_u16 = @as(u16, 0x7C01);
-pub const nan_f16 = @as(f16, @bitCast(nan_u16));
-
-pub const qnan_u16 = @as(u16, 0x7E00);
-pub const qnan_f16 = @as(f16, @bitCast(qnan_u16));
-
-pub const nan_u32 = @as(u32, 0x7F800001);
-pub const nan_f32 = @as(f32, @bitCast(nan_u32));
-
-pub const qnan_u32 = @as(u32, 0x7FC00000);
-pub const qnan_f32 = @as(f32, @bitCast(qnan_u32));
-
-pub const nan_u64 = @as(u64, 0x7FF << 52) | 1;
-pub const nan_f64 = @as(f64, @bitCast(nan_u64));
-
-pub const qnan_u64 = @as(u64, 0x7ff8000000000000);
-pub const qnan_f64 = @as(f64, @bitCast(qnan_u64));
-
-pub const nan_f80 = make_f80(F80{ .fraction = 0xA000000000000000, .exp = 0x7fff });
-pub const qnan_f80 = make_f80(F80{ .fraction = 0xC000000000000000, .exp = 0x7fff });
-
-pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001);
-pub const nan_f128 = @as(f128, @bitCast(nan_u128));
-
-pub const qnan_u128 = @as(u128, 0x7fff8000000000000000000000000000);
-pub const qnan_f128 = @as(f128, @bitCast(qnan_u128));
-
-pub const nan = @import("math/nan.zig").nan;
-pub const snan = @import("math/nan.zig").snan;
-
/// Performs an approximate comparison of two floating point values `x` and `y`.
/// Returns true if the absolute difference between them is less or equal than
/// the specified tolerance.
@@ -336,37 +329,8 @@ test {
_ = floatMax;
_ = floatEps;
_ = inf;
-
- _ = nan_u16;
- _ = nan_f16;
-
- _ = qnan_u16;
- _ = qnan_f16;
-
- _ = nan_u32;
- _ = nan_f32;
-
- _ = qnan_u32;
- _ = qnan_f32;
-
- _ = nan_u64;
- _ = nan_f64;
-
- _ = qnan_u64;
- _ = qnan_f64;
-
- _ = nan_f80;
- _ = qnan_f80;
-
- _ = nan_u128;
- _ = nan_f128;
-
- _ = qnan_u128;
- _ = qnan_f128;
-
_ = nan;
_ = snan;
-
_ = isNan;
_ = isSignalNan;
_ = frexp;
src/codegen/c.zig
@@ -1087,7 +1087,7 @@ pub const DeclGen = struct {
// MSVC doesn't have a way to define a custom or signaling NaN value in a constant expression
// TODO: Re-enable this check, otherwise we're writing qnan bit patterns on msvc incorrectly
- // if (std.math.isNan(f128_val) and f128_val != std.math.qnan_f128)
+ // if (std.math.isNan(f128_val) and f128_val != std.math.nan(f128))
// return dg.fail("Only quiet nans are supported in global variable initializers", .{});
}
@@ -6704,13 +6704,13 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
.Min => switch (scalar_ty.zigTypeTag(mod)) {
.Bool => Value.true,
.Int => try scalar_ty.maxIntScalar(mod, scalar_ty),
- .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
+ .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
else => unreachable,
},
.Max => switch (scalar_ty.zigTypeTag(mod)) {
.Bool => Value.false,
.Int => try scalar_ty.minIntScalar(mod, scalar_ty),
- .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
+ .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
else => unreachable,
},
}, .Initializer);
src/Sema.zig
@@ -15593,7 +15593,7 @@ fn analyzeArithmetic(
return Air.internedToRef(rhs_val.toIntern());
}
if (rhs_val.isInf(mod)) {
- return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan_f128)).toIntern());
+ return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan(f128))).toIntern());
}
} else if (resolved_type.isAnyFloat()) {
break :lz;
@@ -15621,7 +15621,7 @@ fn analyzeArithmetic(
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: {
if (maybe_lhs_val) |lhs_val| {
if (lhs_val.isInf(mod)) {
- return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan_f128)).toIntern());
+ return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan(f128))).toIntern());
}
} else if (resolved_type.isAnyFloat()) {
break :rz;
test/behavior/bugs/14198.zig
@@ -3,16 +3,33 @@ const math = std.math;
const mem = std.mem;
const testing = std.testing;
+const qnan_u16: u16 = 0x7E00;
+const snan_u16: u16 = 0x7D00;
+const qnan_u32: u32 = 0x7FC00000;
+const snan_u32: u32 = 0x7FA00000;
+const qnan_u64: u64 = 0x7FF8000000000000;
+const snan_u64: u64 = 0x7FF4000000000000;
+const qnan_u128: u128 = 0x7FFF8000000000000000000000000000;
+const snan_u128: u128 = 0x7FFF4000000000000000000000000000;
+const qnan_f16: f16 = math.nan(f16);
+const snan_f16: f16 = math.snan(f16);
+const qnan_f32: f32 = math.nan(f32);
+const snan_f32: f32 = math.snan(f32);
+const qnan_f64: f64 = math.nan(f64);
+const snan_f64: f64 = math.snan(f64);
+const qnan_f128: f128 = math.nan(f128);
+const snan_f128: f128 = math.snan(f128);
+
test "nan memory equality" {
// signaled
- try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u16), mem.asBytes(&math.nan_f16)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u32), mem.asBytes(&math.nan_f32)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u64), mem.asBytes(&math.nan_f64)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.nan_u128), mem.asBytes(&math.nan_f128)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&snan_u16), mem.asBytes(&snan_f16)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&snan_u32), mem.asBytes(&snan_f32)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&snan_u64), mem.asBytes(&snan_f64)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&snan_u128), mem.asBytes(&snan_f128)));
// quiet
- try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u16), mem.asBytes(&math.qnan_f16)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u32), mem.asBytes(&math.qnan_f32)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u64), mem.asBytes(&math.qnan_f64)));
- try testing.expect(mem.eql(u8, mem.asBytes(&math.qnan_u128), mem.asBytes(&math.qnan_f128)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&qnan_u16), mem.asBytes(&qnan_f16)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&qnan_u32), mem.asBytes(&qnan_f32)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&qnan_u64), mem.asBytes(&qnan_f64)));
+ try testing.expect(mem.eql(u8, mem.asBytes(&qnan_u128), mem.asBytes(&qnan_f128)));
}
test/behavior/bitcast.zig
@@ -413,7 +413,7 @@ fn bitCastWrapper64(x: f64) u64 {
fn bitCastWrapper128(x: f128) u128 {
return @as(u128, @bitCast(x));
}
-test "bitcast nan float does modify signaling bit" {
+test "bitcast nan float does not modify signaling bit" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
@@ -423,41 +423,46 @@ test "bitcast nan float does modify signaling bit" {
// TODO: https://github.com/ziglang/zig/issues/14366
if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
+ const snan_u16: u16 = 0x7D00;
+ const snan_u32: u32 = 0x7FA00000;
+ const snan_u64: u64 = 0x7FF4000000000000;
+ const snan_u128: u128 = 0x7FFF4000000000000000000000000000;
+
// 16 bit
- const snan_f16_const = math.nan_f16;
- try expectEqual(math.nan_u16, @as(u16, @bitCast(snan_f16_const)));
- try expectEqual(math.nan_u16, bitCastWrapper16(snan_f16_const));
+ const snan_f16_const = math.snan(f16);
+ try expectEqual(snan_u16, @as(u16, @bitCast(snan_f16_const)));
+ try expectEqual(snan_u16, bitCastWrapper16(snan_f16_const));
- var snan_f16_var = math.nan_f16;
- try expectEqual(math.nan_u16, @as(u16, @bitCast(snan_f16_var)));
- try expectEqual(math.nan_u16, bitCastWrapper16(snan_f16_var));
+ var snan_f16_var = math.snan(f16);
+ try expectEqual(snan_u16, @as(u16, @bitCast(snan_f16_var)));
+ try expectEqual(snan_u16, bitCastWrapper16(snan_f16_var));
// 32 bit
- const snan_f32_const = math.nan_f32;
- try expectEqual(math.nan_u32, @as(u32, @bitCast(snan_f32_const)));
- try expectEqual(math.nan_u32, bitCastWrapper32(snan_f32_const));
+ const snan_f32_const = math.snan(f32);
+ try expectEqual(snan_u32, @as(u32, @bitCast(snan_f32_const)));
+ try expectEqual(snan_u32, bitCastWrapper32(snan_f32_const));
- var snan_f32_var = math.nan_f32;
- try expectEqual(math.nan_u32, @as(u32, @bitCast(snan_f32_var)));
- try expectEqual(math.nan_u32, bitCastWrapper32(snan_f32_var));
+ var snan_f32_var = math.snan(f32);
+ try expectEqual(snan_u32, @as(u32, @bitCast(snan_f32_var)));
+ try expectEqual(snan_u32, bitCastWrapper32(snan_f32_var));
// 64 bit
- const snan_f64_const = math.nan_f64;
- try expectEqual(math.nan_u64, @as(u64, @bitCast(snan_f64_const)));
- try expectEqual(math.nan_u64, bitCastWrapper64(snan_f64_const));
+ const snan_f64_const = math.snan(f64);
+ try expectEqual(snan_u64, @as(u64, @bitCast(snan_f64_const)));
+ try expectEqual(snan_u64, bitCastWrapper64(snan_f64_const));
- var snan_f64_var = math.nan_f64;
- try expectEqual(math.nan_u64, @as(u64, @bitCast(snan_f64_var)));
- try expectEqual(math.nan_u64, bitCastWrapper64(snan_f64_var));
+ var snan_f64_var = math.snan(f64);
+ try expectEqual(snan_u64, @as(u64, @bitCast(snan_f64_var)));
+ try expectEqual(snan_u64, bitCastWrapper64(snan_f64_var));
// 128 bit
- const snan_f128_const = math.nan_f128;
- try expectEqual(math.nan_u128, @as(u128, @bitCast(snan_f128_const)));
- try expectEqual(math.nan_u128, bitCastWrapper128(snan_f128_const));
+ const snan_f128_const = math.snan(f128);
+ try expectEqual(snan_u128, @as(u128, @bitCast(snan_f128_const)));
+ try expectEqual(snan_u128, bitCastWrapper128(snan_f128_const));
- var snan_f128_var = math.nan_f128;
- try expectEqual(math.nan_u128, @as(u128, @bitCast(snan_f128_var)));
- try expectEqual(math.nan_u128, bitCastWrapper128(snan_f128_var));
+ var snan_f128_var = math.snan(f128);
+ try expectEqual(snan_u128, @as(u128, @bitCast(snan_f128_var)));
+ try expectEqual(snan_u128, bitCastWrapper128(snan_f128_var));
}
test "@bitCast of packed struct of bools all true" {
test/behavior/maximum_minimum.zig
@@ -44,8 +44,8 @@ test "@max on vectors" {
var y = @max(c, d);
try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ 0, 0.42, -0.64, 7.8 }));
- var e: @Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
- var f: @Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var e: @Vector(2, f32) = [2]f32{ 0, std.math.nan(f32) };
+ var f: @Vector(2, f32) = [2]f32{ std.math.nan(f32), 0 };
var z = @max(e, f);
try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
}
@@ -93,8 +93,8 @@ test "@min for vectors" {
var y = @min(c, d);
try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ -0.23, 0.4, -2.4, 0.9 }));
- var e: @Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
- var f: @Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var e: @Vector(2, f32) = [2]f32{ 0, std.math.nan(f32) };
+ var f: @Vector(2, f32) = [2]f32{ std.math.nan(f32), 0 };
var z = @max(e, f);
try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
}
CMakeLists.txt
@@ -276,7 +276,6 @@ set(ZIG_STAGE2_SOURCES
"${CMAKE_SOURCE_DIR}/lib/std/math/log.zig"
"${CMAKE_SOURCE_DIR}/lib/std/math/log10.zig"
"${CMAKE_SOURCE_DIR}/lib/std/math/log2.zig"
- "${CMAKE_SOURCE_DIR}/lib/std/math/nan.zig"
"${CMAKE_SOURCE_DIR}/lib/std/math/signbit.zig"
"${CMAKE_SOURCE_DIR}/lib/std/math/sqrt.zig"
"${CMAKE_SOURCE_DIR}/lib/std/mem.zig"