@@ -428,6 +428,39 @@ public struct Set<Element : Hashable> :
428
428
self.init(_nativeStorage: _NativeSetStorage.fromArray(elements))
429
429
}
430
430
431
+ /// Remove any members of this set that aren't also in a finite sequence.
432
+ public mutating func intersectInPlace<
433
+ S : SequenceType where S.Generator.Element == Element
434
+ >(sequence: S) {
435
+ if case .Native(let nativeOwner) = _variantStorage {
436
+ // perform this operation at a lower level
437
+ // to avoid invalidating the index and avoiding a copy.
438
+
439
+ let other = sequence as? Set<Element> ?? Set(sequence)
440
+ // FIXME(performance) take the oppurtunity to shrink the storage.
441
+ let native = nativeOwner.nativeStorage
442
+ for bucket in 0..<native.capacity {
443
+ if native.isInitializedEntry(bucket) &&
444
+ !other.contains(native.keyAt(bucket)) {
445
+ native.destroyEntryAt(bucket)
446
+ native.count -= 1
447
+ }
448
+ }
449
+ } else {
450
+ // Because `intersect` needs to both modify and iterate over
451
+ // the left-hand side, the index may become invalidated during
452
+ // traversal so an intermediate set must be created.
453
+ let result = intersect(sequence)
454
+
455
+ // The result can only have fewer or the same number of elements.
456
+ // If no elements were removed, don't perform a reassignment
457
+ // as this may cause an unnecessary uniquing COW.
458
+ if result.count != count {
459
+ self = result
460
+ }
461
+ }
462
+ }
463
+
431
464
//
432
465
// APIs below this comment should be implemented strictly in terms of
433
466
// *public* APIs above. `_variantStorage` should not be accessed directly.
@@ -571,25 +604,6 @@ public struct Set<Element : Hashable> :
571
604
return newSet
572
605
}
573
606
574
- /// Remove any members of this set that aren't also in a finite sequence.
575
- public mutating func intersectInPlace<
576
- S : SequenceType where S.Generator.Element == Element
577
- >(sequence: S) {
578
- // Because `intersect` needs to both modify and iterate over
579
- // the left-hand side, the index may become invalidated during
580
- // traversal so an intermediate set must be created.
581
- //
582
- // FIXME(performance): perform this operation at a lower level
583
- // to avoid invalidating the index and avoiding a copy.
584
- let result = self.intersect(sequence)
585
-
586
- // The result can only have fewer or the same number of elements.
587
- // If no elements were removed, don't perform a reassignment
588
- // as this may cause an unnecessary uniquing COW.
589
- if result.count != count {
590
- self = result
591
- }
592
- }
593
607
594
608
/// Return a new set with elements that are either in the set or a finite
595
609
/// sequence but do not occur in both.
0 commit comments