use crate::vtree::RotationKind;
use crate::vtree::Vtree;
use crate::vtree::VtreeIdx;
use crate::vtree::VtreeNode;
use crate::vtree::rotate::*;
mod inverse;
mod topo_fixup;
fn assert_invariants(vtree: &Vtree) {
let n = vtree.num_nodes();
assert_eq!(vtree.bottomup_topo().len(), n, "topo length mismatch");
let mut seen = vec![false; n];
for &t in vtree.bottomup_topo() {
assert!(!seen[t.idx()], "duplicate {t:?} in topo");
seen[t.idx()] = true;
}
assert!(seen.iter().all(|&b| b), "topo missing a node");
let mut filt_seen = vec![false; n];
for (t, _, _) in vtree.internal_bottomup() {
assert!(!filt_seen[t.idx()], "duplicate {t:?} in internal_topo");
filt_seen[t.idx()] = true;
}
for (t, _) in vtree.leaf_bottomup() {
assert!(!filt_seen[t.idx()], "duplicate {t:?} in leaf_topo");
filt_seen[t.idx()] = true;
}
assert!(
filt_seen.iter().all(|&b| b),
"internal_topo + leaf_topo missing a node"
);
for (t, left, right) in vtree.internal_bottomup() {
assert_eq!(vtree.node(left).parent(), Some(t));
assert_eq!(vtree.node(right).parent(), Some(t));
assert!(
vtree.topo_pos(left) < vtree.topo_pos(t),
"left child {left:?} not before parent {t:?} in topo"
);
assert!(
vtree.topo_pos(right) < vtree.topo_pos(t),
"right child {right:?} not before parent {t:?} in topo"
);
}
let n = vtree.num_nodes();
let mut subtree_max: Vec<u32> = (0..n as u32).map(|_| 0).collect();
for &t in vtree.bottomup_topo() {
let pos = vtree.topo_pos(t);
let m = match vtree.node(t) {
VtreeNode::Leaf { .. } => pos,
VtreeNode::Internal { left, right, .. } => pos
.max(subtree_max[left.idx()])
.max(subtree_max[right.idx()]),
};
subtree_max[t.idx()] = m;
assert_eq!(
m, pos,
"root-last violated at {t:?}: topo_pos={pos} but subtree max={m}",
);
}
}
fn assert_equal(a: &Vtree, b: &Vtree) {
assert_eq!(a.num_nodes(), b.num_nodes());
for i in 0..a.num_nodes() {
let idx = VtreeIdx(i as u32);
match (a.node(idx), b.node(idx)) {
(
VtreeNode::Leaf {
var: v1,
parent: p1,
},
VtreeNode::Leaf {
var: v2,
parent: p2,
},
) => {
assert_eq!(v1, v2);
assert_eq!(p1, p2);
}
(
VtreeNode::Internal {
left: l1,
right: r1,
parent: p1,
},
VtreeNode::Internal {
left: l2,
right: r2,
parent: p2,
},
) => {
assert_eq!(l1, l2);
assert_eq!(r1, r2);
assert_eq!(p1, p2);
}
_ => panic!("node type mismatch at {idx:?}"),
}
}
}
fn unrotate_left_pointers(vtree: &mut Vtree, info: &RotationInfo) {
let RotationInfo {
v_idx,
w_idx,
a_idx,
b_idx,
c_idx,
} = *info;
let v_parent = vtree.nodes[v_idx.idx()].parent();
vtree.nodes[v_idx.idx()] = VtreeNode::Internal {
left: a_idx,
right: w_idx,
parent: v_parent,
};
vtree.nodes[w_idx.idx()] = VtreeNode::Internal {
left: b_idx,
right: c_idx,
parent: Some(v_idx),
};
Vtree::set_parent(&mut vtree.nodes, a_idx, v_idx);
Vtree::set_parent(&mut vtree.nodes, c_idx, w_idx);
}
fn unrotate_left(vtree: &mut Vtree, info: &RotationInfo) {
unrotate_left_pointers(vtree, info);
vtree.fixup_topo_after_rotate(info, RotationKind::Right);
}
fn unrotate_right_pointers(vtree: &mut Vtree, info: &RotationInfo) {
let RotationInfo {
v_idx,
w_idx,
a_idx,
b_idx,
c_idx,
} = *info;
let v_parent = vtree.nodes[v_idx.idx()].parent();
vtree.nodes[v_idx.idx()] = VtreeNode::Internal {
left: w_idx,
right: c_idx,
parent: v_parent,
};
vtree.nodes[w_idx.idx()] = VtreeNode::Internal {
left: a_idx,
right: b_idx,
parent: Some(v_idx),
};
Vtree::set_parent(&mut vtree.nodes, a_idx, w_idx);
Vtree::set_parent(&mut vtree.nodes, c_idx, v_idx);
}
fn unrotate_right(vtree: &mut Vtree, info: &RotationInfo) {
unrotate_right_pointers(vtree, info);
vtree.fixup_topo_after_rotate(info, RotationKind::Left);
}
impl Vtree {
fn rebuild_topo(&mut self) {
let n = self.nodes.len();
self.topo.clear();
self.topo.reserve(n);
self.internal_topo.clear();
self.leaf_topo.clear();
if self.topo_pos.len() != n {
self.topo_pos.resize(n, 0);
}
let mut stack: Vec<(VtreeIdx, bool)> = Vec::with_capacity(n);
stack.push((self.root, false));
while let Some((idx, done)) = stack.pop() {
if done {
self.topo_pos[idx.idx()] = self.topo.len() as u32;
self.topo.push(idx);
if self.nodes[idx.idx()].is_leaf() {
self.leaf_topo.push(idx);
} else {
self.internal_topo.push(idx);
}
} else {
stack.push((idx, true));
if let VtreeNode::Internal { left, right, .. } = self.nodes[idx.idx()] {
stack.push((right, false));
stack.push((left, false));
}
}
}
debug_assert_eq!(
self.topo.len(),
n,
"topo missed nodes (disconnected vtree?)"
);
}
#[inline]
fn bottomup_topo(&self) -> &[VtreeIdx] {
&self.topo
}
}