//! Parallel iterator types for [`IndexSet`] with [rayon][::rayon]. //! //! You will rarely need to interact with this module directly unless you need to name one of the //! iterator types.
usesuper::collect; use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer}; use rayon::prelude::*;
usecrate::vec::Vec; use alloc::boxed::Box; use core::cmp::Ordering; use core::fmt; use core::hash::{BuildHasher, Hash}; use core::ops::RangeBounds;
/// A parallel owning iterator over the items of an [`IndexSet`]. /// /// This `struct` is created by the [`IndexSet::into_par_iter`] method /// (provided by rayon's [`IntoParallelIterator`] trait). See its documentation for more. pubstruct IntoParIter<T> {
entries: Vec<Bucket<T>>,
}
impl<T: fmt::Debug> fmt::Debug for IntoParIter<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::key_ref);
f.debug_list().entries(iter).finish()
}
}
impl<T: Send> ParallelIterator for IntoParIter<T> { type Item = T;
parallel_iterator_methods!(Bucket::key);
}
impl<T: Send> IndexedParallelIterator for IntoParIter<T> {
indexed_parallel_iterator_methods!(Bucket::key);
}
impl<'a, T, S> IntoParallelIterator for &'a IndexSet<T, S> where
T: Sync,
{ type Item = &'a T; type Iter = ParIter<'a, T>;
/// A parallel iterator over the items of an [`IndexSet`]. /// /// This `struct` is created by the [`IndexSet::par_iter`] method /// (provided by rayon's [`IntoParallelRefIterator`] trait). See its documentation for more. /// /// [`IndexSet::par_iter`]: ../struct.IndexSet.html#method.par_iter pubstruct ParIter<'a, T> {
entries: &'a [Bucket<T>],
}
/// A parallel draining iterator over the items of an [`IndexSet`]. /// /// This `struct` is created by the [`IndexSet::par_drain`] method /// (provided by rayon's [`ParallelDrainRange`] trait). See its documentation for more. /// /// [`IndexSet::par_drain`]: ../struct.IndexSet.html#method.par_drain pubstruct ParDrain<'a, T: Send> {
entries: rayon::vec::Drain<'a, Bucket<T>>,
}
impl<T: Send> ParallelIterator for ParDrain<'_, T> { type Item = T;
parallel_iterator_methods!(Bucket::key);
}
impl<T: Send> IndexedParallelIterator for ParDrain<'_, T> {
indexed_parallel_iterator_methods!(Bucket::key);
}
/// Parallel iterator methods and other parallel methods. /// /// The following methods **require crate feature `"rayon"`**. /// /// See also the `IntoParallelIterator` implementations. impl<T, S> IndexSet<T, S> where
T: Hash + Eq + Sync,
S: BuildHasher + Sync,
{ /// Return a parallel iterator over the values that are in `self` but not `other`. /// /// While parallel iterators can process items in any order, their relative order /// in the `self` set is still preserved for operations like `reduce` and `collect`. pubfn par_difference<'a, S2>(
&'a self,
other: &'a IndexSet<T, S2>,
) -> ParDifference<'a, T, S, S2> where
S2: BuildHasher + Sync,
{
ParDifference {
set1: self,
set2: other,
}
}
/// Return a parallel iterator over the values that are in `self` or `other`, /// but not in both. /// /// While parallel iterators can process items in any order, their relative order /// in the sets is still preserved for operations like `reduce` and `collect`. /// Values from `self` are produced in their original order, followed by /// values from `other` in their original order. pubfn par_symmetric_difference<'a, S2>(
&'a self,
other: &'a IndexSet<T, S2>,
) -> ParSymmetricDifference<'a, T, S, S2> where
S2: BuildHasher + Sync,
{
ParSymmetricDifference {
set1: self,
set2: other,
}
}
/// Return a parallel iterator over the values that are in both `self` and `other`. /// /// While parallel iterators can process items in any order, their relative order /// in the `self` set is still preserved for operations like `reduce` and `collect`. pubfn par_intersection<'a, S2>(
&'a self,
other: &'a IndexSet<T, S2>,
) -> ParIntersection<'a, T, S, S2> where
S2: BuildHasher + Sync,
{
ParIntersection {
set1: self,
set2: other,
}
}
/// Return a parallel iterator over all values that are in `self` or `other`. /// /// While parallel iterators can process items in any order, their relative order /// in the sets is still preserved for operations like `reduce` and `collect`. /// Values from `self` are produced in their original order, followed by /// values that are unique to `other` in their original order. pubfn par_union<'a, S2>(&'a self, other: &'a IndexSet<T, S2>) -> ParUnion<'a, T, S, S2> where
S2: BuildHasher + Sync,
{
ParUnion {
set1: self,
set2: other,
}
}
/// Returns `true` if `self` contains all of the same values as `other`, /// regardless of each set's indexed order, determined in parallel. pubfn par_eq<S2>(&self, other: &IndexSet<T, S2>) -> bool where
S2: BuildHasher + Sync,
{ self.len() == other.len() && self.par_is_subset(other)
}
/// Returns `true` if `self` has no elements in common with `other`, /// determined in parallel. pubfn par_is_disjoint<S2>(&self, other: &IndexSet<T, S2>) -> bool where
S2: BuildHasher + Sync,
{ ifself.len() <= other.len() { self.par_iter().all(move |value| !other.contains(value))
} else {
other.par_iter().all(move |value| !self.contains(value))
}
}
/// Returns `true` if all elements of `other` are contained in `self`, /// determined in parallel. pubfn par_is_superset<S2>(&self, other: &IndexSet<T, S2>) -> bool where
S2: BuildHasher + Sync,
{
other.par_is_subset(self)
}
/// Returns `true` if all elements of `self` are contained in `other`, /// determined in parallel. pubfn par_is_subset<S2>(&self, other: &IndexSet<T, S2>) -> bool where
S2: BuildHasher + Sync,
{ self.len() <= other.len() && self.par_iter().all(move |value| other.contains(value))
}
}
/// A parallel iterator producing elements in the difference of [`IndexSet`]s. /// /// This `struct` is created by the [`IndexSet::par_difference`] method. /// See its documentation for more. pubstruct ParDifference<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
}
/// A parallel iterator producing elements in the intersection of [`IndexSet`]s. /// /// This `struct` is created by the [`IndexSet::par_intersection`] method. /// See its documentation for more. pubstruct ParIntersection<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
}
/// A parallel iterator producing elements in the symmetric difference of [`IndexSet`]s. /// /// This `struct` is created by the [`IndexSet::par_symmetric_difference`] method. /// See its documentation for more. pubstruct ParSymmetricDifference<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
}
/// A parallel iterator producing elements in the union of [`IndexSet`]s. /// /// This `struct` is created by the [`IndexSet::par_union`] method. /// See its documentation for more. pubstruct ParUnion<'a, T, S1, S2> {
set1: &'a IndexSet<T, S1>,
set2: &'a IndexSet<T, S2>,
}
/// Parallel sorting methods. /// /// The following methods **require crate feature `"rayon"`**. impl<T, S> IndexSet<T, S> where
T: Send,
{ /// Sort the set’s values in parallel by their default ordering. pubfn par_sort(&mutself) where
T: Ord,
{ self.with_entries(|entries| {
entries.par_sort_by(|a, b| T::cmp(&a.key, &b.key));
});
}
/// Sort the set’s values in place and in parallel, using the comparison function `cmp`. pubfn par_sort_by<F>(&mutself, cmp: F) where
F: Fn(&T, &T) -> Ordering + Sync,
{ self.with_entries(|entries| {
entries.par_sort_by(move |a, b| cmp(&a.key, &b.key));
});
}
/// Sort the values of the set in parallel and return a by-value parallel iterator of /// the values with the result. pubfn par_sorted_by<F>(self, cmp: F) -> IntoParIter<T> where
F: Fn(&T, &T) -> Ordering + Sync,
{ letmut entries = self.into_entries();
entries.par_sort_by(move |a, b| cmp(&a.key, &b.key));
IntoParIter { entries }
}
/// Sort the set's values in parallel by their default ordering. pubfn par_sort_unstable(&mutself) where
T: Ord,
{ self.with_entries(|entries| {
entries.par_sort_unstable_by(|a, b| T::cmp(&a.key, &b.key));
});
}
/// Sort the set’s values in place and in parallel, using the comparison function `cmp`. pubfn par_sort_unstable_by<F>(&mutself, cmp: F) where
F: Fn(&T, &T) -> Ordering + Sync,
{ self.with_entries(|entries| {
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
});
}
/// Sort the values of the set in parallel and return a by-value parallel iterator of /// the values with the result. pubfn par_sorted_unstable_by<F>(self, cmp: F) -> IntoParIter<T> where
F: Fn(&T, &T) -> Ordering + Sync,
{ letmut entries = self.into_entries();
entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
IntoParIter { entries }
}
/// Sort the set’s values in place and in parallel, using a key extraction function. pubfn par_sort_by_cached_key<K, F>(&mutself, sort_key: F) where
K: Ord + Send,
F: Fn(&T) -> K + Sync,
{ self.with_entries(move |entries| {
entries.par_sort_by_cached_key(move |a| sort_key(&a.key));
});
}
}
impl<T, S> FromParallelIterator<T> for IndexSet<T, S> where
T: Eq + Hash + Send,
S: BuildHasher + Default + Send,
{ fn from_par_iter<I>(iter: I) -> Self where
I: IntoParallelIterator<Item = T>,
{ let list = collect(iter); let len = list.iter().map(Vec::len).sum(); letmut set = Self::with_capacity_and_hasher(len, S::default()); for vec in list {
set.extend(vec);
}
set
}
}
impl<T, S> ParallelExtend<T> for IndexSet<T, S> where
T: Eq + Hash + Send,
S: BuildHasher + Send,
{ fn par_extend<I>(&mutself, iter: I) where
I: IntoParallelIterator<Item = T>,
{ for vec in collect(iter) { self.extend(vec);
}
}
}
impl<'a, T: 'a, S> ParallelExtend<&'a T> for IndexSet<T, S> where
T: Copy + Eq + Hash + Send + Sync,
S: BuildHasher + Send,
{ fn par_extend<I>(&mutself, iter: I) where
I: IntoParallelIterator<Item = &'a T>,
{ for vec in collect(iter) { self.extend(vec);
}
}
}
let set_a: IndexSet<_> = (0..3).collect(); let set_b: IndexSet<_> = (3..6).collect(); let set_c: IndexSet<_> = (0..6).collect(); let set_d: IndexSet<_> = (3..9).rev().collect();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.