Skip to content

Commit

Permalink
std.math.big.int: fix shiftRight sign handling
Browse files Browse the repository at this point in the history
Closes #21311

The sign of the result `r` needs to be initialized before the correction
`r.addScalar(r.toConst(), -1)`, or the intended end result could be off
by 2 (depending on the original sign of `r`).
  • Loading branch information
ianprime0509 authored and andrewrk committed Sep 6, 2024
1 parent 3929cac commit 3543f28
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/std/math/big/int.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ pub const Mutable = struct {
llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);

r.len = a.limbs.len - full_limbs_shifted_out;
r.positive = a.positive;
if (nonzero_negative_shiftout) {
if (full_limbs_shifted_out > 0) {
r.limbs[a.limbs.len - full_limbs_shifted_out] = 0;
Expand All @@ -1210,7 +1211,6 @@ pub const Mutable = struct {
r.addScalar(r.toConst(), -1);
}
r.normalize(r.len);
r.positive = a.positive;
}

/// r = ~a under 2s complement wrapping semantics.
Expand Down
9 changes: 9 additions & 0 deletions lib/std/math/big/int_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2083,6 +2083,15 @@ test "shift-right negative" {
try a.shiftRight(&a, 1);
a.setSign(true);
try testing.expect(try a.to(u64) == 0x8000000000000000);

var arg7 = try Managed.initSet(testing.allocator, -32767);
defer arg7.deinit();
a.setSign(false);
try a.shiftRight(&arg7, 4);
try testing.expect(try a.to(i16) == -2048);
a.setSign(true);
try a.shiftRight(&arg7, 4);
try testing.expect(try a.to(i16) == -2048);
}

test "sat shift-left simple unsigned" {
Expand Down

0 comments on commit 3543f28

Please sign in to comment.