Skip to content

Commit a2540c2

Browse files
committed
[stdlib] Optimize Set.isStrictSuperset(of:)
- Use a temporary bitset to speed up the `Sequence` variant by roughly a factor of 4. - Fix a logic error causing the `a == b` case for the set variant to be O(n) instead of O(1).
1 parent 725ee55 commit a2540c2

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

stdlib/public/core/NativeSet.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,25 @@ extension _NativeSet {
636636
return false
637637
}
638638
}
639+
640+
@_alwaysEmitIntoClient
641+
internal func isStrictSuperset<S: Sequence>(of possibleSubset: S) -> Bool
642+
where S.Element == Element {
643+
_UnsafeBitset.withTemporaryBitset(capacity: self.bucketCount) { seen in
644+
// Mark elements in self that we've seen in `possibleStrictSubset`.
645+
var seenCount = 0
646+
for element in possibleSubset {
647+
let (bucket, found) = find(element)
648+
guard found else { return false }
649+
let inserted = seen.uncheckedInsert(bucket.offset)
650+
if inserted {
651+
seenCount += 1
652+
if seenCount == self.count {
653+
return false
654+
}
655+
}
656+
}
657+
return true
658+
}
659+
}
639660
}

stdlib/public/core/Set.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,11 @@ extension Set: SetAlgebra {
796796
@inlinable
797797
public func isStrictSuperset<S: Sequence>(of possibleStrictSubset: S) -> Bool
798798
where S.Element == Element {
799-
let other = Set(possibleStrictSubset)
800-
return other.isStrictSubset(of: self)
799+
if isEmpty { return false }
800+
if let s = possibleStrictSubset as? Set<Element> {
801+
return isStrictSuperset(of: s)
802+
}
803+
return _variant.convertedToNative.isStrictSuperset(of: possibleStrictSubset)
801804
}
802805

803806
/// Returns a Boolean value that indicates whether the set has no members in
@@ -1191,7 +1194,7 @@ extension Set {
11911194
/// `other`; otherwise, `false`.
11921195
@inlinable
11931196
public func isStrictSuperset(of other: Set<Element>) -> Bool {
1194-
return self.isSuperset(of: other) && self != other
1197+
return self.count > other.count && other.isSubset(of: self)
11951198
}
11961199

11971200
/// Returns a Boolean value that indicates whether the set is a strict subset

0 commit comments

Comments
 (0)