From 85d188537538cdb7929ac05d7960d6b724676d7f Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Wed, 27 Mar 2019 15:45:18 -0500 Subject: [PATCH] std.mulWide() whose return is twice as wide --- std/math.zig | 11 +++++++++++ std/math/big/int.zig | 9 +-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/std/math.zig b/std/math.zig index d42d6df0e..4daa96d20 100644 --- a/std/math.zig +++ b/std/math.zig @@ -806,3 +806,14 @@ test "max value type" { const x: u32 = maxInt(i32); testing.expect(x == 2147483647); } + +pub fn mulWide(comptime T: type, a: T, b: T) @IntType(T.is_signed, T.bit_count * 2) { + const ResultInt = @IntType(T.is_signed, T.bit_count * 2); + return ResultInt(a) * ResultInt(b); +} + +test "math.wideMul" { + testing.expect(wideMul(u8, 5, 5) == 25); + testing.expect(wideMul(i8, 5, -5) == -25); + testing.expect(wideMul(u8, 100, 100) == 10000); +} diff --git a/std/math/big/int.zig b/std/math/big/int.zig index bf382f002..8800c2c7a 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -705,14 +705,7 @@ pub const Int = struct { const c1: Limb = @boolToInt(@addWithOverflow(Limb, a, carry.*, &r1)); // r2 = b * c - // - // We still use a DoubleLimb here since the @mulWithOverflow builtin does not - // return the carry and lower bits separately so we would need to perform this - // anyway to get the carry bits. The branch on the overflow case costs more than - // just computing them unconditionally and splitting. - // - // This could be a single x86 mul instruction, which stores the carry/lower in rdx:rax. - const bc = DoubleLimb(b) * DoubleLimb(c); + const bc = DoubleLimb(math.mulWide(Limb, b, c)); const r2 = @truncate(Limb, bc); const c2 = @truncate(Limb, bc >> Limb.bit_count);