@@ -122,13 +122,16 @@ pub struct Difference<'a, T: 'a> {
122
122
}
123
123
enum DifferenceInner < ' a , T : ' a > {
124
124
Stitch {
125
+ // iterate all of self and some of other, spotting matches along the way
125
126
self_iter : Iter < ' a , T > ,
126
127
other_iter : Peekable < Iter < ' a , T > > ,
127
128
} ,
128
129
Search {
130
+ // iterate a small set, look up in the large set
129
131
self_iter : Iter < ' a , T > ,
130
132
other_set : & ' a BTreeSet < T > ,
131
133
} ,
134
+ Iterate ( Iter < ' a , T > ) , // simply stream self's elements
132
135
}
133
136
134
137
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
@@ -147,6 +150,7 @@ impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
147
150
self_iter,
148
151
other_set : _,
149
152
} => f. debug_tuple ( "Difference" ) . field ( & self_iter) . finish ( ) ,
153
+ DifferenceInner :: Iterate ( iter) => f. debug_tuple ( "Difference" ) . field ( & iter) . finish ( ) ,
150
154
}
151
155
}
152
156
}
@@ -187,13 +191,16 @@ pub struct Intersection<'a, T: 'a> {
187
191
}
188
192
enum IntersectionInner < ' a , T : ' a > {
189
193
Stitch {
194
+ // iterate similarly sized sets jointly, spotting matches along the way
190
195
a : Iter < ' a , T > ,
191
196
b : Iter < ' a , T > ,
192
197
} ,
193
198
Search {
199
+ // iterate a small set, look up in the large set
194
200
small_iter : Iter < ' a , T > ,
195
201
large_set : & ' a BTreeSet < T > ,
196
202
} ,
203
+ Answer ( Option < & ' a T > ) , // return a specific value or emptiness
197
204
}
198
205
199
206
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
@@ -212,6 +219,9 @@ impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
212
219
small_iter,
213
220
large_set : _,
214
221
} => f. debug_tuple ( "Intersection" ) . field ( & small_iter) . finish ( ) ,
222
+ IntersectionInner :: Answer ( answer) => {
223
+ f. debug_tuple ( "Intersection" ) . field ( & answer) . finish ( )
224
+ }
215
225
}
216
226
}
217
227
}
@@ -314,24 +324,51 @@ impl<T: Ord> BTreeSet<T> {
314
324
/// ```
315
325
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
316
326
pub fn difference < ' a > ( & ' a self , other : & ' a BTreeSet < T > ) -> Difference < ' a , T > {
317
- if self . len ( ) > other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
318
- // Self is bigger than or not much smaller than other set.
319
- // Iterate both sets jointly, spotting matches along the way.
320
- Difference {
321
- inner : DifferenceInner :: Stitch {
322
- self_iter : self . iter ( ) ,
323
- other_iter : other. iter ( ) . peekable ( ) ,
324
- } ,
325
- }
327
+ let ( self_min, self_max) = if let ( Some ( self_min) , Some ( self_max) ) =
328
+ ( self . iter ( ) . next ( ) , self . iter ( ) . next_back ( ) )
329
+ {
330
+ ( self_min, self_max)
326
331
} else {
327
- // Self is much smaller than other set, or both sets are empty.
328
- // Iterate the small set, searching for matches in the large set.
329
- Difference {
330
- inner : DifferenceInner :: Search {
331
- self_iter : self . iter ( ) ,
332
- other_set : other,
333
- } ,
334
- }
332
+ return Difference {
333
+ inner : DifferenceInner :: Iterate ( self . iter ( ) ) ,
334
+ } ;
335
+ } ;
336
+ let ( other_min, other_max) = if let ( Some ( other_min) , Some ( other_max) ) =
337
+ ( other. iter ( ) . next ( ) , other. iter ( ) . next_back ( ) )
338
+ {
339
+ ( other_min, other_max)
340
+ } else {
341
+ return Difference {
342
+ inner : DifferenceInner :: Iterate ( self . iter ( ) ) ,
343
+ } ;
344
+ } ;
345
+ Difference {
346
+ inner : match ( self_min. cmp ( other_max) , self_max. cmp ( other_min) ) {
347
+ ( Greater , _) | ( _, Less ) => DifferenceInner :: Iterate ( self . iter ( ) ) ,
348
+ ( Equal , _) => {
349
+ let mut self_iter = self . iter ( ) ;
350
+ self_iter. next ( ) ;
351
+ DifferenceInner :: Iterate ( self_iter)
352
+ }
353
+ ( _, Equal ) => {
354
+ let mut self_iter = self . iter ( ) ;
355
+ self_iter. next_back ( ) ;
356
+ DifferenceInner :: Iterate ( self_iter)
357
+ }
358
+ _ => {
359
+ if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
360
+ DifferenceInner :: Search {
361
+ self_iter : self . iter ( ) ,
362
+ other_set : other,
363
+ }
364
+ } else {
365
+ DifferenceInner :: Stitch {
366
+ self_iter : self . iter ( ) ,
367
+ other_iter : other. iter ( ) . peekable ( ) ,
368
+ }
369
+ }
370
+ }
371
+ } ,
335
372
}
336
373
}
337
374
@@ -387,29 +424,48 @@ impl<T: Ord> BTreeSet<T> {
387
424
/// ```
388
425
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
389
426
pub fn intersection < ' a > ( & ' a self , other : & ' a BTreeSet < T > ) -> Intersection < ' a , T > {
390
- let ( small, other) = if self . len ( ) <= other. len ( ) {
391
- ( self , other)
427
+ let ( self_min, self_max) = if let ( Some ( self_min) , Some ( self_max) ) =
428
+ ( self . iter ( ) . next ( ) , self . iter ( ) . next_back ( ) )
429
+ {
430
+ ( self_min, self_max)
392
431
} else {
393
- ( other, self )
432
+ return Intersection {
433
+ inner : IntersectionInner :: Answer ( None ) ,
434
+ } ;
394
435
} ;
395
- if small. len ( ) > other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
396
- // Small set is not much smaller than other set.
397
- // Iterate both sets jointly, spotting matches along the way.
398
- Intersection {
399
- inner : IntersectionInner :: Stitch {
400
- a : small. iter ( ) ,
401
- b : other. iter ( ) ,
402
- } ,
403
- }
436
+ let ( other_min, other_max) = if let ( Some ( other_min) , Some ( other_max) ) =
437
+ ( other. iter ( ) . next ( ) , other. iter ( ) . next_back ( ) )
438
+ {
439
+ ( other_min, other_max)
404
440
} else {
405
- // Big difference in number of elements, or both sets are empty.
406
- // Iterate the small set, searching for matches in the large set.
407
- Intersection {
408
- inner : IntersectionInner :: Search {
409
- small_iter : small. iter ( ) ,
410
- large_set : other,
411
- } ,
412
- }
441
+ return Intersection {
442
+ inner : IntersectionInner :: Answer ( None ) ,
443
+ } ;
444
+ } ;
445
+ Intersection {
446
+ inner : match ( self_min. cmp ( other_max) , self_max. cmp ( other_min) ) {
447
+ ( Greater , _) | ( _, Less ) => IntersectionInner :: Answer ( None ) ,
448
+ ( Equal , _) => IntersectionInner :: Answer ( Some ( self_min) ) ,
449
+ ( _, Equal ) => IntersectionInner :: Answer ( Some ( self_max) ) ,
450
+ _ => {
451
+ if self . len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
452
+ IntersectionInner :: Search {
453
+ small_iter : self . iter ( ) ,
454
+ large_set : other,
455
+ }
456
+ } else if other. len ( ) <= self . len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
457
+ IntersectionInner :: Search {
458
+ small_iter : other. iter ( ) ,
459
+ large_set : self ,
460
+ }
461
+ } else {
462
+ IntersectionInner :: Stitch {
463
+ a : self . iter ( ) ,
464
+ b : other. iter ( ) ,
465
+ }
466
+ }
467
+ }
468
+ } ,
413
469
}
414
470
}
415
471
@@ -544,43 +600,61 @@ impl<T: Ord> BTreeSet<T> {
544
600
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
545
601
pub fn is_subset ( & self , other : & BTreeSet < T > ) -> bool {
546
602
// Same result as self.difference(other).next().is_none()
547
- // but the 3 paths below are faster (in order: hugely, 20%, 5% ).
603
+ // but the code below is faster (hugely in some cases ).
548
604
if self . len ( ) > other. len ( ) {
549
- false
550
- } else if self . len ( ) > other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
551
- // Self is not much smaller than other set.
552
- // Stolen from TreeMap
553
- let mut x = self . iter ( ) ;
554
- let mut y = other. iter ( ) ;
555
- let mut a = x. next ( ) ;
556
- let mut b = y. next ( ) ;
557
- while a. is_some ( ) {
558
- if b. is_none ( ) {
605
+ return false ;
606
+ }
607
+ let ( self_min, self_max) = if let ( Some ( self_min) , Some ( self_max) ) =
608
+ ( self . iter ( ) . next ( ) , self . iter ( ) . next_back ( ) )
609
+ {
610
+ ( self_min, self_max)
611
+ } else {
612
+ return true ; // self is empty
613
+ } ;
614
+ let ( other_min, other_max) = if let ( Some ( other_min) , Some ( other_max) ) =
615
+ ( other. iter ( ) . next ( ) , other. iter ( ) . next_back ( ) )
616
+ {
617
+ ( other_min, other_max)
618
+ } else {
619
+ return false ; // other is empty
620
+ } ;
621
+ let mut self_iter = self . iter ( ) ;
622
+ match self_min. cmp ( other_min) {
623
+ Less => return false ,
624
+ Equal => {
625
+ self_iter. next ( ) ;
626
+ }
627
+ Greater => ( ) ,
628
+ }
629
+ match self_max. cmp ( other_max) {
630
+ Greater => return false ,
631
+ Equal => {
632
+ self_iter. next_back ( ) ;
633
+ }
634
+ Less => ( ) ,
635
+ }
636
+ if self_iter. len ( ) <= other. len ( ) / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
637
+ // Big difference in number of elements.
638
+ for next in self_iter {
639
+ if !other. contains ( next) {
559
640
return false ;
560
641
}
561
-
562
- let a1 = a. unwrap ( ) ;
563
- let b1 = b. unwrap ( ) ;
564
-
565
- match b1. cmp ( a1) {
566
- Less => ( ) ,
567
- Greater => return false ,
568
- Equal => a = x. next ( ) ,
569
- }
570
-
571
- b = y. next ( ) ;
572
642
}
573
- true
574
643
} else {
575
- // Big difference in number of elements, or both sets are empty.
576
- // Iterate the small set, searching for matches in the large set.
577
- for next in self {
578
- if !other. contains ( next) {
579
- return false ;
644
+ // Self is not much smaller than other set.
645
+ let mut other_iter = other. iter ( ) ;
646
+ other_iter. next ( ) ;
647
+ other_iter. next_back ( ) ;
648
+ let mut self_next = self_iter. next ( ) ;
649
+ while let Some ( self1) = self_next {
650
+ match other_iter. next ( ) . map_or ( Less , |other1| self1. cmp ( other1) ) {
651
+ Less => return false ,
652
+ Equal => self_next = self_iter. next ( ) ,
653
+ Greater => ( ) ,
580
654
}
581
655
}
582
- true
583
656
}
657
+ true
584
658
}
585
659
586
660
/// Returns `true` if the set is a superset of another,
@@ -1120,6 +1194,7 @@ impl<T> Clone for Difference<'_, T> {
1120
1194
self_iter : self_iter. clone ( ) ,
1121
1195
other_set,
1122
1196
} ,
1197
+ DifferenceInner :: Iterate ( iter) => DifferenceInner :: Iterate ( iter. clone ( ) ) ,
1123
1198
} ,
1124
1199
}
1125
1200
}
@@ -1138,7 +1213,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
1138
1213
loop {
1139
1214
match other_iter
1140
1215
. peek ( )
1141
- . map_or ( Less , |other_next| Ord :: cmp ( self_next , other_next) )
1216
+ . map_or ( Less , |other_next| self_next . cmp ( other_next) )
1142
1217
{
1143
1218
Less => return Some ( self_next) ,
1144
1219
Equal => {
@@ -1160,19 +1235,21 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
1160
1235
return Some ( self_next) ;
1161
1236
}
1162
1237
} ,
1238
+ DifferenceInner :: Iterate ( iter) => iter. next ( ) ,
1163
1239
}
1164
1240
}
1165
1241
1166
1242
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1167
1243
let ( self_len, other_len) = match & self . inner {
1168
1244
DifferenceInner :: Stitch {
1169
1245
self_iter,
1170
- other_iter
1246
+ other_iter,
1171
1247
} => ( self_iter. len ( ) , other_iter. len ( ) ) ,
1172
1248
DifferenceInner :: Search {
1173
1249
self_iter,
1174
- other_set
1250
+ other_set,
1175
1251
} => ( self_iter. len ( ) , other_set. len ( ) ) ,
1252
+ DifferenceInner :: Iterate ( iter) => ( iter. len ( ) , 0 ) ,
1176
1253
} ;
1177
1254
( self_len. saturating_sub ( other_len) , Some ( self_len) )
1178
1255
}
@@ -1234,6 +1311,7 @@ impl<T> Clone for Intersection<'_, T> {
1234
1311
small_iter : small_iter. clone ( ) ,
1235
1312
large_set,
1236
1313
} ,
1314
+ IntersectionInner :: Answer ( answer) => IntersectionInner :: Answer ( answer. clone ( ) ) ,
1237
1315
} ,
1238
1316
}
1239
1317
}
@@ -1251,7 +1329,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
1251
1329
let mut a_next = a. next ( ) ?;
1252
1330
let mut b_next = b. next ( ) ?;
1253
1331
loop {
1254
- match Ord :: cmp ( a_next , b_next) {
1332
+ match a_next . cmp ( b_next) {
1255
1333
Less => a_next = a. next ( ) ?,
1256
1334
Greater => b_next = b. next ( ) ?,
1257
1335
Equal => return Some ( a_next) ,
@@ -1267,15 +1345,17 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
1267
1345
return Some ( small_next) ;
1268
1346
}
1269
1347
} ,
1348
+ IntersectionInner :: Answer ( answer) => answer. take ( ) ,
1270
1349
}
1271
1350
}
1272
1351
1273
1352
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1274
- let min_len = match & self . inner {
1275
- IntersectionInner :: Stitch { a, b } => min ( a. len ( ) , b. len ( ) ) ,
1276
- IntersectionInner :: Search { small_iter, .. } => small_iter. len ( ) ,
1277
- } ;
1278
- ( 0 , Some ( min_len) )
1353
+ match & self . inner {
1354
+ IntersectionInner :: Stitch { a, b } => ( 0 , Some ( min ( a. len ( ) , b. len ( ) ) ) ) ,
1355
+ IntersectionInner :: Search { small_iter, .. } => ( 0 , Some ( small_iter. len ( ) ) ) ,
1356
+ IntersectionInner :: Answer ( None ) => ( 0 , Some ( 0 ) ) ,
1357
+ IntersectionInner :: Answer ( Some ( _) ) => ( 1 , Some ( 1 ) ) ,
1358
+ }
1279
1359
}
1280
1360
}
1281
1361
0 commit comments