use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use crate::error::{LaurusError, Result};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Vector {
pub data: Vec<f32>,
}
impl Vector {
pub fn new(data: Vec<f32>) -> Self {
Self { data }
}
pub fn dimension(&self) -> usize {
self.data.len()
}
pub fn norm(&self) -> f32 {
self.data.iter().map(|x| x * x).sum::<f32>().sqrt()
}
pub fn normalize(&mut self) {
let norm = self.norm();
if norm > 0.0 {
for value in &mut self.data {
*value /= norm;
}
}
}
pub fn normalized(&self) -> Self {
let mut normalized = self.clone();
normalized.normalize();
normalized
}
pub fn validate_dimension(&self, expected_dim: usize) -> Result<()> {
if self.data.len() != expected_dim {
return Err(LaurusError::InvalidOperation(format!(
"Vector dimension mismatch: expected {}, got {}",
expected_dim,
self.data.len()
)));
}
Ok(())
}
pub fn is_valid(&self) -> bool {
self.data.iter().all(|x| x.is_finite())
}
pub fn norm_parallel(&self) -> f32 {
if self.data.len() > 10000 {
self.data.par_iter().map(|x| x * x).sum::<f32>().sqrt()
} else {
self.norm()
}
}
pub fn normalize_parallel(&mut self) {
let norm = self.norm_parallel();
if norm > 0.0 {
if self.data.len() > 10000 {
self.data.par_iter_mut().for_each(|value| *value /= norm);
} else {
for value in &mut self.data {
*value /= norm;
}
}
}
}
pub fn normalize_batch_parallel(vectors: &mut [Vector]) {
if vectors.len() > 10 {
vectors
.par_iter_mut()
.for_each(|vector| vector.normalize_parallel());
} else {
for vector in vectors {
vector.normalize();
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredVector {
pub data: Vec<f32>,
pub weight: f32,
}
impl StoredVector {
pub fn new(data: Vec<f32>) -> Self {
Self { data, weight: 1.0 }
}
pub fn with_weight(mut self, weight: f32) -> Self {
self.weight = weight;
self
}
pub fn dimension(&self) -> usize {
self.data.len()
}
pub fn to_vector(&self) -> Vector {
Vector {
data: self.data.clone(),
}
}
}
impl From<Vector> for StoredVector {
fn from(vector: Vector) -> Self {
Self {
data: vector.data,
weight: 1.0,
}
}
}