Function divFloor [src]
q = a / b (rem r)
a / b are floored (rounded towards 0).
q may alias with a or b.
Asserts there is enough memory to store q and r.
The upper bound for r limb count is b.limbs.len.
The upper bound for q limb count is given by a.limbs.
limbs_buffer is used for temporary storage. The amount required is given by calcDivLimbsBufferLen.
Prototype
pub fn divFloor( q: *Mutable, r: *Mutable, a: Const, b: Const, limbs_buffer: []Limb, ) void
Parameters
q: *Mutable
r: *Mutable
a: Const
b: Const
limbs_buffer: []Limb
Source
pub fn divFloor(
q: *Mutable,
r: *Mutable,
a: Const,
b: Const,
limbs_buffer: []Limb,
) void {
const sep = a.limbs.len + 2;
var x = a.toMutable(limbs_buffer[0..sep]);
var y = b.toMutable(limbs_buffer[sep..]);
div(q, r, &x, &y);
// Note, `div` performs truncating division, which satisfies
// @divTrunc(a, b) * b + @rem(a, b) = a
// so r = a - @divTrunc(a, b) * b
// Note, @rem(a, -b) = @rem(-b, a) = -@rem(a, b) = -@rem(-a, -b)
// For divTrunc, we want to perform
// @divFloor(a, b) * b + @mod(a, b) = a
// Note:
// @divFloor(-a, b)
// = @divFloor(a, -b)
// = -@divCeil(a, b)
// = -@divFloor(a + b - 1, b)
// = -@divTrunc(a + b - 1, b)
// Note (1):
// @divTrunc(a + b - 1, b) * b + @rem(a + b - 1, b) = a + b - 1
// = @divTrunc(a + b - 1, b) * b + @rem(a - 1, b) = a + b - 1
// = @divTrunc(a + b - 1, b) * b + @rem(a - 1, b) - b + 1 = a
if (a.positive and b.positive) {
// Positive-positive case, don't need to do anything.
} else if (a.positive and !b.positive) {
// a/-b -> q is negative, and so we need to fix flooring.
// Subtract one to make the division flooring.
// @divFloor(a, -b) * -b + @mod(a, -b) = a
// If b divides a exactly, we have @divFloor(a, -b) * -b = a
// Else, we have @divFloor(a, -b) * -b > a, so @mod(a, -b) becomes negative
// We have:
// @divFloor(a, -b) * -b + @mod(a, -b) = a
// = -@divTrunc(a + b - 1, b) * -b + @mod(a, -b) = a
// = @divTrunc(a + b - 1, b) * b + @mod(a, -b) = a
// Substitute a for (1):
// @divTrunc(a + b - 1, b) * b + @rem(a - 1, b) - b + 1 = @divTrunc(a + b - 1, b) * b + @mod(a, -b)
// Yields:
// @mod(a, -b) = @rem(a - 1, b) - b + 1
// Note that `r` holds @rem(a, b) at this point.
//
// If @rem(a, b) is not 0:
// @rem(a - 1, b) = @rem(a, b) - 1
// => @mod(a, -b) = @rem(a, b) - 1 - b + 1 = @rem(a, b) - b
// Else:
// @rem(a - 1, b) = @rem(a + b - 1, b) = @rem(b - 1, b) = b - 1
// => @mod(a, -b) = b - 1 - b + 1 = 0
if (!r.eqlZero()) {
q.addScalar(q.toConst(), -1);
r.positive = true;
r.sub(r.toConst(), y.toConst().abs());
}
} else if (!a.positive and b.positive) {
// -a/b -> q is negative, and so we need to fix flooring.
// Subtract one to make the division flooring.
// @divFloor(-a, b) * b + @mod(-a, b) = a
// If b divides a exactly, we have @divFloor(-a, b) * b = -a
// Else, we have @divFloor(-a, b) * b < -a, so @mod(-a, b) becomes positive
// We have:
// @divFloor(-a, b) * b + @mod(-a, b) = -a
// = -@divTrunc(a + b - 1, b) * b + @mod(-a, b) = -a
// = @divTrunc(a + b - 1, b) * b - @mod(-a, b) = a
// Substitute a for (1):
// @divTrunc(a + b - 1, b) * b + @rem(a - 1, b) - b + 1 = @divTrunc(a + b - 1, b) * b - @mod(-a, b)
// Yields:
// @rem(a - 1, b) - b + 1 = -@mod(-a, b)
// => -@mod(-a, b) = @rem(a - 1, b) - b + 1
// => @mod(-a, b) = -(@rem(a - 1, b) - b + 1) = -@rem(a - 1, b) + b - 1
//
// If @rem(a, b) is not 0:
// @rem(a - 1, b) = @rem(a, b) - 1
// => @mod(-a, b) = -(@rem(a, b) - 1) + b - 1 = -@rem(a, b) + 1 + b - 1 = -@rem(a, b) + b
// Else :
// @rem(a - 1, b) = b - 1
// => @mod(-a, b) = -(b - 1) + b - 1 = 0
if (!r.eqlZero()) {
q.addScalar(q.toConst(), -1);
r.positive = false;
r.add(r.toConst(), y.toConst().abs());
}
} else if (!a.positive and !b.positive) {
// a/b -> q is positive, don't need to do anything to fix flooring.
// @divFloor(-a, -b) * -b + @mod(-a, -b) = -a
// If b divides a exactly, we have @divFloor(-a, -b) * -b = -a
// Else, we have @divFloor(-a, -b) * -b > -a, so @mod(-a, -b) becomes negative
// We have:
// @divFloor(-a, -b) * -b + @mod(-a, -b) = -a
// = @divTrunc(a, b) * -b + @mod(-a, -b) = -a
// = @divTrunc(a, b) * b - @mod(-a, -b) = a
// We also have:
// @divTrunc(a, b) * b + @rem(a, b) = a
// Substitute a:
// @divTrunc(a, b) * b + @rem(a, b) = @divTrunc(a, b) * b - @mod(-a, -b)
// => @rem(a, b) = -@mod(-a, -b)
// => @mod(-a, -b) = -@rem(a, b)
r.positive = false;
}
}