authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-03 16:34:52+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-04 11:25:29+02:00
logbbd50248f25996e707ebacc2f020e23cee6140e3
tree764ecaa9dfa25e655daf00cf2596e93cb2f99f80
parentfdf13fb81940ada1673914cab4ff46a1ddae42dd

big ints: saturate() function


1 files changed, 21 insertions(+), 4 deletions(-)

lib/std/math/big/int.zig+21-4
...@@ -525,9 +525,7 @@ pub const Mutable = struct {...@@ -525,9 +525,7 @@ pub const Mutable = struct {
525 }525 }
526526
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 }
532530
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 }
663661
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);
665663
666 llmulacc(.add, allocator, rma.limbs, a.limbs, b.limbs);664 llmulacc(.add, allocator, rma.limbs, a.limbs, b.limbs);
667665
...@@ -1366,6 +1364,17 @@ pub const Mutable = struct {...@@ -1366,6 +1364,17 @@ pub const Mutable = struct {
1366 }1364 }
1367 }1365 }
13681366
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};
24182435
2419/// Different operators which can be used in accumulation style functions2436/// Different operators which can be used in accumulation style functions