r = r (op) y * xi
The result is computed modulo r.len.
Returns whether the operation overflowed.
fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool
fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool {
assert(!slicesOverlap(acc, y) or @intFromPtr(acc.ptr) <= @intFromPtr(y.ptr));
if (xi == 0) {
return false;
}
const split = @min(y.len, acc.len);
var a_lo = acc[0..split];
var a_hi = acc[split..];
switch (op) {
.add => {
var carry: Limb = 0;
var j: usize = 0;
while (j < a_lo.len) : (j += 1) {
a_lo[j] = addMulLimbWithCarry(a_lo[j], y[j], xi, &carry);
}
j = 0;
while ((carry != 0) and (j < a_hi.len)) : (j += 1) {
const ov = @addWithOverflow(a_hi[j], carry);
a_hi[j] = ov[0];
carry = ov[1];
}
return carry != 0;
},
.sub => {
var borrow: Limb = 0;
var j: usize = 0;
while (j < a_lo.len) : (j += 1) {
a_lo[j] = subMulLimbWithBorrow(a_lo[j], y[j], xi, &borrow);
}
j = 0;
while ((borrow != 0) and (j < a_hi.len)) : (j += 1) {
const ov = @subWithOverflow(a_hi[j], borrow);
a_hi[j] = ov[0];
borrow = ov[1];
}
return borrow != 0;
},
}
}