From 70d7f87be00aa1a372c856759948fd62666be295 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Thu, 10 Feb 2022 13:29:48 -0700 Subject: Fix up sign handling and add arbitrary-length integer support to @bitCast() --- test/behavior/bitcast.zig | 107 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 4 deletions(-) (limited to 'test/behavior') diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index d56e3c1c53..43d6524a4e 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -3,6 +3,7 @@ const builtin = @import("builtin"); const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const maxInt = std.math.maxInt; +const minInt = std.math.minInt; const native_endian = builtin.target.cpu.arch.endian(); test "@bitCast i32 -> u32" { @@ -11,21 +12,119 @@ test "@bitCast i32 -> u32" { } fn testBitCast_i32_u32() !void { - try expect(conv(-1) == maxInt(u32)); - try expect(conv2(maxInt(u32)) == -1); + try expect(conv_i32(-1) == maxInt(u32)); + try expect(conv_u32(maxInt(u32)) == -1); + try expect(conv_u32(0x8000_0000) == minInt(i32)); + try expect(conv_i32(minInt(i32)) == 0x8000_0000); } -fn conv(x: i32) u32 { +fn conv_i32(x: i32) u32 { return @bitCast(u32, x); } -fn conv2(x: u32) i32 { +fn conv_u32(x: u32) i32 { return @bitCast(i32, x); } +test "@bitCast i48 -> u48" { + try testBitCast_i48_u48(); + comptime try testBitCast_i48_u48(); +} + +fn testBitCast_i48_u48() !void { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + try expect(conv_i48(-1) == maxInt(u48)); + try expect(conv_u48(maxInt(u48)) == -1); + try expect(conv_u48(0x8000_0000_0000) == minInt(i48)); + try expect(conv_i48(minInt(i48)) == 0x8000_0000_0000); +} + +fn conv_i48(x: i48) u48 { + return @bitCast(u48, x); +} + +fn conv_u48(x: u48) i48 { + return @bitCast(i48, x); +} + +test "@bitCast i27 -> u27" { + try testBitCast_i27_u27(); + comptime try testBitCast_i27_u27(); +} + +fn testBitCast_i27_u27() !void { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + try expect(conv_i27(-1) == maxInt(u27)); + try expect(conv_u27(maxInt(u27)) == -1); + try expect(conv_u27(0x400_0000) == minInt(i27)); + try expect(conv_i27(minInt(i27)) == 0x400_0000); +} + +fn conv_i27(x: i27) u27 { + return @bitCast(u27, x); +} + +fn conv_u27(x: u27) i27 { + return @bitCast(i27, x); +} + +test "@bitCast i512 -> u512" { + try testBitCast_i512_u512(); + comptime try testBitCast_i512_u512(); +} + +fn testBitCast_i512_u512() !void { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + try expect(conv_i512(-1) == maxInt(u512)); + try expect(conv_u512(maxInt(u512)) == -1); + try expect(conv_u512(@as(u512, 1) << 511) == minInt(i512)); + try expect(conv_i512(minInt(i512)) == (@as(u512, 1) << 511)); +} + +fn conv_i512(x: i512) u512 { + return @bitCast(u512, x); +} + +fn conv_u512(x: u512) i512 { + return @bitCast(i512, x); +} + test "bitcast result to _" { _ = @bitCast(u8, @as(i8, 1)); } +test "@bitCast i493 -> u493" { + try testBitCast_i493_u493(); + comptime try testBitCast_i493_u493(); +} + +fn testBitCast_i493_u493() !void { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + try expect(conv_i493(-1) == maxInt(u493)); + try expect(conv_u493(maxInt(u493)) == -1); + try expect(conv_u493(@as(u493, 1) << 492) == minInt(i493)); + try expect(conv_i493(minInt(i493)) == (@as(u493, 1) << 492)); +} + +fn conv_i493(x: i493) u493 { + return @bitCast(u493, x); +} + +fn conv_u493(x: u493) i493 { + return @bitCast(i493, x); +} + test "nested bitcast" { const S = struct { fn moo(x: isize) !void { -- cgit v1.2.3 From c586e3ba1bbc7784aee22bf96f69b8003611112a Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Sun, 13 Feb 2022 11:59:14 -0700 Subject: Add additional tests for `@bitCast` --- lib/std/math/big/int_test.zig | 91 ++++++++++++++++++++++++++++++ test/behavior/bitcast.zig | 126 ++++++++++-------------------------------- 2 files changed, 119 insertions(+), 98 deletions(-) (limited to 'test/behavior') diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 69600425a4..e7469326e4 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -2550,6 +2550,43 @@ test "big int conversion read twos complement with padding" { try testing.expect(std.mem.eql(u8, buffer1, &[_]u8{ 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 })); } +test "big int write twos complement +/- zero" { + var a = try Managed.initSet(testing.allocator, 0x0); + defer a.deinit(); + var m = a.toMutable(); + + var buffer1 = try testing.allocator.alloc(u8, 16); + defer testing.allocator.free(buffer1); + @memset(buffer1.ptr, 0xaa, buffer1.len); + + var bit_count: usize = 0; + + // Test zero + + m.toConst().writeTwosComplement(buffer1, bit_count, 13, .Little); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 13, .Big); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 16, .Little); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 16, .Big); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + + @memset(buffer1.ptr, 0xaa, buffer1.len); + m.positive = false; + + // Test negative zero + + m.toConst().writeTwosComplement(buffer1, bit_count, 13, .Little); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 13, .Big); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 13) ++ ([_]u8{0xaa} ** 3)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 16, .Little); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); + m.toConst().writeTwosComplement(buffer1, bit_count, 16, .Big); + try testing.expect(std.mem.eql(u8, buffer1, &(([_]u8{0} ** 16)))); +} + test "big int conversion write twos complement with padding" { var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff); defer a.deinit(); @@ -2564,6 +2601,8 @@ test "big int conversion write twos complement with padding" { var bit_count: usize = 12 * 8 + 1; var buffer: []const u8 = undefined; + // Test 0x01_02030405_06070809_0a0b0c0d + buffer = &[_]u8{ 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0xb }; m.readTwosComplement(buffer, bit_count, 13, .Little, .unsigned); try testing.expect(m.toConst().orderAgainstScalar(0x01_02030405_06070809_0a0b0c0d) == .eq); @@ -2582,6 +2621,8 @@ test "big int conversion write twos complement with padding" { bit_count = 12 * 8 + 2; + // Test -0x01_02030405_06070809_0a0b0c0d + buffer = &[_]u8{ 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x02 }; m.readTwosComplement(buffer, bit_count, 13, .Little, .signed); try testing.expect(m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d) == .eq); @@ -2597,4 +2638,54 @@ test "big int conversion write twos complement with padding" { buffer = &[_]u8{ 0xaa, 0xaa, 0xaa, 0x02, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf3 }; m.readTwosComplement(buffer, bit_count, 16, .Big, .signed); try testing.expect(m.toConst().orderAgainstScalar(-0x01_02030405_06070809_0a0b0c0d) == .eq); + + // Test 0 + + buffer = &([_]u8{0} ** 16); + m.readTwosComplement(buffer, bit_count, 13, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 13, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 16, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 16, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + + bit_count = 0; + buffer = &([_]u8{0xaa} ** 16); + m.readTwosComplement(buffer, bit_count, 13, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 13, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 16, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 16, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); +} + +test "big int conversion write twos complement zero" { + var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff); + defer a.deinit(); + + var m = a.toMutable(); + + // readTwosComplement: + // (1) should not read beyond buffer[0..abi_size] + // (2) should correctly interpret bytes based on the provided endianness + // (3) should ignore any bits from bit_count to 8 * abi_size + + var bit_count: usize = 12 * 8 + 1; + var buffer: []const u8 = undefined; + + buffer = &([_]u8{0} ** 13); + m.readTwosComplement(buffer, bit_count, 13, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 13, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + + buffer = &([_]u8{0} ** 16); + m.readTwosComplement(buffer, bit_count, 16, .Little, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); + m.readTwosComplement(buffer, bit_count, 16, .Big, .unsigned); + try testing.expect(m.toConst().orderAgainstScalar(0x0) == .eq); } diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 43d6524a4e..59a16c5fc9 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -6,123 +6,53 @@ const maxInt = std.math.maxInt; const minInt = std.math.minInt; const native_endian = builtin.target.cpu.arch.endian(); -test "@bitCast i32 -> u32" { - try testBitCast_i32_u32(); - comptime try testBitCast_i32_u32(); -} - -fn testBitCast_i32_u32() !void { - try expect(conv_i32(-1) == maxInt(u32)); - try expect(conv_u32(maxInt(u32)) == -1); - try expect(conv_u32(0x8000_0000) == minInt(i32)); - try expect(conv_i32(minInt(i32)) == 0x8000_0000); -} - -fn conv_i32(x: i32) u32 { - return @bitCast(u32, x); -} -fn conv_u32(x: u32) i32 { - return @bitCast(i32, x); -} - -test "@bitCast i48 -> u48" { - try testBitCast_i48_u48(); - comptime try testBitCast_i48_u48(); -} - -fn testBitCast_i48_u48() !void { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - - try expect(conv_i48(-1) == maxInt(u48)); - try expect(conv_u48(maxInt(u48)) == -1); - try expect(conv_u48(0x8000_0000_0000) == minInt(i48)); - try expect(conv_i48(minInt(i48)) == 0x8000_0000_0000); -} - -fn conv_i48(x: i48) u48 { - return @bitCast(u48, x); -} - -fn conv_u48(x: u48) i48 { - return @bitCast(i48, x); -} +test "@bitCast iX -> uX" { + const bit_values = [_]usize{ 8, 16, 32, 64 }; -test "@bitCast i27 -> u27" { - try testBitCast_i27_u27(); - comptime try testBitCast_i27_u27(); + inline for (bit_values) |bits| { + try testBitCast(bits); + comptime try testBitCast(bits); + } } -fn testBitCast_i27_u27() !void { +test "@bitCast iX -> uX exotic integers" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - try expect(conv_i27(-1) == maxInt(u27)); - try expect(conv_u27(maxInt(u27)) == -1); - try expect(conv_u27(0x400_0000) == minInt(i27)); - try expect(conv_i27(minInt(i27)) == 0x400_0000); -} - -fn conv_i27(x: i27) u27 { - return @bitCast(u27, x); -} - -fn conv_u27(x: u27) i27 { - return @bitCast(i27, x); -} - -test "@bitCast i512 -> u512" { - try testBitCast_i512_u512(); - comptime try testBitCast_i512_u512(); -} - -fn testBitCast_i512_u512() !void { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 }; - try expect(conv_i512(-1) == maxInt(u512)); - try expect(conv_u512(maxInt(u512)) == -1); - try expect(conv_u512(@as(u512, 1) << 511) == minInt(i512)); - try expect(conv_i512(minInt(i512)) == (@as(u512, 1) << 511)); + inline for (bit_values) |bits| { + try testBitCast(bits); + comptime try testBitCast(bits); + } } -fn conv_i512(x: i512) u512 { - return @bitCast(u512, x); -} +fn testBitCast(comptime N: usize) !void { + const iN = std.meta.Int(.signed, N); + const uN = std.meta.Int(.unsigned, N); -fn conv_u512(x: u512) i512 { - return @bitCast(i512, x); -} + try expect(conv_iN(N, -1) == maxInt(uN)); + try expect(conv_uN(N, maxInt(uN)) == -1); -test "bitcast result to _" { - _ = @bitCast(u8, @as(i8, 1)); -} + try expect(conv_iN(N, maxInt(iN)) == maxInt(iN)); + try expect(conv_uN(N, maxInt(iN)) == maxInt(iN)); -test "@bitCast i493 -> u493" { - try testBitCast_i493_u493(); - comptime try testBitCast_i493_u493(); -} + try expect(conv_uN(N, 1 << (N - 1)) == minInt(iN)); + try expect(conv_iN(N, minInt(iN)) == (1 << (N - 1))); -fn testBitCast_i493_u493() !void { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + try expect(conv_uN(N, 0) == 0); + try expect(conv_iN(N, 0) == 0); - try expect(conv_i493(-1) == maxInt(u493)); - try expect(conv_u493(maxInt(u493)) == -1); - try expect(conv_u493(@as(u493, 1) << 492) == minInt(i493)); - try expect(conv_i493(minInt(i493)) == (@as(u493, 1) << 492)); + try expect(conv_iN(N, -0) == 0); } -fn conv_i493(x: i493) u493 { - return @bitCast(u493, x); +fn conv_iN(comptime N: usize, x: std.meta.Int(.signed, N)) std.meta.Int(.unsigned, N) { + return @bitCast(std.meta.Int(.unsigned, N), x); } -fn conv_u493(x: u493) i493 { - return @bitCast(i493, x); +fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signed, N) { + return @bitCast(std.meta.Int(.signed, N), x); } test "nested bitcast" { -- cgit v1.2.3 From 45aed7171c5cafb06671714ac1b15fdcf056d040 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Sun, 13 Feb 2022 13:01:55 -0700 Subject: Skip 8/16-bit `@bitCast` test for wasm --- test/behavior/bitcast.zig | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'test/behavior') diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 59a16c5fc9..1bf33af57b 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -6,8 +6,18 @@ const maxInt = std.math.maxInt; const minInt = std.math.minInt; const native_endian = builtin.target.cpu.arch.endian(); -test "@bitCast iX -> uX" { - const bit_values = [_]usize{ 8, 16, 32, 64 }; +test "@bitCast iX -> uX (32, 64)" { + const bit_values = [_]usize{ 32, 64 }; + + inline for (bit_values) |bits| { + try testBitCast(bits); + comptime try testBitCast(bits); + } +} + +test "@bitCast iX -> uX (8, 16, 128)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + const bit_values = [_]usize{ 8, 16, 128 }; inline for (bit_values) |bits| { try testBitCast(bits); -- cgit v1.2.3