vector_victor/lib.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5extern crate core;
6
7use index::MatrixIndex;
8use itertools::Itertools;
9use num_traits::{Bounded, One, Zero};
10use std::cmp::min;
11use std::fmt::Debug;
12use std::iter::{zip, Flatten};
13use std::ops::{Index, IndexMut};
14
15pub mod decompose;
16pub mod index;
17mod math;
18mod ops;
19
20mod swizzle;
21mod util;
22
23/** A 2D array of values which can be operated upon.
24
25Matrices have a fixed size known at compile time */
26#[derive(Debug, Copy, Clone, PartialEq)]
27pub struct Matrix<T, const M: usize, const N: usize>
28where
29 T: Copy,
30{
31 data: [[T; N]; M], // Row-Major order
32}
33
34/// An alias for a [Matrix] with a single column
35pub type Vector<T, const N: usize> = Matrix<T, N, 1>;
36
37// CONSTRUCTORS
38
39// Default
40impl<T: Copy + Default, const M: usize, const N: usize> Default for Matrix<T, M, N> {
41 fn default() -> Self {
42 Matrix::fill(T::default())
43 }
44}
45
46// Zero
47impl<T: Copy + Zero, const M: usize, const N: usize> Zero for Matrix<T, M, N> {
48 fn zero() -> Self {
49 Matrix::fill(T::zero())
50 }
51
52 fn is_zero(&self) -> bool {
53 self.elements().all(|e| e.is_zero())
54 }
55}
56
57// One
58impl<T: Copy + One, const M: usize, const N: usize> One for Matrix<T, M, N> {
59 fn one() -> Self {
60 Matrix::fill(T::one())
61 }
62}
63
64// min_value and max_value
65// LowerBounded and UpperBounded are automatically implemented from this
66impl<T: Copy + Bounded, const N: usize, const M: usize> Bounded for Matrix<T, N, M> {
67 fn min_value() -> Self {
68 Self::fill(T::min_value())
69 }
70
71 fn max_value() -> Self {
72 Self::fill(T::max_value())
73 }
74}
75
76// Identity
77impl<T: Copy + Zero + One, const N: usize> Matrix<T, N, N> {
78 /** Create an identity matrix, a square matrix where the diagonals are 1 and
79 all other elements are 0.
80
81 for example,
82
83 $bbI = \[\[1,0,0],\[0,1,0],\[0,0,1]]$
84
85 Matrix multiplication between a matrix and the identity matrix always results in itself
86
87 $bbA xx bbI = bbA$
88
89 # Examples
90 ```
91 # use vector_victor::Matrix;
92 let i = Matrix::<i32,3,3>::identity();
93 assert_eq!(i, Matrix::mat([[1, 0, 0],
94 [0, 1, 0],
95 [0, 0, 1]]))
96 ```
97
98 Note that the identity only exists for matrices that are square, so this doesnt work:
99 ```compile_fail
100 # use vector_victor::Matrix;
101 let i = Matrix::<i32,4,2>::identity();
102 ``` */
103 #[must_use]
104 pub fn identity() -> Self {
105 let mut result = Self::zero();
106 for i in 0..N {
107 result[(i, i)] = T::one();
108 }
109 return result;
110 }
111}
112
113// Matrix constructors
114impl<T: Copy, const M: usize, const N: usize> Matrix<T, M, N> {
115 /** Generate a new matrix from a 2D Array
116
117 # Arguments
118
119 * `data`: A 2D array of elements to copy into the new matrix
120
121 # Examples
122
123 ```
124 # use vector_victor::Matrix;
125 let a = Matrix::mat([[1,2,3,4];4]);
126 ``` */
127 #[must_use]
128 pub fn mat(data: [[T; N]; M]) -> Self {
129 assert!(M > 0, "Matrix must have at least 1 row");
130 assert!(N > 0, "Matrix must have at least 1 column");
131 Matrix::<T, M, N> { data }
132 }
133
134 /** Generate a new matrix from a single scalar
135
136 # Arguments
137
138 * `scalar`: Scalar value to copy into the new matrix.
139
140 # Examples
141
142 ```
143 # use vector_victor::Matrix;
144 // these are equivalent
145 assert_eq!(Matrix::<i32,4,4>::fill(5), Matrix::mat([[5;4];4]))
146 ``` */
147 #[must_use]
148 pub fn fill(scalar: T) -> Matrix<T, M, N> {
149 assert!(M > 0, "Matrix must have at least 1 row");
150 assert!(N > 0, "Matrix must have at least 1 column");
151 Matrix::<T, M, N> {
152 data: [[scalar; N]; M],
153 }
154 }
155
156 /** Create a matrix from an iterator of vectors
157
158 # Arguments
159
160 * `iter`: iterator of vectors to copy into rows
161
162 # Examples
163
164 The following is another way of performing [`Matrix::transpose()`]
165 ```
166 # use vector_victor::Matrix;
167 let my_matrix = Matrix::mat([[1, 2, 3],
168 [4, 5, 6]]);
169
170 let transpose : Matrix<_,3,2>= Matrix::from_rows(my_matrix.cols());
171
172 assert_eq!(transpose, Matrix::mat([[1, 4],
173 [2, 5],
174 [3, 6]]))
175 ``` */
176 #[must_use]
177 pub fn from_rows<I>(iter: I) -> Self
178 where
179 I: IntoIterator<Item = Vector<T, N>>,
180 Self: Default,
181 {
182 let mut result = Self::default();
183 for (m, row) in iter.into_iter().enumerate().take(M) {
184 result.set_row(m, &row)
185 }
186 result
187 }
188
189 /** Create a matrix from an iterator of vectors
190
191 # Arguments
192
193 * `iter`: iterator of vectors to copy into columns
194
195 # Examples
196
197 The following is another way of performing [`Matrix::transpose()`]
198 ```
199 # use vector_victor::Matrix;
200 let my_matrix = Matrix::mat([[1, 2, 3],
201 [4, 5, 6]]);
202
203 let transpose : Matrix<_,3,2>= Matrix::from_cols(my_matrix.rows());
204
205 assert_eq!(transpose, Matrix::mat([[1, 4],
206 [2, 5],
207 [3, 6]]))
208 ``` */
209 #[must_use]
210 pub fn from_cols<I>(iter: I) -> Self
211 where
212 I: IntoIterator<Item = Vector<T, M>>,
213 Self: Default,
214 {
215 let mut result = Self::default();
216 for (n, col) in iter.into_iter().enumerate().take(N) {
217 result.set_col(n, &col)
218 }
219 result
220 }
221}
222
223// Vector constructor
224impl<T: Copy, const N: usize> Vector<T, N> {
225 /** Create a vector from a 1D array.
226 Note that vectors are always column vectors unless explicitly instantiated as row vectors
227
228 # Examples
229 ```
230 # use vector_victor::{Matrix, Vector};
231 // these are equivalent
232 assert_eq!(Vector::vec([1,2,3,4]), Matrix::mat([[1],[2],[3],[4]]));
233 ``` */
234 pub fn vec(data: [T; N]) -> Self {
235 assert!(N > 0, "Vector must have at least 1 element");
236 return Vector::<T, N> {
237 data: data.map(|e| [e]),
238 };
239 }
240}
241
242// ACCESSORS AND MUTATORS
243impl<T: Copy, const M: usize, const N: usize> Matrix<T, M, N> {
244 /** Returns an iterator over the elements of the matrix in row-major order.
245
246 This is identical to the behavior of [`IntoIterator`](#associatedtype.IntoIter)
247
248 # Examples
249 ```
250 # use vector_victor::Matrix;
251 let my_matrix = Matrix::mat([[1, 2],
252 [3, 4]]);
253
254 itertools::assert_equal(my_matrix.elements(), [1,2,3,4].iter())
255 ``` */
256 #[must_use]
257 pub fn elements<'s>(&'s self) -> impl Iterator<Item = &'s T> + 's {
258 self.data.iter().flatten()
259 }
260
261 /** Returns a mutable iterator over the elements of the matrix in row-major order.
262
263 # Examples
264 ```
265 # use vector_victor::Matrix;
266 let mut my_matrix = Matrix::mat([[1, 2],
267 [3, 4]]);
268
269 for elem in my_matrix.elements_mut() {*elem += 2;}
270 itertools::assert_equal(my_matrix.elements(), [3,4,5,6].iter())
271 ``` */
272 #[must_use]
273 pub fn elements_mut<'s>(&'s mut self) -> impl Iterator<Item = &'s mut T> + 's {
274 self.data.iter_mut().flatten()
275 }
276
277 /** returns an iterator over the elements along the diagonal of a matrix
278
279 # Examples
280 ```
281 # use vector_victor::Matrix;
282 let my_matrix = Matrix::mat([[1, 2, 3],
283 [4, 5, 6],
284 [7, 8, 9],
285 [10,11,12]]);
286
287 itertools::assert_equal(my_matrix.diagonals(), [1,5,9].iter())
288 ``` */
289 #[must_use]
290 pub fn diagonals<'s>(&'s self) -> impl Iterator<Item = &'s T> + 's {
291 (0..min(N, M)).map(|n| &self[(n, n)])
292 }
293
294 /** Returns an iterator over the elements directly below the diagonal of a matrix
295
296 # Examples
297 ```
298 # use vector_victor::Matrix;
299 let my_matrix = Matrix::mat([[1, 2, 3],
300 [4, 5, 6],
301 [7, 8, 9],
302 [10,11,12]]);
303
304 itertools::assert_equal(my_matrix.subdiagonals(), [4,8,12].iter());
305 ``` */
306 #[must_use]
307 pub fn subdiagonals<'s>(&'s self) -> impl Iterator<Item = &'s T> + 's {
308 (0..min(N, M - 1)).map(|n| &self[(n + 1, n)])
309 }
310
311 /** Returns a reference to the element at that position in the matrix, or `None` if out of bounds.
312
313 [`Index`](#impl-Index%3CI%3E-for-Matrix%3CT,+M,+N%3E) behaves similarly,
314 but will panic if the index is out of bounds instead of returning an option
315
316 # Arguments
317
318 * `index`: a 1D or 2D index into the matrix. See [MatrixIndex] for more information on matrix indexing.
319
320 # Examples
321
322 ```
323 # use vector_victor::Matrix;
324 let my_matrix = Matrix::mat([[1, 2],
325 [3, 4]]);
326
327 // element at index 2 is the same as the element at row 1, column 0.
328 assert_eq!(my_matrix.get(2), my_matrix.get((1,0)));
329
330 // my_matrix.get() is equivalent to my_matrix[],
331 // but returns an Option instead of panicking
332 assert_eq!(my_matrix.get(2), Some(&my_matrix[2]));
333
334 // index 4 is out of range, so get(4) returns None.
335 assert_eq!(my_matrix.get(4), None);
336 ``` */
337 #[inline]
338 #[must_use]
339 pub fn get(&self, index: impl MatrixIndex) -> Option<&T> {
340 let (m, n) = index.to_2d(M, N)?;
341 Some(&self.data[m][n])
342 }
343
344 /** Returns a mutable reference to the element at that position in the matrix,
345 or `None` if out of bounds.
346
347 [`IndexMut`](#impl-IndexMut%3CI%3E-for-Matrix%3CT,+M,+N%3E) behaves similarly,
348 but will panic if the index is out of bounds instead of returning an option
349
350 # Arguments
351
352 * `index`: a 1D or 2D index into the matrix. See [MatrixIndex] for more information
353 on matrix indexing.
354
355 # Examples
356
357 ```
358 # use vector_victor::Matrix;
359 let mut my_matrix = Matrix::mat([[1, 2],
360 [3, 4]]);
361
362 match my_matrix.get_mut(2) {
363 Some(t) => *t = 5,
364 None => panic!()};
365 assert_eq!(my_matrix, Matrix::mat([[1,2],[5,4]]))
366 ``` */
367 #[inline]
368 #[must_use]
369 pub fn get_mut(&mut self, index: impl MatrixIndex) -> Option<&mut T> {
370 let (m, n) = index.to_2d(M, N)?;
371 Some(&mut self.data[m][n])
372 }
373
374 /** Returns a row of the matrix.
375
376 # Panics
377
378 Panics if row index `m` is out of bounds.
379
380 # Examples
381
382 ```
383 # use vector_victor::{Matrix, Vector};
384 let my_matrix = Matrix::mat([[1, 2],
385 [3, 4]]);
386
387 // row at index 1
388 assert_eq!(my_matrix.row(1), Vector::vec([3,4]));
389 ``` */
390 #[inline]
391 #[must_use]
392 pub fn row(&self, m: usize) -> Vector<T, N> {
393 assert!(
394 m < M,
395 "Row index {} out of bounds for {}×{} matrix",
396 m,
397 M,
398 N
399 );
400 Vector::<T, N>::vec(self.data[m])
401 }
402
403 /** Sets a row of the matrix.
404
405 # Panics
406
407 Panics if row index `m` is out of bounds.
408
409 # Examples
410
411 ```
412 # use vector_victor::{Matrix, Vector};
413 let mut my_matrix = Matrix::mat([[1, 2],
414 [3, 4]]);
415 // row at index 1
416 my_matrix.set_row(1, &Vector::vec([5,6]));
417 assert_eq!(my_matrix, Matrix::mat([[1,2],[5,6]]));
418 ``` */
419 #[inline]
420 pub fn set_row(&mut self, m: usize, val: &Vector<T, N>) {
421 assert!(
422 m < M,
423 "Row index {} out of bounds for {}×{} matrix",
424 m,
425 M,
426 N
427 );
428 for n in 0..N {
429 self.data[m][n] = val.data[n][0];
430 }
431 }
432
433 /** Returns a column of the matrix.
434
435 # Panics
436
437 Panics if column index `n` is out of bounds.
438
439 # Examples
440
441 ```
442 # use vector_victor::{Matrix, Vector};
443 let my_matrix = Matrix::mat([[1, 2],
444 [3, 4]]);
445
446 // column at index 1
447 assert_eq!(my_matrix.col(1), Vector::vec([2,4]));
448 ``` */
449 #[inline]
450 #[must_use]
451 pub fn col(&self, n: usize) -> Vector<T, M> {
452 assert!(
453 n < N,
454 "Column index {} out of bounds for {}×{} matrix",
455 n,
456 M,
457 N
458 );
459 Vector::<T, M>::vec(self.data.map(|r| r[n]))
460 }
461
462 /** Sets a column of the matrix.
463
464 # Panics
465
466 Panics if column index `n` is out of bounds.
467
468 # Examples
469
470 ```
471 # use vector_victor::{Matrix, Vector};
472 let mut my_matrix = Matrix::mat([[1, 2],
473 [3, 4]]);
474 // column at index 1
475 my_matrix.set_col(1, &Vector::vec([5,6]));
476 assert_eq!(my_matrix, Matrix::mat([[1,5],[3,6]]));
477 ``` */
478 #[inline]
479 pub fn set_col(&mut self, n: usize, val: &Vector<T, M>) {
480 assert!(
481 n < N,
482 "Column index {} out of bounds for {}×{} matrix",
483 n,
484 M,
485 N
486 );
487
488 for m in 0..M {
489 self.data[m][n] = val.data[m][0];
490 }
491 }
492
493 /// Returns an iterator over the rows of the matrix, returning them as column vectors.
494 #[must_use]
495 pub fn rows<'a>(&'a self) -> impl Iterator<Item = Vector<T, N>> + 'a {
496 (0..M).map(|m| self.row(m))
497 }
498
499 /// Returns an iterator over the columns of the matrix, returning them as column vectors.
500 #[must_use]
501 pub fn cols<'a>(&'a self) -> impl Iterator<Item = Vector<T, M>> + 'a {
502 (0..N).map(|n| self.col(n))
503 }
504
505 /** Interchange two rows
506
507 # Panics
508
509 Panics if row index `m1` or `m2` are out of bounds */
510 pub fn pivot_row(&mut self, m1: usize, m2: usize) {
511 let tmp = self.row(m2);
512 self.set_row(m2, &self.row(m1));
513 self.set_row(m1, &tmp);
514 }
515
516 /** Interchange two columns
517
518 # Panics
519
520 Panics if column index `n1` or `n2` are out of bounds */
521 pub fn pivot_col(&mut self, n1: usize, n2: usize) {
522 let tmp = self.col(n2);
523 self.set_col(n2, &self.col(n1));
524 self.set_col(n1, &tmp);
525 }
526
527 /** Apply a permutation matrix to the rows of a matrix
528
529 # Arguments
530
531 * `ms`: a [`Vector`] of [`usize`] of length P. Each entry is the index of the row that will
532 appear in the result
533
534 Returns: a P×N matrix
535
536 # Panics
537
538 Panics if any of the row indices in `ms` is out of bounds
539
540 # Examples
541
542 ```
543 # use vector_victor::{Matrix, Vector};
544 let my_matrix = Matrix::mat([[1, 2, 3],
545 [4, 5, 6],
546 [7, 8, 9]]);
547
548 let permuted = my_matrix.permute_rows(&Vector::vec([1, 0, 2]));
549 assert_eq!(permuted, Matrix::mat([[4, 5, 6],
550 [1, 2, 3],
551 [7, 8, 9]]))
552 ``` */
553 #[must_use]
554 pub fn permute_rows<const P: usize>(&self, ms: &Vector<usize, P>) -> Matrix<T, P, N>
555 where
556 T: Default,
557 {
558 Matrix::<T, P, N>::from_rows(ms.elements().map(|&m| self.row(m)))
559 }
560
561 /** Apply a permutation matrix to the columns of a matrix
562
563 # Arguments
564
565 * `ns`: a [`Vector`] of [`usize`] of length P. Each entry is the index of the column that will
566 appear in the result
567
568 Returns: a P×N matrix
569
570 # Panics
571
572 Panics if any of the column indices in `ns` is out of bounds */
573 #[must_use]
574 pub fn permute_cols<const P: usize>(&self, ns: &Vector<usize, P>) -> Matrix<T, M, P>
575 where
576 T: Default,
577 {
578 Matrix::<T, M, P>::from_cols(ns.elements().map(|&n| self.col(n)))
579 }
580
581 /** Returns the transpose $M^T$ of the matrix, or the matrix flipped across its diagonal.
582
583 # Examples
584 ```
585 # use vector_victor::Matrix;
586 let my_matrix = Matrix::mat([[1, 2, 3],
587 [4, 5, 6]]);
588
589 assert_eq!(
590 my_matrix.transpose(),
591 Matrix::mat([[1, 4],
592 [2, 5],
593 [3, 6]]))
594 ``` */
595 pub fn transpose(&self) -> Matrix<T, N, M>
596 where
597 Matrix<T, N, M>: Default,
598 {
599 Matrix::<T, N, M>::from_rows(self.cols())
600 }
601}
602
603// Index
604impl<I, T, const M: usize, const N: usize> Index<I> for Matrix<T, M, N>
605where
606 I: MatrixIndex,
607 T: Copy,
608{
609 type Output = T;
610
611 #[inline(always)]
612 fn index(&self, index: I) -> &Self::Output {
613 self.get(index).expect(&*format!(
614 "index {:?} out of range for {}×{} Matrix",
615 index, M, N
616 ))
617 }
618}
619
620// IndexMut
621impl<I, T, const M: usize, const N: usize> IndexMut<I> for Matrix<T, M, N>
622where
623 I: MatrixIndex,
624 T: Copy,
625{
626 #[inline(always)]
627 fn index_mut(&mut self, index: I) -> &mut Self::Output {
628 self.get_mut(index).expect(&*format!(
629 "index {:?} out of range for {}×{} Matrix",
630 index, M, N
631 ))
632 }
633}
634
635// CONVERSIONS
636
637// Convert from 2D Array (equivalent to new)
638impl<T: Copy, const M: usize, const N: usize> From<[[T; N]; M]> for Matrix<T, M, N> {
639 fn from(data: [[T; N]; M]) -> Self {
640 Self::mat(data)
641 }
642}
643
644// Convert from 1D Array (equivalent to vec)
645impl<T: Copy, const M: usize> From<[T; M]> for Vector<T, M> {
646 fn from(data: [T; M]) -> Self {
647 Self::vec(data)
648 }
649}
650
651// Convert from scalar (equivalent to fill)
652impl<T: Copy, const M: usize, const N: usize> From<T> for Matrix<T, M, N> {
653 fn from(scalar: T) -> Self {
654 Self::fill(scalar)
655 }
656}
657
658// Convert to 2D Array
659impl<T: Copy + Debug, const M: usize, const N: usize> Into<[[T; N]; M]> for Matrix<T, M, N> {
660 fn into(self) -> [[T; N]; M] {
661 self.rows()
662 .map(|row| row.into())
663 .collect_vec()
664 .try_into()
665 .unwrap()
666 }
667}
668
669// convert to 1D Array
670impl<T: Copy + Debug, const M: usize> Into<[T; M]> for Vector<T, M> {
671 fn into(self) -> [T; M] {
672 self.elements().cloned().collect_vec().try_into().unwrap()
673 }
674}
675
676// IntoIter
677impl<T: Copy, const M: usize, const N: usize> IntoIterator for Matrix<T, M, N> {
678 type Item = T;
679 type IntoIter = Flatten<std::array::IntoIter<[T; N], M>>;
680
681 fn into_iter(self) -> Self::IntoIter {
682 self.data.into_iter().flatten()
683 }
684}
685
686// FromIterator
687impl<T: Copy, const M: usize, const N: usize> FromIterator<T> for Matrix<T, M, N>
688where
689 Self: Default,
690{
691 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
692 let mut result: Self = Default::default();
693 for (l, r) in zip(result.elements_mut(), iter) {
694 *l = r;
695 }
696 result
697 }
698}