Skip to content

Commit 9043c71

Browse files
committed
[stdlib] Optimize Set.isStrictSubset<S>(of: S)
Use a temporary bitset to speed up the Sequence variant by roughly a factor of 3.
1 parent 5e642d2 commit 9043c71

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

stdlib/public/core/NativeSet.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,4 +608,32 @@ extension _NativeSet {
608608
return false
609609
}
610610
}
611+
612+
@_alwaysEmitIntoClient
613+
internal func isStrictSubset<S: Sequence>(of possibleSuperset: S) -> Bool
614+
where S.Element == Element {
615+
_UnsafeBitset.withTemporaryBitset(capacity: self.bucketCount) { seen in
616+
// Mark elements in self that we've seen in `possibleSuperset`.
617+
var seenCount = 0
618+
var isStrict = false
619+
for element in possibleSuperset {
620+
let (bucket, found) = find(element)
621+
guard found else {
622+
if !isStrict {
623+
isStrict = true
624+
if seenCount == self.count { return true }
625+
}
626+
continue
627+
}
628+
let inserted = seen.uncheckedInsert(bucket.offset)
629+
if inserted {
630+
seenCount += 1
631+
if seenCount == self.count, isStrict {
632+
return true
633+
}
634+
}
635+
}
636+
return false
637+
}
638+
}
611639
}

stdlib/public/core/Set.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,9 +740,10 @@ extension Set: SetAlgebra {
740740
@inlinable
741741
public func isStrictSubset<S: Sequence>(of possibleStrictSuperset: S) -> Bool
742742
where S.Element == Element {
743-
// FIXME: code duplication.
744-
let other = Set(possibleStrictSuperset)
745-
return isStrictSubset(of: other)
743+
if let s = possibleStrictSuperset as? Set<Element> {
744+
return isStrictSubset(of: s)
745+
}
746+
return _variant.convertedToNative.isStrictSubset(of: possibleStrictSuperset)
746747
}
747748

748749
/// Returns a Boolean value that indicates whether the set is a superset of
@@ -1211,7 +1212,7 @@ extension Set {
12111212
/// `other`; otherwise, `false`.
12121213
@inlinable
12131214
public func isStrictSubset(of other: Set<Element>) -> Bool {
1214-
return other.isStrictSuperset(of: self)
1215+
return self.count < other.count && self.isSubset(of: other)
12151216
}
12161217

12171218
/// Returns a new set with the elements that are common to both this set and

0 commit comments

Comments
 (0)