Commit c1d16a2b80

Jacob Young <jacobly0@users.noreply.github.com>
2023-03-07 08:11:49
compiler_rt: fix rare case in udivei4
Unsigned integers are never less than zero, and so zig helpfully deleted the entire case. :D Closes #14816
1 parent 6218e40
Changed files (2)
lib
compiler_rt
test
behavior
lib/compiler_rt/udivmodei4.zig
@@ -79,16 +79,16 @@ fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
             }
             break;
         }
-        var carry: u64 = 0;
+        var carry: i64 = 0;
         i = 0;
         while (i <= n) : (i += 1) {
             const p = qhat * limb(&vn, i);
             const t = limb(&un, i + j) - carry - @truncate(u32, p);
-            limb_set(&un, i + j, @truncate(u32, t));
-            carry = @intCast(u64, p >> 32) - @intCast(u64, t >> 32);
+            limb_set(&un, i + j, @truncate(u32, @bitCast(u64, t)));
+            carry = @intCast(i64, p >> 32) - @intCast(i64, t >> 32);
         }
-        const t = limb(&un, j + n + 1) - carry;
-        limb_set(&un, j + n + 1, @truncate(u32, t));
+        const t = limb(&un, j + n + 1) -% carry;
+        limb_set(&un, j + n + 1, @truncate(u32, @bitCast(u64, t)));
         if (q) |q_| limb_set(q_, j, @truncate(u32, qhat));
         if (t < 0) {
             if (q) |q_| limb_set(q_, j, limb(q_, j) - 1);
@@ -99,7 +99,7 @@ fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
                 limb_set(&un, i + j, @truncate(u32, t2));
                 carry2 = t2 >> 32;
             }
-            limb_set(un, j + n + 1, @truncate(u32, limb(&un, j + n + 1) + carry2));
+            limb_set(&un, j + n + 1, @truncate(u32, limb(&un, j + n + 1) + carry2));
         }
         if (j == 0) break;
     }
test/behavior/int_div.zig
@@ -91,3 +91,23 @@ fn mod(comptime T: type, a: T, b: T) T {
 fn rem(comptime T: type, a: T, b: T) T {
     return @rem(a, b);
 }
+
+test "large integer division" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+
+    {
+        var numerator: u256 = 99999999999999999997315645440;
+        var divisor: u256 = 10000000000000000000000000000;
+        try expect(numerator / divisor == 9);
+    }
+    {
+        var numerator: u256 = 99999999999999999999000000000000000000000;
+        var divisor: u256 = 10000000000000000000000000000000000000000;
+        try expect(numerator / divisor == 9);
+    }
+}