Skip to content

Commit

Permalink
Add reduction operation
Browse files Browse the repository at this point in the history
  • Loading branch information
JayKickliter committed Jan 13, 2023
1 parent ca7d1da commit 83441a8
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/hex_tree_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,23 @@ impl<V, C> HexTreeMap<V, C> {
}
}

/// Reduces the all children of `hex` using the user-provided
/// function.
pub fn reduce<F>(&self, hex: H3Cell, f: F) -> Option<V>
where
V: Copy,
F: FnMut(u8, &[V]) -> V,
{
let base_cell = base(hex);
match self.nodes[base_cell as usize].as_ref() {
Some(node) => {
let digits = Digits::new(hex);
node.reduce(digits, 0, f)
}
None => None,
}
}

/// Returns a reference to the value corresponding to the given
/// hex or one of its parents.
pub fn get_mut(&mut self, hex: H3Cell) -> Option<&mut V> {
Expand Down
38 changes: 38 additions & 0 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,49 @@ impl<V> Node<V> {
self.coalesce(res, compactor);
}

pub(crate) fn reduce<F>(&self, mut digits: Digits, res: u8, mut f: F) -> Option<V>
where
V: Copy,
F: FnMut(u8, &[V]) -> V,
{
if let Self::Leaf(val) = self {
return Some(*val);
}

match (digits.next(), self) {
(Some(digit), Self::Leaf(_)) => unreachable!(),
(Some(digit), Self::Parent(children)) => match &children.as_slice()[digit as usize] {
Some(node) => node.reduce(digits, res + 1, f),
None => None,
},
(None, node) => Some(node.apply_reduction(res, &mut f)),
}
}

pub(crate) fn apply_reduction<F>(&self, res: u8, f: &mut F) -> V
where
V: Copy,
F: FnMut(u8, &[V]) -> V,
{
match self {
Node::Leaf(val) => *val,
Node::Parent(children) => {
let nodes_to_reduce: Vec<V> = children
.iter()
.flatten()
.map(|child_node| child_node.apply_reduction(res + 1, f))
.collect();
f(res, nodes_to_reduce.as_slice())
}
}
}

pub(crate) fn coalesce<C>(&mut self, res: u8, compactor: &mut C)
where
C: Compactor<V>,
{
if let Self::Parent(children) = self {
// Return early if this node contains any non-leaf children.
if children
.iter()
.any(|n| matches!(n.as_ref().map(|n| n.as_ref()), Some(Self::Parent(_))))
Expand Down

0 comments on commit 83441a8

Please sign in to comment.