feature. See also
. The project being documented here (as the example) is the Zig library itself.
Builder.bigIntConstAssumeCapacity
fn bigIntConstAssumeCapacity(
self: *Builder,
ty: Type,
value: std.math.big.int.Const,
) Allocator.Error!Constant
File
Code
fn bigIntConstAssumeCapacity(
self: *Builder,
ty: Type,
value: std.math.big.int.Const,
) Allocator.Error!Constant {
const type_item = self.type_items.items[@backingInt(ty)];
assert(type_item.tag == .integer);
const bits = type_item.data;
const ExpectedContents = [64 / @sizeOf(std.math.big.Limb)]std.math.big.Limb;
var bfa_buf: ExpectedContents = undefined;
var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa);
const allocator = bfa.allocator();
var limbs: []std.math.big.Limb = &.{};
defer allocator.free(limbs);
const canonical_value = if (value.fitsInTwosComp(.signed, bits)) value else canon: {
assert(value.fitsInTwosComp(.unsigned, bits));
limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits));
var temp_value = std.math.big.int.Mutable.init(limbs, 0);
temp_value.truncate(value, .signed, bits);
break :canon temp_value.toConst();
};
assert(canonical_value.fitsInTwosComp(.signed, bits));
const ExtraPtr = *align(@alignOf(std.math.big.Limb)) Constant.Integer;
const Key = struct { tag: Constant.Tag, type: Type, limbs: []const std.math.big.Limb };
const tag: Constant.Tag = switch (canonical_value.positive) {
true => .positive_integer,
false => .negative_integer,
};
const Adapter = struct {
builder: *const Builder,
pub fn hash(_: @This(), key: Key) u32 {
var hasher = std.hash.Wyhash.init(std.hash.int(@backingInt(key.tag)));
hasher.update(std.mem.asBytes(&key.type));
hasher.update(std.mem.sliceAsBytes(key.limbs));
return @truncate(hasher.final());
}
pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false;
const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index];
const rhs_extra: ExtraPtr =
@ptrCast(ctx.builder.constant_limbs.items[rhs_data..][0..Constant.Integer.limbs]);
const rhs_limbs = ctx.builder.constant_limbs
.items[rhs_data + Constant.Integer.limbs ..][0..rhs_extra.limbs_len];
return lhs_key.type == rhs_extra.type and
std.mem.eql(std.math.big.Limb, lhs_key.limbs, rhs_limbs);
}
};
const gop = self.constant_map.getOrPutAssumeCapacityAdapted(
Key{ .tag = tag, .type = ty, .limbs = canonical_value.limbs },
Adapter{ .builder = self },
);
if (!gop.found_existing) {
gop.key_ptr.* = {};
gop.value_ptr.* = {};
self.constant_items.appendAssumeCapacity(.{
.tag = tag,
.data = @intCast(self.constant_limbs.items.len),
});
const extra: ExtraPtr =
@ptrCast(self.constant_limbs.addManyAsArrayAssumeCapacity(Constant.Integer.limbs));
extra.* = .{ .type = ty, .limbs_len = @intCast(canonical_value.limbs.len) };
self.constant_limbs.appendSliceAssumeCapacity(canonical_value.limbs);
}
return @fromBackingInt(@intCast(gop.index));
}