Skip to main content

construct/memory/
vector.rs

1//! Vector operations — minimal stubs retained for active callers.
2//!
3//! The full hybrid merge and serialization code has been removed.
4//! Only `cosine_similarity` is kept as it is used by `skills/creator.rs`.
5
6/// Cosine similarity between two vectors. Returns 0.0-1.0.
7pub fn cosine_similarity(a: &[f32], b: &[f32]) -> f32 {
8    if a.len() != b.len() || a.is_empty() {
9        return 0.0;
10    }
11
12    let mut dot = 0.0_f64;
13    let mut norm_a = 0.0_f64;
14    let mut norm_b = 0.0_f64;
15
16    for (x, y) in a.iter().zip(b.iter()) {
17        let x = f64::from(*x);
18        let y = f64::from(*y);
19        dot += x * y;
20        norm_a += x * x;
21        norm_b += y * y;
22    }
23
24    let denom = norm_a.sqrt() * norm_b.sqrt();
25    if !denom.is_finite() || denom < f64::EPSILON {
26        return 0.0;
27    }
28
29    let raw = dot / denom;
30    if !raw.is_finite() {
31        return 0.0;
32    }
33
34    // Clamp to [0, 1] -- embeddings are typically positive
35    #[allow(clippy::cast_possible_truncation)]
36    let sim = raw.clamp(0.0, 1.0) as f32;
37    sim
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn cosine_identical_vectors() {
46        let v = vec![1.0, 2.0, 3.0];
47        let sim = cosine_similarity(&v, &v);
48        assert!((sim - 1.0).abs() < 0.001);
49    }
50
51    #[test]
52    fn cosine_orthogonal_vectors() {
53        let a = vec![1.0, 0.0, 0.0];
54        let b = vec![0.0, 1.0, 0.0];
55        let sim = cosine_similarity(&a, &b);
56        assert!(sim.abs() < 0.001);
57    }
58
59    #[test]
60    fn cosine_empty_returns_zero() {
61        assert_eq!(cosine_similarity(&[], &[]), 0.0);
62    }
63}