1 //! Parallel iterator types for `IndexSet` with [rayon](https://docs.rs/rayon/1.0/rayon). 2 //! 3 //! You will rarely need to interact with this module directly unless you need to name one of the 4 //! iterator types. 5 //! 6 //! Requires crate feature `"rayon"`. 7 8 use super::collect; 9 use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer}; 10 use rayon::prelude::*; 11 12 use crate::vec::Vec; 13 use core::cmp::Ordering; 14 use core::fmt; 15 use core::hash::{BuildHasher, Hash}; 16 use core::ops::RangeBounds; 17 18 use crate::Entries; 19 use crate::IndexSet; 20 21 type Bucket<T> = crate::Bucket<T, ()>; 22 23 /// Requires crate feature `"rayon"`. 24 impl<T, S> IntoParallelIterator for IndexSet<T, S> 25 where 26 T: Send, 27 { 28 type Item = T; 29 type Iter = IntoParIter<T>; 30 into_par_iter(self) -> Self::Iter31 fn into_par_iter(self) -> Self::Iter { 32 IntoParIter { 33 entries: self.into_entries(), 34 } 35 } 36 } 37 38 /// A parallel owning iterator over the items of a `IndexSet`. 39 /// 40 /// This `struct` is created by the [`into_par_iter`] method on [`IndexSet`] 41 /// (provided by rayon's `IntoParallelIterator` trait). See its documentation for more. 42 /// 43 /// [`IndexSet`]: ../struct.IndexSet.html 44 /// [`into_par_iter`]: ../struct.IndexSet.html#method.into_par_iter 45 pub struct IntoParIter<T> { 46 entries: Vec<Bucket<T>>, 47 } 48 49 impl<T: fmt::Debug> fmt::Debug for IntoParIter<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 51 let iter = self.entries.iter().map(Bucket::key_ref); 52 f.debug_list().entries(iter).finish() 53 } 54 } 55 56 impl<T: Send> ParallelIterator for IntoParIter<T> { 57 type Item = T; 58 59 parallel_iterator_methods!(Bucket::key); 60 } 61 62 impl<T: Send> IndexedParallelIterator for IntoParIter<T> { 63 indexed_parallel_iterator_methods!(Bucket::key); 64 } 65 66 /// Requires crate feature `"rayon"`. 67 impl<'a, T, S> IntoParallelIterator for &'a IndexSet<T, S> 68 where 69 T: Sync, 70 { 71 type Item = &'a T; 72 type Iter = ParIter<'a, T>; 73 into_par_iter(self) -> Self::Iter74 fn into_par_iter(self) -> Self::Iter { 75 ParIter { 76 entries: self.as_entries(), 77 } 78 } 79 } 80 81 /// A parallel iterator over the items of a `IndexSet`. 82 /// 83 /// This `struct` is created by the [`par_iter`] method on [`IndexSet`] 84 /// (provided by rayon's `IntoParallelRefIterator` trait). See its documentation for more. 85 /// 86 /// [`IndexSet`]: ../struct.IndexSet.html 87 /// [`par_iter`]: ../struct.IndexSet.html#method.par_iter 88 pub struct ParIter<'a, T> { 89 entries: &'a [Bucket<T>], 90 } 91 92 impl<T> Clone for ParIter<'_, T> { clone(&self) -> Self93 fn clone(&self) -> Self { 94 ParIter { ..*self } 95 } 96 } 97 98 impl<T: fmt::Debug> fmt::Debug for ParIter<'_, T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 100 let iter = self.entries.iter().map(Bucket::key_ref); 101 f.debug_list().entries(iter).finish() 102 } 103 } 104 105 impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> { 106 type Item = &'a T; 107 108 parallel_iterator_methods!(Bucket::key_ref); 109 } 110 111 impl<T: Sync> IndexedParallelIterator for ParIter<'_, T> { 112 indexed_parallel_iterator_methods!(Bucket::key_ref); 113 } 114 115 /// Requires crate feature `"rayon"`. 116 impl<'a, T, S> ParallelDrainRange<usize> for &'a mut IndexSet<T, S> 117 where 118 T: Send, 119 { 120 type Item = T; 121 type Iter = ParDrain<'a, T>; 122 par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter123 fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter { 124 ParDrain { 125 entries: self.map.core.par_drain(range), 126 } 127 } 128 } 129 130 /// A parallel draining iterator over the items of a `IndexSet`. 131 /// 132 /// This `struct` is created by the [`par_drain`] method on [`IndexSet`] 133 /// (provided by rayon's `ParallelDrainRange` trait). See its documentation for more. 134 /// 135 /// [`par_drain`]: ../struct.IndexSet.html#method.par_drain 136 /// [`IndexSet`]: ../struct.IndexSet.html 137 pub struct ParDrain<'a, T: Send> { 138 entries: rayon::vec::Drain<'a, Bucket<T>>, 139 } 140 141 impl<T: Send> ParallelIterator for ParDrain<'_, T> { 142 type Item = T; 143 144 parallel_iterator_methods!(Bucket::key); 145 } 146 147 impl<T: Send> IndexedParallelIterator for ParDrain<'_, T> { 148 indexed_parallel_iterator_methods!(Bucket::key); 149 } 150 151 /// Parallel iterator methods and other parallel methods. 152 /// 153 /// The following methods **require crate feature `"rayon"`**. 154 /// 155 /// See also the `IntoParallelIterator` implementations. 156 impl<T, S> IndexSet<T, S> 157 where 158 T: Hash + Eq + Sync, 159 S: BuildHasher + Sync, 160 { 161 /// Return a parallel iterator over the values that are in `self` but not `other`. 162 /// 163 /// While parallel iterators can process items in any order, their relative order 164 /// in the `self` set is still preserved for operations like `reduce` and `collect`. par_difference<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParDifference<'a, T, S, S2> where S2: BuildHasher + Sync,165 pub fn par_difference<'a, S2>( 166 &'a self, 167 other: &'a IndexSet<T, S2>, 168 ) -> ParDifference<'a, T, S, S2> 169 where 170 S2: BuildHasher + Sync, 171 { 172 ParDifference { 173 set1: self, 174 set2: other, 175 } 176 } 177 178 /// Return a parallel iterator over the values that are in `self` or `other`, 179 /// but not in both. 180 /// 181 /// While parallel iterators can process items in any order, their relative order 182 /// in the sets is still preserved for operations like `reduce` and `collect`. 183 /// Values from `self` are produced in their original order, followed by 184 /// values from `other` in their original order. par_symmetric_difference<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParSymmetricDifference<'a, T, S, S2> where S2: BuildHasher + Sync,185 pub fn par_symmetric_difference<'a, S2>( 186 &'a self, 187 other: &'a IndexSet<T, S2>, 188 ) -> ParSymmetricDifference<'a, T, S, S2> 189 where 190 S2: BuildHasher + Sync, 191 { 192 ParSymmetricDifference { 193 set1: self, 194 set2: other, 195 } 196 } 197 198 /// Return a parallel iterator over the values that are in both `self` and `other`. 199 /// 200 /// While parallel iterators can process items in any order, their relative order 201 /// in the `self` set is still preserved for operations like `reduce` and `collect`. par_intersection<'a, S2>( &'a self, other: &'a IndexSet<T, S2>, ) -> ParIntersection<'a, T, S, S2> where S2: BuildHasher + Sync,202 pub fn par_intersection<'a, S2>( 203 &'a self, 204 other: &'a IndexSet<T, S2>, 205 ) -> ParIntersection<'a, T, S, S2> 206 where 207 S2: BuildHasher + Sync, 208 { 209 ParIntersection { 210 set1: self, 211 set2: other, 212 } 213 } 214 215 /// Return a parallel iterator over all values that are in `self` or `other`. 216 /// 217 /// While parallel iterators can process items in any order, their relative order 218 /// in the sets is still preserved for operations like `reduce` and `collect`. 219 /// Values from `self` are produced in their original order, followed by 220 /// values that are unique to `other` in their original order. par_union<'a, S2>(&'a self, other: &'a IndexSet<T, S2>) -> ParUnion<'a, T, S, S2> where S2: BuildHasher + Sync,221 pub fn par_union<'a, S2>(&'a self, other: &'a IndexSet<T, S2>) -> ParUnion<'a, T, S, S2> 222 where 223 S2: BuildHasher + Sync, 224 { 225 ParUnion { 226 set1: self, 227 set2: other, 228 } 229 } 230 231 /// Returns `true` if `self` contains all of the same values as `other`, 232 /// regardless of each set's indexed order, determined in parallel. par_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,233 pub fn par_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool 234 where 235 S2: BuildHasher + Sync, 236 { 237 self.len() == other.len() && self.par_is_subset(other) 238 } 239 240 /// Returns `true` if `self` has no elements in common with `other`, 241 /// determined in parallel. par_is_disjoint<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,242 pub fn par_is_disjoint<S2>(&self, other: &IndexSet<T, S2>) -> bool 243 where 244 S2: BuildHasher + Sync, 245 { 246 if self.len() <= other.len() { 247 self.par_iter().all(move |value| !other.contains(value)) 248 } else { 249 other.par_iter().all(move |value| !self.contains(value)) 250 } 251 } 252 253 /// Returns `true` if all elements of `other` are contained in `self`, 254 /// determined in parallel. par_is_superset<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,255 pub fn par_is_superset<S2>(&self, other: &IndexSet<T, S2>) -> bool 256 where 257 S2: BuildHasher + Sync, 258 { 259 other.par_is_subset(self) 260 } 261 262 /// Returns `true` if all elements of `self` are contained in `other`, 263 /// determined in parallel. par_is_subset<S2>(&self, other: &IndexSet<T, S2>) -> bool where S2: BuildHasher + Sync,264 pub fn par_is_subset<S2>(&self, other: &IndexSet<T, S2>) -> bool 265 where 266 S2: BuildHasher + Sync, 267 { 268 self.len() <= other.len() && self.par_iter().all(move |value| other.contains(value)) 269 } 270 } 271 272 /// A parallel iterator producing elements in the difference of `IndexSet`s. 273 /// 274 /// This `struct` is created by the [`par_difference`] method on [`IndexSet`]. 275 /// See its documentation for more. 276 /// 277 /// [`IndexSet`]: ../struct.IndexSet.html 278 /// [`par_difference`]: ../struct.IndexSet.html#method.par_difference 279 pub struct ParDifference<'a, T, S1, S2> { 280 set1: &'a IndexSet<T, S1>, 281 set2: &'a IndexSet<T, S2>, 282 } 283 284 impl<T, S1, S2> Clone for ParDifference<'_, T, S1, S2> { clone(&self) -> Self285 fn clone(&self) -> Self { 286 ParDifference { ..*self } 287 } 288 } 289 290 impl<T, S1, S2> fmt::Debug for ParDifference<'_, T, S1, S2> 291 where 292 T: fmt::Debug + Eq + Hash, 293 S1: BuildHasher, 294 S2: BuildHasher, 295 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 297 f.debug_list() 298 .entries(self.set1.difference(self.set2)) 299 .finish() 300 } 301 } 302 303 impl<'a, T, S1, S2> ParallelIterator for ParDifference<'a, T, S1, S2> 304 where 305 T: Hash + Eq + Sync, 306 S1: BuildHasher + Sync, 307 S2: BuildHasher + Sync, 308 { 309 type Item = &'a T; 310 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,311 fn drive_unindexed<C>(self, consumer: C) -> C::Result 312 where 313 C: UnindexedConsumer<Self::Item>, 314 { 315 let Self { set1, set2 } = self; 316 317 set1.par_iter() 318 .filter(move |&item| !set2.contains(item)) 319 .drive_unindexed(consumer) 320 } 321 } 322 323 /// A parallel iterator producing elements in the intersection of `IndexSet`s. 324 /// 325 /// This `struct` is created by the [`par_intersection`] method on [`IndexSet`]. 326 /// See its documentation for more. 327 /// 328 /// [`IndexSet`]: ../struct.IndexSet.html 329 /// [`par_intersection`]: ../struct.IndexSet.html#method.par_intersection 330 pub struct ParIntersection<'a, T, S1, S2> { 331 set1: &'a IndexSet<T, S1>, 332 set2: &'a IndexSet<T, S2>, 333 } 334 335 impl<T, S1, S2> Clone for ParIntersection<'_, T, S1, S2> { clone(&self) -> Self336 fn clone(&self) -> Self { 337 ParIntersection { ..*self } 338 } 339 } 340 341 impl<T, S1, S2> fmt::Debug for ParIntersection<'_, T, S1, S2> 342 where 343 T: fmt::Debug + Eq + Hash, 344 S1: BuildHasher, 345 S2: BuildHasher, 346 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result347 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 348 f.debug_list() 349 .entries(self.set1.intersection(self.set2)) 350 .finish() 351 } 352 } 353 354 impl<'a, T, S1, S2> ParallelIterator for ParIntersection<'a, T, S1, S2> 355 where 356 T: Hash + Eq + Sync, 357 S1: BuildHasher + Sync, 358 S2: BuildHasher + Sync, 359 { 360 type Item = &'a T; 361 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,362 fn drive_unindexed<C>(self, consumer: C) -> C::Result 363 where 364 C: UnindexedConsumer<Self::Item>, 365 { 366 let Self { set1, set2 } = self; 367 368 set1.par_iter() 369 .filter(move |&item| set2.contains(item)) 370 .drive_unindexed(consumer) 371 } 372 } 373 374 /// A parallel iterator producing elements in the symmetric difference of `IndexSet`s. 375 /// 376 /// This `struct` is created by the [`par_symmetric_difference`] method on 377 /// [`IndexSet`]. See its documentation for more. 378 /// 379 /// [`IndexSet`]: ../struct.IndexSet.html 380 /// [`par_symmetric_difference`]: ../struct.IndexSet.html#method.par_symmetric_difference 381 pub struct ParSymmetricDifference<'a, T, S1, S2> { 382 set1: &'a IndexSet<T, S1>, 383 set2: &'a IndexSet<T, S2>, 384 } 385 386 impl<T, S1, S2> Clone for ParSymmetricDifference<'_, T, S1, S2> { clone(&self) -> Self387 fn clone(&self) -> Self { 388 ParSymmetricDifference { ..*self } 389 } 390 } 391 392 impl<T, S1, S2> fmt::Debug for ParSymmetricDifference<'_, T, S1, S2> 393 where 394 T: fmt::Debug + Eq + Hash, 395 S1: BuildHasher, 396 S2: BuildHasher, 397 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 399 f.debug_list() 400 .entries(self.set1.symmetric_difference(self.set2)) 401 .finish() 402 } 403 } 404 405 impl<'a, T, S1, S2> ParallelIterator for ParSymmetricDifference<'a, T, S1, S2> 406 where 407 T: Hash + Eq + Sync, 408 S1: BuildHasher + Sync, 409 S2: BuildHasher + Sync, 410 { 411 type Item = &'a T; 412 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,413 fn drive_unindexed<C>(self, consumer: C) -> C::Result 414 where 415 C: UnindexedConsumer<Self::Item>, 416 { 417 let Self { set1, set2 } = self; 418 419 set1.par_difference(set2) 420 .chain(set2.par_difference(set1)) 421 .drive_unindexed(consumer) 422 } 423 } 424 425 /// A parallel iterator producing elements in the union of `IndexSet`s. 426 /// 427 /// This `struct` is created by the [`par_union`] method on [`IndexSet`]. 428 /// See its documentation for more. 429 /// 430 /// [`IndexSet`]: ../struct.IndexSet.html 431 /// [`par_union`]: ../struct.IndexSet.html#method.par_union 432 pub struct ParUnion<'a, T, S1, S2> { 433 set1: &'a IndexSet<T, S1>, 434 set2: &'a IndexSet<T, S2>, 435 } 436 437 impl<T, S1, S2> Clone for ParUnion<'_, T, S1, S2> { clone(&self) -> Self438 fn clone(&self) -> Self { 439 ParUnion { ..*self } 440 } 441 } 442 443 impl<T, S1, S2> fmt::Debug for ParUnion<'_, T, S1, S2> 444 where 445 T: fmt::Debug + Eq + Hash, 446 S1: BuildHasher, 447 S2: BuildHasher, 448 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 450 f.debug_list().entries(self.set1.union(self.set2)).finish() 451 } 452 } 453 454 impl<'a, T, S1, S2> ParallelIterator for ParUnion<'a, T, S1, S2> 455 where 456 T: Hash + Eq + Sync, 457 S1: BuildHasher + Sync, 458 S2: BuildHasher + Sync, 459 { 460 type Item = &'a T; 461 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,462 fn drive_unindexed<C>(self, consumer: C) -> C::Result 463 where 464 C: UnindexedConsumer<Self::Item>, 465 { 466 let Self { set1, set2 } = self; 467 468 set1.par_iter() 469 .chain(set2.par_difference(set1)) 470 .drive_unindexed(consumer) 471 } 472 } 473 474 /// Parallel sorting methods. 475 /// 476 /// The following methods **require crate feature `"rayon"`**. 477 impl<T, S> IndexSet<T, S> 478 where 479 T: Hash + Eq + Send, 480 S: BuildHasher + Send, 481 { 482 /// Sort the set’s values in parallel by their default ordering. par_sort(&mut self) where T: Ord,483 pub fn par_sort(&mut self) 484 where 485 T: Ord, 486 { 487 self.with_entries(|entries| { 488 entries.par_sort_by(|a, b| T::cmp(&a.key, &b.key)); 489 }); 490 } 491 492 /// Sort the set’s values in place and in parallel, using the comparison function `cmp`. par_sort_by<F>(&mut self, cmp: F) where F: Fn(&T, &T) -> Ordering + Sync,493 pub fn par_sort_by<F>(&mut self, cmp: F) 494 where 495 F: Fn(&T, &T) -> Ordering + Sync, 496 { 497 self.with_entries(|entries| { 498 entries.par_sort_by(move |a, b| cmp(&a.key, &b.key)); 499 }); 500 } 501 502 /// Sort the values of the set in parallel and return a by-value parallel iterator of 503 /// the values with the result. par_sorted_by<F>(self, cmp: F) -> IntoParIter<T> where F: Fn(&T, &T) -> Ordering + Sync,504 pub fn par_sorted_by<F>(self, cmp: F) -> IntoParIter<T> 505 where 506 F: Fn(&T, &T) -> Ordering + Sync, 507 { 508 let mut entries = self.into_entries(); 509 entries.par_sort_by(move |a, b| cmp(&a.key, &b.key)); 510 IntoParIter { entries } 511 } 512 513 /// Sort the set's values in parallel by their default ordering. par_sort_unstable(&mut self) where T: Ord,514 pub fn par_sort_unstable(&mut self) 515 where 516 T: Ord, 517 { 518 self.with_entries(|entries| { 519 entries.par_sort_unstable_by(|a, b| T::cmp(&a.key, &b.key)); 520 }); 521 } 522 523 /// Sort the set’s values in place and in parallel, using the comparison function `cmp`. par_sort_unstable_by<F>(&mut self, cmp: F) where F: Fn(&T, &T) -> Ordering + Sync,524 pub fn par_sort_unstable_by<F>(&mut self, cmp: F) 525 where 526 F: Fn(&T, &T) -> Ordering + Sync, 527 { 528 self.with_entries(|entries| { 529 entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key)); 530 }); 531 } 532 533 /// Sort the values of the set in parallel and return a by-value parallel iterator of 534 /// the values with the result. par_sorted_unstable_by<F>(self, cmp: F) -> IntoParIter<T> where F: Fn(&T, &T) -> Ordering + Sync,535 pub fn par_sorted_unstable_by<F>(self, cmp: F) -> IntoParIter<T> 536 where 537 F: Fn(&T, &T) -> Ordering + Sync, 538 { 539 let mut entries = self.into_entries(); 540 entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key)); 541 IntoParIter { entries } 542 } 543 } 544 545 /// Requires crate feature `"rayon"`. 546 impl<T, S> FromParallelIterator<T> for IndexSet<T, S> 547 where 548 T: Eq + Hash + Send, 549 S: BuildHasher + Default + Send, 550 { from_par_iter<I>(iter: I) -> Self where I: IntoParallelIterator<Item = T>,551 fn from_par_iter<I>(iter: I) -> Self 552 where 553 I: IntoParallelIterator<Item = T>, 554 { 555 let list = collect(iter); 556 let len = list.iter().map(Vec::len).sum(); 557 let mut set = Self::with_capacity_and_hasher(len, S::default()); 558 for vec in list { 559 set.extend(vec); 560 } 561 set 562 } 563 } 564 565 /// Requires crate feature `"rayon"`. 566 impl<T, S> ParallelExtend<T> for IndexSet<T, S> 567 where 568 T: Eq + Hash + Send, 569 S: BuildHasher + Send, 570 { par_extend<I>(&mut self, iter: I) where I: IntoParallelIterator<Item = T>,571 fn par_extend<I>(&mut self, iter: I) 572 where 573 I: IntoParallelIterator<Item = T>, 574 { 575 for vec in collect(iter) { 576 self.extend(vec); 577 } 578 } 579 } 580 581 /// Requires crate feature `"rayon"`. 582 impl<'a, T: 'a, S> ParallelExtend<&'a T> for IndexSet<T, S> 583 where 584 T: Copy + Eq + Hash + Send + Sync, 585 S: BuildHasher + Send, 586 { par_extend<I>(&mut self, iter: I) where I: IntoParallelIterator<Item = &'a T>,587 fn par_extend<I>(&mut self, iter: I) 588 where 589 I: IntoParallelIterator<Item = &'a T>, 590 { 591 for vec in collect(iter) { 592 self.extend(vec); 593 } 594 } 595 } 596 597 #[cfg(test)] 598 mod tests { 599 use super::*; 600 601 #[test] insert_order()602 fn insert_order() { 603 let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 604 let mut set = IndexSet::new(); 605 606 for &elt in &insert { 607 set.insert(elt); 608 } 609 610 assert_eq!(set.par_iter().count(), set.len()); 611 assert_eq!(set.par_iter().count(), insert.len()); 612 insert.par_iter().zip(&set).for_each(|(a, b)| { 613 assert_eq!(a, b); 614 }); 615 (0..insert.len()) 616 .into_par_iter() 617 .zip(&set) 618 .for_each(|(i, v)| { 619 assert_eq!(set.get_index(i).unwrap(), v); 620 }); 621 } 622 623 #[test] partial_eq_and_eq()624 fn partial_eq_and_eq() { 625 let mut set_a = IndexSet::new(); 626 set_a.insert(1); 627 set_a.insert(2); 628 let mut set_b = set_a.clone(); 629 assert!(set_a.par_eq(&set_b)); 630 set_b.swap_remove(&1); 631 assert!(!set_a.par_eq(&set_b)); 632 set_b.insert(3); 633 assert!(!set_a.par_eq(&set_b)); 634 635 let set_c: IndexSet<_> = set_b.into_par_iter().collect(); 636 assert!(!set_a.par_eq(&set_c)); 637 assert!(!set_c.par_eq(&set_a)); 638 } 639 640 #[test] extend()641 fn extend() { 642 let mut set = IndexSet::new(); 643 set.par_extend(vec![&1, &2, &3, &4]); 644 set.par_extend(vec![5, 6]); 645 assert_eq!( 646 set.into_par_iter().collect::<Vec<_>>(), 647 vec![1, 2, 3, 4, 5, 6] 648 ); 649 } 650 651 #[test] comparisons()652 fn comparisons() { 653 let set_a: IndexSet<_> = (0..3).collect(); 654 let set_b: IndexSet<_> = (3..6).collect(); 655 let set_c: IndexSet<_> = (0..6).collect(); 656 let set_d: IndexSet<_> = (3..9).collect(); 657 658 assert!(!set_a.par_is_disjoint(&set_a)); 659 assert!(set_a.par_is_subset(&set_a)); 660 assert!(set_a.par_is_superset(&set_a)); 661 662 assert!(set_a.par_is_disjoint(&set_b)); 663 assert!(set_b.par_is_disjoint(&set_a)); 664 assert!(!set_a.par_is_subset(&set_b)); 665 assert!(!set_b.par_is_subset(&set_a)); 666 assert!(!set_a.par_is_superset(&set_b)); 667 assert!(!set_b.par_is_superset(&set_a)); 668 669 assert!(!set_a.par_is_disjoint(&set_c)); 670 assert!(!set_c.par_is_disjoint(&set_a)); 671 assert!(set_a.par_is_subset(&set_c)); 672 assert!(!set_c.par_is_subset(&set_a)); 673 assert!(!set_a.par_is_superset(&set_c)); 674 assert!(set_c.par_is_superset(&set_a)); 675 676 assert!(!set_c.par_is_disjoint(&set_d)); 677 assert!(!set_d.par_is_disjoint(&set_c)); 678 assert!(!set_c.par_is_subset(&set_d)); 679 assert!(!set_d.par_is_subset(&set_c)); 680 assert!(!set_c.par_is_superset(&set_d)); 681 assert!(!set_d.par_is_superset(&set_c)); 682 } 683 684 #[test] iter_comparisons()685 fn iter_comparisons() { 686 use std::iter::empty; 687 688 fn check<'a, I1, I2>(iter1: I1, iter2: I2) 689 where 690 I1: ParallelIterator<Item = &'a i32>, 691 I2: Iterator<Item = i32>, 692 { 693 let v1: Vec<_> = iter1.copied().collect(); 694 let v2: Vec<_> = iter2.collect(); 695 assert_eq!(v1, v2); 696 } 697 698 let set_a: IndexSet<_> = (0..3).collect(); 699 let set_b: IndexSet<_> = (3..6).collect(); 700 let set_c: IndexSet<_> = (0..6).collect(); 701 let set_d: IndexSet<_> = (3..9).rev().collect(); 702 703 check(set_a.par_difference(&set_a), empty()); 704 check(set_a.par_symmetric_difference(&set_a), empty()); 705 check(set_a.par_intersection(&set_a), 0..3); 706 check(set_a.par_union(&set_a), 0..3); 707 708 check(set_a.par_difference(&set_b), 0..3); 709 check(set_b.par_difference(&set_a), 3..6); 710 check(set_a.par_symmetric_difference(&set_b), 0..6); 711 check(set_b.par_symmetric_difference(&set_a), (3..6).chain(0..3)); 712 check(set_a.par_intersection(&set_b), empty()); 713 check(set_b.par_intersection(&set_a), empty()); 714 check(set_a.par_union(&set_b), 0..6); 715 check(set_b.par_union(&set_a), (3..6).chain(0..3)); 716 717 check(set_a.par_difference(&set_c), empty()); 718 check(set_c.par_difference(&set_a), 3..6); 719 check(set_a.par_symmetric_difference(&set_c), 3..6); 720 check(set_c.par_symmetric_difference(&set_a), 3..6); 721 check(set_a.par_intersection(&set_c), 0..3); 722 check(set_c.par_intersection(&set_a), 0..3); 723 check(set_a.par_union(&set_c), 0..6); 724 check(set_c.par_union(&set_a), 0..6); 725 726 check(set_c.par_difference(&set_d), 0..3); 727 check(set_d.par_difference(&set_c), (6..9).rev()); 728 check( 729 set_c.par_symmetric_difference(&set_d), 730 (0..3).chain((6..9).rev()), 731 ); 732 check( 733 set_d.par_symmetric_difference(&set_c), 734 (6..9).rev().chain(0..3), 735 ); 736 check(set_c.par_intersection(&set_d), 3..6); 737 check(set_d.par_intersection(&set_c), (3..6).rev()); 738 check(set_c.par_union(&set_d), (0..6).chain((6..9).rev())); 739 check(set_d.par_union(&set_c), (3..9).rev().chain(0..3)); 740 } 741 } 742