ark/tree/
mod.rs

1
2pub mod signed;
3
4use std::cmp;
5
6/// The max radix of this tree is 4.
7const RADIX: usize = 4;
8
9#[derive(Debug, Clone)]
10pub struct Node {
11	idx: u32,
12	parent: Option<u32>,
13	children: [Option<u32>; RADIX],
14	/// Exclusive range of leaves, allowed to revolve back to 0.
15	leaves: (u32, u32),
16	nb_tree_leaves: u32,
17	level: u32,
18}
19
20impl Node {
21	fn new_leaf(idx: usize, nb_tree_leaves: usize) -> Node {
22		let idx = idx as u32;
23		Node {
24			idx,
25			parent: None,
26			children: [None; RADIX],
27			leaves: (idx, (idx+1) % nb_tree_leaves as u32),
28			nb_tree_leaves: nb_tree_leaves as u32,
29			level: 0,
30		}
31	}
32
33	pub fn idx(&self) -> usize {
34		self.idx as usize
35	}
36
37	pub fn parent(&self) -> Option<usize> {
38		self.parent.map(|p| p as usize)
39	}
40
41	pub fn children(&self) -> impl Iterator<Item = usize> {
42		self.children.clone().into_iter().filter_map(|c| c).map(|c| c as usize)
43	}
44
45	pub fn level(&self) -> usize {
46		self.level as usize
47	}
48
49	/// An iterator over all leaf indices under this node.
50	pub fn leaves(&self) -> impl Iterator<Item = usize> + Clone {
51		let (first, last) = self.leaves;
52		let nb = self.nb_tree_leaves;
53		(first..)
54			.take(nb as usize)
55			.map(move |e| e % nb)
56			.take_while(move |e| first == last || *e != last)
57			.map(|e| e as usize)
58	}
59
60	pub fn is_leaf(&self) -> bool {
61		self.children.iter().all(|o| o.is_none())
62	}
63
64	pub fn is_root(&self) -> bool {
65		self.parent.is_none()
66	}
67}
68
69//TODO(stevenroose) consider eliminating this type in favor of straight in-line iterators
70// for all nodes and for branches
71/// A radix-4 tree.
72#[derive(Debug, Clone)]
73pub struct Tree {
74	/// The nodes in the tree, starting with all the leaves
75	/// and then building up towards the root.
76	nodes: Vec<Node>,
77	nb_leaves: usize,
78}
79
80impl Tree {
81	/// Calculate the total number of nodes a tree would have
82	/// for the given number of leaves.
83	pub fn nb_nodes_for_leaves(nb_leaves: usize) -> usize {
84		let mut ret = nb_leaves;
85		let mut left = nb_leaves;
86		while left > 1 {
87			let radix = cmp::min(left, RADIX);
88			left -= radix;
89			left += 1;
90			ret += 1;
91		}
92		ret
93	}
94
95	pub fn new(
96		nb_leaves: usize,
97	) -> Tree {
98		assert_ne!(nb_leaves, 0, "trees can't be empty");
99
100		let mut nodes = Vec::with_capacity(Tree::nb_nodes_for_leaves(nb_leaves));
101
102		// First we add all the leaves to the tree.
103		nodes.extend((0..nb_leaves).map(|i| Node::new_leaf(i, nb_leaves)));
104
105		let mut cursor = 0;
106		// As long as there is more than 1 element on the leftover stack,
107		// we have to add more nodes.
108		while cursor < nodes.len() - 1 {
109			let mut children = [None; RADIX];
110			let mut nb_children = 0;
111			let mut max_child_level = 0;
112			while cursor < nodes.len() && nb_children < RADIX {
113				children[nb_children] = Some(cursor as u32);
114
115				let new_idx = nodes.len(); // idx of next node
116				let child = &mut nodes[cursor];
117				child.parent = Some(new_idx as u32);
118
119				// adjust level and leaf indices
120				if child.level > max_child_level {
121					max_child_level = child.level;
122				}
123
124				cursor += 1;
125				nb_children += 1;
126			}
127			nodes.push(Node {
128				idx: nodes.len() as u32,
129				leaves: (
130					nodes[children.first().unwrap().unwrap() as usize].leaves.0,
131					nodes[children.iter().filter_map(|c| *c).last().unwrap() as usize].leaves.1,
132				),
133				children,
134				level: max_child_level + 1,
135				parent: None,
136				nb_tree_leaves: nb_leaves as u32,
137			});
138		}
139
140		Tree { nodes, nb_leaves }
141	}
142
143	pub fn nb_leaves(&self) -> usize {
144		self.nb_leaves
145	}
146
147	pub fn nb_nodes(&self) -> usize {
148		self.nodes.len()
149	}
150
151	pub fn root(&self) -> &Node {
152		self.nodes.last().expect("no empty trees")
153	}
154
155	/// Iterate over all nodes, starting with the leaves, towards the root.
156	pub fn iter(&self) -> std::slice::Iter<'_, Node> {
157		self.nodes.iter()
158	}
159
160	/// Iterate over all nodes, starting with the leaves, towards the root.
161	pub fn into_iter(self) -> std::vec::IntoIter<Node> {
162		self.nodes.into_iter()
163	}
164
165	/// Iterate nodes over a branch starting at the leaf
166	/// with index `leaf_idx` ending in the root.
167	pub fn iter_branch(&self, leaf_idx: usize) -> BranchIter<'_> {
168		assert!(leaf_idx < self.nodes.len());
169		BranchIter {
170			tree: &self,
171			cursor: Some(leaf_idx),
172		}
173	}
174
175	pub fn parent_idx_of(&self, idx: usize) -> Option<usize> {
176		self.nodes.get(idx).and_then(|n| n.parent.map(|c| c as usize))
177	}
178
179	/// Returns index of the the parent of the node with given `idx`,
180	/// and the index of the node among its siblings.
181	pub fn parent_idx_of_with_sibling_idx(&self, idx: usize) -> Option<(usize, usize)> {
182		self.nodes.get(idx).and_then(|n| n.parent).map(|parent_idx| {
183			let child_idx = self.nodes[parent_idx as usize].children.iter()
184				.position(|c| *c == Some(idx as u32))
185				.expect("broken tree");
186			(self.nodes[parent_idx as usize].idx as usize, child_idx as usize)
187		})
188	}
189
190}
191
192/// Iterates a tree branch.
193pub struct BranchIter<'a> {
194	tree: &'a Tree,
195	cursor: Option<usize>,
196}
197
198impl<'a> Iterator for BranchIter<'a> {
199	type Item = &'a Node;
200	fn next(&mut self) -> Option<Self::Item> {
201		if let Some(cursor) = self.cursor {
202			let ret = &self.tree.nodes[cursor];
203			self.cursor = ret.parent();
204			Some(ret)
205		} else {
206			None
207		}
208	}
209}
210
211#[cfg(test)]
212mod test {
213	use std::collections::HashSet;
214
215use super::*;
216
217	#[test]
218	fn test_simple_tree() {
219		for n in 1..100 {
220			let tree = Tree::new(n);
221
222			assert!(tree.nodes.iter().rev().skip(1).all(|n| n.parent.is_some()));
223			assert!(tree.nodes.iter().enumerate().skip(tree.nb_leaves).all(|(i, n)| {
224				n.children.iter().filter_map(|v| *v)
225					.all(|c| tree.nodes[c as usize].parent == Some(i as u32))
226			}));
227			assert!(tree.nodes.iter().enumerate().rev().skip(1).all(|(i, n)| {
228				tree.nodes[n.parent.unwrap() as usize].children.iter().find(|c| **c == Some(i as u32)).is_some()
229			}));
230			assert_eq!(Tree::nb_nodes_for_leaves(n), tree.nb_nodes(), "leaves: {}", n);
231		}
232	}
233
234	#[test]
235	fn test_leaves_range() {
236		for n in 1..42 {
237			let tree = Tree::new(n);
238
239			for node in &tree.nodes[0..tree.nb_leaves()] {
240				assert_eq!(node.leaves().collect::<Vec<_>>(), vec![node.idx()]);
241			}
242			for node in tree.iter() {
243				if !node.is_leaf() {
244					assert_eq!(
245						node.leaves().count(),
246						node.children().map(|c| tree.nodes[c].leaves().count()).sum::<usize>(),
247						"idx: {}", node.idx(),
248					);
249				}
250				assert!(node.leaves().all(|l| l < tree.nb_leaves()));
251				assert_eq!(
252					node.leaves().count(),
253					node.leaves().collect::<HashSet<_>>().len(),
254				);
255			}
256			println!("n={n} ok");
257		}
258	}
259}