1use serde::{Deserialize, Serialize};
7use std::hash::Hash;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub enum VectorValue {
12 Dense(Vec<f32>),
14 Sparse { indices: Vec<u32>, values: Vec<f32> },
16}
17
18impl VectorValue {
19 pub fn dense(data: Vec<f32>) -> Self {
21 VectorValue::Dense(data)
22 }
23
24 pub fn sparse(indices: Vec<u32>, values: Vec<f32>) -> Self {
26 VectorValue::Sparse { indices, values }
27 }
28
29 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 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 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 pub fn as_dense(&self) -> Option<&[f32]> {
57 match self {
58 VectorValue::Dense(data) => Some(data),
59 VectorValue::Sparse { .. } => None,
60 }
61 }
62
63 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 pub fn is_sparse(&self) -> bool {
75 matches!(self, VectorValue::Sparse { .. })
76 }
77
78 pub fn is_dense(&self) -> bool {
80 matches!(self, VectorValue::Dense(_))
81 }
82
83 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 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 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 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 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 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 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 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 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 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#[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); }
374}