From 3543f283208951514c0fdb45b0dde7393e5e40c7 Mon Sep 17 00:00:00 2001 From: Ian Johnson Date: Thu, 5 Sep 2024 23:05:21 -0400 Subject: [PATCH] std.math.big.int: fix shiftRight sign handling 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`). --- lib/std/math/big/int.zig | 2 +- lib/std/math/big/int_test.zig | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 2c656033e91b..2d38517661a8 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -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; @@ -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. diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 17652179f599..2e0ccc96c17b 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -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" {