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 {
14051405 r.normalize(r.len);
14061406 }
14071407 } else {
1408 r.copy(a);
1409 if (r.len < req_limbs) {
1408 if (a.limbs.len < req_limbs) {
14101409 // Integer fits within target bits, no wrapping required.
1410 r.copy(a);
14111411 return;
14121412 }
14131413
1414 r.len = req_limbs;
1414 r.copy(.{
1415 .positive = a.positive,
1416 .limbs = a.limbs[0..req_limbs],
1417 });
14151418 r.limbs[r.len - 1] &= mask;
14161419 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" {
16541654 try testing.expect((try a.to(i17)) == 0);
16551655}
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
16571669test "big.int saturate single signed positive" {
16581670 var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
16591671 defer a.deinit();
src/Sema.zig+6-2
......@@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
94779477 }
94789478
94799479 const target = sema.mod.getTarget();
9480 const src_info = operand_ty.intInfo(target);
94819480 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) {
94849483 return sema.addConstant(dest_ty, Value.zero);
94859484 }
94869485
94879486 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
94889492 if (src_info.signedness != dest_info.signedness) {
94899493 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
94909494 @tagName(dest_info.signedness), operand_ty,
test/behavior.zig+1-1
......@@ -51,6 +51,7 @@ test {
5151 _ = @import("behavior/switch.zig");
5252 _ = @import("behavior/this.zig");
5353 _ = @import("behavior/translate_c_macros.zig");
54 _ = @import("behavior/truncate.zig");
5455 _ = @import("behavior/underscore.zig");
5556 _ = @import("behavior/union.zig");
5657 _ = @import("behavior/usingnamespace.zig");
......@@ -163,7 +164,6 @@ test {
163164 _ = @import("behavior/switch_prong_err_enum.zig");
164165 _ = @import("behavior/switch_prong_implicit_cast.zig");
165166 _ = @import("behavior/switch_stage1.zig");
166 _ = @import("behavior/truncate.zig");
167167 _ = @import("behavior/try.zig");
168168 _ = @import("behavior/tuple.zig");
169169 _ = @import("behavior/type.zig");