use crate::graph::{ImageEdge, ImageNode, ImageNodeColor};
use std::cell::Cell;
#[derive(Debug, Clone, Default)]
pub struct ImageGraph {
k: Cell<usize>,
nodes: Nodes,
edges: Edges,
}
#[derive(Debug, Clone, Default)]
pub struct Nodes {
nodes: Vec<Cell<ImageNode>>,
node_colors: Vec<Cell<ImageNodeColor>>,
}
#[derive(Debug, Clone, Default)]
pub struct Edges {
edges: Vec<Cell<ImageEdge>>,
}
impl ImageGraph {
pub fn new_with_nodes(n: usize) -> Self {
Self {
k: Cell::new(n),
nodes: Nodes::allocated(n),
..Self::default()
}
}
pub fn reset(&mut self, n: usize) {
self.k.replace(n);
self.nodes = Nodes::allocated(n);
self.edges.clear();
}
pub fn num_nodes(&self) -> usize {
self.nodes.len()
}
pub fn num_edges(&self) -> usize {
self.edges.len()
}
pub fn num_components(&self) -> usize {
self.k.get()
}
pub fn merge(&self, s_n: &Cell<ImageNode>, s_m: &Cell<ImageNode>, e: &ImageEdge) {
let mut lhs = s_n.get();
let mut rhs = s_m.get();
debug_assert_ne!(lhs.id, rhs.id);
rhs.label = lhs.id;
lhs.n += rhs.n;
lhs.max_w = lhs.max_w.max(rhs.max_w).max(e.w);
s_n.set(lhs);
s_m.set(rhs);
let new_k = self.k.get() - 1;
self.k.replace(new_k);
}
pub fn node_at(&self, n: usize) -> &Cell<ImageNode> {
self.nodes.at(n)
}
#[inline(always)]
pub fn node_color_at(&self, n: usize) -> &Cell<ImageNodeColor> {
self.nodes.color_at(n)
}
#[inline(always)]
pub fn node_id_at(&self, n: usize) -> usize {
let id = self.nodes.at(n).get().id;
debug_assert_eq!(id, n); id
}
pub fn edge_at(&self, n: usize) -> &Cell<ImageEdge> {
self.edges.at(n)
}
pub fn find_node_component_at(&self, index: usize) -> usize {
self.nodes.find_component_at(index)
}
pub fn add_edges<I>(&mut self, edges: I)
where
I: Iterator<Item = ImageEdge>,
{
self.edges.add_many(edges)
}
pub fn clear_edges(&mut self) {
self.edges.clear();
}
pub fn sort_edges(&mut self) {
self.edges.sort_by_weight()
}
}
impl Nodes {
pub fn allocated(n: usize) -> Self {
let mut nodes = vec![Default::default(); n];
let mut colors = vec![Default::default(); n];
Self {
nodes,
node_colors: colors,
}
}
#[allow(dead_code)]
pub fn set(&mut self, n: usize, node: ImageNode) {
assert!(n < self.nodes.len());
self.nodes[n].replace(node);
}
#[allow(dead_code)]
pub fn add(&mut self, node: ImageNode) {
self.nodes.push(Cell::new(node))
}
pub fn at(&self, n: usize) -> &Cell<ImageNode> {
assert!(n < self.nodes.len());
&self.nodes[n]
}
#[inline(always)]
pub fn color_at(&self, n: usize) -> &Cell<ImageNodeColor> {
assert!(n < self.node_colors.len());
&self.node_colors[n]
}
pub fn find_component_at(&self, index: usize) -> usize {
let mut n = self.nodes[index].get();
debug_assert_eq!(n.id, index);
if n.label == n.id {
return index;
}
let mut l = n.label;
let mut id = n.id;
while l != id {
let token = self.nodes[l].get();
l = token.label;
id = token.id;
}
debug_assert_ne!(l, index);
let s = self.nodes[l].get();
debug_assert_eq!(s.label, s.id);
n.label = s.id;
self.nodes[index].set(n);
l
}
pub fn len(&self) -> usize {
self.nodes.len()
}
}
impl Edges {
pub fn add(&mut self, edge: ImageEdge) {
self.edges.push(Cell::new(edge))
}
pub fn add_many<I>(&mut self, edges: I)
where
I: Iterator<Item = ImageEdge>,
{
for edge in edges.into_iter() {
self.add(edge);
}
}
pub fn at(&self, n: usize) -> &Cell<ImageEdge> {
assert!(n < self.edges.len());
&self.edges[n]
}
pub fn sort_by_weight(&mut self) {
self.edges.sort_by(|a, b| {
let a = a.get();
let b = b.get();
let ord_w = a.w.partial_cmp(&b.w).unwrap();
let ord_n = a.n.partial_cmp(&b.n).unwrap();
let ord_m = a.m.partial_cmp(&b.m).unwrap();
ord_w.then(ord_n).then(ord_m)
});
}
pub fn clear(&mut self) {
self.edges.clear()
}
pub fn len(&self) -> usize {
self.edges.len()
}
}