big ints: saturate() function

This commit is contained in:
Robin Voetter 2021-10-03 16:34:52 +02:00
parent fdf13fb819
commit bbd50248f2

View File

@ -525,9 +525,7 @@ pub const Mutable = struct {
}
// Saturate if the result didn't fit.
if (!r.toConst().fitsInTwosComp(signedness, bit_count)) {
r.setTwosCompIntLimit(if (r.positive) .max else .min, signedness, bit_count);
}
r.saturate(r.toConst(), signedness, bit_count);
}
/// Base implementation for subtraction. Subtracts `max(a.limbs.len, b.limbs.len)` elements from a and b,
@ -661,7 +659,7 @@ pub const Mutable = struct {
}
}
mem.set(Limb, rma.limbs[0 .. a.limbs.len + b.limbs.len + 1], 0);
mem.set(Limb, rma.limbs[0 .. a.limbs.len + b.limbs.len], 0);
llmulacc(.add, allocator, rma.limbs, a.limbs, b.limbs);
@ -1366,6 +1364,17 @@ pub const Mutable = struct {
}
}
/// Saturate an integer to a number of bits, following 2s-complement semantics.
/// r may alias a.
///
/// Asserts `r` has enough storage to store the result.
/// The upper bound is `calcTwosCompLimbCount(a.len)`.
pub fn saturate(r: *Mutable, a: Const, signedness: std.builtin.Signedness, bit_count: usize) void {
if (!a.fitsInTwosComp(signedness, bit_count)) {
r.setTwosCompIntLimit(if (r.positive) .max else .min, signedness, bit_count);
}
}
/// Normalize a possible sequence of leading zeros.
///
/// [1, 2, 3, 4, 0] -> [1, 2, 3, 4]
@ -2414,6 +2423,14 @@ pub const Managed = struct {
m.truncate(a, signedness, bit_count);
r.setMetadata(m.positive, m.len);
}
/// r = saturate(Int(signedness, bit_count), a)
pub fn saturate(r: *Managed, a: Const, signedness: std.builtin.Signedness, bit_count: usize) !void {
try r.ensureCapacity(calcTwosCompLimbCount(bit_count));
var m = r.toMutable();
m.saturate(a, signedness, bit_count);
r.setMetadata(m.positive, m.len);
}
};
/// Different operators which can be used in accumulation style functions