diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-21 19:05:26 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-21 19:05:26 -0700 |
| commit | 7f70c27e9d57c8234545120da81861e2cfb354b5 (patch) | |
| tree | 47948dcf37e5e5767db2b428a8ef8177ef8eee86 /lib/std | |
| parent | a3c9bfef301e0a4675fcea57356653334e07df45 (diff) | |
| download | zig-7f70c27e9d57c8234545120da81861e2cfb354b5.tar.gz zig-7f70c27e9d57c8234545120da81861e2cfb354b5.zip | |
stage2: more division support
AIR:
* div is renamed to div_trunc.
* Add div_float, div_floor, div_exact.
- Implemented in Sema and LLVM codegen. C backend has a stub.
Improvements to std.math.big.Int:
* Add `eqZero` function to `Mutable`.
* Fix incorrect results for `divFloor`.
Compiler-rt:
* Add muloti4 to the stage2 section.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/math/big/int.zig | 18 | ||||
| -rw-r--r-- | lib/std/math/big/int_test.zig | 57 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt.zig | 9 |
3 files changed, 75 insertions, 9 deletions
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 68a0c7f740..7bcd76b221 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -135,6 +135,11 @@ pub const Mutable = struct { }; } + /// Returns true if `a == 0`. + pub fn eqZero(self: Mutable) bool { + return self.toConst().eqZero(); + } + /// Asserts that the allocator owns the limbs memory. If this is not the case, /// use `toConst().toManaged()`. pub fn toManaged(self: Mutable, allocator: *Allocator) Managed { @@ -773,12 +778,15 @@ pub const Mutable = struct { div(q, r, a, b, limbs_buffer, allocator); // Trunc -> Floor. - if (!q.positive) { + if (a.positive and b.positive) return; + + if ((!q.positive or q.eqZero()) and !r.eqZero()) { const one: Const = .{ .limbs = &[_]Limb{1}, .positive = true }; q.sub(q.toConst(), one); - r.add(q.toConst(), one); } - r.positive = b.positive; + + r.mulNoAlias(q.toConst(), b, allocator); + r.sub(a, r.toConst()); } /// q = a / b (rem r) @@ -1220,12 +1228,12 @@ pub const Mutable = struct { var x: Mutable = .{ .limbs = x_limbs, - .positive = a.positive, + .positive = true, .len = a.limbs.len - ab_zero_limb_count, }; var y: Mutable = .{ .limbs = y_limbs, - .positive = b.positive, + .positive = true, .len = b.limbs.len - ab_zero_limb_count, }; diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 00594b640f..2ca7b253e0 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -1399,6 +1399,63 @@ test "big.int div floor single-single -/-" { try testing.expect((try r.to(i32)) == er); } +test "big.int div floor no remainder negative quotient" { + const u: i32 = -0x80000000; + const v: i32 = 1; + + var a = try Managed.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Managed.initSet(testing.allocator, v); + defer b.deinit(); + + var q = try Managed.init(testing.allocator); + defer q.deinit(); + var r = try Managed.init(testing.allocator); + defer r.deinit(); + try Managed.divFloor(&q, &r, a.toConst(), b.toConst()); + + try testing.expect((try q.to(i32)) == -0x80000000); + try testing.expect((try r.to(i32)) == 0); +} + +test "big.int div floor negative close to zero" { + const u: i32 = -2; + const v: i32 = 12; + + var a = try Managed.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Managed.initSet(testing.allocator, v); + defer b.deinit(); + + var q = try Managed.init(testing.allocator); + defer q.deinit(); + var r = try Managed.init(testing.allocator); + defer r.deinit(); + try Managed.divFloor(&q, &r, a.toConst(), b.toConst()); + + try testing.expect((try q.to(i32)) == -1); + try testing.expect((try r.to(i32)) == 10); +} + +test "big.int div floor positive close to zero" { + const u: i32 = 10; + const v: i32 = 12; + + var a = try Managed.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Managed.initSet(testing.allocator, v); + defer b.deinit(); + + var q = try Managed.init(testing.allocator); + defer q.deinit(); + var r = try Managed.init(testing.allocator); + defer r.deinit(); + try Managed.divFloor(&q, &r, a.toConst(), b.toConst()); + + try testing.expect((try q.to(i32)) == 0); + try testing.expect((try r.to(i32)) == 10); +} + test "big.int div multi-multi with rem" { var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); defer a.deinit(); diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index 3582b93070..caf43ded19 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -74,6 +74,11 @@ comptime { @export(__getf2, .{ .name = "__gttf2", .linkage = linkage }); @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); + + const __muloti4 = @import("compiler_rt/muloti4.zig").__muloti4; + @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); + const __mulodi4 = @import("compiler_rt/mulodi4.zig").__mulodi4; + @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); } if (!builtin.zig_is_stage2) { @@ -621,10 +626,6 @@ comptime { const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); } - const __muloti4 = @import("compiler_rt/muloti4.zig").__muloti4; - @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); - const __mulodi4 = @import("compiler_rt/mulodi4.zig").__mulodi4; - @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); _ = @import("compiler_rt/atomics.zig"); |
