mini_matrix/
vector.rs

1//! # mini_matrix
2//!
3//! A mini linear algebra library implemented in Rust.
4
5use num::{Float, Num, Signed};
6use std::fmt::Display;
7use std::iter::Sum;
8use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
9use std::ops::{Deref, DerefMut, Index, IndexMut};
10
11/// Represents a vector of `N` elements of type `T`.
12///
13/// # Examples
14///
15/// ```
16/// use mini_matrix::Vector;
17///
18/// let v = Vector::from([1, 2, 3]);
19/// assert_eq!(v[0], 1);
20/// assert_eq!(v[1], 2);
21/// assert_eq!(v[2], 3);
22/// ```
23#[derive(Debug, Clone, Copy)]
24pub struct Vector<T, const N: usize> {
25    pub store: [T; N],
26}
27
28impl<T, const N: usize> IndexMut<usize> for Vector<T, N> {
29    fn index_mut(&mut self, index: usize) -> &mut T {
30        &mut self.store[index]
31    }
32}
33
34impl<T, const N: usize> Index<usize> for Vector<T, N> {
35    type Output = T;
36
37    fn index(&self, index: usize) -> &Self::Output {
38        &self.store.index(index)
39    }
40}
41
42impl<T, const N: usize> Deref for Vector<T, N> {
43    type Target = [T; N];
44
45    fn deref(&self) -> &Self::Target {
46        &self.store
47    }
48}
49
50impl<T, const N: usize> DerefMut for Vector<T, N> {
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        &mut self.store
53    }
54}
55
56impl<T, const N: usize> PartialEq for Vector<T, N>
57where
58    T: PartialEq,
59{
60    fn eq(&self, other: &Self) -> bool {
61        self.store == other.store
62    }
63}
64
65impl<T, const N: usize> Eq for Vector<T, N> where T: Eq {}
66
67impl<T, const N: usize> Vector<T, N>
68where
69    T: Copy + Default,
70{
71    /// Creates a new `Vector` from an array of elements.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use mini_matrix::Vector;
77    ///
78    /// let v = Vector::from([1, 2, 3]);
79    /// ```
80    pub fn from(data: [T; N]) -> Self {
81        Self { store: data }
82    }
83
84    /// Returns the number of elements in the `Vector`.
85    ///
86    /// # Examples
87    ///
88    /// ```
89    /// use mini_matrix::Vector;
90    ///
91    /// let v: Vector<i32, 3> = Vector::from([1, 2, 3]);
92    /// assert_eq!(v.size(), 3);
93    /// ```
94    pub const fn size(&self) -> usize {
95        N
96    }
97
98    /// Creates a new `Vector` with all elements set to the default value of type `T`.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use mini_matrix::Vector;
104    ///
105    /// let v: Vector<i32, 3> = Vector::zero();
106    /// assert_eq!(v[0], 0);
107    /// assert_eq!(v[1], 0);
108    /// assert_eq!(v[2], 0);
109    /// ```
110    pub fn zero() -> Self {
111        Self {
112            store: [T::default(); N],
113        }
114    }
115}
116
117impl<T, const N: usize> Vector<T, N>
118where
119    T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Copy + Clone + Default,
120{
121    /// Adds another vector to this vector in-place.
122    ///
123    /// # Examples
124    ///
125    /// ```
126    /// use mini_matrix::Vector;
127    ///
128    /// let mut v1 = Vector::from([1, 2, 3]);
129    /// let v2 = Vector::from([4, 5, 6]);
130    /// v1.add(&v2);
131    /// assert_eq!(v1[0], 5);
132    /// assert_eq!(v1[1], 7);
133    /// assert_eq!(v1[2], 9);
134    /// ```
135    pub fn add(&mut self, rhs: &Self) {
136        for (lsh_e, rhs_e) in self.store.iter_mut().zip(rhs.store.iter()) {
137            *lsh_e = *lsh_e + *rhs_e;
138        }
139    }
140
141    /// Subtracts another vector from this vector in-place.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use mini_matrix::Vector;
147    ///
148    /// let mut v1 = Vector::from([4, 5, 6]);
149    /// let v2 = Vector::from([1, 2, 3]);
150    /// v1.sub(&v2);
151    /// assert_eq!(v1[0], 3);
152    /// assert_eq!(v1[1], 3);
153    /// assert_eq!(v1[2], 3);
154    /// ```
155    pub fn sub(&mut self, rhs: &Self) {
156        for (lsh_e, rhs_e) in self.store.iter_mut().zip(rhs.store.iter()) {
157            *lsh_e = *lsh_e - *rhs_e;
158        }
159    }
160
161    /// Multiplies this vector by a scalar value in-place.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use mini_matrix::Vector;
167    ///
168    /// let mut v = Vector::from([1, 2, 3]);
169    /// v.scl(2);
170    /// assert_eq!(v[0], 2);
171    /// assert_eq!(v[1], 4);
172    /// assert_eq!(v[2], 6);
173    /// ```
174    pub fn scl(&mut self, scalar: T) {
175        for elem in self.store.iter_mut() {
176            *elem = *elem * scalar;
177        }
178    }
179}
180
181impl<T, const N: usize> Vector<T, N>
182where
183    T: Num + Sum + Copy + Clone,
184{
185    /// Computes the dot product of two vectors.
186    ///
187    /// The dot product is the sum of the products of corresponding elements.
188    ///
189    /// # Examples
190    ///
191    /// ```
192    /// use mini_matrix::Vector;
193    ///
194    /// let v1 = Vector::from([1, 2, 3]);
195    /// let v2 = Vector::from([4, 5, 6]);
196    /// assert_eq!(v1.dot(&v2), 32); // 1*4 + 2*5 + 3*6 = 32
197    /// ```
198    pub fn dot(&self, v: &Self) -> T {
199        self.store
200            .iter()
201            .zip(v.store.iter())
202            .map(|(a, b)| *a * *b)
203            .sum()
204    }
205}
206
207impl<T, const N: usize> Add for Vector<T, N>
208where
209    T: Add<Output = T> + Default + Clone + Copy,
210{
211    type Output = Self;
212    /// Adds two vectors element-wise.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use mini_matrix::Vector;
218    ///
219    /// let v1 = Vector::from([1, 2, 3]);
220    /// let v2 = Vector::from([4, 5, 6]);
221    /// let v3 = v1 + v2;
222    /// assert_eq!(v3, Vector::from([5, 7, 9]));
223    /// ```
224    fn add(self, rhs: Self) -> Self::Output {
225        let mut result = self.clone();
226        for (e1, e2) in result.store.iter_mut().zip(rhs.store.iter()) {
227            *e1 = *e1 + *e2;
228        }
229        result
230    }
231}
232
233impl<T, const N: usize> AddAssign for Vector<T, N>
234where
235    T: Num + Default + Clone + Copy,
236{
237    /// Adds another vector to this vector in-place.
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// use mini_matrix::Vector;
243    ///
244    /// let mut v1 = Vector::from([1, 2, 3]);
245    /// let v2 = Vector::from([4, 5, 6]);
246    /// v1 += v2;
247    /// assert_eq!(v1, Vector::from([5, 7, 9]));
248    /// ```
249    fn add_assign(&mut self, rhs: Self) {
250        *self = *self + rhs;
251    }
252}
253
254impl<T, const N: usize> Sub for Vector<T, N>
255where
256    T: Sub<Output = T> + Default + Clone + Copy,
257{
258    type Output = Self;
259    /// Subtracts one vector from another element-wise.
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// use mini_matrix::Vector;
265    ///
266    /// let v1 = Vector::from([4, 5, 6]);
267    /// let v2 = Vector::from([1, 2, 3]);
268    /// let v3 = v1 - v2;
269    /// assert_eq!(v3, Vector::from([3, 3, 3]));
270    /// ```
271    fn sub(self, rhs: Self) -> Self::Output {
272        let mut result = self.clone();
273        for (e1, e2) in result.store.iter_mut().zip(rhs.store.iter()) {
274            *e1 = *e1 - *e2;
275        }
276        result
277    }
278}
279
280impl<T, const N: usize> SubAssign for Vector<T, N>
281where
282    T: Num + Default + Clone + Copy,
283{
284    /// Subtracts another vector from this vector in-place.
285    ///
286    /// # Examples
287    ///
288    /// ```
289    /// use mini_matrix::Vector;
290    ///
291    /// let mut v1 = Vector::from([4, 5, 6]);
292    /// let v2 = Vector::from([1, 2, 3]);
293    /// v1 -= v2;
294    /// assert_eq!(v1, Vector::from([3, 3, 3]));
295    /// ```
296    fn sub_assign(&mut self, rhs: Self) {
297        *self = *self - rhs;
298    }
299}
300
301impl<T, const N: usize> Mul<T> for Vector<T, N>
302where
303    T: Mul + Num + Copy,
304{
305    type Output = Self;
306    /// Multiplies a vector by a scalar.
307    ///
308    /// # Examples
309    ///
310    /// ```
311    /// use mini_matrix::Vector;
312    ///
313    /// let v1 = Vector::from([1.0, 2.0, 3.0]);
314    /// let v2 = v1 * 2.0;
315    /// assert_eq!(v2, Vector::from([2.0, 4.0, 6.0]));
316    /// ```
317    fn mul(self, scalar: T) -> Self::Output {
318        let mut result = self.clone();
319        for element in result.store.iter_mut() {
320            *element = element.clone() * scalar;
321        }
322        result
323    }
324}
325
326// Implement the Mul trait for Vector<T, N> with f32
327impl<T, const N: usize> Mul for Vector<T, N>
328where
329    T: Mul + Num + Sum + Copy,
330{
331    type Output = T;
332    /// Computes the dot product of two vectors.
333    ///
334    /// This is an alternative way to compute the dot product using the * operator.
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// use mini_matrix::Vector;
340    ///
341    /// let v1 = Vector::from([1, 2, 3]);
342    /// let v2 = Vector::from([4, 5, 6]);
343    /// assert_eq!(v1 * v2, 32); // 1*4 + 2*5 + 3*6 = 32
344    /// ```
345    fn mul(self, rhs: Self) -> Self::Output {
346        self.store
347            .into_iter()
348            .zip(rhs.store.into_iter())
349            .map(|(a, b)| a * b)
350            .sum()
351    }
352}
353
354// Implement the Neg trait for Vector<T, N>
355impl<T, const N: usize> Neg for Vector<T, N>
356where
357    T: Num + Copy + Signed,
358{
359    type Output = Self;
360    /// Negates a vector, inverting the sign of all its elements.
361    ///
362    /// # Examples
363    ///
364    /// ```
365    /// use mini_matrix::Vector;
366    ///
367    /// let v1 = Vector::from([1, -2, 3]);
368    /// let v2 = -v1;
369    /// assert_eq!(v2, Vector::from([-1, 2, -3]));
370    /// ```
371    fn neg(self) -> Self::Output {
372        let mut result = self.clone();
373        for element in result.store.iter_mut() {
374            *element = -(*element);
375        }
376        result
377    }
378}
379
380impl<T, const N: usize> Display for Vector<T, N>
381where
382    T: Display,
383{
384    /// Formats the vector for display.
385    ///
386    /// # Examples
387    ///
388    /// ```
389    /// use mini_matrix::Vector;
390    ///
391    /// let v = Vector::from([1.0, 2.5, 3.7]);
392    /// println!("{}", v); // Outputs: //-> [1.0, 2.5, 3.7]
393    /// ```
394    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
395        write!(f, "//-> [")?;
396        for (i, val) in self.store.iter().enumerate() {
397            if i > 0 {
398                write!(f, ", ")?;
399            }
400            write!(f, "{:.1}", val)?;
401        }
402        write!(f, "]\n")
403    }
404}
405
406/* *************** */
407/*      Norms      */
408/* *************** */
409impl<T, const N: usize> Vector<T, N>
410where
411    T: Float + Sum<T>,
412{
413    /// Calculates the L1 norm (Manhattan norm) of the vector.
414    ///
415    /// The L1 norm is the sum of the absolute values of the vector's components.
416    ///
417    /// # Returns
418    /// The L1 norm as a value of type `T`.
419    /// # Examples
420    /// ```
421    /// use mini_matrix::Vector;
422    /// let v = Vector::from([1.0, -2.0, 3.0]);
423    /// assert_eq!(v.norm_1(), 6.0);
424    /// ```
425    pub fn norm_1(&self) -> T {
426        self.store.iter().map(|x| x.abs()).sum()
427    }
428
429    /// Calculates the L2 norm (Euclidean norm) of the vector.
430    ///
431    /// The L2 norm is the square root of the sum of the squared components.
432    ///
433    /// # Returns
434    /// The L2 norm as a value of type `T`.
435    /// # Examples
436    /// ```
437    /// use mini_matrix::Vector;
438    /// let v = Vector::from([1.0, -2.0, 3.0]);
439    /// assert_eq!(v.norm(), [1.0 + 4.0 + 9.0].iter().sum::<f32>().sqrt());
440    /// ```
441    pub fn norm(&self) -> T {
442        self.store.iter().map(|x| x.powi(2)).sum::<T>().sqrt()
443    }
444
445    /// Calculates the L-infinity norm (maximum norm) of the vector.
446    ///
447    /// The L-infinity norm is the maximum of the absolute values of the vector's components.
448    ///
449    /// # Returns
450    /// The L-infinity norm as a value of type `T`.
451    /// # Examples
452    /// ```
453    /// use mini_matrix::Vector;
454    /// let v = Vector::from([1.0, -2.0, 3.0]);
455    /// assert_eq!(v.norm_inf(), 3.0);
456    /// ```
457    pub fn norm_inf(&self) -> T {
458        self.store
459            .iter()
460            .map(|x| x.abs())
461            .fold(T::zero(), |a, b| a.max(b))
462    }
463}