zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit c1d16a2b80e258a126ed496dab09a8a7c26f8468 (tree)
parent 6218e4004608000ba2e42e07ed1bd56745626820
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date:   Tue,  7 Mar 2023 02:11:49 -0500

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

Diffstat:
Mlib/compiler_rt/udivmodei4.zig | 12++++++------
Mtest/behavior/int_div.zig | 20++++++++++++++++++++
2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/lib/compiler_rt/udivmodei4.zig b/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; } diff --git a/test/behavior/int_div.zig b/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); + } +}