authorgravatar for ian@ianjohnson.devIan Johnson <ian@ianjohnson.dev> 2024-09-05 23:05:21-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-06 10:36:12-07:00
log3543f283208951514c0fdb45b0dde7393e5e40c7
treebf1b41d57db171388b42e827a0e96c05175b7ef0
parent3929cac154d71a3e19fd028fc67c1d1d15823ca2

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`).

2 files changed, 10 insertions(+), 1 deletions(-)

lib/std/math/big/int.zig+1-1
...@@ -1202,6 +1202,7 @@ pub const Mutable = struct {...@@ -1202,6 +1202,7 @@ pub const Mutable = struct {
1202 llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);1202 llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);
12031203
1204 r.len = a.limbs.len - full_limbs_shifted_out;1204 r.len = a.limbs.len - full_limbs_shifted_out;
1205 r.positive = a.positive;
1205 if (nonzero_negative_shiftout) {1206 if (nonzero_negative_shiftout) {
1206 if (full_limbs_shifted_out > 0) {1207 if (full_limbs_shifted_out > 0) {
1207 r.limbs[a.limbs.len - full_limbs_shifted_out] = 0;1208 r.limbs[a.limbs.len - full_limbs_shifted_out] = 0;
...@@ -1210,7 +1211,6 @@ pub const Mutable = struct {...@@ -1210,7 +1211,6 @@ pub const Mutable = struct {
1210 r.addScalar(r.toConst(), -1);1211 r.addScalar(r.toConst(), -1);
1211 }1212 }
1212 r.normalize(r.len);1213 r.normalize(r.len);
1213 r.positive = a.positive;
1214 }1214 }
12151215
1216 /// r = ~a under 2s complement wrapping semantics.1216 /// r = ~a under 2s complement wrapping semantics.
lib/std/math/big/int_test.zig+9
...@@ -2083,6 +2083,15 @@ test "shift-right negative" {...@@ -2083,6 +2083,15 @@ test "shift-right negative" {
2083 try a.shiftRight(&a, 1);2083 try a.shiftRight(&a, 1);
2084 a.setSign(true);2084 a.setSign(true);
2085 try testing.expect(try a.to(u64) == 0x8000000000000000);2085 try testing.expect(try a.to(u64) == 0x8000000000000000);
2086
2087 var arg7 = try Managed.initSet(testing.allocator, -32767);
2088 defer arg7.deinit();
2089 a.setSign(false);
2090 try a.shiftRight(&arg7, 4);
2091 try testing.expect(try a.to(i16) == -2048);
2092 a.setSign(true);
2093 try a.shiftRight(&arg7, 4);
2094 try testing.expect(try a.to(i16) == -2048);
2086}2095}
20872096
2088test "sat shift-left simple unsigned" {2097test "sat shift-left simple unsigned" {