1#![warn(clippy::all, clippy::pedantic)]
2
3use std::{
4 iter::Sum,
5 ops::{Add, Index, IndexMut, Mul, Sub},
6};
7
8use crate::{
9 errors::{MatrixOperationError, NewMatrixError},
10 identities::Identity,
11 math::arr_dot,
12 position::Position,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq)]
18pub struct Matrix<T, const M: usize, const N: usize, const LEN: usize> {
19 data: [T; LEN],
20}
21
22impl<T, const M: usize, const N: usize, const LEN: usize> Matrix<T, M, N, LEN> {
23 pub fn new(data: [T; LEN]) -> Result<Self, NewMatrixError> {
35 if M * N != LEN {
36 return Err(NewMatrixError::IllegalGenerics);
37 }
38 Ok(Matrix { data })
39 }
40
41 #[must_use]
48 pub fn as_flat_array(&self) -> &[T; LEN] {
49 &self.data
50 }
51
52 #[must_use]
54 #[allow(clippy::unused_self)] pub fn rows(&self) -> usize {
56 M
57 }
58
59 #[must_use]
61 #[allow(clippy::unused_self)] pub fn cols(&self) -> usize {
63 N
64 }
65
66 #[must_use]
68 #[allow(clippy::unused_self)] pub fn vol(&self) -> usize {
70 LEN
71 }
72
73 pub fn iter(&self) -> Iter<T, M, N, LEN> {
75 Iter {
76 data: &self.data,
77 i: 0,
78 }
79 }
80
81 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
84 self.data.iter_mut()
85 }
86
87 pub fn into_iter_row(self) -> IntoIterRow<T, M, N, LEN> {
89 IntoIterRow {
90 i: 0,
91 data: self.data,
92 }
93 }
94
95 pub fn iter_row(&self) -> IterRow<'_, T, M, N, LEN> {
97 IterRow {
98 i: 0,
99 data: &self.data,
100 }
101 }
102
103 #[allow(clippy::unused_self)]
106 pub fn iter_row_mut(&mut self) {
107 unimplemented!();
108 }
109
110 pub fn into_iter_col(self) -> IntoIterCol<T, M, N, LEN> {
112 IntoIterCol {
113 i: 0,
114 data: self.data,
115 }
116 }
117
118 pub fn iter_col(&self) -> IterCol<'_, T, M, N, LEN> {
120 IterCol {
121 i: 0,
122 data: &self.data,
123 }
124 }
125
126 #[allow(clippy::unused_self)]
129 pub fn iter_col_mut(&mut self) {
130 unimplemented!();
131 }
132}
133
134impl<T, const M: usize, const N: usize, const LEN: usize> Matrix<T, M, N, LEN>
135where
136 T: Default + Copy,
137{
138 pub fn empty() -> Result<Self, NewMatrixError> {
148 Self::new([Default::default(); LEN])
149 }
150
151 #[allow(clippy::missing_errors_doc)] pub fn from_rows(data: [[T; N]; M]) -> Result<Self, NewMatrixError> {
155 let mut flat_data: [T; LEN] = [Default::default(); LEN];
156 let mut i: usize = 0;
157 for row in data {
158 for elem in row {
159 flat_data[i] = elem;
160 i += 1;
161 }
162 }
163 Self::new(flat_data)
164 }
165
166 #[must_use]
181 pub fn get_row(&self, row: usize) -> Matrix<T, N, 1, N> {
182 let mut output = Matrix::empty().unwrap();
183 for i in 0..N {
184 output.data[i] = self.data[row * N + i];
185 }
186 output
187 }
188
189 #[must_use]
204 pub fn get_col(&self, col: usize) -> Matrix<T, M, 1, M> {
205 let mut output = Matrix::empty().unwrap();
206 for row in 0..M {
207 output.data[row] = self[[row, col]];
208 }
209 output
210 }
211}
212
213impl<T, const M: usize, const N: usize, const LEN: usize> Matrix<T, M, N, LEN>
214where
215 T: Default + Copy + Mul + Sum<<T as Mul>::Output>,
216{
217 pub fn multiply<const O: usize, const Q: usize, const RES_LEN: usize>(
239 &self,
240 other: &Matrix<T, N, O, Q>,
241 ) -> Matrix<T, M, O, RES_LEN> {
242 let mut out: Matrix<T, M, O, RES_LEN> = Matrix::empty().unwrap();
243
244 for row in 0..N {
245 for col in 0..O {
246 out[[row, col]] = self.get_row(row).dot(&other.get_col(col));
247 }
248 }
249
250 out
251 }
252}
253
254impl<T, const M: usize, const N: usize, const LEN: usize> Matrix<T, M, N, LEN>
255where
256 T: Default + Copy + Mul<Output = T>,
257{
258 #[must_use]
274 pub fn mul_scalar(&self, scalar: T) -> Self {
275 let mut out = Matrix::empty().unwrap();
276 for i in 0..LEN {
277 out.data[i] = self.data[i] * scalar;
278 }
279 out
280 }
281}
282
283impl<T, const M: usize, const N: usize, const LEN: usize> Index<Position> for Matrix<T, M, N, LEN> {
284 type Output = T;
285 fn index(&self, pos: Position) -> &Self::Output {
286 &self.data[pos.0 * N + pos.1]
287 }
288}
289
290impl<T, const M: usize, const N: usize, const LEN: usize> IndexMut<Position>
291 for Matrix<T, M, N, LEN>
292{
293 fn index_mut(&mut self, pos: Position) -> &mut Self::Output {
294 &mut self.data[pos.0 * N + pos.1]
295 }
296}
297
298impl<T, const M: usize, const N: usize, const LEN: usize> Index<[usize; 2]>
299 for Matrix<T, M, N, LEN>
300{
301 type Output = T;
302
303 fn index(&self, pos: [usize; 2]) -> &Self::Output {
315 &self.data[pos[0] * N + pos[1]]
319 }
320}
321
322impl<T, const M: usize, const N: usize, const LEN: usize> IndexMut<[usize; 2]>
323 for Matrix<T, M, N, LEN>
324{
325 fn index_mut(&mut self, pos: [usize; 2]) -> &mut Self::Output {
333 &mut self.data[pos[0] * N + pos[1]]
337 }
338}
339
340impl<T, const M: usize, const N: usize, const LEN: usize> Add for Matrix<T, M, N, LEN>
341where
342 T: Add<Output = T> + Default + Copy,
343{
344 type Output = Self;
345
346 fn add(self, rhs: Self) -> Self::Output {
362 let mut added = Self::empty().unwrap();
363
364 for i in 0..LEN {
365 added.data[i] = self.data[i] + rhs.data[i];
366 }
367
368 added
369 }
370}
371
372impl<T, const M: usize> Matrix<T, M, 1, M>
373where
374 T: Copy + Mul + Sum<<T as Mul>::Output>,
375{
376 #[must_use]
386 pub fn dot(&self, other: &Self) -> T {
387 arr_dot(*self.as_flat_array(), *other.as_flat_array())
389 }
390}
391
392impl<T, const M: usize, const N: usize, const LEN: usize> Sub for Matrix<T, M, N, LEN>
393where
394 T: Sub<Output = T> + Default + Copy,
395{
396 type Output = Self;
397
398 fn sub(self, rhs: Self) -> Self::Output {
412 let mut subbed = Self::empty().unwrap();
413 for i in 0..LEN {
414 subbed.data[i] = self.data[i] - rhs.data[i];
415 }
416 subbed
417 }
418}
419
420impl<T, const M: usize, const LEN: usize> Matrix<T, M, M, LEN>
421where
422 T: Default + Copy,
423{
424 #[must_use]
439 pub fn diag(val: T) -> Self {
440 let mut mat = Self::empty().unwrap();
441
442 for i in 0..M {
443 mat[[i, i]] = val;
444 }
445
446 mat
447 }
448}
449
450impl<T, const M: usize, const N: usize, const LEN: usize> Matrix<T, M, N, LEN>
451where
452 T: num_traits::Num + Copy,
453{
454 #[must_use]
456 pub fn det(&self) -> T {
457 let mat = self;
458 let mut mat = *mat; let mut temp = [T::zero(); N]; let mut total: T = T::one();
461 let mut det: T = T::one(); for i in 0..N {
465 let mut index = i;
466
467 while index < N && self[[index, i]] == T::zero() {
469 index += 1;
470 }
471
472 if index == N {
473 continue;
476 }
477 if index != i {
478 for j in 0..N {
480 (mat[[index, j]], mat[[i, j]]) = (mat[[i, j]], mat[[index, j]]);
481 }
482
483 let exp = index - i;
485 if exp % 2 == 1 {
486 det = det * (T::zero() - T::one());
487 }
488 }
489
490 for j in 0..N {
492 temp[j] = mat[[i, j]];
493 }
494
495 for j in (i + 1)..N {
497 let num1 = temp[i]; let num2 = mat[[j, i]]; for k in 0..N {
502 mat[[j, k]] = (num1 * mat[[j, k]]) - (num2 * temp[k]);
504 }
505
506 total = total * num1; }
508 }
509
510 for i in 0..N {
511 det = det * mat[[i, i]];
512 }
513
514 det / total
515 }
516}
517
518impl<T, const M: usize, const LEN: usize> Matrix<T, M, M, LEN>
519where
520 T: num_traits::Num + Copy + Default + Identity,
521{
522 pub fn inverse(&self) -> Result<Self, MatrixOperationError> {
529 match M {
530 2 => self.inverse_2x2(),
531 _ => self.inverse_gauss_jordan(),
532 }
533 }
534
535 fn inverse_2x2(&self) -> Result<Self, MatrixOperationError> {
536 let det = self.det();
537 if det.is_zero() {
538 return Err(MatrixOperationError::InvalidDeterminant);
539 }
540
541 let min1 = T::zero() - T::one();
542
543 let mut augmented = Self::empty().unwrap();
544 augmented.data[0] = self.data[3]; augmented.data[1] = self.data[1] * min1; augmented.data[2] = self.data[2] * min1; augmented.data[3] = self.data[0]; Ok(augmented.mul_scalar(T::one() / det))
550 }
551
552 fn inverse_gauss_jordan(&self) -> Result<Self, MatrixOperationError> {
555 todo!();
556 }
557}
558
559impl<T, const M: usize, const N: usize, const LEN: usize> IntoIterator for Matrix<T, M, N, LEN>
560where
561 T: Clone,
562{
563 type IntoIter = IntoIter<T, M, N, LEN>;
564 type Item = T;
565
566 fn into_iter(self) -> Self::IntoIter {
567 Self::IntoIter {
568 data: self.data,
569 i: 0,
570 }
571 }
572}
573
574#[derive(Debug)]
575pub struct IntoIter<T, const M: usize, const N: usize, const LEN: usize> {
576 i: usize,
577 data: [T; LEN],
578}
579impl<T, const M: usize, const N: usize, const LEN: usize> Iterator for IntoIter<T, M, N, LEN>
580where
581 T: Clone,
582{
583 type Item = T;
584
585 fn next(&mut self) -> Option<Self::Item> {
586 if self.i >= LEN {
587 None
588 } else {
589 let val = self.data[self.i].clone();
590 self.i += 1;
591 Some(val)
592 }
593 }
594}
595
596#[derive(Debug)]
597pub struct Iter<'a, T, const M: usize, const N: usize, const LEN: usize> {
598 i: usize,
599 data: &'a [T; LEN],
600}
601impl<'a, T, const M: usize, const N: usize, const LEN: usize> Iterator for Iter<'a, T, M, N, LEN> {
602 type Item = &'a T;
603
604 fn next(&mut self) -> Option<Self::Item> {
605 if self.i >= LEN {
606 None
607 } else {
608 let val = &self.data[self.i];
609 self.i += 1;
610 Some(val)
611 }
612 }
613}
614
615#[derive(Debug)]
616pub struct IntoIterRow<T, const M: usize, const N: usize, const LEN: usize> {
617 i: usize,
618 data: [T; LEN],
619}
620impl<T, const M: usize, const N: usize, const LEN: usize> Iterator for IntoIterRow<T, M, N, LEN>
621where
622 T: Copy + Default,
623{
624 type Item = Matrix<T, M, 1, M>;
625 fn next(&mut self) -> Option<Self::Item> {
626 if self.i >= N {
627 return None;
628 }
629
630 let offset = self.i * M;
631 let mut row: [T; M] = [Default::default(); M];
632
633 for (j, elem) in row.iter_mut().enumerate() {
634 *elem = self.data[offset + j];
635 }
636
637 self.i += 1;
638
639 if let Ok(mat) = Matrix::<T, M, 1, M>::new(row) {
640 Some(mat)
641 } else {
642 None
643 }
644 }
645}
646
647#[derive(Debug)]
648pub struct IterRow<'a, T, const M: usize, const N: usize, const LEN: usize> {
649 i: usize,
650 data: &'a [T; LEN],
651}
652impl<'a, T, const M: usize, const N: usize, const LEN: usize> Iterator for IterRow<'a, T, M, N, LEN>
653where
654 T: 'a,
655{
656 type Item = Matrix<&'a T, M, 1, M>;
657 fn next(&mut self) -> Option<Self::Item> {
658 if self.i >= N {
659 return None;
660 }
661
662 let offset = self.i * M;
663 let mut row: [&'a T; M] = [&self.data[offset]; M];
664
665 for (j, elem) in row.iter_mut().enumerate() {
666 *elem = &self.data[offset + j];
667 }
668
669 self.i += 1;
670
671 if let Ok(mat) = Matrix::<&T, M, 1, M>::new(row) {
672 Some(mat)
673 } else {
674 None
675 }
676 }
677}
678
679#[derive(Debug)]
680pub struct IntoIterCol<T, const M: usize, const N: usize, const LEN: usize> {
681 i: usize,
682 data: [T; LEN],
683}
684impl<T, const M: usize, const N: usize, const LEN: usize> Iterator for IntoIterCol<T, M, N, LEN>
685where
686 T: Copy + Default,
687{
688 type Item = Matrix<T, 1, N, N>;
689 fn next(&mut self) -> Option<Self::Item> {
690 if self.i >= M {
691 return None;
692 }
693
694 let mut col: [T; N] = [Default::default(); N];
695
696 for (j, elem) in col.iter_mut().enumerate() {
697 *elem = self.data[M * j + self.i];
698 }
699
700 self.i += 1;
701
702 if let Ok(mat) = Matrix::<T, 1, N, N>::new(col) {
703 Some(mat)
704 } else {
705 None
706 }
707 }
708}
709
710#[derive(Debug)]
711pub struct IterCol<'a, T, const M: usize, const N: usize, const LEN: usize> {
712 i: usize,
713 data: &'a [T; LEN],
714}
715impl<'a, T, const M: usize, const N: usize, const LEN: usize> Iterator for IterCol<'a, T, M, N, LEN>
716where
717 T: 'a,
718{
719 type Item = Matrix<&'a T, 1, N, N>;
720 fn next(&mut self) -> Option<Self::Item> {
721 if self.i >= N {
722 return None;
723 }
724
725 let mut col: [&'a T; N] = [&self.data[M + self.i]; N];
726 for (j, elem) in col.iter_mut().enumerate() {
727 *elem = &self.data[M * j + self.i];
728 }
729
730 self.i += 1;
731
732 if let Ok(mat) = Matrix::<&T, 1, N, N>::new(col) {
733 Some(mat)
734 } else {
735 None
736 }
737 }
738}