Commit 9e74e4c1f8

Pyrolistical <pyrogx1133@gmail.com>
2022-12-04 23:32:10
std: added pure functions to StaticBitSet The following functions were added to both IntegerBitSet and ArrayBitSet: fn eql(self: Self, other: Self) bool fn subsetOf(self: Self, other: Self) bool fn supersetOf(self: Self, other: Self) bool fn complement(self: Self) Self fn unionWith(self: Self, other: Self) Self fn intersectWith(self: Self, other: Self) Self fn xorWith(self: Self, other: Self) Self fn differenceWith(self: Self, other: Self) Self
1 parent a7cb502
Changed files (1)
lib
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" {