diskann_quantization/multi_vector/distance/kernel.rs
1/*
2 * Copyright (c) Microsoft Corporation.
3 * Licensed under the MIT license.
4 */
5
6//! Object-safe kernel boundary trait plus BYOTE visitor trait.
7
8use crate::multi_vector::{MatRef, MaxSimError, Standard};
9
10/// Object-safe interface for computing per-query MaxSim scores.
11pub trait MaxSimKernel<T: Copy>: Send + Sync + std::fmt::Debug {
12 /// Number of query rows whose scores this kernel produces.
13 fn nrows(&self) -> usize;
14
15 /// Compute per-query MaxSim scores into `scores`. On zero docs, fills
16 /// every slot with `f32::MAX`.
17 ///
18 /// # Errors
19 ///
20 /// * [`MaxSimError::InvalidBufferLength`] if `scores.len() != self.nrows()`.
21 /// * [`MaxSimError::UnequalDim`] if `doc.vector_dim()` does not match the internal
22 /// vector dim.
23 fn compute_max_sim(
24 &self,
25 doc: MatRef<'_, Standard<T>>,
26 scores: &mut [f32],
27 ) -> Result<(), MaxSimError>;
28}
29
30/// "Bring your own type erasure" visitor: the factory hands a concrete
31/// kernel to [`Erase::erase`], which decides how to package it (e.g. as
32/// `Box<dyn MaxSimKernel<T>>` via [`BoxErase`], a chamfer-only closure, a
33/// batched evaluator, …).
34pub trait Erase<T: Copy> {
35 type Output;
36 /// `K` is generic so the body sees its concrete type and the compiler
37 /// can inline it.
38 fn erase<K: MaxSimKernel<T> + 'static>(self, kernel: K) -> Self::Output;
39}
40
41/// Default boxing [`Erase`] impl.
42#[derive(Debug, Clone, Copy)]
43pub struct BoxErase;
44
45impl<T: Copy + 'static> Erase<T> for BoxErase {
46 type Output = Box<dyn MaxSimKernel<T>>;
47
48 fn erase<K: MaxSimKernel<T> + 'static>(self, kernel: K) -> Self::Output {
49 Box::new(kernel)
50 }
51}