Strengthen abstraction for node types

This commit is contained in:
Dirkjan Ochtman 2021-01-20 16:53:31 +01:00
parent d80a2e3f67
commit 28f133a9f8
2 changed files with 24 additions and 26 deletions

View File

@ -301,11 +301,7 @@ where
// with `nearest` truncated to `M` elements. // with `nearest` truncated to `M` elements.
if layer.0 > 0 { if layer.0 > 0 {
let mut upper = Vec::with_capacity(zero.len()); let mut upper = Vec::with_capacity(zero.len());
upper.extend(zero.iter().map(|zero| { upper.extend(zero.iter().map(UpperNode::from_zero));
let mut upper = UpperNode::default();
upper.nearest.copy_from_slice(&zero.nearest[..M]);
upper
}));
layers[layer.0 - 1] = upper; layers[layer.0 - 1] = upper;
} }
} }
@ -416,7 +412,7 @@ fn insert<P: Point>(
let found = let found =
insertion.select_heuristic(&layer, M * 2, candidate_point, points, *heuristic); insertion.select_heuristic(&layer, M * 2, candidate_point, points, *heuristic);
for (i, slot) in layer[pid].nearest.iter_mut().enumerate() { for (i, slot) in layer[pid].0.iter_mut().enumerate() {
if let Some(&Candidate { pid, .. }) = found.get(i) { if let Some(&Candidate { pid, .. }) = found.get(i) {
*slot = pid; *slot = pid;
} else if *slot != PointId::invalid() { } else if *slot != PointId::invalid() {
@ -426,11 +422,11 @@ fn insert<P: Point>(
} }
} }
layer[new].nearest[i] = pid; layer[new].set(i, pid);
} else { } else {
// Find the correct index to insert at to keep the neighbor's neighbors sorted // Find the correct index to insert at to keep the neighbor's neighbors sorted
let old = &points[pid]; let old = &points[pid];
let nearest = &layer[pid].nearest; let nearest = &layer[pid].0;
let idx = nearest let idx = nearest
.binary_search_by(|third| { .binary_search_by(|third| {
// `third` here is one of the neighbors of the new node's neighbor. // `third` here is one of the neighbors of the new node's neighbor.
@ -447,18 +443,18 @@ fn insert<P: Point>(
// It might be possible for all the neighbor's current neighbors to be closer to our // It might be possible for all the neighbor's current neighbors to be closer to our
// neighbor than to the new node, in which case we skip insertion of our new node's ID. // neighbor than to the new node, in which case we skip insertion of our new node's ID.
if idx >= nearest.len() { if idx >= nearest.len() {
layer[new].nearest[i] = pid; layer[new].set(i, pid);
continue; continue;
} }
let nearest = &mut layer[pid].nearest; let nearest = &mut layer[pid].0;
if nearest[idx].is_valid() { if nearest[idx].is_valid() {
let end = (M * 2) - 1; let end = (M * 2) - 1;
nearest.copy_within(idx..end, idx + 1); nearest.copy_within(idx..end, idx + 1);
} }
nearest[idx] = new; nearest[idx] = new;
layer[new].nearest[i] = pid; layer[new].set(i, pid);
} }
} }
} }

View File

@ -59,42 +59,44 @@ impl Visited {
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub(crate) struct UpperNode { pub(crate) struct UpperNode([PointId; M]);
/// The nearest neighbors on this layer
/// impl UpperNode {
/// This is always kept in sorted order (near to far). pub(crate) fn from_zero(node: &ZeroNode) -> Self {
pub(crate) nearest: [PointId; M], let mut nearest = [PointId::invalid(); M];
nearest.copy_from_slice(&node.0[..M]);
Self(nearest)
}
} }
impl Layer for &Vec<UpperNode> { impl Layer for &Vec<UpperNode> {
fn nearest_iter(&self, pid: PointId) -> NearestIter<'_> { fn nearest_iter(&self, pid: PointId) -> NearestIter<'_> {
NearestIter { NearestIter {
nearest: &self[pid.0 as usize].nearest, nearest: &self[pid.0 as usize].0,
} }
} }
} }
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub(crate) struct ZeroNode { pub(crate) struct ZeroNode(pub(crate) [PointId; M * 2]);
/// The nearest neighbors on this layer
/// impl ZeroNode {
/// This is always kept in sorted order (near to far). pub(crate) fn set(&mut self, idx: usize, pid: PointId) {
pub(crate) nearest: [PointId; M * 2], self.0[idx] = pid;
}
} }
impl Default for ZeroNode { impl Default for ZeroNode {
fn default() -> ZeroNode { fn default() -> ZeroNode {
ZeroNode { ZeroNode([PointId::invalid(); M * 2])
nearest: [PointId::invalid(); M * 2],
}
} }
} }
impl Layer for &Vec<ZeroNode> { impl Layer for &Vec<ZeroNode> {
fn nearest_iter(&self, pid: PointId) -> NearestIter<'_> { fn nearest_iter(&self, pid: PointId) -> NearestIter<'_> {
NearestIter { NearestIter {
nearest: &self[pid.0 as usize].nearest, nearest: &self[pid.0 as usize].0,
} }
} }
} }