rayon/iter/
walk_tree.rs

1use crate::iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer};
2use crate::prelude::*;
3use std::iter::once;
4
5#[derive(Debug)]
6struct WalkTreePrefixProducer<'b, S, B> {
7    to_explore: Vec<S>, // nodes (and subtrees) we have to process
8    seen: Vec<S>,       // nodes which have already been explored
9    children_of: &'b B, // function generating children
10}
11
12impl<S, B, I> UnindexedProducer for WalkTreePrefixProducer<'_, S, B>
13where
14    S: Send,
15    B: Fn(&S) -> I + Send + Sync,
16    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,
17{
18    type Item = S;
19
20    fn split(mut self) -> (Self, Option<Self>) {
21        // explore while front is of size one.
22        while self.to_explore.len() == 1 {
23            let front_node = self.to_explore.pop().unwrap();
24            self.to_explore
25                .extend((self.children_of)(&front_node).into_iter().rev());
26            self.seen.push(front_node);
27        }
28        // now take half of the front.
29        let right_children = split_vec(&mut self.to_explore);
30        let right = right_children
31            .map(|mut c| {
32                std::mem::swap(&mut c, &mut self.to_explore);
33                WalkTreePrefixProducer {
34                    to_explore: c,
35                    seen: Vec::new(),
36                    children_of: self.children_of,
37                }
38            })
39            .or_else(|| {
40                // we can still try to divide 'seen'
41                let right_seen = split_vec(&mut self.seen);
42                right_seen.map(|s| WalkTreePrefixProducer {
43                    to_explore: Default::default(),
44                    seen: s,
45                    children_of: self.children_of,
46                })
47            });
48        (self, right)
49    }
50
51    fn fold_with<F>(mut self, mut folder: F) -> F
52    where
53        F: Folder<Self::Item>,
54    {
55        // start by consuming everything seen
56        folder = folder.consume_iter(self.seen);
57        if folder.full() {
58            return folder;
59        }
60        // now do all remaining explorations
61        while let Some(e) = self.to_explore.pop() {
62            self.to_explore
63                .extend((self.children_of)(&e).into_iter().rev());
64            folder = folder.consume(e);
65            if folder.full() {
66                return folder;
67            }
68        }
69        folder
70    }
71}
72
73/// ParallelIterator for arbitrary tree-shaped patterns.
74/// Returned by the [`walk_tree_prefix()`] function.
75#[derive(Debug)]
76pub struct WalkTreePrefix<S, B> {
77    initial_state: S,
78    children_of: B,
79}
80
81impl<S, B, I> ParallelIterator for WalkTreePrefix<S, B>
82where
83    S: Send,
84    B: Fn(&S) -> I + Send + Sync,
85    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,
86{
87    type Item = S;
88
89    fn drive_unindexed<C>(self, consumer: C) -> C::Result
90    where
91        C: UnindexedConsumer<Self::Item>,
92    {
93        let producer = WalkTreePrefixProducer {
94            to_explore: once(self.initial_state).collect(),
95            seen: Vec::new(),
96            children_of: &self.children_of,
97        };
98        bridge_unindexed(producer, consumer)
99    }
100}
101
102/// Create a tree-like prefix parallel iterator from an initial root node.
103/// The `children_of` function should take a node and return an iterator over its child nodes.
104/// The best parallelization is obtained when the tree is balanced
105/// but we should also be able to handle harder cases.
106///
107/// # Ordering
108///
109/// This function guarantees a prefix ordering. See also [`walk_tree_postfix`],
110/// which guarantees a postfix order.
111/// If you don't care about ordering, you should use [`walk_tree`],
112/// which will use whatever is believed to be fastest.
113/// For example a perfect binary tree of 7 nodes will reduced in the following order:
114///
115/// ```text
116///      a
117///     / \
118///    /   \
119///   b     c
120///  / \   / \
121/// d   e f   g
122///
123/// reduced as a,b,d,e,c,f,g
124///
125/// ```
126///
127/// # Example
128///
129/// ```text
130///      4
131///     / \
132///    /   \
133///   2     3
134///        / \
135///       1   2
136/// ```
137///
138/// ```
139/// use rayon::iter::walk_tree_prefix;
140/// use rayon::prelude::*;
141///
142/// let par_iter = walk_tree_prefix(4, |&e| {
143///     if e <= 2 {
144///         Vec::new()
145///     } else {
146///         vec![e / 2, e / 2 + 1]
147///     }
148/// });
149/// assert_eq!(par_iter.sum::<u32>(), 12);
150/// ```
151///
152/// # Example
153///
154/// ```
155/// use rayon::prelude::*;
156/// use rayon::iter::walk_tree_prefix;
157///
158/// struct Node {
159///     content: u32,
160///     left: Option<Box<Node>>,
161///     right: Option<Box<Node>>,
162/// }
163///
164/// // Here we loop on the following tree:
165/// //
166/// //       10
167/// //      /  \
168/// //     /    \
169/// //    3     14
170/// //            \
171/// //             \
172/// //              18
173///
174/// let root = Node {
175///     content: 10,
176///     left: Some(Box::new(Node {
177///         content: 3,
178///         left: None,
179///         right: None,
180///     })),
181///     right: Some(Box::new(Node {
182///         content: 14,
183///         left: None,
184///         right: Some(Box::new(Node {
185///             content: 18,
186///             left: None,
187///             right: None,
188///         })),
189///     })),
190/// };
191///
192/// let mut v: Vec<u32> = walk_tree_prefix(&root, |r| {
193///     r.left
194///         .as_ref()
195///         .into_iter()
196///         .chain(r.right.as_ref())
197///         .map(|n| &**n)
198/// })
199/// .map(|node| node.content)
200/// .collect();
201/// assert_eq!(v, vec![10, 3, 14, 18]);
202/// ```
203///
204pub fn walk_tree_prefix<S, B, I>(root: S, children_of: B) -> WalkTreePrefix<S, B>
205where
206    S: Send,
207    B: Fn(&S) -> I + Send + Sync,
208    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,
209{
210    WalkTreePrefix {
211        initial_state: root,
212        children_of,
213    }
214}
215
216// post fix
217
218#[derive(Debug)]
219struct WalkTreePostfixProducer<'b, S, B> {
220    to_explore: Vec<S>, // nodes (and subtrees) we have to process
221    seen: Vec<S>,       // nodes which have already been explored
222    children_of: &'b B, // function generating children
223}
224
225impl<S, B, I> UnindexedProducer for WalkTreePostfixProducer<'_, S, B>
226where
227    S: Send,
228    B: Fn(&S) -> I + Send + Sync,
229    I: IntoIterator<Item = S>,
230{
231    type Item = S;
232
233    fn split(mut self) -> (Self, Option<Self>) {
234        // explore while front is of size one.
235        while self.to_explore.len() == 1 {
236            let front_node = self.to_explore.pop().unwrap();
237            self.to_explore
238                .extend((self.children_of)(&front_node).into_iter());
239            self.seen.push(front_node);
240        }
241        // now take half of the front.
242        let right_children = split_vec(&mut self.to_explore);
243        let right = right_children
244            .map(|c| {
245                let right_seen = std::mem::take(&mut self.seen); // postfix -> upper nodes are processed last
246                WalkTreePostfixProducer {
247                    to_explore: c,
248                    seen: right_seen,
249                    children_of: self.children_of,
250                }
251            })
252            .or_else(|| {
253                // we can still try to divide 'seen'
254                let right_seen = split_vec(&mut self.seen);
255                right_seen.map(|mut s| {
256                    std::mem::swap(&mut self.seen, &mut s);
257                    WalkTreePostfixProducer {
258                        to_explore: Default::default(),
259                        seen: s,
260                        children_of: self.children_of,
261                    }
262                })
263            });
264        (self, right)
265    }
266
267    fn fold_with<F>(self, mut folder: F) -> F
268    where
269        F: Folder<Self::Item>,
270    {
271        // now do all remaining explorations
272        for e in self.to_explore {
273            folder = consume_rec_postfix(&self.children_of, e, folder);
274            if folder.full() {
275                return folder;
276            }
277        }
278        // end by consuming everything seen
279        folder.consume_iter(self.seen.into_iter().rev())
280    }
281}
282
283fn consume_rec_postfix<F, S, B, I>(children_of: &B, s: S, mut folder: F) -> F
284where
285    F: Folder<S>,
286    B: Fn(&S) -> I,
287    I: IntoIterator<Item = S>,
288{
289    let children = (children_of)(&s).into_iter();
290    for child in children {
291        folder = consume_rec_postfix(children_of, child, folder);
292        if folder.full() {
293            return folder;
294        }
295    }
296    folder.consume(s)
297}
298
299/// ParallelIterator for arbitrary tree-shaped patterns.
300/// Returned by the [`walk_tree_postfix()`] function.
301#[derive(Debug)]
302pub struct WalkTreePostfix<S, B> {
303    initial_state: S,
304    children_of: B,
305}
306
307impl<S, B, I> ParallelIterator for WalkTreePostfix<S, B>
308where
309    S: Send,
310    B: Fn(&S) -> I + Send + Sync,
311    I: IntoIterator<Item = S>,
312{
313    type Item = S;
314
315    fn drive_unindexed<C>(self, consumer: C) -> C::Result
316    where
317        C: UnindexedConsumer<Self::Item>,
318    {
319        let producer = WalkTreePostfixProducer {
320            to_explore: once(self.initial_state).collect(),
321            seen: Vec::new(),
322            children_of: &self.children_of,
323        };
324        bridge_unindexed(producer, consumer)
325    }
326}
327
328/// Divide given vector in two equally sized vectors.
329/// Return `None` if initial size is <=1.
330/// We return the first half and keep the last half in `v`.
331fn split_vec<T>(v: &mut Vec<T>) -> Option<Vec<T>> {
332    if v.len() <= 1 {
333        None
334    } else {
335        let n = v.len() / 2;
336        Some(v.split_off(n))
337    }
338}
339
340/// Create a tree like postfix parallel iterator from an initial root node.
341/// The `children_of` function should take a node and iterate on all of its child nodes.
342/// The best parallelization is obtained when the tree is balanced
343/// but we should also be able to handle harder cases.
344///
345/// # Ordering
346///
347/// This function guarantees a postfix ordering. See also [`walk_tree_prefix`] which guarantees a
348/// prefix order. If you don't care about ordering, you should use [`walk_tree`], which will use
349/// whatever is believed to be fastest.
350///
351/// Between siblings, children are reduced in order -- that is first children are reduced first.
352///
353/// For example a perfect binary tree of 7 nodes will reduced in the following order:
354///
355/// ```text
356///      a
357///     / \
358///    /   \
359///   b     c
360///  / \   / \
361/// d   e f   g
362///
363/// reduced as d,e,b,f,g,c,a
364///
365/// ```
366///
367/// # Example
368///
369/// ```text
370///      4
371///     / \
372///    /   \
373///   2     3
374///        / \
375///       1   2
376/// ```
377///
378/// ```
379/// use rayon::iter::walk_tree_postfix;
380/// use rayon::prelude::*;
381///
382/// let par_iter = walk_tree_postfix(4, |&e| {
383///     if e <= 2 {
384///         Vec::new()
385///     } else {
386///         vec![e / 2, e / 2 + 1]
387///     }
388/// });
389/// assert_eq!(par_iter.sum::<u32>(), 12);
390/// ```
391///
392/// # Example
393///
394/// ```
395/// use rayon::prelude::*;
396/// use rayon::iter::walk_tree_postfix;
397///
398/// struct Node {
399///     content: u32,
400///     left: Option<Box<Node>>,
401///     right: Option<Box<Node>>,
402/// }
403///
404/// // Here we loop on the following tree:
405/// //
406/// //       10
407/// //      /  \
408/// //     /    \
409/// //    3     14
410/// //            \
411/// //             \
412/// //              18
413///
414/// let root = Node {
415///     content: 10,
416///     left: Some(Box::new(Node {
417///         content: 3,
418///         left: None,
419///         right: None,
420///     })),
421///     right: Some(Box::new(Node {
422///         content: 14,
423///         left: None,
424///         right: Some(Box::new(Node {
425///             content: 18,
426///             left: None,
427///             right: None,
428///         })),
429///     })),
430/// };
431///
432/// let mut v: Vec<u32> = walk_tree_postfix(&root, |r| {
433///     r.left
434///         .as_ref()
435///         .into_iter()
436///         .chain(r.right.as_ref())
437///         .map(|n| &**n)
438/// })
439/// .map(|node| node.content)
440/// .collect();
441/// assert_eq!(v, vec![3, 18, 14, 10]);
442/// ```
443///
444pub fn walk_tree_postfix<S, B, I>(root: S, children_of: B) -> WalkTreePostfix<S, B>
445where
446    S: Send,
447    B: Fn(&S) -> I + Send + Sync,
448    I: IntoIterator<Item = S>,
449{
450    WalkTreePostfix {
451        initial_state: root,
452        children_of,
453    }
454}
455
456/// ParallelIterator for arbitrary tree-shaped patterns.
457/// Returned by the [`walk_tree()`] function.
458#[derive(Debug)]
459pub struct WalkTree<S, B>(WalkTreePostfix<S, B>);
460
461/// Create a tree like parallel iterator from an initial root node.
462/// The `children_of` function should take a node and iterate on all of its child nodes.
463/// The best parallelization is obtained when the tree is balanced
464/// but we should also be able to handle harder cases.
465///
466/// # Ordering
467///
468/// This function does not guarantee any ordering but will
469/// use whatever algorithm is thought to achieve the fastest traversal.
470/// See also [`walk_tree_prefix`] which guarantees a
471/// prefix order and [`walk_tree_postfix`] which guarantees a postfix order.
472///
473/// # Example
474///
475/// ```text
476///      4
477///     / \
478///    /   \
479///   2     3
480///        / \
481///       1   2
482/// ```
483///
484/// ```
485/// use rayon::iter::walk_tree;
486/// use rayon::prelude::*;
487///
488/// let par_iter = walk_tree(4, |&e| {
489///     if e <= 2 {
490///         Vec::new()
491///     } else {
492///         vec![e / 2, e / 2 + 1]
493///     }
494/// });
495/// assert_eq!(par_iter.sum::<u32>(), 12);
496/// ```
497pub fn walk_tree<S, B, I>(root: S, children_of: B) -> WalkTree<S, B>
498where
499    S: Send,
500    B: Fn(&S) -> I + Send + Sync,
501    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator>,
502{
503    let walker = WalkTreePostfix {
504        initial_state: root,
505        children_of,
506    };
507    WalkTree(walker)
508}
509
510impl<S, B, I> ParallelIterator for WalkTree<S, B>
511where
512    S: Send,
513    B: Fn(&S) -> I + Send + Sync,
514    I: IntoIterator<Item = S, IntoIter: DoubleEndedIterator> + Send,
515{
516    type Item = S;
517
518    fn drive_unindexed<C>(self, consumer: C) -> C::Result
519    where
520        C: UnindexedConsumer<Self::Item>,
521    {
522        self.0.drive_unindexed(consumer)
523    }
524}