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