use std::cmp::{Ordering, Reverse};
use std::collections::BinaryHeap;
#[derive(Clone)]
pub(crate) struct Node {
pub(crate) id: String,
pub(crate) vector: Vec<f32>,
pub(crate) deleted: bool,
pub(crate) neighbors: Vec<Vec<usize>>,
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct ScoredNode {
pub(crate) index: usize,
pub(crate) score: f32,
}
#[derive(Default)]
pub(crate) struct SearchScratch {
marks: Vec<u32>,
mark: u32,
pub(crate) candidates: BinaryHeap<ScoredNode>,
pub(crate) results: BinaryHeap<Reverse<ScoredNode>>,
pub(crate) found: Vec<ScoredNode>,
}
impl SearchScratch {
pub(crate) fn reset(&mut self, nodes: usize) {
if self.marks.len() < nodes {
self.marks.resize(nodes, 0);
}
self.mark = self.mark.wrapping_add(1);
if self.mark == 0 {
self.marks.fill(0);
self.mark = 1;
}
self.candidates.clear();
self.results.clear();
self.found.clear();
}
pub(crate) fn visit(&mut self, index: usize) -> bool {
if self.marks[index] == self.mark {
return false;
}
self.marks[index] = self.mark;
true
}
}
impl Eq for ScoredNode {}
impl PartialEq for ScoredNode {
fn eq(&self, other: &Self) -> bool {
self.index == other.index && self.score.to_bits() == other.score.to_bits()
}
}
impl Ord for ScoredNode {
fn cmp(&self, other: &Self) -> Ordering {
self.score
.total_cmp(&other.score)
.then_with(|| other.index.cmp(&self.index))
}
}
impl PartialOrd for ScoredNode {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub(crate) fn compare_scored_desc(left: &ScoredNode, right: &ScoredNode) -> Ordering {
right
.score
.total_cmp(&left.score)
.then_with(|| left.index.cmp(&right.index))
}