Commit f466667888
lib/std/math/big/int.zig
@@ -2376,6 +2376,34 @@ pub const Const = struct {
pub fn eq(a: Const, b: Const) bool {
return order(a, b) == .eq;
}
+
+ pub fn clz(a: Const, bits: Limb) Limb {
+ // Limbs are stored in little-endian order but we need
+ // to iterate big-endian.
+ var total_limb_lz: Limb = 0;
+ var i: usize = a.limbs.len;
+ const bits_per_limb = @sizeOf(Limb) * 8;
+ while (i != 0) {
+ i -= 1;
+ const limb = a.limbs[i];
+ const this_limb_lz = @clz(limb);
+ total_limb_lz += this_limb_lz;
+ if (this_limb_lz != bits_per_limb) break;
+ }
+ const total_limb_bits = a.limbs.len * bits_per_limb;
+ return total_limb_lz + bits - total_limb_bits;
+ }
+
+ pub fn ctz(a: Const) Limb {
+ // Limbs are stored in little-endian order.
+ var result: Limb = 0;
+ for (a.limbs) |limb| {
+ const limb_tz = @ctz(limb);
+ result += limb_tz;
+ if (limb_tz != @sizeOf(Limb) * 8) break;
+ }
+ return result;
+ }
};
/// An arbitrary-precision big integer along with an allocator which manages the memory.
src/Sema.zig
@@ -19299,6 +19299,7 @@ fn zirBitCount(
.Int => {
if (try sema.resolveMaybeUndefVal(operand)) |val| {
if (val.isUndef()) return sema.addConstUndef(result_scalar_ty);
+ try sema.resolveLazyValue(val);
return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, target));
} else {
try sema.requireRuntimeBlock(block, src, operand_src);
src/value.zig
@@ -1677,22 +1677,8 @@ pub const Value = extern union {
@panic("TODO implement i64 Value clz");
},
.int_big_positive => {
- // TODO: move this code into std lib big ints
const bigint = val.castTag(.int_big_positive).?.asBigInt();
- // Limbs are stored in little-endian order but we need
- // to iterate big-endian.
- var total_limb_lz: u64 = 0;
- var i: usize = bigint.limbs.len;
- const bits_per_limb = @sizeOf(std.math.big.Limb) * 8;
- while (i != 0) {
- i -= 1;
- const limb = bigint.limbs[i];
- const this_limb_lz = @clz(limb);
- total_limb_lz += this_limb_lz;
- if (this_limb_lz != bits_per_limb) break;
- }
- const total_limb_bits = bigint.limbs.len * bits_per_limb;
- return total_limb_lz + ty_bits - total_limb_bits;
+ return bigint.clz(ty_bits);
},
.int_big_negative => {
@panic("TODO implement int_big_negative Value clz");
@@ -1703,6 +1689,12 @@ pub const Value = extern union {
return ty_bits;
},
+ .lazy_align, .lazy_size => {
+ var bigint_buf: BigIntSpace = undefined;
+ const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
+ return bigint.clz(ty_bits);
+ },
+
else => unreachable,
}
}
@@ -1721,16 +1713,8 @@ pub const Value = extern union {
@panic("TODO implement i64 Value ctz");
},
.int_big_positive => {
- // TODO: move this code into std lib big ints
const bigint = val.castTag(.int_big_positive).?.asBigInt();
- // Limbs are stored in little-endian order.
- var result: u64 = 0;
- for (bigint.limbs) |limb| {
- const limb_tz = @ctz(limb);
- result += limb_tz;
- if (limb_tz != @sizeOf(std.math.big.Limb) * 8) break;
- }
- return result;
+ return bigint.ctz();
},
.int_big_negative => {
@panic("TODO implement int_big_negative Value ctz");
@@ -1741,6 +1725,12 @@ pub const Value = extern union {
return ty_bits;
},
+ .lazy_align, .lazy_size => {
+ var bigint_buf: BigIntSpace = undefined;
+ const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
+ return bigint.ctz();
+ },
+
else => unreachable,
}
}