pub fn popCount(self: Const, bit_count: usize) usize self: Constbit_count: usize2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302 pub fn popCount(self: Const, bit_count: usize) usize {
var sum: usize = 0;
if (self.positive) {
for (self.limbs) |limb| {
sum += @popCount(limb);
}
} else {
assert(self.fitsInTwosComp(.signed, bit_count));
assert(self.limbs[self.limbs.len - 1] != 0);
var remaining_bits = bit_count;
var carry: u1 = 1;
var add_res: Limb = undefined;
// All but the most significant limb.
for (self.limbs[0 .. self.limbs.len - 1]) |limb| {
const ov = @addWithOverflow(~limb, carry);
add_res = ov[0];
carry = ov[1];
sum += @popCount(add_res);
remaining_bits -= limb_bits; // Asserted not to underflow by fitsInTwosComp
}
// The most significant limb may have fewer than @bitSizeOf(Limb) meaningful bits,
// which we can detect with @clz().
// There may also be fewer limbs than needed to fill bit_count.
const limb = self.limbs[self.limbs.len - 1];
const leading_zeroes = @clz(limb);
// The most significant limb is asserted not to be all 0s (above),
// so ~limb cannot be all 1s, and ~limb + 1 cannot overflow.
sum += @popCount(~limb + carry);
sum -= leading_zeroes; // All leading zeroes were flipped and added to sum, so undo those
const remaining_ones = remaining_bits - (limb_bits - leading_zeroes); // All bits not covered by limbs
sum += remaining_ones;
}
return sum;
}
@popCount with two's complement semantics.
This returns the number of 1 bits set when the value would be represented in two's complement with the given integer width (bit_count). This includes the leading sign bit, which will be set for negative values.
Asserts that bit_count is enough to represent value in two's compliment and that the final result fits in a usize. Asserts that there are no trailing empty limbs on the most significant end, i.e. that limb count matches
calcLimbLen()and zero is not negative.