feature. See also
. The project being documented here (as the example) is the Zig library itself.
limb64.__mulo_limb64
fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool
File
Code
fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
const limb_cnt = usedLimbCount(bits);
const out = varLimbs(out_ptr, bits);
const a = constLimbs(a_ptr, bits);
const b = constLimbs(b_ptr, bits);
@memset(out, 0);
const all_ones = ~@as(u64, 0);
const a_neg = is_signed and ((limbGet(a, limb_cnt - 1) >> 63) != 0);
const b_neg = is_signed and ((limbGet(b, limb_cnt - 1) >> 63) != 0);
var carry: [3]u64 = @splat(0);
var hi_zero = true;
var hi_ones = true;
var hi_borrow: u1 = 0;
var raw_last: u64 = 0;
var k: usize = 0;
while (k < 2 * limb_cnt) : (k += 1) {
var acc = carry;
var i: usize = if (k < limb_cnt) 0 else k - (limb_cnt - 1);
while (i < limb_cnt and i <= k) : (i += 1) {
const j = k - i;
if (j >= limb_cnt) continue;
const p = mulwide(limbGet(a, i), limbGet(b, j));
add3(&acc, 0, p[0]);
add3(&acc, 1, p[1]);
}
var limb = acc[0];
if (k < limb_cnt) {
limbSet(out, k, limb);
if (k == limb_cnt - 1) raw_last = limb;
} else {
if (is_signed) {
const h = k - limb_cnt;
const s0 = @subWithOverflow(limb, if (a_neg) limbGet(b, h) else 0);
const s1 = @subWithOverflow(s0[0], if (b_neg) limbGet(a, h) else 0);
const s2 = @subWithOverflow(s1[0], hi_borrow);
limb = s2[0];
hi_borrow = @intFromBool(s0[1] != 0 or s1[1] != 0 or s2[1] != 0);
}
hi_zero = hi_zero and limb == 0;
hi_ones = hi_ones and limb == all_ones;
}
carry = .{ acc[1], acc[2], 0 };
}
const last = if (bits % 64 == 0) raw_last else limbWrap(raw_last, is_signed, bits);
if (bits % 64 != 0) {
limbSet(out, limb_cnt - 1, last);
}
fixLastLimb(out_ptr, is_signed, bits);
if (!is_signed) {
return !hi_zero or raw_last != last;
}
const sign_extend: u64 = if ((last >> 63) == 1) all_ones else 0;
return (raw_last != last) or if (sign_extend == 0) !hi_zero else !hi_ones;
}