| ... | @@ -431,6 +431,30 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type { | ... | @@ -431,6 +431,30 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type { |
| 431 | return true; | 431 | return true; |
| 432 | } | 432 | } |
| 433 | | 433 | |
| | 434 | /// Returns true iff all key counts less than or |
| | 435 | /// equal to the given multiset. |
| | 436 | pub fn subsetOf(self: Self, other: Self) bool { |
| | 437 | inline for (@typeInfo(E).Enum.fields) |field| { |
| | 438 | const key = @intToEnum(E, field.value); |
| | 439 | if (self.getCount(key) > other.getCount(key)) { |
| | 440 | return false; |
| | 441 | } |
| | 442 | } |
| | 443 | return true; |
| | 444 | } |
| | 445 | |
| | 446 | /// Returns true iff all key counts greater than or |
| | 447 | /// equal to the given multiset. |
| | 448 | pub fn supersetOf(self: Self, other: Self) bool { |
| | 449 | inline for (@typeInfo(E).Enum.fields) |field| { |
| | 450 | const key = @intToEnum(E, field.value); |
| | 451 | if (self.getCount(key) < other.getCount(key)) { |
| | 452 | return false; |
| | 453 | } |
| | 454 | } |
| | 455 | return true; |
| | 456 | } |
| | 457 | |
| 434 | /// Returns a multiset with the total key count of this | 458 | /// Returns a multiset with the total key count of this |
| 435 | /// multiset and the other multiset. Caller asserts | 459 | /// multiset and the other multiset. Caller asserts |
| 436 | /// operation will not overflow any key. | 460 | /// operation will not overflow any key. |
| ... | @@ -582,6 +606,38 @@ test "EnumMultiset" { | ... | @@ -582,6 +606,38 @@ test "EnumMultiset" { |
| 582 | try testing.expect(!r0_g1_b2.eql(ten_of_each)); | 606 | try testing.expect(!r0_g1_b2.eql(ten_of_each)); |
| 583 | try testing.expect(!ten_of_each.eql(empty)); | 607 | try testing.expect(!ten_of_each.eql(empty)); |
| 584 | | 608 | |
| | 609 | try testing.expect(empty.subsetOf(empty)); |
| | 610 | try testing.expect(r0_g1_b2.subsetOf(r0_g1_b2)); |
| | 611 | try testing.expect(empty.subsetOf(r0_g1_b2)); |
| | 612 | try testing.expect(r0_g1_b2.subsetOf(ten_of_each)); |
| | 613 | try testing.expect(!ten_of_each.subsetOf(r0_g1_b2)); |
| | 614 | try testing.expect(!r0_g1_b2.subsetOf(empty)); |
| | 615 | |
| | 616 | try testing.expect(empty.supersetOf(empty)); |
| | 617 | try testing.expect(r0_g1_b2.supersetOf(r0_g1_b2)); |
| | 618 | try testing.expect(r0_g1_b2.supersetOf(empty)); |
| | 619 | try testing.expect(ten_of_each.supersetOf(r0_g1_b2)); |
| | 620 | try testing.expect(!r0_g1_b2.supersetOf(ten_of_each)); |
| | 621 | try testing.expect(!empty.supersetOf(r0_g1_b2)); |
| | 622 | |
| | 623 | { |
| | 624 | // with multisets it could be the case where two |
| | 625 | // multisets are neither subset nor superset of each |
| | 626 | // other. |
| | 627 | |
| | 628 | const r10 = EnumMultiset(Ball).init(.{ |
| | 629 | .red = 10, |
| | 630 | }); |
| | 631 | const b10 = EnumMultiset(Ball).init(.{ |
| | 632 | .blue = 10, |
| | 633 | }); |
| | 634 | |
| | 635 | try testing.expect(!r10.subsetOf(b10)); |
| | 636 | try testing.expect(!b10.subsetOf(r10)); |
| | 637 | try testing.expect(!r10.supersetOf(b10)); |
| | 638 | try testing.expect(!b10.supersetOf(r10)); |
| | 639 | } |
| | 640 | |
| 585 | { | 641 | { |
| 586 | const result = r0_g1_b2.plusAssertSafe(ten_of_each); | 642 | const result = r0_g1_b2.plusAssertSafe(ten_of_each); |
| 587 | try testing.expectEqual(result.getCount(.red), 10); | 643 | try testing.expectEqual(result.getCount(.red), 10); |