#[derive(Debug, Clone)]
pub struct HTNode {
pub id: usize,
pub mode_start: usize,
pub mode_end: usize,
pub left: Option<usize>,
pub right: Option<usize>,
pub parent: Option<usize>,
pub rank: usize,
pub is_leaf: bool,
}
impl HTNode {
pub fn new(id: usize, mode_start: usize, mode_end: usize, parent: Option<usize>) -> Self {
HTNode {
id,
mode_start,
mode_end,
left: None,
right: None,
parent,
rank: 0,
is_leaf: mode_end - mode_start == 1,
}
}
pub fn n_modes(&self) -> usize {
self.mode_end - self.mode_start
}
}
pub fn build_dimension_tree(n_dims: usize) -> Vec<HTNode> {
let mut nodes: Vec<HTNode> = Vec::new();
build_recursive(&mut nodes, 0, n_dims, None);
nodes
}
fn build_recursive(
nodes: &mut Vec<HTNode>,
mode_start: usize,
mode_end: usize,
parent: Option<usize>,
) -> usize {
let id = nodes.len();
let node = HTNode::new(id, mode_start, mode_end, parent);
nodes.push(node);
let n = mode_end - mode_start;
if n > 1 {
let mid = mode_start + n / 2;
let left_id = build_recursive(nodes, mode_start, mid, Some(id));
let right_id = build_recursive(nodes, mid, mode_end, Some(id));
nodes[id].left = Some(left_id);
nodes[id].right = Some(right_id);
nodes[id].is_leaf = false;
}
id
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_4d_tree() {
let nodes = build_dimension_tree(4);
assert_eq!(nodes[0].mode_start, 0);
assert_eq!(nodes[0].mode_end, 4);
assert!(nodes[0].left.is_some());
assert!(nodes[0].right.is_some());
for node in &nodes {
if node.is_leaf {
assert_eq!(node.n_modes(), 1);
}
}
}
#[test]
fn test_leaf_count() {
for d in 2..=8 {
let nodes = build_dimension_tree(d);
let leaves: Vec<_> = nodes.iter().filter(|n| n.is_leaf).collect();
assert_eq!(leaves.len(), d, "d={d}: expected {d} leaves, got {}", leaves.len());
}
}
}