From cd3dcc225b52be981b52b71dcdb34ba176f4081b Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 23 Sep 2021 06:22:18 +0200 Subject: [PATCH] big ints: only write xor overflow if required --- lib/std/math/big/int.zig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index fa8a63b67d..b7ea284004 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2495,6 +2495,8 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ // r may alias. // a and b must not be -0. // Returns `true` when the result is positive. +// If the sign of a and b is equal, then r requires at least `max(a.len, b.len)` limbs are required. +// Otherwise, r requires at least `max(a.len, b.len) + 1` limbs. fn llsignedxor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_positive: bool) bool { @setRuntimeSafety(debug_safety); assert(a.len != 0 and b.len != 0); @@ -2538,7 +2540,12 @@ fn llsignedxor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); } - r[i] = r_carry; + // If both inputs don't share the same sign, an extra limb is required. + if (a_positive != b_positive) { + r[i] = r_carry; + } else { + assert(r_carry == 0); + } assert(a_borrow == 0); assert(b_borrow == 0);