@@ -551,21 +551,19 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
551
551
552
552
while let i = boundaryIterator. next ( ) {
553
553
if !flag {
554
- // Starting a range; if the edge is contained or not depends on the xor of this particular value.
555
- let startInclusive = self . contains ( i) != other. contains ( i)
556
- start = startInclusive ? i : i + 1
557
- flag = true
554
+ // Start a range if one set contains but not the other.
555
+ if self . contains ( i) != other. contains ( i) {
556
+ flag = true
557
+ start = i
558
+ }
558
559
} else {
559
- // Ending a range; if the edge is contained or not depends on the xor of this particular value.
560
- let endInclusive = self . contains ( i) != other. contains ( i)
561
- let end = endInclusive ? i + 1 : i
562
- if start < end {
563
- // Otherwise, we had an empty range
564
- result. insert ( integersIn: start..< end)
560
+ // End a range if both sets contain or both sets do not contain.
561
+ if self . contains ( i) == other. contains ( i) {
562
+ flag = false
563
+ result. insert ( integersIn: start..< i)
565
564
}
566
- flag = false
567
565
}
568
- // We never have to worry about having flag set to false after exiting this loop because the iterator will always return an even number of results; ranges come in pairs, and we always alternate flag
566
+ // We never have to worry about having flag set to false after exiting this loop because the last boundary is guaranteed to be past the end of ranges in both index sets
569
567
}
570
568
571
569
return result
@@ -591,10 +589,10 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
591
589
start = i
592
590
}
593
591
} else {
594
- // If both sets contain then end a range.
595
- if self . contains ( i) && other. contains ( i) {
592
+ // If both sets do not contain then end a range.
593
+ if ! self . contains ( i) || ! other. contains ( i) {
596
594
flag = false
597
- result. insert ( integersIn: start..< ( i + 1 ) )
595
+ result. insert ( integersIn: start..< i )
598
596
}
599
597
}
600
598
}
@@ -783,8 +781,8 @@ private struct IndexSetBoundaryIterator : IteratorProtocol {
783
781
private var i2 : IndexSet . RangeView . Iterator
784
782
private var i1Range : CountableRange < Element > ?
785
783
private var i2Range : CountableRange < Element > ?
786
- private var i1UsedFirst : Bool
787
- private var i2UsedFirst : Bool
784
+ private var i1UsedLower : Bool
785
+ private var i2UsedLower : Bool
788
786
789
787
private init ( _ is1 : IndexSet , _ is2 : IndexSet ) {
790
788
i1 = is1. rangeView. makeIterator ( )
@@ -793,9 +791,9 @@ private struct IndexSetBoundaryIterator : IteratorProtocol {
793
791
i1Range = i1. next ( )
794
792
i2Range = i2. next ( )
795
793
796
- // A sort of cheap iterator on [i1Range.first , i1Range.last ]
797
- i1UsedFirst = false
798
- i2UsedFirst = false
794
+ // A sort of cheap iterator on [i1Range.lowerBound , i1Range.upperBound ]
795
+ i1UsedLower = false
796
+ i2UsedLower = false
799
797
}
800
798
801
799
private mutating func next( ) -> Element ? {
@@ -805,29 +803,34 @@ private struct IndexSetBoundaryIterator : IteratorProtocol {
805
803
806
804
let nextIn1 : Element
807
805
if let r = i1Range {
808
- nextIn1 = i1UsedFirst ? r. last! : r. first!
806
+ nextIn1 = i1UsedLower ? r. upperBound : r. lowerBound
809
807
} else {
810
808
nextIn1 = Int . max
811
809
}
812
810
813
811
let nextIn2 : Element
814
812
if let r = i2Range {
815
- nextIn2 = i2UsedFirst ? r. last! : r. first!
813
+ nextIn2 = i2UsedLower ? r. upperBound : r. lowerBound
816
814
} else {
817
815
nextIn2 = Int . max
818
816
}
819
817
820
818
var result : Element
821
819
if nextIn1 <= nextIn2 {
822
- // 1 has the next element, or they are the same. We need to iterate both the value from is1 and is2 in the == case.
820
+ // 1 has the next element, or they are the same.
823
821
result = nextIn1
824
- if i1UsedFirst { i1Range = i1. next ( ) }
825
- i1UsedFirst = !i1UsedFirst
822
+ if i1UsedLower { i1Range = i1. next ( ) }
823
+ // We need to iterate both the value from is1 and is2 in the == case.
824
+ if result == nextIn2 {
825
+ if i2UsedLower { i2Range = i2. next ( ) }
826
+ i2UsedLower = !i2UsedLower
827
+ }
828
+ i1UsedLower = !i1UsedLower
826
829
} else {
827
830
// 2 has the next element
828
831
result = nextIn2
829
- if i2UsedFirst { i2Range = i2. next ( ) }
830
- i2UsedFirst = !i2UsedFirst
832
+ if i2UsedLower { i2Range = i2. next ( ) }
833
+ i2UsedLower = !i2UsedLower
831
834
}
832
835
833
836
return result
0 commit comments