authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2021-01-31 20:58:11+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-01 12:10:01-08:00
loga03f9548d3dd32876f99f5b7bdf1d678c5a5b98e
tree157e2951f458d9f63c7e9cda2789f19b2dea36b0
parentbf76501b5d46277d3706a1f0b92ba52f2a47d894

std/math/big/int: normalize after a right shift

After a right shift, top limbs may be all zero. However, without normalization, the number of limbs is not going to change. In order to check if a big number is zero, we used to assume that the number of limbs is 1. Which may not be the case after right shifts, even if the actual value is zero. - Normalize after a right shift - Add a test for that issue - Check all the limbs in `eqlZero()`. It may not be necessary if callers always remember to normalize before calling the function. But checking all the limbs is very cheap and makes the function less bug-prone.

2 files changed, 11 insertions(+), 3 deletions(-)

lib/std/math/big/int.zig+5-3
...@@ -549,8 +549,8 @@ pub const Mutable = struct {...@@ -549,8 +549,8 @@ pub const Mutable = struct {
549 return;549 return;
550 }550 }
551551
552 const r_len = llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);552 llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);
553 r.len = a.limbs.len - (shift / limb_bits);553 r.normalize(a.limbs.len - (shift / limb_bits));
554 r.positive = a.positive;554 r.positive = a.positive;
555 }555 }
556556
...@@ -1348,7 +1348,9 @@ pub const Const = struct {...@@ -1348,7 +1348,9 @@ pub const Const = struct {
13481348
1349 /// Returns true if `a == 0`.1349 /// Returns true if `a == 0`.
1350 pub fn eqZero(a: Const) bool {1350 pub fn eqZero(a: Const) bool {
1351 return a.limbs.len == 1 and a.limbs[0] == 0;1351 var d: Limb = 0;
1352 for (a.limbs) |limb| d |= limb;
1353 return d == 0;
1352 }1354 }
13531355
1354 /// Returns true if `|a| == |b|`.1356 /// Returns true if `|a| == |b|`.
lib/std/math/big/int_test.zig+6
...@@ -1287,6 +1287,12 @@ test "big.int shift-right multi" {...@@ -1287,6 +1287,12 @@ test "big.int shift-right multi" {
1287 try a.shiftRight(a, 67);1287 try a.shiftRight(a, 67);
12881288
1289 testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);1289 testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
1290
1291 try a.set(0xffff0000eeee1111dddd2222cccc3333);
1292 try a.shiftRight(a, 63);
1293 try a.shiftRight(a, 63);
1294 try a.shiftRight(a, 2);
1295 testing.expect(a.eqZero());
1290}1296}
12911297
1292test "big.int shift-left single" {1298test "big.int shift-left single" {