authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-22 01:24:38+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-21 20:10:27-04:00
loga3c9bfef301e0a4675fcea57356653334e07df45
tree6b5ca8affd586340ebb0f43d9aef8b558671e0f6
parentd49c601d623d0b5a90f47c95cb931fe21a13d89e

stage2: truncation

* Also fixes a related case where big int truncate would assume that the input fits in the output limbs buffer

4 files changed, 25 insertions(+), 6 deletions(-)

lib/std/math/big/int.zig+6-3
...@@ -1405,13 +1405,16 @@ pub const Mutable = struct {...@@ -1405,13 +1405,16 @@ pub const Mutable = struct {
1405 r.normalize(r.len);1405 r.normalize(r.len);
1406 }1406 }
1407 } else {1407 } else {
1408 r.copy(a);1408 if (a.limbs.len < req_limbs) {
1409 if (r.len < req_limbs) {
1410 // Integer fits within target bits, no wrapping required.1409 // Integer fits within target bits, no wrapping required.
1410 r.copy(a);
1411 return;1411 return;
1412 }1412 }
14131413
1414 r.len = req_limbs;1414 r.copy(.{
1415 .positive = a.positive,
1416 .limbs = a.limbs[0..req_limbs],
1417 });
1415 r.limbs[r.len - 1] &= mask;1418 r.limbs[r.len - 1] &= mask;
1416 r.normalize(r.len);1419 r.normalize(r.len);
14171420
lib/std/math/big/int_test.zig+12
...@@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" {...@@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" {
1654 try testing.expect((try a.to(i17)) == 0);1654 try testing.expect((try a.to(i17)) == 0);
1655}1655}
16561656
1657test "big.int truncate multi unsigned many" {
1658 var a = try Managed.initSet(testing.allocator, 1);
1659 defer a.deinit();
1660 try a.shiftLeft(a, 1023);
1661
1662 var b = try Managed.init(testing.allocator);
1663 defer b.deinit();
1664 try b.truncate(a.toConst(), .signed, @bitSizeOf(i1));
1665
1666 try testing.expect((try b.to(i1)) == 0);
1667}
1668
1657test "big.int saturate single signed positive" {1669test "big.int saturate single signed positive" {
1658 var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);1670 var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
1659 defer a.deinit();1671 defer a.deinit();
src/Sema.zig+6-2
...@@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9477 }9477 }
94789478
9479 const target = sema.mod.getTarget();9479 const target = sema.mod.getTarget();
9480 const src_info = operand_ty.intInfo(target);
9481 const dest_info = dest_ty.intInfo(target);9480 const dest_info = dest_ty.intInfo(target);
94829481
9483 if (src_info.bits == 0 or dest_info.bits == 0) {9482 if (dest_info.bits == 0) {
9484 return sema.addConstant(dest_ty, Value.zero);9483 return sema.addConstant(dest_ty, Value.zero);
9485 }9484 }
94869485
9487 if (!src_is_comptime_int) {9486 if (!src_is_comptime_int) {
9487 const src_info = operand_ty.intInfo(target);
9488 if (src_info.bits == 0) {
9489 return sema.addConstant(dest_ty, Value.zero);
9490 }
9491
9488 if (src_info.signedness != dest_info.signedness) {9492 if (src_info.signedness != dest_info.signedness) {
9489 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{9493 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
9490 @tagName(dest_info.signedness), operand_ty,9494 @tagName(dest_info.signedness), operand_ty,
test/behavior.zig+1-1
...@@ -51,6 +51,7 @@ test {...@@ -51,6 +51,7 @@ test {
51 _ = @import("behavior/switch.zig");51 _ = @import("behavior/switch.zig");
52 _ = @import("behavior/this.zig");52 _ = @import("behavior/this.zig");
53 _ = @import("behavior/translate_c_macros.zig");53 _ = @import("behavior/translate_c_macros.zig");
54 _ = @import("behavior/truncate.zig");
54 _ = @import("behavior/underscore.zig");55 _ = @import("behavior/underscore.zig");
55 _ = @import("behavior/union.zig");56 _ = @import("behavior/union.zig");
56 _ = @import("behavior/usingnamespace.zig");57 _ = @import("behavior/usingnamespace.zig");
...@@ -163,7 +164,6 @@ test {...@@ -163,7 +164,6 @@ test {
163 _ = @import("behavior/switch_prong_err_enum.zig");164 _ = @import("behavior/switch_prong_err_enum.zig");
164 _ = @import("behavior/switch_prong_implicit_cast.zig");165 _ = @import("behavior/switch_prong_implicit_cast.zig");
165 _ = @import("behavior/switch_stage1.zig");166 _ = @import("behavior/switch_stage1.zig");
166 _ = @import("behavior/truncate.zig");
167 _ = @import("behavior/try.zig");167 _ = @import("behavior/try.zig");
168 _ = @import("behavior/tuple.zig");168 _ = @import("behavior/tuple.zig");
169 _ = @import("behavior/type.zig");169 _ = @import("behavior/type.zig");