zig/src/RangeSet.zig
r00ster91 2b8687ba2d std.math.big.int: better name for equal function
All of the std except these few functions call it "eql" instead of "eq".
This has previously tripped me up when I expected the equality check function to be called "eql"
(just like all the rest of the std) instead of "eq".

The motivation is consistency.

If search "eq" on Autodoc, these functions stick out and it looks inconsistent.

I just noticed there are also a few functions spelling it out as "equal" (such as std.mem.allEqual).
Maybe those functions should also spell it "eql" but that can be done in a future PR.
2023-07-03 11:00:13 -07:00

105 lines
2.7 KiB
Zig

const std = @import("std");
const assert = std.debug.assert;
const Order = std.math.Order;
const InternPool = @import("InternPool.zig");
const Module = @import("Module.zig");
const RangeSet = @This();
const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
ranges: std.ArrayList(Range),
module: *Module,
pub const Range = struct {
first: InternPool.Index,
last: InternPool.Index,
src: SwitchProngSrc,
};
pub fn init(allocator: std.mem.Allocator, module: *Module) RangeSet {
return .{
.ranges = std.ArrayList(Range).init(allocator),
.module = module,
};
}
pub fn deinit(self: *RangeSet) void {
self.ranges.deinit();
}
pub fn add(
self: *RangeSet,
first: InternPool.Index,
last: InternPool.Index,
src: SwitchProngSrc,
) !?SwitchProngSrc {
const mod = self.module;
const ip = &mod.intern_pool;
const ty = ip.typeOf(first);
assert(ty == ip.typeOf(last));
for (self.ranges.items) |range| {
assert(ty == ip.typeOf(range.first));
assert(ty == ip.typeOf(range.last));
if (last.toValue().compareScalar(.gte, range.first.toValue(), ty.toType(), mod) and
first.toValue().compareScalar(.lte, range.last.toValue(), ty.toType(), mod))
{
return range.src; // They overlap.
}
}
try self.ranges.append(.{
.first = first,
.last = last,
.src = src,
});
return null;
}
/// Assumes a and b do not overlap
fn lessThan(mod: *Module, a: Range, b: Range) bool {
const ty = mod.intern_pool.typeOf(a.first).toType();
return a.first.toValue().compareScalar(.lt, b.first.toValue(), ty, mod);
}
pub fn spans(self: *RangeSet, first: InternPool.Index, last: InternPool.Index) !bool {
const mod = self.module;
const ip = &mod.intern_pool;
assert(ip.typeOf(first) == ip.typeOf(last));
if (self.ranges.items.len == 0)
return false;
std.mem.sort(Range, self.ranges.items, mod, lessThan);
if (self.ranges.items[0].first != first or
self.ranges.items[self.ranges.items.len - 1].last != last)
{
return false;
}
var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
defer counter.deinit();
// look for gaps
for (self.ranges.items[1..], 0..) |cur, i| {
// i starts counting from the second item.
const prev = self.ranges.items[i];
// prev.last + 1 == cur.first
try counter.copy(prev.last.toValue().toBigInt(&space, mod));
try counter.addScalar(&counter, 1);
const cur_start_int = cur.first.toValue().toBigInt(&space, mod);
if (!cur_start_int.eql(counter.toConst())) {
return false;
}
}
return true;
}