weavatrix-search-vector 0.3.1

Persistent, mutable, bounded vector candidate search for Rust and Weavatrix
Documentation
use crate::config::DistanceMetric;
use crate::error::SearchError;
use crate::simd::DistanceKernel;

#[allow(clippy::cast_possible_truncation)]
pub(crate) fn squared_norm(vector: &[f32], position: Option<usize>) -> Result<f32, SearchError> {
    let mut squared = 0.0_f64;
    for (dimension, value) in vector.iter().copied().enumerate() {
        if !value.is_finite() {
            return Err(SearchError::NonFiniteValue {
                vector: position,
                dimension,
            });
        }
        squared += f64::from(value) * f64::from(value);
    }
    Ok(squared as f32)
}

pub(crate) fn inverse_norm(vector: &[f32], position: Option<usize>) -> Result<f32, SearchError> {
    let squared = squared_norm(vector, position)?;
    if squared == 0.0 {
        return Err(SearchError::ZeroVector { vector: position });
    }
    Ok(squared.sqrt().recip())
}

pub(crate) fn distance(
    kernel: DistanceKernel,
    metric: DistanceMetric,
    left: &[f32],
    left_squared_norm: f32,
    right: &[f32],
    right_squared_norm: f32,
) -> f32 {
    let dot = kernel.dot(left, right);
    match metric {
        DistanceMetric::Cosine => {
            let denominator = (left_squared_norm * right_squared_norm).sqrt();
            (1.0 - dot / denominator).clamp(0.0, 2.0)
        }
        DistanceMetric::Dot => -dot,
        DistanceMetric::SquaredEuclidean => left_squared_norm
            .mul_add(1.0, right_squared_norm - 2.0 * dot)
            .max(0.0),
    }
}