| ... | @@ -525,9 +525,7 @@ pub const Mutable = struct { | ... | @@ -525,9 +525,7 @@ pub const Mutable = struct { |
| 525 | } | 525 | } |
| 526 | | 526 | |
| 527 | // Saturate if the result didn't fit. | 527 | // Saturate if the result didn't fit. |
| 528 | if (!r.toConst().fitsInTwosComp(signedness, bit_count)) { | 528 | r.saturate(r.toConst(), signedness, bit_count); |
| 529 | r.setTwosCompIntLimit(if (r.positive) .max else .min, signedness, bit_count); | | |
| 530 | } | | |
| 531 | } | 529 | } |
| 532 | | 530 | |
| 533 | /// Base implementation for subtraction. Subtracts `max(a.limbs.len, b.limbs.len)` elements from a and b, | 531 | /// 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 { | ... | @@ -661,7 +659,7 @@ pub const Mutable = struct { |
| 661 | } | 659 | } |
| 662 | } | 660 | } |
| 663 | | 661 | |
| 664 | mem.set(Limb, rma.limbs[0 .. a.limbs.len + b.limbs.len + 1], 0); | 662 | mem.set(Limb, rma.limbs[0 .. a.limbs.len + b.limbs.len], 0); |
| 665 | | 663 | |
| 666 | llmulacc(.add, allocator, rma.limbs, a.limbs, b.limbs); | 664 | llmulacc(.add, allocator, rma.limbs, a.limbs, b.limbs); |
| 667 | | 665 | |
| ... | @@ -1366,6 +1364,17 @@ pub const Mutable = struct { | ... | @@ -1366,6 +1364,17 @@ pub const Mutable = struct { |
| 1366 | } | 1364 | } |
| 1367 | } | 1365 | } |
| 1368 | | 1366 | |
| | 1367 | /// Saturate an integer to a number of bits, following 2s-complement semantics. |
| | 1368 | /// r may alias a. |
| | 1369 | /// |
| | 1370 | /// Asserts `r` has enough storage to store the result. |
| | 1371 | /// The upper bound is `calcTwosCompLimbCount(a.len)`. |
| | 1372 | pub fn saturate(r: *Mutable, a: Const, signedness: std.builtin.Signedness, bit_count: usize) void { |
| | 1373 | if (!a.fitsInTwosComp(signedness, bit_count)) { |
| | 1374 | r.setTwosCompIntLimit(if (r.positive) .max else .min, signedness, bit_count); |
| | 1375 | } |
| | 1376 | } |
| | 1377 | |
| 1369 | /// Normalize a possible sequence of leading zeros. | 1378 | /// Normalize a possible sequence of leading zeros. |
| 1370 | /// | 1379 | /// |
| 1371 | /// [1, 2, 3, 4, 0] -> [1, 2, 3, 4] | 1380 | /// [1, 2, 3, 4, 0] -> [1, 2, 3, 4] |
| ... | @@ -2414,6 +2423,14 @@ pub const Managed = struct { | ... | @@ -2414,6 +2423,14 @@ pub const Managed = struct { |
| 2414 | m.truncate(a, signedness, bit_count); | 2423 | m.truncate(a, signedness, bit_count); |
| 2415 | r.setMetadata(m.positive, m.len); | 2424 | r.setMetadata(m.positive, m.len); |
| 2416 | } | 2425 | } |
| | 2426 | |
| | 2427 | /// r = saturate(Int(signedness, bit_count), a) |
| | 2428 | pub fn saturate(r: *Managed, a: Const, signedness: std.builtin.Signedness, bit_count: usize) !void { |
| | 2429 | try r.ensureCapacity(calcTwosCompLimbCount(bit_count)); |
| | 2430 | var m = r.toMutable(); |
| | 2431 | m.saturate(a, signedness, bit_count); |
| | 2432 | r.setMetadata(m.positive, m.len); |
| | 2433 | } |
| 2417 | }; | 2434 | }; |
| 2418 | | 2435 | |
| 2419 | /// Different operators which can be used in accumulation style functions | 2436 | /// Different operators which can be used in accumulation style functions |