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 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 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 pub fn into_inner(self) -> Vec<f32> {
65 self.0
66 }
67
68 fn slice(&self) -> &[f32; N] {
69 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}