vector_lite/
vector.rs

1use std::hash::{Hash, Hasher};
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Vector<const N: usize>(Vec<f32>);
7
8impl<const N: usize> From<[f32; N]> for Vector<N> {
9    fn from(values: [f32; N]) -> Self {
10        Self(values.to_vec())
11    }
12}
13
14impl<const N: usize> Hash for Vector<N> {
15    fn hash<H: Hasher>(&self, state: &mut H) {
16        let bytes: &[u8] =
17            unsafe { std::slice::from_raw_parts(self.0.as_ptr() as *const u8, N * 4) };
18        bytes.hash(state);
19    }
20}
21
22impl<const N: usize> PartialEq for Vector<N> {
23    // Eq when the underlying memory is the same. Very strict.
24    fn eq(&self, other: &Self) -> bool {
25        let bytes_left: &[u8] =
26            unsafe { std::slice::from_raw_parts(self.0.as_ptr() as *const u8, N * 4) };
27        let bytes_right: &[u8] =
28            unsafe { std::slice::from_raw_parts(other.0.as_ptr() as *const u8, N * 4) };
29        bytes_left == bytes_right
30    }
31}
32
33impl<const N: usize> Eq for Vector<N> {}
34
35impl<const N: usize> Vector<N> {
36    /// Try to create a Vector from a `Vec<f32>`.
37    ///
38    /// # Arguments
39    ///
40    /// * `values` - The vector to create the Vector from, must be of size N.
41    ///
42    /// # Returns
43    ///
44    /// * `Ok(Vector<N>)` - The Vector created from the `Vec<f32>`.
45    /// * `Err(Vec<f32>)` - The `Vec<f32>` is not the correct size.
46    ///
47    /// # Examples
48    ///
49    /// ```rust
50    /// use vector_lite::Vector;
51    /// let vec = vec![1.0, 2.0, 3.0];
52    /// let vector: Vector<3> = Vector::try_from(vec).unwrap();
53    /// assert_eq!(vector.into_inner(), vec![1.0, 2.0, 3.0]);
54    /// ```
55    pub fn try_from(values: Vec<f32>) -> Result<Self, Vec<f32>> {
56        if values.len() != N {
57            Err(values)
58        } else {
59            Ok(Self(values))
60        }
61    }
62
63    /// Get the inner vector.
64    pub fn into_inner(self) -> Vec<f32> {
65        self.0
66    }
67
68    fn slice(&self) -> &[f32; N] {
69        // Convert the Vec<f32> slice to a fixed-size array reference
70        // This is safe because we know the Vector always has exactly N elements
71        unsafe { &*(self.0.as_ptr() as *const [f32; N]) }
72    }
73
74    pub(crate) fn subtract_from(&self, other: &Vector<N>) -> Vector<N> {
75        let vals = self
76            .slice()
77            .iter()
78            .zip(other.slice().iter())
79            .map(|(a, b)| a - b)
80            .collect::<Vec<_>>();
81        debug_assert_eq!(vals.capacity(), N);
82        Vector(vals)
83    }
84
85    pub(crate) fn memory_usage(&self) -> usize {
86        std::mem::size_of::<Self>() + self.0.len() * 4
87    }
88
89    #[cfg(test)]
90    pub(crate) fn add(&self, vector: &Vector<N>) -> Vector<N> {
91        let vals = self
92            .slice()
93            .iter()
94            .zip(vector.slice().iter())
95            .map(|(a, b)| a + b)
96            .collect::<Vec<_>>();
97        Vector(vals)
98    }
99
100    pub(crate) fn avg(&self, vector: &Vector<N>) -> Vector<N> {
101        let vals = self
102            .slice()
103            .iter()
104            .zip(vector.slice().iter())
105            .map(|(a, b)| (a + b) / 2.0)
106            .collect::<Vec<_>>();
107        Vector(vals)
108    }
109
110    pub(crate) fn dot_product(&self, vector: &Vector<N>) -> f32 {
111        self.slice()
112            .iter()
113            .zip(vector.slice().iter())
114            .map(|(a, b)| a * b)
115            .sum()
116    }
117
118    pub(crate) fn sq_euc_dist(&self, vector: &Vector<N>) -> f32 {
119        self.slice()
120            .iter()
121            .zip(vector.slice().iter())
122            .map(|(a, b)| (a - b).powi(2))
123            .sum()
124    }
125}