use std::cmp::Ordering;
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct Candidate {
index: usize,
score: f32,
}
impl Candidate {
pub(crate) fn new(index: usize, score: f32) -> Self {
Self { index, score }
}
pub(crate) fn index(self) -> usize {
self.index
}
pub(crate) fn score(self) -> f32 {
self.score
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Vectors<'a> {
rows: &'a [f32],
stride: usize,
}
impl<'a> Vectors<'a> {
#[must_use]
pub(crate) fn new(rows: &'a [f32], stride: usize) -> Self {
Self { rows, stride }
}
#[must_use]
pub(crate) fn row(self, index: usize) -> Option<&'a [f32]> {
if self.stride == 0 {
return None;
}
let start = index.checked_mul(self.stride)?;
let end = start.checked_add(self.stride)?;
self.rows.get(start..end)
}
#[must_use]
pub(crate) fn similarity(self, a: usize, b: usize) -> Option<f32> {
Some(dot(self.row(a)?, self.row(b)?))
}
}
#[derive(Debug)]
pub(crate) struct Index {
rows: Vec<f32>,
stride: usize,
}
impl Index {
pub(crate) fn new(rows: Vec<f32>, stride: usize, count: usize) -> Result<Self, String> {
if stride == 0 {
return Err("the model reported a zero embedding dimension".to_owned());
}
let expected = stride
.checked_mul(count)
.ok_or_else(|| "the vector buffer length overflowed".to_owned())?;
if rows.len() != expected {
return Err(format!(
"the vector buffer holds {} floats, expected {expected} for {count} rows of {stride}",
rows.len()
));
}
Ok(Self { rows, stride })
}
#[must_use]
pub(crate) fn vectors(&self) -> Vectors<'_> {
Vectors::new(&self.rows, self.stride)
}
#[must_use]
pub(crate) fn top_k(&self, query: &[f32], k: usize) -> Vec<Candidate> {
top_k(query, &self.rows, k)
}
}
#[must_use]
fn top_k(query: &[f32], vectors: &[f32], k: usize) -> Vec<Candidate> {
if query.is_empty() || k == 0 {
return Vec::new();
}
let mut candidates: Vec<Candidate> = vectors
.chunks_exact(query.len())
.enumerate()
.map(|(index, row)| Candidate::new(index, dot(query, row)))
.collect();
candidates.sort_unstable_by(by_score_then_position);
candidates.truncate(k);
candidates
}
fn dot(a: &[f32], b: &[f32]) -> f32 {
a.iter().zip(b).map(|(x, y)| x * y).sum()
}
fn by_score_then_position(a: &Candidate, b: &Candidate) -> Ordering {
comparable(b.score)
.total_cmp(&comparable(a.score))
.then(a.index.cmp(&b.index))
}
#[must_use]
pub(crate) fn comparable(score: f32) -> f32 {
if score.is_finite() {
score
} else {
f32::NEG_INFINITY
}
}
#[cfg(test)]
mod tests {
use super::{Candidate, Index, Vectors};
fn positions(candidates: &[Candidate]) -> Vec<usize> {
candidates
.iter()
.map(|candidate| candidate.index())
.collect()
}
const ROWS: [f32; 8] = [
0.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.6, 0.8, ];
fn index() -> Index {
Index::new(ROWS.to_vec(), 2, 4).expect("a well-formed layout is accepted")
}
#[test]
fn candidates_come_back_in_descending_score_order() {
let ranked = index().top_k(&[1.0, 0.0], 4);
assert_eq!(positions(&ranked), vec![1, 3, 0, 2]);
for pair in ranked.windows(2) {
assert!(pair[0].score() >= pair[1].score());
}
}
#[test]
fn a_k_larger_than_the_index_returns_the_index_unpadded() {
let ranked = index().top_k(&[1.0, 0.0], 99);
assert_eq!(ranked.len(), 4);
}
#[test]
fn a_k_smaller_than_the_index_truncates_the_same_ranking() {
let index = index();
let full = index.top_k(&[1.0, 0.0], 4);
for k in 0..=4 {
assert_eq!(index.top_k(&[1.0, 0.0], k).as_slice(), &full[..k]);
}
}
#[test]
fn an_empty_query_yields_no_candidates() {
assert!(index().top_k(&[], 3).is_empty());
}
#[test]
fn exactly_tied_scores_are_ordered_by_catalog_position() {
let query = [0.6_f32, 0.8];
let tied: Vec<f32> = query.iter().copied().cycle().take(8).collect();
let index = Index::new(tied, 2, 4).expect("layout");
let ranked = index.top_k(&query, 4);
assert_eq!(positions(&ranked), vec![0, 1, 2, 3]);
for _ in 0..8 {
assert_eq!(index.top_k(&query, 4), ranked);
}
}
#[test]
fn a_non_finite_score_never_outranks_a_real_one() {
let rows = vec![f32::NAN, 0.0, 0.5, 0.0, f32::INFINITY, 0.0, 1.0, 0.0];
let ranked = Index::new(rows, 2, 4)
.expect("layout")
.top_k(&[1.0, 0.0], 4);
assert_eq!(positions(&ranked), vec![3, 1, 0, 2]);
}
#[test]
fn similarities_read_two_stored_rows() {
let vectors = Vectors::new(&ROWS, 2);
assert_eq!(vectors.similarity(1, 1), Some(1.0));
assert_eq!(vectors.similarity(1, 2), Some(-1.0));
assert_eq!(vectors.similarity(0, 1), Some(0.0));
assert_eq!(vectors.similarity(1, 3), Some(0.6));
assert_eq!(vectors.similarity(0, 9), None);
}
#[test]
fn construction_rejects_malformed_layouts() {
assert!(Index::new(vec![1.0, 0.0], 0, 1).is_err(), "zero stride");
assert!(
Index::new(vec![1.0, 0.0, 0.5], 2, 2).is_err(),
"partial row"
);
assert!(Index::new(vec![1.0, 0.0], 2, 2).is_err(), "count mismatch");
assert!(
Index::new(Vec::new(), 2, 0).is_ok(),
"an empty index is valid"
);
}
}