diff --git a/src/models/graph.rs b/src/models/graph.rs index eddaa5c..fa3262e 100644 --- a/src/models/graph.rs +++ b/src/models/graph.rs @@ -18,73 +18,19 @@ pub struct VertexIncidenceHeader { first_incidence: Option, } +#[derive(Copy, Clone)] pub struct IncidenceEntry { next: Option, adjacent: VertexSlot, } -struct AdjacentVertexIterator<'a> { - graph: &'a Graph, - incidence: Option, -} - -impl<'a> Iterator for AdjacentVertexIterator<'a> { - type Item = Vertex; - - fn next(&mut self) -> Option { - // TODO: Benchmark storing full Index (one read, larger entries) vs. slot + get_idx() (two reads, smaller entries). - let incidence = self.incidence?; - let i = self.graph.incidences.get_idx(incidence.0).unwrap(); - let entry = &self.graph.incidences[i]; - self.incidence = entry.next; - Some(self.graph.vertices.get_idx(entry.adjacent.0).unwrap()) - } -} - -struct IncidentEdgeIterator<'a> { - graph: &'a Graph, - incidence: Option, -} - -impl<'a> Iterator for IncidentEdgeIterator<'a> { - type Item = Edge; - - fn next(&mut self) -> Option { - let current = self.incidence?; - let e = self.graph.incidences.get_idx(current.0).unwrap(); - self.incidence = self.graph.incidences[e].next; - Some(e) - } -} - struct IncidentEdgeCursor { incidence: Option, } impl IncidentEdgeCursor { fn next(&mut self, graph: &Graph) -> Option { - let current = self.incidence?; - let e = graph.incidences.get_idx(current.0).unwrap(); - self.incidence = graph.incidences[e].next; - Some(e) - } -} - -struct IncidenceIterator<'a> { - graph: &'a Graph, - incidence: Option, -} - -impl<'a> Iterator for IncidenceIterator<'a> { - type Item = (Vertex, Edge); - - fn next(&mut self) -> Option { - let current = self.incidence?; - let e = self.graph.incidences.get_idx(current.0).unwrap(); - let entry = &self.graph.incidences[e]; - self.incidence = entry.next; - let v = self.graph.vertices.get_idx(entry.adjacent.0).unwrap(); - Some((v, self.graph.normalize_edge(e))) + graph.step_incidence(&mut self.incidence).map(|(_, e)| e) } } @@ -151,16 +97,27 @@ impl Graph { if first.0 == e.arr_idx() { vertex_header.first_incidence = next; } else { - let previous = IncidentEdgeIterator { - graph: self, - incidence: self.vertices[source_vertex].first_incidence, - } - .find(|f| self.incidences[*f].next.is_some_and(|i| i.0 == e.arr_idx())) - .expect("cannot find previous incidence, corrupt internal data state"); + let graph: &Graph = self; + let mut incidence = self.vertices[source_vertex].first_incidence; + let (_, previous) = std::iter::from_fn(move || graph.step_incidence(&mut incidence)) + .find(|(_, f)| { + graph.incidences[*f] + .next + .is_some_and(|i| i.0 == e.arr_idx()) + }) + .expect("cannot find previous incidence, corrupt internal data state"); self.incidences[previous].next = next; } } + fn step_incidence(&self, incidence: &mut Option) -> Option<(VertexSlot, Edge)> { + let current = (*incidence)?; + let e = self.incidences.get_idx(current.0).unwrap(); + let entry = self.incidences[e]; + *incidence = entry.next; + Some((entry.adjacent, e)) + } + fn normalize_edge(&self, e: Edge) -> Edge { self.incidences.get_idx(e.arr_idx() & !1).unwrap() } @@ -214,10 +171,9 @@ impl GraphTopology for Graph { } fn adjacent_vertices(&self, v: Self::Vertex) -> impl Iterator { - AdjacentVertexIterator { - graph: self, - incidence: self.vertices[v].first_incidence, - } + let mut incidence = self.vertices[v].first_incidence; + std::iter::from_fn(move || self.step_incidence(&mut incidence)) + .map(|(vs, _)| self.vertices.get_idx(vs.0).unwrap()) } fn edges(&self) -> impl Iterator { @@ -228,10 +184,9 @@ impl GraphTopology for Graph { } fn incidences(&self, v: Self::Vertex) -> impl Iterator { - IncidenceIterator { - graph: self, - incidence: self.vertices[v].first_incidence, - } + let mut incidence = self.vertices[v].first_incidence; + std::iter::from_fn(move || self.step_incidence(&mut incidence)) + .map(|(vs, e)| (self.vertices.get_idx(vs.0).unwrap(), self.normalize_edge(e))) } fn add_vertex(&mut self) -> Self::Vertex {