math/big: correct fix for divmod (#11271)

Fixes #11166.
This commit is contained in:
Marc Tiehuis 2022-03-24 07:24:25 +13:00 committed by GitHub
parent 1cf1346323
commit 2e0de0b4e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 7 deletions

View File

@ -1576,10 +1576,6 @@ pub const Mutable = struct {
// for i from n down to t + 1, do
var i = n;
while (i >= t + 1) : (i -= 1) {
if (x.eqZero()) {
break;
}
const k = i - t - 1;
// 3.1.
// if x_i == y_t:
@ -1630,7 +1626,6 @@ pub const Mutable = struct {
// Note, we multiply by a single limb here.
// The shift doesn't need to be performed if we add the result of the first multiplication
// to x[i - t - 1].
// mem.set(Limb, x.limbs, 0);
const underflow = llmulLimb(.sub, x.limbs[k..x.len], y.limbs[0..y.len], q.limbs[k]);
// 3.4.
@ -1643,10 +1638,9 @@ pub const Mutable = struct {
llaccum(.add, x.limbs[k..x.len], y.limbs[0..y.len]);
q.limbs[k] -= 1;
}
x.normalize(x.len);
}
x.normalize(x.len);
q.normalize(q.len);
// De-normalize r and y.

View File

@ -1369,6 +1369,33 @@ test "big.int divFloor #10932" {
try testing.expect((try mod.to(i32)) == 0);
}
test "big.int divFloor #11166" {
var a = try Managed.init(testing.allocator);
defer a.deinit();
var b = try Managed.init(testing.allocator);
defer b.deinit();
var res = try Managed.init(testing.allocator);
defer res.deinit();
try a.setString(10, "10000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
try b.setString(10, "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
var mod = try Managed.init(testing.allocator);
defer mod.deinit();
try res.divFloor(&mod, a.toConst(), b.toConst());
const ress = try res.toString(testing.allocator, 10, .lower);
defer testing.allocator.free(ress);
try testing.expect(std.mem.eql(u8, ress, "1000000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
const mods = try mod.toString(testing.allocator, 10, .lower);
defer testing.allocator.free(mods);
try testing.expect(std.mem.eql(u8, mods, "870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
}
test "big.int gcd #10932" {
var a = try Managed.init(testing.allocator);
defer a.deinit();