Skip to main content

linkrs_core/value/
vector.rs

1//! Vector Type Module
2//!
3//! This module provides vector types for efficient storage and manipulation of vector data.
4//! Vector types are essential for vector similarity search and embedding operations.
5
6use serde::{Deserialize, Serialize};
7use std::hash::Hash;
8
9/// Vector value type for efficient storage of numerical vectors
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub enum VectorValue {
12    /// Dense vector - most common, stores all values
13    Dense(Vec<f32>),
14    /// Sparse vector - stores only non-zero values with indices
15    Sparse { indices: Vec<u32>, values: Vec<f32> },
16}
17
18impl VectorValue {
19    /// Create a new dense vector
20    pub fn dense(data: Vec<f32>) -> Self {
21        VectorValue::Dense(data)
22    }
23
24    /// Create a new sparse vector
25    pub fn sparse(indices: Vec<u32>, values: Vec<f32>) -> Self {
26        VectorValue::Sparse { indices, values }
27    }
28
29    /// Get the dimension of the vector
30    pub fn dimension(&self) -> usize {
31        match self {
32            VectorValue::Dense(data) => data.len(),
33            VectorValue::Sparse { indices, .. } => {
34                indices.last().map(|i| *i as usize + 1).unwrap_or(0)
35            }
36        }
37    }
38
39    /// Get the number of non-zero elements
40    pub fn nnz(&self) -> usize {
41        match self {
42            VectorValue::Dense(data) => data.iter().filter(|&&x| x != 0.0).count(),
43            VectorValue::Sparse { values, .. } => values.len(),
44        }
45    }
46
47    /// Convert to dense vector (Vec<f32>)
48    pub fn into_dense(self) -> Option<Vec<f32>> {
49        match self {
50            VectorValue::Dense(data) => Some(data),
51            VectorValue::Sparse { .. } => None,
52        }
53    }
54
55    /// Get reference to dense vector data
56    pub fn as_dense(&self) -> Option<&[f32]> {
57        match self {
58            VectorValue::Dense(data) => Some(data),
59            VectorValue::Sparse { .. } => None,
60        }
61    }
62
63    /// Validate dimension matches expected value
64    pub fn validate_dimension(&self, expected: usize) -> Result<(), VectorError> {
65        let actual = self.dimension();
66        if actual != expected {
67            Err(VectorError::DimensionMismatch { expected, actual })
68        } else {
69            Ok(())
70        }
71    }
72
73    /// Check if this is a sparse vector
74    pub fn is_sparse(&self) -> bool {
75        matches!(self, VectorValue::Sparse { .. })
76    }
77
78    /// Check if this is a dense vector
79    pub fn is_dense(&self) -> bool {
80        matches!(self, VectorValue::Dense(_))
81    }
82
83    /// Convert sparse to dense representation
84    pub fn to_dense(&self) -> Vec<f32> {
85        match self {
86            VectorValue::Dense(data) => data.clone(),
87            VectorValue::Sparse { indices, values } => {
88                let dim = self.dimension();
89                let mut dense = vec![0.0f32; dim];
90                for (&idx, &val) in indices.iter().zip(values.iter()) {
91                    if idx < dim as u32 {
92                        dense[idx as usize] = val;
93                    }
94                }
95                dense
96            }
97        }
98    }
99
100    /// Estimate memory usage in bytes
101    pub fn estimated_size(&self) -> usize {
102        match self {
103            VectorValue::Dense(data) => {
104                std::mem::size_of::<Self>() + data.len() * std::mem::size_of::<f32>()
105            }
106            VectorValue::Sparse { indices, values } => {
107                std::mem::size_of::<Self>()
108                    + indices.len() * std::mem::size_of::<u32>()
109                    + values.len() * std::mem::size_of::<f32>()
110            }
111        }
112    }
113
114    /// Compute dot product with another vector
115    pub fn dot(&self, other: &VectorValue) -> Result<f32, VectorError> {
116        let dim = self.dimension();
117        if dim != other.dimension() {
118            return Err(VectorError::DimensionMismatch {
119                expected: dim,
120                actual: other.dimension(),
121            });
122        }
123
124        match (self, other) {
125            (VectorValue::Dense(a), VectorValue::Dense(b)) => {
126                Ok(a.iter().zip(b.iter()).map(|(&x, &y)| x * y).sum())
127            }
128            (
129                VectorValue::Sparse {
130                    indices: idx_a,
131                    values: val_a,
132                },
133                VectorValue::Sparse {
134                    indices: idx_b,
135                    values: val_b,
136                },
137            ) => {
138                // Sparse dot product - only multiply non-zero elements
139                let mut result = 0.0f32;
140                let mut i = 0;
141                let mut j = 0;
142                while i < idx_a.len() && j < idx_b.len() {
143                    if idx_a[i] == idx_b[j] {
144                        result += val_a[i] * val_b[j];
145                        i += 1;
146                        j += 1;
147                    } else if idx_a[i] < idx_b[j] {
148                        i += 1;
149                    } else {
150                        j += 1;
151                    }
152                }
153                Ok(result)
154            }
155            _ => {
156                // Mixed sparse/dense - convert sparse to dense
157                Ok(self
158                    .to_dense()
159                    .iter()
160                    .zip(other.to_dense().iter())
161                    .map(|(&x, &y)| x * y)
162                    .sum())
163            }
164        }
165    }
166
167    /// Compute L2 norm (Euclidean norm)
168    pub fn l2_norm(&self) -> f32 {
169        match self {
170            VectorValue::Dense(data) => data.iter().map(|&x| x * x).sum::<f32>().sqrt(),
171            VectorValue::Sparse { values, .. } => values.iter().map(|&x| x * x).sum::<f32>().sqrt(),
172        }
173    }
174
175    /// Compute cosine similarity with another vector
176    pub fn cosine_similarity(&self, other: &VectorValue) -> Result<f32, VectorError> {
177        let dot = self.dot(other)?;
178        let norm_self = self.l2_norm();
179        let norm_other = other.l2_norm();
180
181        if norm_self == 0.0 || norm_other == 0.0 {
182            return Ok(0.0);
183        }
184
185        Ok(dot / (norm_self * norm_other))
186    }
187}
188
189impl PartialEq for VectorValue {
190    fn eq(&self, other: &Self) -> bool {
191        match (self, other) {
192            (VectorValue::Dense(a), VectorValue::Dense(b)) => a == b,
193            (
194                VectorValue::Sparse {
195                    indices: idx_a,
196                    values: val_a,
197                },
198                VectorValue::Sparse {
199                    indices: idx_b,
200                    values: val_b,
201                },
202            ) => idx_a == idx_b && val_a == val_b,
203            _ => {
204                // Compare dense representations for mixed types
205                self.to_dense() == other.to_dense()
206            }
207        }
208    }
209}
210
211impl Eq for VectorValue {}
212
213impl Hash for VectorValue {
214    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
215        match self {
216            VectorValue::Dense(data) => {
217                "dense".hash(state);
218                // Hash f32 values by their bit representation
219                for &val in data {
220                    val.to_bits().hash(state);
221                }
222            }
223            VectorValue::Sparse { indices, values } => {
224                "sparse".hash(state);
225                indices.hash(state);
226                // Hash f32 values by their bit representation
227                for &val in values {
228                    val.to_bits().hash(state);
229                }
230            }
231        }
232    }
233}
234
235impl std::fmt::Display for VectorValue {
236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237        match self {
238            VectorValue::Dense(data) => {
239                write!(f, "[")?;
240                for (i, val) in data.iter().enumerate() {
241                    if i > 0 {
242                        write!(f, ", ")?;
243                    }
244                    write!(f, "{:.6}", val)?;
245                }
246                write!(f, "]")
247            }
248            VectorValue::Sparse { indices, values } => {
249                write!(f, "sparse[")?;
250                for (i, (&idx, &val)) in indices.iter().zip(values.iter()).enumerate() {
251                    if i > 0 {
252                        write!(f, ", ")?;
253                    }
254                    write!(f, "{}:{:.6}", idx, val)?;
255                }
256                write!(f, "]")
257            }
258        }
259    }
260}
261
262/// Vector error types
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub enum VectorError {
265    DimensionMismatch { expected: usize, actual: usize },
266    InvalidSparseIndices,
267    OutOfBounds { index: usize, dimension: usize },
268    InvalidOperation(String),
269}
270
271impl std::fmt::Display for VectorError {
272    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273        match self {
274            VectorError::DimensionMismatch { expected, actual } => {
275                write!(
276                    f,
277                    "Dimension mismatch: expected {}, got {}",
278                    expected, actual
279                )
280            }
281            VectorError::InvalidSparseIndices => {
282                write!(f, "Invalid sparse vector indices")
283            }
284            VectorError::OutOfBounds { index, dimension } => {
285                write!(
286                    f,
287                    "Index {} out of bounds for dimension {}",
288                    index, dimension
289                )
290            }
291            VectorError::InvalidOperation(op) => {
292                write!(f, "Invalid vector operation: {}", op)
293            }
294        }
295    }
296}
297
298impl std::error::Error for VectorError {}
299
300#[cfg(test)]
301mod tests {
302    use super::*;
303
304    #[test]
305    fn test_dense_vector_creation() {
306        let vec = VectorValue::dense(vec![1.0, 2.0, 3.0]);
307        assert_eq!(vec.dimension(), 3);
308        assert!(vec.is_dense());
309        assert!(!vec.is_sparse());
310    }
311
312    #[test]
313    fn test_sparse_vector_creation() {
314        let vec = VectorValue::sparse(vec![0, 2, 5], vec![1.0, 2.0, 3.0]);
315        assert_eq!(vec.dimension(), 6);
316        assert_eq!(vec.nnz(), 3);
317        assert!(vec.is_sparse());
318    }
319
320    #[test]
321    fn test_vector_dimension() {
322        let dense = VectorValue::dense(vec![1.0; 1536]);
323        assert_eq!(dense.dimension(), 1536);
324
325        let sparse = VectorValue::sparse(vec![0, 100, 1535], vec![1.0, 2.0, 3.0]);
326        assert_eq!(sparse.dimension(), 1536);
327    }
328
329    #[test]
330    fn test_vector_dot_product() {
331        let a = VectorValue::dense(vec![1.0, 2.0, 3.0]);
332        let b = VectorValue::dense(vec![4.0, 5.0, 6.0]);
333        let dot = a.dot(&b).unwrap();
334        assert!((dot - 32.0).abs() < 1e-6);
335    }
336
337    #[test]
338    fn test_vector_cosine_similarity() {
339        let a = VectorValue::dense(vec![1.0, 0.0, 0.0]);
340        let b = VectorValue::dense(vec![0.0, 1.0, 0.0]);
341        let similarity = a.cosine_similarity(&b).unwrap();
342        assert!(similarity.abs() < 1e-6);
343
344        let c = VectorValue::dense(vec![1.0, 0.0, 0.0]);
345        let similarity_same = a.cosine_similarity(&c).unwrap();
346        assert!((similarity_same - 1.0).abs() < 1e-6);
347    }
348
349    #[test]
350    fn test_vector_to_dense() {
351        let sparse = VectorValue::sparse(vec![0, 2], vec![1.0, 3.0]);
352        let dense = sparse.to_dense();
353        assert_eq!(dense, vec![1.0, 0.0, 3.0]);
354    }
355
356    #[test]
357    fn test_vector_equality() {
358        let a = VectorValue::dense(vec![1.0, 2.0, 3.0]);
359        let b = VectorValue::dense(vec![1.0, 2.0, 3.0]);
360        assert_eq!(a, b);
361
362        let sparse_a = VectorValue::sparse(vec![0, 2], vec![1.0, 3.0]);
363        let sparse_b = VectorValue::sparse(vec![0, 2], vec![1.0, 3.0]);
364        assert_eq!(sparse_a, sparse_b);
365    }
366
367    #[test]
368    fn test_vector_memory_usage() {
369        let dense = VectorValue::dense(vec![1.0; 1000]);
370        let size = dense.estimated_size();
371        assert!(size > 0);
372        assert!(size < 10000); // Should be around 4KB + overhead
373    }
374}