mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Merge pull request #23310 from Rexicon226/fix-23309
big.int: return normalized results from `{add,sub}Carry`
This commit is contained in:
parent
cb3eec285f
commit
38ececf0a7
4 changed files with 53 additions and 5 deletions
|
|
@ -76,9 +76,18 @@ pub fn calcSqrtLimbsBufferLen(a_bit_count: usize) usize {
|
|||
return a_limb_count + 3 * u_s_rem_limb_count + calcDivLimbsBufferLen(a_limb_count, u_s_rem_limb_count);
|
||||
}
|
||||
|
||||
// Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
|
||||
/// Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
|
||||
pub fn calcNonZeroTwosCompLimbCount(bit_count: usize) usize {
|
||||
assert(bit_count != 0);
|
||||
return calcTwosCompLimbCount(bit_count);
|
||||
}
|
||||
|
||||
/// Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
|
||||
///
|
||||
/// Special cases `bit_count == 0` to return 1. Zero-bit integers can only store the value zero
|
||||
/// and this big integer implementation stores zero using one limb.
|
||||
pub fn calcTwosCompLimbCount(bit_count: usize) usize {
|
||||
return std.math.divCeil(usize, bit_count, @bitSizeOf(Limb)) catch unreachable;
|
||||
return @max(std.math.divCeil(usize, bit_count, @bitSizeOf(Limb)) catch unreachable, 1);
|
||||
}
|
||||
|
||||
/// a + b * c + *carry, sets carry to the overflow bits
|
||||
|
|
@ -188,8 +197,10 @@ pub const Mutable = struct {
|
|||
if (self.limbs.ptr != other.limbs.ptr) {
|
||||
@memcpy(self.limbs[0..other.limbs.len], other.limbs[0..other.limbs.len]);
|
||||
}
|
||||
self.positive = other.positive;
|
||||
self.len = other.limbs.len;
|
||||
// Normalize before setting `positive` so the `eqlZero` doesn't need to iterate
|
||||
// over the extra zero limbs.
|
||||
self.normalize(other.limbs.len);
|
||||
self.positive = other.positive or other.eqlZero();
|
||||
}
|
||||
|
||||
/// Efficiently swap an Mutable with another. This swaps the limb pointers and a full copy is not
|
||||
|
|
|
|||
|
|
@ -726,6 +726,34 @@ test "subWrap single-multi, signed, limb aligned" {
|
|||
try testing.expect((try a.toInt(SignedDoubleLimb)) == maxInt(SignedDoubleLimb));
|
||||
}
|
||||
|
||||
test "addWrap returns normalized result" {
|
||||
var x = try Managed.initSet(testing.allocator, 0);
|
||||
defer x.deinit();
|
||||
var y = try Managed.initSet(testing.allocator, 0);
|
||||
defer y.deinit();
|
||||
|
||||
// make them both non normalized "-0"
|
||||
x.setMetadata(false, 1);
|
||||
y.setMetadata(false, 1);
|
||||
|
||||
var r = try Managed.init(testing.allocator);
|
||||
defer r.deinit();
|
||||
try testing.expect(!(try r.addWrap(&x, &y, .unsigned, 64)));
|
||||
try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0);
|
||||
}
|
||||
|
||||
test "subWrap returns normalized result" {
|
||||
var x = try Managed.initSet(testing.allocator, 0);
|
||||
defer x.deinit();
|
||||
var y = try Managed.initSet(testing.allocator, 0);
|
||||
defer y.deinit();
|
||||
|
||||
var r = try Managed.init(testing.allocator);
|
||||
defer r.deinit();
|
||||
try testing.expect(!(try r.subWrap(&x, &y, .unsigned, 64)));
|
||||
try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0);
|
||||
}
|
||||
|
||||
test "addSat single-single, unsigned" {
|
||||
var a = try Managed.initSet(testing.allocator, maxInt(u17) - 5);
|
||||
defer a.deinit();
|
||||
|
|
|
|||
|
|
@ -2677,7 +2677,7 @@ pub fn shlSatScalar(
|
|||
const shift: usize = @intCast(rhs.toUnsignedInt(zcu));
|
||||
const limbs = try arena.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(info.bits) + 1,
|
||||
std.math.big.int.calcTwosCompLimbCount(info.bits),
|
||||
);
|
||||
var result_bigint = BigIntMutable{
|
||||
.limbs = limbs,
|
||||
|
|
|
|||
|
|
@ -535,3 +535,12 @@ test "return from inline for" {
|
|||
};
|
||||
try std.testing.expect(!S.do());
|
||||
}
|
||||
|
||||
test "for loop 0 length range" {
|
||||
const map: []const u8 = &.{};
|
||||
for (map, 0..map.len) |i, j| {
|
||||
_ = i;
|
||||
_ = j;
|
||||
comptime unreachable;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue