Commit bbd50248f2

Robin Voetter <robin@voetter.nl>
2021-10-03 16:34:52
big ints: saturate() function
1 parent fdf13fb
Changed files (1)
lib
std
math
lib/std/math/big/int.zig
@@ -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