diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index 2c4e50dee3..323b8852ba 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -192,6 +192,68 @@ pub fn IntegerBitSet(comptime size: u16) type { return index; } + /// Returns true iff every corresponding bit in both + /// bit sets are the same. + pub fn eql(self: Self, other: Self) bool { + return bit_length == 0 or self.mask == other.mask; + } + + /// Returns iff the first bit set is the subset of the + /// second one. + pub fn subsetOf(self: Self, other: Self) bool { + return self.intersectWith(other).eql(self); + } + + /// Returns iff the first bit set is the superset of the + /// second one. + pub fn supersetOf(self: Self, other: Self) bool { + return other.subsetOf(self); + } + + /// Returns the complement bit sets. Bits in the result + /// are set if the corresponding bits were not set. + pub fn complement(self: Self) Self { + var result = self; + result.toggleAll(); + return result; + } + + /// Returns the union of two bit sets. Bits in the + /// result are set if the corresponding bits were set + /// in both inputs. + pub fn unionWith(self: Self, other: Self) Self { + var result = self; + result.setUnion(other); + return result; + } + + /// Returns the intersection of two bit sets. Bits in + /// the result are set if the corresponding bits were + /// set in both inputs. + pub fn intersectWith(self: Self, other: Self) Self { + var result = self; + result.setIntersection(other); + return result; + } + + /// Returns the xor of two bit sets. Bits in the + /// result are set if the corresponding bits were + /// set in not the same in both inputs. + pub fn xorWith(self: Self, other: Self) Self { + var result = self; + result.toggleSet(other); + return result; + } + + /// Returns the difference of two bit sets. Bits in + /// the result are set if set in the first but not + /// set in the second set. + pub fn differenceWith(self: Self, other: Self) Self { + var result = self; + result.setIntersection(other.complement()); + return result; + } + /// Iterates through the items in the set, according to the options. /// The default options (.{}) will iterate indices of set bits in /// ascending order. Modifications to the underlying bit set may @@ -491,6 +553,76 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type { return offset + index; } + /// Returns true iff every corresponding bit in both + /// bit sets are the same. + pub fn eql(self: Self, other: Self) bool { + if (bit_length == 0) { + return true; + } + var i: usize = 0; + return while (i < num_masks) : (i += 1) { + if (self.masks[i] != other.masks[i]) { + break false; + } + } else true; + } + + /// Returns iff the first bit set is the subset of the + /// second one. + pub fn subsetOf(self: Self, other: Self) bool { + return self.intersectWith(other).eql(self); + } + + /// Returns iff the first bit set is the superset of the + /// second one. + pub fn supersetOf(self: Self, other: Self) bool { + return other.subsetOf(self); + } + + /// Returns the complement bit sets. Bits in the result + /// are set if the corresponding bits were not set. + pub fn complement(self: Self) Self { + var result = self; + result.toggleAll(); + return result; + } + + /// Returns the union of two bit sets. Bits in the + /// result are set if the corresponding bits were set + /// in both inputs. + pub fn unionWith(self: Self, other: Self) Self { + var result = self; + result.setUnion(other); + return result; + } + + /// Returns the intersection of two bit sets. Bits in + /// the result are set if the corresponding bits were + /// set in both inputs. + pub fn intersectWith(self: Self, other: Self) Self { + var result = self; + result.setIntersection(other); + return result; + } + + /// Returns the xor of two bit sets. Bits in the + /// result are set if the corresponding bits were + /// set in not the same in both inputs. + pub fn xorWith(self: Self, other: Self) Self { + var result = self; + result.toggleSet(other); + return result; + } + + /// Returns the difference of two bit sets. Bits in + /// the result are set if set in the first but not + /// set in the second set. + pub fn differenceWith(self: Self, other: Self) Self { + var result = self; + result.setIntersection(other.complement()); + return result; + } + /// Iterates through the items in the set, according to the options. /// The default options (.{}) will iterate indices of set bits in /// ascending order. Modifications to the underlying bit set may @@ -1320,6 +1452,115 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void { } } +fn testPureBitSet(comptime Set: type) !void { + const empty = Set.initEmpty(); + const full = Set.initFull(); + + const even = even: { + var bit_set = Set.initEmpty(); + var i: usize = 0; + while (i < Set.bit_length) : (i += 1) { + bit_set.setValue(i, i & 1 == 0); + } + break :even bit_set; + }; + + const odd = odd: { + var bit_set = Set.initEmpty(); + var i: usize = 0; + while (i < Set.bit_length) : (i += 1) { + bit_set.setValue(i, i & 1 == 1); + } + break :odd bit_set; + }; + + try testing.expect(empty.eql(empty)); + try testing.expect(full.eql(full)); + switch (Set.bit_length) { + 0 => { + try testing.expect(empty.eql(full)); + try testing.expect(full.eql(empty)); + try testing.expect(even.eql(odd)); + try testing.expect(odd.eql(even)); + }, + else => { + try testing.expect(!empty.eql(full)); + try testing.expect(!full.eql(empty)); + try testing.expect(!even.eql(odd)); + try testing.expect(!odd.eql(even)); + }, + } + + try testing.expect(empty.subsetOf(empty)); + try testing.expect(empty.subsetOf(full)); + try testing.expect(full.subsetOf(full)); + switch (Set.bit_length) { + 0 => { + try testing.expect(even.subsetOf(odd)); + try testing.expect(odd.subsetOf(even)); + }, + 1 => { + try testing.expect(!even.subsetOf(odd)); + try testing.expect(odd.subsetOf(even)); + }, + else => { + try testing.expect(!even.subsetOf(odd)); + try testing.expect(!odd.subsetOf(even)); + }, + } + + try testing.expect(full.supersetOf(full)); + try testing.expect(full.supersetOf(empty)); + try testing.expect(empty.supersetOf(empty)); + switch (Set.bit_length) { + 0 => { + try testing.expect(even.supersetOf(odd)); + try testing.expect(odd.supersetOf(even)); + }, + 1 => { + try testing.expect(even.supersetOf(odd)); + try testing.expect(!odd.supersetOf(even)); + }, + else => { + try testing.expect(!even.supersetOf(odd)); + try testing.expect(!odd.supersetOf(even)); + }, + } + + try testing.expect(empty.complement().eql(full)); + try testing.expect(full.complement().eql(empty)); + try testing.expect(even.complement().eql(odd)); + try testing.expect(odd.complement().eql(even)); + + try testing.expect(empty.unionWith(empty).eql(empty)); + try testing.expect(empty.unionWith(full).eql(full)); + try testing.expect(full.unionWith(full).eql(full)); + try testing.expect(full.unionWith(empty).eql(full)); + try testing.expect(even.unionWith(odd).eql(full)); + try testing.expect(odd.unionWith(even).eql(full)); + + try testing.expect(empty.intersectWith(empty).eql(empty)); + try testing.expect(empty.intersectWith(full).eql(empty)); + try testing.expect(full.intersectWith(full).eql(full)); + try testing.expect(full.intersectWith(empty).eql(empty)); + try testing.expect(even.intersectWith(odd).eql(empty)); + try testing.expect(odd.intersectWith(even).eql(empty)); + + try testing.expect(empty.xorWith(empty).eql(empty)); + try testing.expect(empty.xorWith(full).eql(full)); + try testing.expect(full.xorWith(full).eql(empty)); + try testing.expect(full.xorWith(empty).eql(full)); + try testing.expect(even.xorWith(odd).eql(full)); + try testing.expect(odd.xorWith(even).eql(full)); + + try testing.expect(empty.differenceWith(empty).eql(empty)); + try testing.expect(empty.differenceWith(full).eql(empty)); + try testing.expect(full.differenceWith(full).eql(empty)); + try testing.expect(full.differenceWith(empty).eql(full)); + try testing.expect(full.differenceWith(odd).eql(even)); + try testing.expect(full.differenceWith(even).eql(odd)); +} + fn testStaticBitSet(comptime Set: type) !void { var a = Set.initEmpty(); var b = Set.initFull(); @@ -1327,6 +1568,8 @@ fn testStaticBitSet(comptime Set: type) !void { try testing.expectEqual(@as(usize, Set.bit_length), b.count()); try testBitSet(&a, &b, Set.bit_length); + + try testPureBitSet(Set); } test "IntegerBitSet" {