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