Commit 2e0de0b4e2

Marc Tiehuis <marc@tiehu.is>
2022-03-23 19:24:25
math/big: correct fix for divmod (#11271)
Fixes #11166.
1 parent 1cf1346
Changed files (2)
lib
std
lib/std/math/big/int.zig
@@ -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.
lib/std/math/big/int_test.zig
@@ -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();