authorgravatar for shawn@git.icuShawn Landden <shawn@git.icu> 2019-03-27 15:45:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-28 15:51:10-04:00
log85d188537538cdb7929ac05d7960d6b724676d7f
tree7081624832f2880ad46a33dad7d72c6f24b95f3a
parent64b2cf776c4efa92f6be180c25ff13d49b495cbf

std.mulWide() whose return is twice as wide


2 files changed, 12 insertions(+), 8 deletions(-)

std/math.zig+11
......@@ -806,3 +806,14 @@ test "max value type" {
806806 const x: u32 = maxInt(i32);
807807 testing.expect(x == 2147483647);
808808}
809
810pub fn mulWide(comptime T: type, a: T, b: T) @IntType(T.is_signed, T.bit_count * 2) {
811 const ResultInt = @IntType(T.is_signed, T.bit_count * 2);
812 return ResultInt(a) * ResultInt(b);
813}
814
815test "math.wideMul" {
816 testing.expect(wideMul(u8, 5, 5) == 25);
817 testing.expect(wideMul(i8, 5, -5) == -25);
818 testing.expect(wideMul(u8, 100, 100) == 10000);
819}
std/math/big/int.zig+1-8
......@@ -705,14 +705,7 @@ pub const Int = struct {
705705 const c1: Limb = @boolToInt(@addWithOverflow(Limb, a, carry.*, &r1));
706706
707707 // r2 = b * c
708 //
709 // We still use a DoubleLimb here since the @mulWithOverflow builtin does not
710 // return the carry and lower bits separately so we would need to perform this
711 // anyway to get the carry bits. The branch on the overflow case costs more than
712 // just computing them unconditionally and splitting.
713 //
714 // This could be a single x86 mul instruction, which stores the carry/lower in rdx:rax.
715 const bc = DoubleLimb(b) * DoubleLimb(c);
708 const bc = DoubleLimb(math.mulWide(Limb, b, c));
716709 const r2 = @truncate(Limb, bc);
717710 const c2 = @truncate(Limb, bc >> Limb.bit_count);
718711