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}