rayon_scan/
lib.rs

1use self::scan::Scan;
2use rayon::prelude::ParallelIterator;
3
4mod scan;
5
6pub trait ScanParallelIterator: ParallelIterator {
7    /// Folds the items in the iterator using `scan_op`, and produces a
8    /// new iterator with all of the intermediate results.
9    ///
10    /// Specifically, the nth element of the scan iterator will be the
11    /// result of reducing the first n elements of the input with `scan_op`.
12    ///
13    /// # Examples
14    ///
15    /// ```
16    /// // Iterate over a sequence of numbers `x0, ..., xN`
17    /// // and use scan to compute the partial sums
18    /// use rayon::prelude::*;
19    /// use rayon_scan::ScanParallelIterator;
20    ///
21    /// let partial_sums = [1, 2, 3, 4, 5]
22    ///                     .into_par_iter()       // iterating over i32
23    ///                     .scan(|a, b| *a + *b,  // add (&i32, &i32) -> i32
24    ///                           0)               // identity
25    ///                     .collect::<Vec<i32>>();
26    /// assert_eq!(partial_sums, vec![1, 3, 6, 10, 15]);
27    /// ```
28    ///
29    /// **Note:** Unlike a sequential `scan` operation, the order in
30    /// which `scan_op` will be applied to produce the result is not fully
31    /// specified. So `scan_op` should be [associative] or else the results
32    /// will be non-deterministic. Also unlike sequential `scan`, there is
33    /// no internal state for this operation, so the operation has a
34    /// different signature.
35    ///
36    /// The argument `identity` should be an "identity" value for
37    /// `scan_op`, which may be inserted into the sequence as
38    /// needed to create opportunities for parallel execution. So, for
39    /// example, if you are doing a summation, then `identity` ought
40    /// to represent the zero for your type.
41    ///
42    /// [associative]: https://en.wikipedia.org/wiki/Associative_property
43    fn scan<F>(self, scan_op: F, identity: Self::Item) -> Scan<Self::Item, F>
44    where
45        F: Fn(&Self::Item, &Self::Item) -> Self::Item + Sync + Send,
46        <Self as ParallelIterator>::Item: Send + Sync,
47    {
48        scan::scan(self, scan_op, identity)
49    }
50}
51
52impl<T: ParallelIterator> ScanParallelIterator for T {}