orx_parallel/using/
u_par_iter.rs

1use crate::{
2    ChunkSize, DefaultRunner, IterationOrder, NumThreads, ParCollectInto, ParallelRunner, Params,
3    Sum,
4    using::{
5        Using,
6        computations::{u_map_clone, u_map_copy, u_map_count, u_reduce_sum, u_reduce_unit},
7    },
8};
9use orx_concurrent_iter::ConcurrentIter;
10use std::cmp::Ordering;
11
12/// Parallel iterator which allows mutable access to a variable of type `U` within its iterator methods.
13///
14/// Note that one variable will be created per thread used by the parallel computation.
15pub trait ParIterUsing<U, R = DefaultRunner>: Sized + Send + Sync
16where
17    R: ParallelRunner,
18    U: Using,
19{
20    /// Element type of the parallel iterator.
21    type Item: Send + Sync;
22
23    /// Returns a reference to the input concurrent iterator.
24    fn con_iter(&self) -> &impl ConcurrentIter;
25
26    /// Parameters of the parallel iterator.
27    ///
28    /// See [crate::ParIter::params] for details.
29    fn params(&self) -> Params;
30
31    // params transformations
32
33    /// Sets the number of threads to be used in the parallel execution.
34    /// Integers can be used as the argument with the following mapping:
35    ///
36    /// * `0` -> `NumThreads::Auto`
37    /// * `1` -> `NumThreads::sequential()`
38    /// * `n > 0` -> `NumThreads::Max(n)`
39    ///
40    ///     /// Parameters of the parallel iterator.
41    ///
42    /// See [crate::ParIter::num_threads] for details.
43    fn num_threads(self, num_threads: impl Into<NumThreads>) -> Self;
44
45    /// Sets the number of elements to be pulled from the concurrent iterator during the
46    /// parallel execution. When integers are used as argument, the following mapping applies:
47    ///
48    /// * `0` -> `ChunkSize::Auto`
49    /// * `n > 0` -> `ChunkSize::Exact(n)`
50    ///
51    /// Please use the default enum constructor for creating `ChunkSize::Min` variant.
52    ///
53    /// See [crate::ParIter::chunk_size] for details.
54    fn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self;
55
56    /// Sets the iteration order of the parallel computation.
57    ///
58    /// See [crate::ParIter::iteration_order] for details.
59    fn iteration_order(self, collect: IterationOrder) -> Self;
60
61    /// Rather than the [`DefaultRunner`], uses the parallel runner `Q` which implements [`ParallelRunner`].
62    ///
63    /// See [crate::ParIter::with_runner] for details.
64    fn with_runner<Q: ParallelRunner>(self) -> impl ParIterUsing<U, Q, Item = Self::Item>;
65
66    // computation transformations
67
68    /// Takes a closure `map` and creates a parallel iterator which calls that closure on each element.
69    ///
70    /// Unlike [crate::ParIter::map], the closure allows access to mutable reference of the used variable.
71    ///
72    /// Please see [`crate::ParIter::using`] transformation for details and examples.
73    ///
74    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
75    fn map<Out, Map>(self, map: Map) -> impl ParIterUsing<U, R, Item = Out>
76    where
77        Out: Send + Sync,
78        Map: Fn(&mut U::Item, Self::Item) -> Out + Send + Sync + Clone;
79
80    /// Creates an iterator which uses a closure `filter` to determine if an element should be yielded.
81    ///
82    /// Unlike [crate::ParIter::filter], the closure allows access to mutable reference of the used variable.
83    ///
84    /// Please see [`crate::ParIter::using`] transformation for details and examples.
85    ///
86    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
87    fn filter<Filter>(self, filter: Filter) -> impl ParIterUsing<U, R, Item = Self::Item>
88    where
89        Filter: Fn(&mut U::Item, &Self::Item) -> bool + Send + Sync + Clone;
90
91    /// Creates an iterator that works like map, but flattens nested structure.
92    ///
93    /// Unlike [crate::ParIter::flat_map], the closure allows access to mutable reference of the used variable.
94    ///
95    /// Please see [`crate::ParIter::using`] transformation for details and examples.
96    ///
97    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
98    fn flat_map<IOut, FlatMap>(
99        self,
100        flat_map: FlatMap,
101    ) -> impl ParIterUsing<U, R, Item = IOut::Item>
102    where
103        IOut: IntoIterator + Send + Sync,
104        IOut::IntoIter: Send + Sync,
105        IOut::Item: Send + Sync,
106        FlatMap: Fn(&mut U::Item, Self::Item) -> IOut + Send + Sync + Clone;
107
108    /// Creates an iterator that both filters and maps.
109    ///
110    /// The returned iterator yields only the values for which the supplied closure `filter_map` returns `Some(value)`.
111    ///
112    /// `filter_map` can be used to make chains of `filter` and `map` more concise.
113    /// The example below shows how a `map().filter().map()` can be shortened to a single call to `filter_map`.
114    ///
115    /// Unlike [crate::ParIter::filter_map], the closure allows access to mutable reference of the used variable.
116    ///
117    /// Please see [`crate::ParIter::using`] transformation for details and examples.
118    ///
119    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
120    fn filter_map<Out, FilterMap>(
121        self,
122        filter_map: FilterMap,
123    ) -> impl ParIterUsing<U, R, Item = Out>
124    where
125        Out: Send + Sync,
126        FilterMap: Fn(&mut U::Item, Self::Item) -> Option<Out> + Send + Sync + Clone;
127
128    /// Does something with each element of an iterator, passing the value on.
129    ///
130    /// Unlike [crate::ParIter::inspect], the closure allows access to mutable reference of the used variable.
131    ///
132    /// Please see [`crate::ParIter::using`] transformation for details and examples.
133    ///
134    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
135    fn inspect<Operation>(self, operation: Operation) -> impl ParIterUsing<U, R, Item = Self::Item>
136    where
137        Operation: Fn(&mut U::Item, &Self::Item) + Sync + Send + Clone,
138    {
139        let map = move |u: &mut U::Item, x: Self::Item| {
140            operation(u, &x);
141            x
142        };
143        self.map(map)
144    }
145
146    // special item transformations
147
148    /// Creates an iterator which copies all of its elements.
149    ///
150    /// Unlike [crate::ParIter::copied], the closure allows access to mutable reference of the used variable.
151    ///
152    /// Please see [`crate::ParIter::using`] transformation for details and examples.
153    ///
154    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
155    fn copied<'a, T>(self) -> impl ParIterUsing<U, R, Item = T>
156    where
157        T: 'a + Copy + Send + Sync,
158        Self: ParIterUsing<U, R, Item = &'a T>,
159    {
160        self.map(u_map_copy)
161    }
162
163    /// Creates an iterator which clones all of its elements.
164    ///
165    /// Unlike [crate::ParIter::cloned], the closure allows access to mutable reference of the used variable.
166    ///
167    /// Please see [`crate::ParIter::using`] transformation for details and examples.
168    ///
169    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
170    fn cloned<'a, T>(self) -> impl ParIterUsing<U, R, Item = T>
171    where
172        T: 'a + Clone + Send + Sync,
173        Self: ParIterUsing<U, R, Item = &'a T>,
174    {
175        self.map(u_map_clone)
176    }
177
178    /// Creates an iterator that flattens nested structure.
179    ///
180    /// Unlike [crate::ParIter::flatten], the closure allows access to mutable reference of the used variable.
181    ///
182    /// Please see [`crate::ParIter::using`] transformation for details and examples.
183    ///
184    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
185    fn flatten(self) -> impl ParIterUsing<U, R, Item = <Self::Item as IntoIterator>::Item>
186    where
187        Self::Item: IntoIterator,
188        <Self::Item as IntoIterator>::IntoIter: Send + Sync,
189        <Self::Item as IntoIterator>::Item: Send + Sync,
190        R: Send + Sync,
191        Self: Send + Sync,
192    {
193        let map = |_: &mut U::Item, e: Self::Item| e.into_iter();
194        self.flat_map(map)
195    }
196
197    // collect
198
199    /// Collects all the items from an iterator into a collection.
200    ///
201    /// Unlike [crate::ParIter::collect_into], the closure allows access to mutable reference of the used variable.
202    ///
203    /// Please see [`crate::ParIter::using`] transformation for details and examples.
204    ///
205    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
206    fn collect_into<C>(self, output: C) -> C
207    where
208        C: ParCollectInto<Self::Item>;
209
210    /// Transforms an iterator into a collection.
211    ///
212    /// Unlike [crate::ParIter::collect], the closure allows access to mutable reference of the used variable.
213    ///
214    /// Please see [`crate::ParIter::using`] transformation for details and examples.
215    ///
216    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
217    fn collect<C>(self) -> C
218    where
219        C: ParCollectInto<Self::Item>,
220    {
221        let output = C::empty(self.con_iter().try_get_len());
222        self.collect_into(output)
223    }
224
225    // reduce
226
227    /// Reduces the elements to a single one, by repeatedly applying a reducing operation.
228    ///
229    /// See the details here: [crate::ParIter::reduce].
230    fn reduce<Reduce>(self, reduce: Reduce) -> Option<Self::Item>
231    where
232        Reduce: Fn(&mut U::Item, Self::Item, Self::Item) -> Self::Item + Send + Sync;
233
234    /// Tests if every element of the iterator matches a predicate.
235    ///
236    /// Unlike [crate::ParIter::all], the closure allows access to mutable reference of the used variable.
237    ///
238    /// Please see [`crate::ParIter::using`] transformation for details and examples.
239    ///
240    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
241    fn all<Predicate>(self, predicate: Predicate) -> bool
242    where
243        Predicate: Fn(&mut U::Item, &Self::Item) -> bool + Send + Sync + Clone,
244    {
245        let violates = |u: &mut U::Item, x: &Self::Item| !predicate(u, x);
246        self.find(violates).is_none()
247    }
248
249    /// Tests if any element of the iterator matches a predicate.
250    ///
251    /// Unlike [crate::ParIter::any], the closure allows access to mutable reference of the used variable.
252    ///
253    /// Please see [`crate::ParIter::using`] transformation for details and examples.
254    ///
255    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
256    fn any<Predicate>(self, predicate: Predicate) -> bool
257    where
258        Predicate: Fn(&mut U::Item, &Self::Item) -> bool + Send + Sync + Clone,
259    {
260        self.find(predicate).is_some()
261    }
262
263    /// Consumes the iterator, counting the number of iterations and returning it.
264    ///
265    /// See the details here: [crate::ParIter::count].
266    fn count(self) -> usize {
267        self.map(u_map_count).reduce(u_reduce_sum).unwrap_or(0)
268    }
269
270    /// Calls a closure on each element of an iterator.
271    ///
272    /// Unlike [crate::ParIter::for_each], the closure allows access to mutable reference of the used variable.
273    ///
274    /// Please see [`crate::ParIter::using`] transformation for details and examples.
275    ///
276    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
277    fn for_each<Operation>(self, operation: Operation)
278    where
279        Operation: Fn(&mut U::Item, Self::Item) + Sync + Send,
280    {
281        let map = |u: &mut U::Item, x| operation(u, x);
282        let _ = self.map(map).reduce(u_reduce_unit);
283    }
284
285    /// Returns the maximum element of an iterator.
286    ///
287    /// See the details here: [crate::ParIter::max].
288    fn max(self) -> Option<Self::Item>
289    where
290        Self::Item: Ord,
291    {
292        self.reduce(|_, a, b| Ord::max(a, b))
293    }
294
295    /// Returns the element that gives the maximum value with respect to the specified `compare` function.
296    ///
297    /// See the details here: [crate::ParIter::max_by].
298    fn max_by<Compare>(self, compare: Compare) -> Option<Self::Item>
299    where
300        Compare: Fn(&Self::Item, &Self::Item) -> Ordering + Sync,
301    {
302        let reduce = |_: &mut U::Item, x, y| match compare(&x, &y) {
303            Ordering::Greater | Ordering::Equal => x,
304            Ordering::Less => y,
305        };
306        self.reduce(reduce)
307    }
308
309    /// Returns the element that gives the maximum value from the specified function.
310    ///
311    /// See the details here: [crate::ParIter::max_by_key].
312    fn max_by_key<Key, GetKey>(self, key: GetKey) -> Option<Self::Item>
313    where
314        Key: Ord,
315        GetKey: Fn(&Self::Item) -> Key + Sync,
316    {
317        let reduce = |_: &mut U::Item, x, y| match key(&x).cmp(&key(&y)) {
318            Ordering::Greater | Ordering::Equal => x,
319            Ordering::Less => y,
320        };
321        self.reduce(reduce)
322    }
323
324    /// Returns the minimum element of an iterator.
325    ///
326    /// See the details here: [crate::ParIter::min].
327    fn min(self) -> Option<Self::Item>
328    where
329        Self::Item: Ord,
330    {
331        self.reduce(|_, a, b| Ord::min(a, b))
332    }
333
334    /// Returns the element that gives the minimum value with respect to the specified `compare` function.
335    ///
336    /// See the details here: [crate::ParIter::min_by].
337    fn min_by<Compare>(self, compare: Compare) -> Option<Self::Item>
338    where
339        Compare: Fn(&Self::Item, &Self::Item) -> Ordering + Sync,
340    {
341        let reduce = |_: &mut U::Item, x, y| match compare(&x, &y) {
342            Ordering::Less | Ordering::Equal => x,
343            Ordering::Greater => y,
344        };
345        self.reduce(reduce)
346    }
347
348    /// Returns the element that gives the minimum value from the specified function.
349    ///
350    /// See the details here: [crate::ParIter::min_by_key].
351    fn min_by_key<Key, GetKey>(self, get_key: GetKey) -> Option<Self::Item>
352    where
353        Key: Ord,
354        GetKey: Fn(&Self::Item) -> Key + Sync,
355    {
356        let reduce = |_: &mut U::Item, x, y| match get_key(&x).cmp(&get_key(&y)) {
357            Ordering::Less | Ordering::Equal => x,
358            Ordering::Greater => y,
359        };
360        self.reduce(reduce)
361    }
362
363    /// Sums the elements of an iterator.
364    ///
365    /// See the details here: [crate::ParIter::sum].
366    fn sum<Out>(self) -> Out
367    where
368        Self::Item: Sum<Out>,
369        Out: Send + Sync,
370    {
371        self.map(Self::Item::u_map)
372            .reduce(Self::Item::u_reduce)
373            .unwrap_or(Self::Item::zero())
374    }
375
376    // early exit
377
378    /// Returns the first (or any) element of the iterator; returns None if it is empty.
379    ///
380    /// * first element is returned if default iteration order `IterationOrder::Ordered` is used,
381    /// * any element is returned if `IterationOrder::Arbitrary` is set.
382    ///
383    /// See the details here: [crate::ParIter::first].
384    fn first(self) -> Option<Self::Item>;
385
386    /// Searches for an element of an iterator that satisfies a `predicate`.
387    ///
388    /// Unlike [crate::ParIter::find], the closure allows access to mutable reference of the used variable.
389    ///
390    /// Please see [`crate::ParIter::using`] transformation for details and examples.
391    ///
392    /// Further documentation can be found here: [`using.md`](https://github.com/orxfun/orx-parallel/blob/main/docs/using.md).
393    fn find<Predicate>(self, predicate: Predicate) -> Option<Self::Item>
394    where
395        Predicate: Fn(&mut U::Item, &Self::Item) -> bool + Send + Sync + Clone,
396    {
397        self.filter(predicate).first()
398    }
399}