1use std::{fmt, fmt::Debug, marker::PhantomData};
59
60use super::{vector::DynamicVector, *};
61
62#[derive(Debug, Clone, PartialEq, Eq, Hash)]
68pub struct PivotInfo {
69 pub row: usize,
71 pub col: usize,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct RowEchelonOutput {
81 pub rank: usize,
83 pub pivots: Vec<PivotInfo>,
85}
86
87mod sealed {
89 pub trait Sealed {}
90 impl Sealed for super::RowMajor {}
91 impl Sealed for super::ColumnMajor {}
92}
93
94pub trait MatrixOrientation: sealed::Sealed {}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub struct RowMajor;
107impl MatrixOrientation for RowMajor {}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
114pub struct ColumnMajor;
115impl MatrixOrientation for ColumnMajor {}
116
117#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
144pub struct DynamicDenseMatrix<F, O: MatrixOrientation = RowMajor> {
145 components: DynamicVector<DynamicVector<F>>,
150 orientation: PhantomData<O>,
152}
153
154impl<F, O: MatrixOrientation> DynamicDenseMatrix<F, O> {
155 pub const fn new() -> Self {
175 Self { components: DynamicVector::new(Vec::new()), orientation: PhantomData }
176 }
177}
178
179impl<F: Field + Copy> DynamicDenseMatrix<F, RowMajor> {
181 pub fn zeros(rows: usize, cols: usize) -> Self {
193 let mut mat = Self::new();
194 for _ in 0..rows {
195 mat.append_row(DynamicVector::zeros(cols));
196 }
197 mat
198 }
199
200 pub const fn num_rows(&self) -> usize {
208 self.components.dimension() }
210
211 pub fn num_cols(&self) -> usize {
220 if self.components.dimension() == 0 {
221 0
222 } else {
223 self.components.components()[0].dimension()
224 }
225 }
226
227 pub fn append_column(&mut self, column: &DynamicVector<F>) {
266 let num_r = self.num_rows();
267 if num_r == 0 {
268 if column.dimension() == 0 {
269 return;
270 }
271 for i in 0..column.dimension() {
272 self.components.components_mut().push(DynamicVector::new(vec![*column.get_component(i)]));
273 }
274 } else {
275 assert_eq!(num_r, column.dimension(), "Column length must match the number of rows");
276 for i in 0..num_r {
277 self.components.components_mut()[i].append(*column.get_component(i));
278 }
279 }
280 }
281
282 pub fn get_column(&self, index: usize) -> DynamicVector<F> {
305 let num_r = self.num_rows();
306 if num_r == 0 {
307 return DynamicVector::new(Vec::new());
308 }
309 assert!(index < self.num_cols(), "Column index out of bounds");
310 let mut col_components = Vec::with_capacity(num_r);
311 for i in 0..num_r {
312 col_components.push(*self.components.components()[i].get_component(index));
313 }
314 DynamicVector::new(col_components)
315 }
316
317 pub fn set_column(&mut self, index: usize, column: &DynamicVector<F>) {
335 let num_r = self.num_rows();
336 assert_eq!(num_r, column.dimension(), "New column length must match the number of rows");
337 if num_r == 0 {
338 return;
339 }
340 assert!(index < self.num_cols(), "Column index out of bounds");
341 for i in 0..num_r {
342 self.components.components_mut()[i].set_component(index, *column.get_component(i));
343 }
344 }
345
346 pub fn append_row(&mut self, row: DynamicVector<F>) {
374 if self.num_rows() > 0 {
375 assert_eq!(
376 self.num_cols(),
377 row.dimension(),
378 "New row length must match existing number of columns"
379 );
380 }
381 self.components.components_mut().push(row);
382 }
383
384 pub fn get_row(&self, index: usize) -> &DynamicVector<F> {
400 assert!(index < self.num_rows(), "Row index out of bounds");
401 &self.components.components()[index]
402 }
403
404 pub fn set_row(&mut self, index: usize, row: DynamicVector<F>) {
416 assert!(index < self.num_rows(), "Row index out of bounds");
417 if self.num_rows() > 0 {
418 assert_eq!(
419 self.num_cols(),
420 row.dimension(),
421 "New row length must match existing number of columns"
422 );
423 }
424 self.components.components_mut()[index] = row;
425 }
426
427 pub fn get_component(&self, row: usize, col: usize) -> &F {
442 assert!(row < self.num_rows(), "Row index out of bounds");
443 assert!(col < self.num_cols(), "Column index out of bounds");
444 self.components.components()[row].get_component(col)
445 }
446
447 pub fn set_component(&mut self, row: usize, col: usize, value: F) {
459 assert!(row < self.num_rows(), "Row index out of bounds");
460 assert!(col < self.num_cols(), "Column index out of bounds");
461 self.components.components_mut()[row].set_component(col, value);
462 }
463
464 pub fn transpose(self) -> DynamicDenseMatrix<F, ColumnMajor> {
472 DynamicDenseMatrix { components: self.components, orientation: PhantomData }
473 }
474
475 pub fn row_echelon_form(&mut self) -> RowEchelonOutput {
510 let matrix = self.components.components_mut();
511 if matrix.is_empty() || matrix[0].dimension() == 0 {
512 return RowEchelonOutput { rank: 0, pivots: Vec::new() };
513 }
514 let rows = matrix.len();
515 let cols = matrix[0].dimension();
516 let mut lead = 0; let mut rank = 0;
518 let mut pivots = Vec::new();
519
520 for r in 0..rows {
521 if lead >= cols {
522 break;
523 }
524 let mut i = r;
525 while matrix[i].get_component(lead).is_zero() {
526 i += 1;
527 if i == rows {
528 i = r;
529 lead += 1;
530 if lead == cols {
531 return RowEchelonOutput { rank, pivots };
532 }
533 }
534 }
535 matrix.swap(i, r);
536
537 pivots.push(PivotInfo { row: r, col: lead });
538
539 let pivot_val = *matrix[r].get_component(lead);
540 let inv_pivot = pivot_val.multiplicative_inverse();
541
542 for j in lead..cols {
543 let val = *matrix[r].get_component(j);
544 matrix[r].set_component(j, val * inv_pivot);
545 }
546
547 for i_row in 0..rows {
548 if i_row != r {
549 let factor = *matrix[i_row].get_component(lead);
550 if !factor.is_zero() {
551 for j_col in lead..cols {
552 let val_r_j_col = *matrix[r].get_component(j_col);
553 let term = factor * val_r_j_col;
554 let val_i_row_j_col = *matrix[i_row].get_component(j_col); matrix[i_row].set_component(j_col, val_i_row_j_col - term);
556 }
557 }
558 }
559 }
560 lead += 1;
561 rank += 1;
562 }
563 RowEchelonOutput { rank, pivots }
564 }
565
566 pub fn image(&self) -> Vec<DynamicVector<F>> {
572 if self.num_rows() == 0 || self.num_cols() == 0 {
573 return Vec::new();
574 }
575
576 let mut rref_candidate = self.clone();
577 let echelon_output = rref_candidate.row_echelon_form(); let mut pivot_col_indices: Vec<usize> = echelon_output.pivots.iter().map(|p| p.col).collect();
580 pivot_col_indices.sort_unstable();
581 pivot_col_indices.dedup();
582
583 let mut image_basis: Vec<DynamicVector<F>> = Vec::new();
584 for &col_idx in &pivot_col_indices {
585 image_basis.push(self.get_column(col_idx)); }
588 image_basis
589 }
590
591 pub fn kernel(&self) -> Vec<DynamicVector<F>> {
597 if self.num_cols() == 0 {
598 return Vec::new();
599 }
600
601 if self.num_rows() == 0 {
602 let mut basis: Vec<DynamicVector<F>> = Vec::with_capacity(self.num_cols());
603 for i in 0..self.num_cols() {
604 let mut v_data = vec![F::zero(); self.num_cols()];
605 if i < v_data.len() {
606 v_data[i] = F::one();
607 }
608 basis.push(DynamicVector::new(v_data));
609 }
610 return basis;
611 }
612
613 let mut rref_matrix = self.clone();
614 let echelon_output = rref_matrix.row_echelon_form();
615
616 let num_cols = rref_matrix.num_cols();
617 let num_rows_of_rref = rref_matrix.num_rows();
618
619 let mut is_pivot_col = vec![false; num_cols];
620 for pivot_info in &echelon_output.pivots {
621 if pivot_info.col < num_cols {
622 is_pivot_col[pivot_info.col] = true;
623 }
624 }
625
626 let mut free_col_indices: Vec<usize> = Vec::new();
627 (0..num_cols).for_each(|j| {
628 if !is_pivot_col[j] {
629 free_col_indices.push(j);
630 }
631 });
632
633 let mut kernel_basis: Vec<DynamicVector<F>> = Vec::new();
634
635 for &free_idx in &free_col_indices {
636 let mut basis_vector_comps = vec![F::zero(); num_cols];
637 if free_idx < num_cols {
638 basis_vector_comps[free_idx] = F::one();
639 }
640
641 for pivot_info in &echelon_output.pivots {
642 let pivot_col = pivot_info.col;
643 let pivot_row = pivot_info.row;
644
645 if pivot_col < num_cols && free_idx < num_cols && pivot_row < num_rows_of_rref {
646 let coefficient = *rref_matrix.get_component(pivot_row, free_idx);
647 basis_vector_comps[pivot_col] = -coefficient;
648 }
649 }
650 kernel_basis.push(DynamicVector::new(basis_vector_comps));
651 }
652 kernel_basis
653 }
654}
655
656impl<F: Field + Copy> DynamicDenseMatrix<F, ColumnMajor> {
657 pub fn zeros(rows: usize, cols: usize) -> Self {
669 let mut mat = Self::new();
670 for _ in 0..cols {
671 mat.append_column(DynamicVector::zeros(rows));
672 }
673 mat
674 }
675
676 pub fn num_rows(&self) -> usize {
684 if self.components.dimension() == 0 {
685 0
686 } else {
687 self.components.components()[0].dimension()
688 }
689 }
690
691 pub const fn num_cols(&self) -> usize { self.components.dimension() }
699
700 pub fn append_column(&mut self, column: DynamicVector<F>) {
730 if self.num_cols() > 0 {
731 assert_eq!(
732 self.num_rows(),
733 column.dimension(),
734 "New column length must match existing number of rows"
735 );
736 }
737 self.components.components_mut().push(column); }
739
740 pub fn get_column(&self, index: usize) -> &DynamicVector<F> {
756 assert!(index < self.num_cols(), "Column index out of bounds");
757 &self.components.components()[index]
758 }
759
760 pub fn set_column(&mut self, index: usize, column: DynamicVector<F>) {
774 assert!(index < self.num_cols(), "Column index out of bounds");
775 if self.num_cols() > 0 {
776 assert_eq!(
777 self.num_rows(),
778 column.dimension(),
779 "New column length must match existing number of rows"
780 );
781 }
782 self.components.components_mut()[index] = column;
783 }
784
785 pub fn append_row(&mut self, row: &DynamicVector<F>) {
801 let num_c = self.num_cols();
802 if num_c == 0 {
803 if row.dimension() == 0 {
804 return;
805 }
806 for i in 0..row.dimension() {
807 self.components.components_mut().push(DynamicVector::new(vec![*row.get_component(i)]));
808 }
809 } else {
810 assert_eq!(num_c, row.dimension(), "Row length must match the number of columns");
811 for i in 0..num_c {
812 self.components.components_mut()[i].append(*row.get_component(i));
813 }
814 }
815 }
816
817 pub fn get_row(&self, index: usize) -> DynamicVector<F> {
837 let num_c = self.num_cols();
838 if num_c == 0 {
839 return DynamicVector::new(Vec::new());
840 }
841 assert!(index < self.num_rows(), "Row index out of bounds");
842 let mut row_components = Vec::with_capacity(num_c);
843 for i in 0..num_c {
844 row_components.push(*self.components.components()[i].get_component(index));
845 }
846 DynamicVector::new(row_components)
847 }
848
849 pub fn set_row(&mut self, index: usize, row: &DynamicVector<F>) {
867 let num_c = self.num_cols();
868 assert_eq!(num_c, row.dimension(), "New row length must match the number of columns");
869 if num_c == 0 {
870 return; }
872 assert!(index < self.num_rows(), "Row index out of bounds");
873
874 for i in 0..num_c {
875 self.components.components_mut()[i].set_component(index, *row.get_component(i));
876 }
877 }
878
879 pub fn get_component(&self, row: usize, col: usize) -> &F {
894 assert!(col < self.num_cols(), "Column index out of bounds");
895 assert!(row < self.num_rows(), "Row index out of bounds");
896 self.components.components()[col].get_component(row)
897 }
898
899 pub fn set_component(&mut self, row: usize, col: usize, value: F) {
911 assert!(col < self.num_cols(), "Column index out of bounds");
912 assert!(row < self.num_rows(), "Row index out of bounds");
913 self.components.components_mut()[col].set_component(row, value);
914 }
915
916 pub fn transpose(self) -> DynamicDenseMatrix<F, RowMajor> {
924 DynamicDenseMatrix { components: self.components, orientation: PhantomData }
925 }
926
927 pub fn row_echelon_form(&mut self) -> RowEchelonOutput {
947 let matrix = self.components.components_mut();
948 if matrix.is_empty() || matrix[0].dimension() == 0 {
949 return RowEchelonOutput { rank: 0, pivots: Vec::new() };
950 }
951 let num_actual_cols = matrix.len();
952 let num_actual_rows = matrix[0].dimension();
953
954 let mut pivot_row_idx = 0;
955 let mut rank = 0;
956 let mut pivots = Vec::new();
957
958 for pivot_col_idx in 0..num_actual_cols {
959 if pivot_row_idx >= num_actual_rows {
960 break;
961 }
962
963 let mut i_search_row = pivot_row_idx;
964 while i_search_row < num_actual_rows
965 && matrix[pivot_col_idx].get_component(i_search_row).is_zero()
966 {
967 i_search_row += 1;
968 }
969
970 if i_search_row < num_actual_rows {
971 if i_search_row != pivot_row_idx {
973 (0..num_actual_cols).for_each(|k_col| {
975 let temp = *matrix[k_col].get_component(i_search_row);
977 let val_at_pivot_row = *matrix[k_col].get_component(pivot_row_idx);
978 matrix[k_col].set_component(i_search_row, val_at_pivot_row);
979 matrix[k_col].set_component(pivot_row_idx, temp);
980 });
981 }
982
983 pivots.push(PivotInfo { row: pivot_row_idx, col: pivot_col_idx });
984
985 let pivot_val = *matrix[pivot_col_idx].get_component(pivot_row_idx);
986
987 if !pivot_val.is_zero() {
988 let inv_pivot_val = pivot_val.multiplicative_inverse();
989 (pivot_col_idx..num_actual_cols).for_each(|k_col| {
990 let current_val = *matrix[k_col].get_component(pivot_row_idx);
991 matrix[k_col].set_component(pivot_row_idx, current_val * inv_pivot_val);
992 });
993 }
994
995 for k_row in 0..num_actual_rows {
996 if k_row != pivot_row_idx {
997 let factor = *matrix[pivot_col_idx].get_component(k_row);
998 if !factor.is_zero() {
999 (pivot_col_idx..num_actual_cols).for_each(|j_col_elim| {
1000 let val_from_pivot_row_at_j_col = *matrix[j_col_elim].get_component(pivot_row_idx);
1001 let term_to_subtract = factor * val_from_pivot_row_at_j_col;
1002 let current_val_in_k_row_at_j_col = *matrix[j_col_elim].get_component(k_row);
1003 matrix[j_col_elim]
1004 .set_component(k_row, current_val_in_k_row_at_j_col - term_to_subtract);
1005 });
1006 }
1007 }
1008 }
1009 pivot_row_idx += 1;
1010 rank += 1;
1011 }
1012 }
1013 RowEchelonOutput { rank, pivots }
1014 }
1015
1016 pub fn image(&self) -> Vec<DynamicVector<F>> {
1022 if self.num_rows() == 0 || self.num_cols() == 0 {
1023 return Vec::new();
1024 }
1025
1026 let mut rref_candidate = self.clone();
1027 let echelon_output = rref_candidate.row_echelon_form(); let mut pivot_col_indices: Vec<usize> = echelon_output.pivots.iter().map(|p| p.col).collect();
1030 pivot_col_indices.sort_unstable();
1031 pivot_col_indices.dedup();
1032
1033 let mut image_basis: Vec<DynamicVector<F>> = Vec::new();
1034 for &col_idx in &pivot_col_indices {
1035 image_basis.push(self.get_column(col_idx).clone());
1037 }
1038 image_basis
1039 }
1040
1041 pub fn kernel(&self) -> Vec<DynamicVector<F>> {
1047 if self.num_cols() == 0 {
1048 return Vec::new();
1049 }
1050
1051 if self.num_rows() == 0 {
1052 let mut basis: Vec<DynamicVector<F>> = Vec::with_capacity(self.num_cols());
1053 for i in 0..self.num_cols() {
1054 let mut v_data = vec![F::zero(); self.num_cols()];
1055 if i < v_data.len() {
1056 v_data[i] = F::one();
1057 }
1058 basis.push(DynamicVector::new(v_data));
1059 }
1060 return basis;
1061 }
1062
1063 let mut rref_matrix = self.clone();
1064 let echelon_output = rref_matrix.row_echelon_form();
1065
1066 let num_cols = rref_matrix.num_cols();
1067 let num_rows_of_rref = rref_matrix.num_rows();
1068
1069 let mut is_pivot_col = vec![false; num_cols];
1070 for pivot_info in &echelon_output.pivots {
1071 if pivot_info.col < num_cols {
1072 is_pivot_col[pivot_info.col] = true;
1073 }
1074 }
1075
1076 let mut free_col_indices: Vec<usize> = Vec::new();
1077 (0..num_cols).for_each(|j| {
1078 if !is_pivot_col[j] {
1079 free_col_indices.push(j);
1080 }
1081 });
1082
1083 let mut kernel_basis: Vec<DynamicVector<F>> = Vec::new();
1084
1085 for &free_idx in &free_col_indices {
1086 let mut basis_vector_comps = vec![F::zero(); num_cols];
1087 if free_idx < num_cols {
1088 basis_vector_comps[free_idx] = F::one();
1089 }
1090
1091 for pivot_info in &echelon_output.pivots {
1092 let pivot_col = pivot_info.col;
1093 let pivot_row = pivot_info.row;
1094
1095 if pivot_col < num_cols && free_idx < num_cols && pivot_row < num_rows_of_rref {
1096 let coefficient = *rref_matrix.get_component(pivot_row, free_idx);
1097 basis_vector_comps[pivot_col] = -coefficient;
1098 }
1099 }
1100 kernel_basis.push(DynamicVector::new(basis_vector_comps));
1101 }
1102 kernel_basis
1103 }
1104}
1105
1106impl<T: Field + Copy> Mul<DynamicVector<T>> for DynamicDenseMatrix<T, RowMajor> {
1107 type Output = DynamicVector<T>;
1108
1109 fn mul(self, rhs: DynamicVector<T>) -> Self::Output {
1110 assert_eq!(self.num_cols(), rhs.dimension(), "Matrix-vector dimension mismatch");
1111
1112 let mut result = vec![T::zero(); self.num_rows()];
1113 (0..self.num_rows()).for_each(|i| {
1114 for j in 0..self.num_cols() {
1115 result[i] += *self.get_component(i, j) * *rhs.get_component(j);
1116 }
1117 });
1118
1119 DynamicVector::new(result)
1120 }
1121}
1122
1123impl<T: Field + Copy> Mul<DynamicVector<T>> for DynamicDenseMatrix<T, ColumnMajor> {
1124 type Output = DynamicVector<T>;
1125
1126 fn mul(self, rhs: DynamicVector<T>) -> Self::Output {
1127 assert_eq!(self.num_cols(), rhs.dimension(), "Matrix-vector dimension mismatch");
1128
1129 let mut result = vec![T::zero(); self.num_rows()];
1130 (0..self.num_rows()).for_each(|i| {
1131 for j in 0..self.num_cols() {
1132 result[i] += *self.get_component(i, j) * *rhs.get_component(j);
1133 }
1134 });
1135
1136 DynamicVector::new(result)
1137 }
1138}
1139
1140impl<T: Field + Copy> Mul<Self> for DynamicDenseMatrix<T, RowMajor> {
1141 type Output = Self;
1142
1143 fn mul(self, rhs: Self) -> Self::Output {
1144 let mut result = Self::new();
1145 for i in 0..self.num_rows() {
1146 let mut new_row = DynamicVector::<T>::zeros(rhs.num_cols());
1147 for j in 0..rhs.num_cols() {
1148 let col = rhs.get_column(j);
1149 let mut sum = T::zero();
1150 for k in 0..self.num_cols() {
1151 sum += *self.get_component(i, k) * *col.get_component(k);
1152 }
1153 new_row.set_component(j, sum);
1154 }
1155 result.append_row(new_row);
1156 }
1157 result
1158 }
1159}
1160
1161impl<T: Field + Copy> Mul<Self> for DynamicDenseMatrix<T, ColumnMajor> {
1162 type Output = Self;
1163
1164 fn mul(self, rhs: Self) -> Self::Output {
1165 assert_eq!(
1166 self.num_cols(),
1167 rhs.num_rows(),
1168 "Matrix dimensions incompatible for multiplication"
1169 );
1170 let m = self.num_rows();
1171 let n = self.num_cols(); let p = rhs.num_cols();
1173
1174 let mut result_matrix = Self::new();
1175
1176 for j_res in 0..p {
1177 let mut new_col_components = Vec::with_capacity(m);
1179 for i_res in 0..m {
1180 let mut sum = T::zero();
1182 for k in 0..n {
1183 sum += *self.get_component(i_res, k) * *rhs.get_component(k, j_res);
1187 }
1188 new_col_components.push(sum);
1189 }
1190 result_matrix.append_column(DynamicVector::new(new_col_components));
1191 }
1192 result_matrix
1193 }
1194}
1195
1196impl<T: Field + Copy> Mul<DynamicDenseMatrix<T, RowMajor>> for DynamicDenseMatrix<T, ColumnMajor> {
1197 type Output = Self;
1198
1199 fn mul(self, rhs: DynamicDenseMatrix<T, RowMajor>) -> Self::Output {
1200 assert_eq!(
1201 self.num_cols(),
1202 rhs.num_rows(),
1203 "Matrix dimensions incompatible for multiplication"
1204 );
1205 let m = self.num_rows();
1206 let n = self.num_cols(); let p = rhs.num_cols();
1208
1209 let mut result_matrix = Self::new();
1210
1211 for j_res in 0..p {
1212 let mut new_col_components = Vec::with_capacity(m);
1214 for i_res in 0..m {
1215 let mut sum = T::zero();
1217 for k in 0..n {
1218 sum += *self.get_component(i_res, k) * *rhs.get_component(k, j_res);
1222 }
1223 new_col_components.push(sum);
1224 }
1225 result_matrix.append_column(DynamicVector::new(new_col_components));
1226 }
1227 result_matrix
1228 }
1229}
1230
1231impl<F: Field + Copy + fmt::Display> fmt::Display for DynamicDenseMatrix<F, RowMajor> {
1232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1233 if self.num_rows() == 0 {
1234 return write!(f, "( )");
1235 }
1236
1237 let mut col_widths = vec![0; self.num_cols()];
1239 for i in 0..self.num_rows() {
1240 #[allow(clippy::needless_range_loop)]
1241 for j in 0..self.num_cols() {
1242 let element_str = format!("{}", self.get_component(i, j));
1243 col_widths[j] = col_widths[j].max(element_str.len());
1244 }
1245 }
1246
1247 for i in 0..self.num_rows() {
1249 if self.num_rows() == 1 {
1251 write!(f, "( ")?; } else if i == 0 {
1253 write!(f, "⎛ ")?; } else if i == self.num_rows() - 1 {
1255 write!(f, "⎝ ")?; } else {
1257 write!(f, "⎜ ")?; }
1259
1260 #[allow(clippy::needless_range_loop)]
1262 for j in 0..self.num_cols() {
1263 if j > 0 {
1264 write!(f, " ")?; }
1266 write!(f, "{:>width$}", self.get_component(i, j), width = col_widths[j])?;
1267 }
1268
1269 if self.num_rows() == 1 {
1271 write!(f, " )")?; } else if i == 0 {
1273 writeln!(f, " ⎞")?; } else if i == self.num_rows() - 1 {
1275 write!(f, " ⎠")?; } else {
1277 writeln!(f, " ⎟")?; }
1279 }
1280
1281 Ok(())
1282 }
1283}
1284
1285impl<F: Field + Copy + fmt::Display> fmt::Display for DynamicDenseMatrix<F, ColumnMajor> {
1286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1287 if self.num_rows() == 0 {
1288 return write!(f, "( )");
1289 }
1290
1291 let mut col_widths = vec![0; self.num_cols()];
1293 #[allow(clippy::needless_range_loop)]
1294 for i in 0..self.num_rows() {
1295 #[allow(clippy::needless_range_loop)]
1296 for j in 0..self.num_cols() {
1297 let element_str = format!("{}", self.get_component(i, j));
1298 col_widths[j] = col_widths[j].max(element_str.len());
1299 }
1300 }
1301
1302 for i in 0..self.num_rows() {
1304 if self.num_rows() == 1 {
1306 write!(f, "( ")?; } else if i == 0 {
1308 write!(f, "⎛ ")?; } else if i == self.num_rows() - 1 {
1310 write!(f, "⎝ ")?; } else {
1312 write!(f, "⎜ ")?; }
1314
1315 #[allow(clippy::needless_range_loop)]
1317 for j in 0..self.num_cols() {
1318 if j > 0 {
1319 write!(f, " ")?; }
1321 write!(f, "{:>width$}", self.get_component(i, j), width = col_widths[j])?;
1322 }
1323
1324 if self.num_rows() == 1 {
1326 write!(f, " )")?; } else if i == 0 {
1328 writeln!(f, " ⎞")?; } else if i == self.num_rows() - 1 {
1330 write!(f, " ⎠")?; } else {
1332 writeln!(f, " ⎟")?; }
1334 }
1335
1336 Ok(())
1337 }
1338}
1339
1340#[cfg(test)]
1341mod tests {
1342 #![allow(non_snake_case)]
1343 use super::*;
1344 use crate::{algebras::boolean::Boolean, fixtures::Mod7};
1345
1346 #[test]
1348 fn test_new_matrix_properties() {
1349 let m_rm_f64: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1351 assert_eq!(m_rm_f64.num_rows(), 0);
1352 assert_eq!(m_rm_f64.num_cols(), 0);
1353
1354 let m_cm_bool: DynamicDenseMatrix<Boolean, ColumnMajor> = DynamicDenseMatrix::new();
1356 assert_eq!(m_cm_bool.num_rows(), 0);
1357 assert_eq!(m_cm_bool.num_cols(), 0);
1358 }
1359
1360 #[test]
1362 fn test_row_operations_row_major_mod7() {
1363 let mut m: DynamicDenseMatrix<Mod7, RowMajor> = DynamicDenseMatrix::new();
1364 let r0_data = vec![Mod7::new(1), Mod7::new(2)];
1365 let r1_data = vec![Mod7::new(3), Mod7::new(4)];
1366 let r0 = DynamicVector::new(r0_data.clone());
1367 let r1 = DynamicVector::new(r1_data.clone());
1368
1369 m.append_row(r0);
1370 assert_eq!(m.num_rows(), 1);
1371 assert_eq!(m.num_cols(), 2);
1372 assert_eq!(m.get_row(0).components(), &r0_data);
1373
1374 m.append_row(r1);
1375 assert_eq!(m.num_rows(), 2);
1376 assert_eq!(m.num_cols(), 2);
1377 assert_eq!(m.get_row(1).components(), &r1_data);
1378
1379 let r_new_data = vec![Mod7::new(5), Mod7::new(6)];
1380 let r_new = DynamicVector::new(r_new_data.clone());
1381 m.set_row(0, r_new);
1382 assert_eq!(m.num_rows(), 2);
1383 assert_eq!(m.num_cols(), 2);
1384 assert_eq!(m.get_row(0).components(), &r_new_data);
1385 assert_eq!(m.get_row(1).components(), &r1_data);
1386 }
1387
1388 #[test]
1390 fn test_column_operations_row_major_f64() {
1391 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1392
1393 let c0_data = vec![1.0, 2.0];
1395 let c0 = DynamicVector::new(c0_data.clone());
1396 m.append_column(&c0);
1397 assert_eq!(m.num_rows(), 2);
1398 assert_eq!(m.num_cols(), 1);
1399 assert_eq!(m.get_column(0).components(), &c0_data);
1400 assert_eq!(*m.get_component(0, 0), 1.0);
1401 assert_eq!(*m.get_component(1, 0), 2.0);
1402
1403 let c1_data = vec![3.0, 4.0];
1405 let c1 = DynamicVector::new(c1_data.clone());
1406 m.append_column(&c1);
1407 assert_eq!(m.num_rows(), 2);
1408 assert_eq!(m.num_cols(), 2);
1409 assert_eq!(m.get_column(1).components(), &c1_data);
1410 assert_eq!(*m.get_component(0, 1), 3.0);
1411 assert_eq!(*m.get_component(1, 1), 4.0);
1412
1413 let c_new_data = vec![5.0, 6.0];
1415 let c_new = DynamicVector::new(c_new_data.clone());
1416 m.set_column(0, &c_new);
1417 assert_eq!(m.num_rows(), 2);
1418 assert_eq!(m.num_cols(), 2);
1419 assert_eq!(m.get_column(0).components(), &c_new_data);
1420 assert_eq!(m.get_column(1).components(), &c1_data);
1421 }
1422
1423 #[test]
1425 fn test_column_operations_col_major_boolean() {
1426 let mut m: DynamicDenseMatrix<Boolean, ColumnMajor> = DynamicDenseMatrix::new();
1427 let c0_data = vec![Boolean(true), Boolean(false)];
1428 let c1_data = vec![Boolean(false), Boolean(true)];
1429 let c0 = DynamicVector::new(c0_data.clone());
1430 let c1 = DynamicVector::new(c1_data.clone());
1431
1432 m.append_column(c0.clone());
1433 assert_eq!(m.num_rows(), 2);
1434 assert_eq!(m.num_cols(), 1);
1435 assert_eq!(m.get_column(0).components(), &c0_data);
1436
1437 m.append_column(c1.clone());
1438 assert_eq!(m.num_rows(), 2);
1439 assert_eq!(m.num_cols(), 2);
1440 assert_eq!(m.get_column(1).components(), &c1_data);
1441
1442 let c_new_data = vec![Boolean(true), Boolean(true)];
1443 let c_new = DynamicVector::new(c_new_data.clone());
1444 m.set_column(0, c_new.clone());
1445 assert_eq!(m.num_rows(), 2);
1446 assert_eq!(m.num_cols(), 2);
1447 assert_eq!(m.get_column(0).components(), &c_new_data);
1448 assert_eq!(m.get_column(1).components(), &c1_data);
1449 }
1450
1451 #[test]
1453 fn test_row_operations_col_major_f64() {
1454 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1455
1456 let r0_data = vec![1.0, 2.0];
1458 let r0 = DynamicVector::new(r0_data.clone());
1459 m.append_row(&r0);
1460 assert_eq!(m.num_rows(), 1);
1461 assert_eq!(m.num_cols(), 2);
1462 assert_eq!(m.get_row(0).components(), &r0_data);
1463 assert_eq!(*m.get_component(0, 0), 1.0);
1464 assert_eq!(*m.get_component(0, 1), 2.0);
1465
1466 let r1_data = vec![3.0, 4.0];
1468 let r1 = DynamicVector::new(r1_data.clone());
1469 m.append_row(&r1);
1470 assert_eq!(m.num_rows(), 2);
1471 assert_eq!(m.num_cols(), 2);
1472 assert_eq!(m.get_row(1).components(), &r1_data);
1473 assert_eq!(*m.get_component(1, 0), 3.0);
1474 assert_eq!(*m.get_component(1, 1), 4.0);
1475
1476 let r_new_data = vec![5.0, 6.0];
1478 let r_new = DynamicVector::new(r_new_data.clone());
1479 m.set_row(0, &r_new);
1480 assert_eq!(m.num_rows(), 2);
1481 assert_eq!(m.num_cols(), 2);
1482 assert_eq!(m.get_row(0).components(), &r_new_data);
1483 assert_eq!(m.get_row(1).components(), &r1_data);
1484 }
1485
1486 #[test]
1488 fn test_get_set_component() {
1489 let mut m_rm: DynamicDenseMatrix<Mod7, RowMajor> = DynamicDenseMatrix::new();
1490 m_rm.append_row(DynamicVector::new(vec![Mod7::new(1), Mod7::new(2)]));
1491 m_rm.append_row(DynamicVector::new(vec![Mod7::new(3), Mod7::new(4)]));
1492 assert_eq!(*m_rm.get_component(0, 1), Mod7::new(2));
1493 m_rm.set_component(0, 1, Mod7::new(5));
1494 assert_eq!(*m_rm.get_component(0, 1), Mod7::new(5));
1495
1496 let mut m_cm: DynamicDenseMatrix<Mod7, ColumnMajor> = DynamicDenseMatrix::new();
1497 m_cm.append_column(DynamicVector::new(vec![Mod7::new(1), Mod7::new(2)]));
1498 m_cm.append_column(DynamicVector::new(vec![Mod7::new(3), Mod7::new(4)]));
1499 assert_eq!(*m_cm.get_component(1, 0), Mod7::new(2));
1500 m_cm.set_component(1, 0, Mod7::new(6));
1501 assert_eq!(*m_cm.get_component(1, 0), Mod7::new(6));
1502 }
1503
1504 #[test]
1506 fn test_transpose() {
1507 let mut m_rm: DynamicDenseMatrix<Mod7, RowMajor> = DynamicDenseMatrix::new();
1508 m_rm.append_row(DynamicVector::new(vec![Mod7::new(1), Mod7::new(2), Mod7::new(3)]));
1509 m_rm.append_row(DynamicVector::new(vec![Mod7::new(4), Mod7::new(5), Mod7::new(6)]));
1510 assert_eq!(m_rm.num_rows(), 2);
1511 assert_eq!(m_rm.num_cols(), 3);
1512
1513 let m_cm: DynamicDenseMatrix<Mod7, ColumnMajor> = m_rm.transpose();
1514 assert_eq!(m_cm.num_rows(), 3);
1515 assert_eq!(m_cm.num_cols(), 2);
1516
1517 assert_eq!(*m_cm.get_component(0, 0), Mod7::new(1));
1518 assert_eq!(*m_cm.get_component(1, 0), Mod7::new(2));
1519 assert_eq!(*m_cm.get_component(2, 0), Mod7::new(3));
1520 assert_eq!(*m_cm.get_component(0, 1), Mod7::new(4));
1521 assert_eq!(*m_cm.get_component(1, 1), Mod7::new(5));
1522 assert_eq!(*m_cm.get_component(2, 1), Mod7::new(6));
1523
1524 let m_rm_again: DynamicDenseMatrix<Mod7, RowMajor> = m_cm.transpose();
1526 assert_eq!(m_rm_again.num_rows(), 2);
1527 assert_eq!(m_rm_again.num_cols(), 3);
1528 assert_eq!(*m_rm_again.get_component(0, 0), Mod7::new(1));
1529 assert_eq!(*m_rm_again.get_component(0, 1), Mod7::new(2));
1530 assert_eq!(*m_rm_again.get_component(0, 2), Mod7::new(3));
1531 assert_eq!(*m_rm_again.get_component(1, 0), Mod7::new(4));
1532 assert_eq!(*m_rm_again.get_component(1, 1), Mod7::new(5));
1533 assert_eq!(*m_rm_again.get_component(1, 2), Mod7::new(6));
1534 }
1535
1536 #[test]
1537 #[should_panic]
1538 fn test_append_row_mismatch_cols_row_major() {
1539 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1540 m.append_row(DynamicVector::new(vec![1.0, 2.0]));
1541 m.append_row(DynamicVector::new(vec![3.0])); }
1543
1544 #[test]
1545 #[should_panic]
1546 fn test_append_column_mismatch_rows_row_major() {
1547 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1548 m.append_column(&DynamicVector::new(vec![1.0, 2.0]));
1549 m.append_column(&DynamicVector::new(vec![3.0])); }
1551
1552 #[test]
1553 #[should_panic]
1554 fn test_set_row_mismatch_cols_row_major() {
1555 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1556 m.append_row(DynamicVector::new(vec![1.0, 2.0]));
1557 m.set_row(0, DynamicVector::new(vec![3.0])); }
1559
1560 #[test]
1561 #[should_panic]
1562 fn test_set_column_mismatch_rows_row_major() {
1563 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1564 m.append_column(&DynamicVector::new(vec![1.0]));
1565 m.set_column(0, &DynamicVector::new(vec![3.0, 4.0, 5.0])); }
1567
1568 #[test]
1569 #[should_panic]
1570 fn test_append_column_mismatch_rows_col_major() {
1571 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1572 m.append_column(DynamicVector::new(vec![1.0, 2.0]));
1573 m.append_column(DynamicVector::new(vec![3.0])); }
1575
1576 #[test]
1577 #[should_panic]
1578 fn test_append_row_mismatch_cols_col_major() {
1579 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1580 m.append_row(&DynamicVector::new(vec![1.0, 2.0]));
1581 m.append_row(&DynamicVector::new(vec![3.0])); }
1583
1584 #[test]
1585 fn test_row_echelon_form_row_major() {
1586 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1587 m.append_row(DynamicVector::new(vec![1.0, 2.0, 3.0]));
1588 m.append_row(DynamicVector::new(vec![4.0, 5.0, 6.0]));
1589 m.append_row(DynamicVector::new(vec![7.0, 8.0, 9.0]));
1590 let result = m.row_echelon_form();
1591 assert_eq!(result.rank, 2);
1592 assert_eq!(result.pivots, vec![PivotInfo { row: 0, col: 0 }, PivotInfo { row: 1, col: 1 }]);
1593
1594 assert_eq!(m.num_rows(), 3);
1595 assert_eq!(m.num_cols(), 3);
1596
1597 assert_eq!(*m.get_component(0, 0), 1.0);
1598 assert_eq!(*m.get_component(0, 1), 0.0);
1599 assert_eq!(*m.get_component(0, 2), -1.0);
1600 assert_eq!(*m.get_component(1, 0), 0.0);
1601 assert_eq!(*m.get_component(1, 1), 1.0);
1602 assert_eq!(*m.get_component(1, 2), 2.0);
1603 assert_eq!(*m.get_component(2, 0), 0.0);
1604 assert_eq!(*m.get_component(2, 1), 0.0);
1605 assert_eq!(*m.get_component(2, 2), 0.0);
1606 }
1607
1608 #[test]
1609 fn test_row_echelon_form_col_major() {
1610 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1611 m.append_column(DynamicVector::new(vec![1.0, 2.0, 3.0]));
1612 m.append_column(DynamicVector::new(vec![4.0, 5.0, 6.0]));
1613 m.append_column(DynamicVector::new(vec![7.0, 8.0, 9.0]));
1614 let result = m.row_echelon_form();
1615 assert_eq!(result.rank, 2);
1616 assert_eq!(result.pivots, vec![PivotInfo { row: 0, col: 0 }, PivotInfo { row: 1, col: 1 }]);
1617
1618 assert_eq!(m.num_rows(), 3);
1619 assert_eq!(m.num_cols(), 3);
1620
1621 assert_eq!(*m.get_component(0, 0), 1.0);
1622 assert_eq!(*m.get_component(0, 1), 0.0);
1623 assert_eq!(*m.get_component(0, 2), -1.0);
1624 assert_eq!(*m.get_component(1, 0), 0.0);
1625 assert_eq!(*m.get_component(1, 1), 1.0);
1626 assert_eq!(*m.get_component(1, 2), 2.0);
1627 assert_eq!(*m.get_component(2, 0), 0.0);
1628 assert_eq!(*m.get_component(2, 1), 0.0);
1629 assert_eq!(*m.get_component(2, 2), 0.0);
1630 }
1631
1632 fn contains_vector<F: Field + Copy + PartialEq>(
1636 basis: &[DynamicVector<F>],
1637 vector: &DynamicVector<F>,
1638 ) -> bool {
1639 basis.iter().any(|v| v == vector)
1640 }
1641
1642 #[test]
1643 fn test_image_kernel_row_major_simple() {
1644 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1645 m.append_row(DynamicVector::from(vec![1.0, 0.0, -1.0]));
1648 m.append_row(DynamicVector::from(vec![0.0, 1.0, 2.0]));
1649
1650 let image = m.image();
1651 let expected_image_basis = [
1653 DynamicVector::from(vec![1.0, 0.0]), DynamicVector::from(vec![0.0, 1.0]), ];
1656 assert_eq!(image.len(), 2);
1657 assert!(contains_vector(&image, &expected_image_basis[0]));
1658 assert!(contains_vector(&image, &expected_image_basis[1]));
1659
1660 let kernel = m.kernel();
1661 let expected_kernel_basis = [DynamicVector::from(vec![1.0, -2.0, 1.0])];
1664 assert_eq!(kernel.len(), 1);
1665 assert!(contains_vector(&kernel, &expected_kernel_basis[0]));
1666
1667 for k_vec in &kernel {
1669 let mut Ax_components = vec![0.0; m.num_rows()];
1670 (0..m.num_rows()).for_each(|r| {
1671 let mut sum = 0.0;
1672 for c in 0..m.num_cols() {
1673 sum += m.get_component(r, c) * k_vec.get_component(c);
1674 }
1675 Ax_components[r] = sum;
1676 });
1677 let Ax = DynamicVector::new(Ax_components);
1678 let zero_vec = DynamicVector::new(vec![0.0; m.num_rows()]);
1679 assert_eq!(Ax, zero_vec, "Kernel vector validation failed: Ax != 0");
1680 }
1681 }
1682
1683 #[test]
1684 fn test_image_kernel_col_major_simple() {
1685 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1686 m.append_column(DynamicVector::from(vec![1.0, 0.0, -1.0]));
1691 m.append_column(DynamicVector::from(vec![0.0, 1.0, 2.0]));
1692
1693 let image = m.image();
1696 let expected_image_basis =
1697 [DynamicVector::from(vec![1.0, 0.0, -1.0]), DynamicVector::from(vec![0.0, 1.0, 2.0])];
1698 assert_eq!(image.len(), 2);
1699 assert!(contains_vector(&image, &expected_image_basis[0]));
1700 assert!(contains_vector(&image, &expected_image_basis[1]));
1701
1702 let kernel = m.kernel();
1704 assert_eq!(kernel.len(), 0, "Kernel should be trivial for this matrix");
1705 }
1706
1707 #[test]
1708 fn test_image_kernel_identity_row_major() {
1709 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1710 m.append_row(DynamicVector::from(vec![1.0, 0.0]));
1711 m.append_row(DynamicVector::from(vec![0.0, 1.0]));
1712
1713 let image = m.image();
1714 let expected_image_basis =
1715 [DynamicVector::from(vec![1.0, 0.0]), DynamicVector::from(vec![0.0, 1.0])];
1716 assert_eq!(image.len(), 2);
1717 assert!(contains_vector(&image, &expected_image_basis[0]));
1718 assert!(contains_vector(&image, &expected_image_basis[1]));
1719
1720 let kernel = m.kernel();
1721 assert_eq!(kernel.len(), 0, "Kernel of identity matrix should be trivial");
1722 }
1723
1724 #[test]
1725 fn test_image_kernel_zero_matrix_row_major() {
1726 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1727 m.append_row(DynamicVector::from(vec![0.0, 0.0]));
1728 m.append_row(DynamicVector::from(vec![0.0, 0.0]));
1729
1730 let image = m.image();
1731 assert_eq!(image.len(), 0, "Image of zero matrix should be trivial");
1732
1733 let kernel = m.kernel();
1734 let expected_kernel_basis =
1736 [DynamicVector::from(vec![1.0, 0.0]), DynamicVector::from(vec![0.0, 1.0])];
1737 assert_eq!(kernel.len(), 2);
1738 assert!(contains_vector(&kernel, &expected_kernel_basis[0]));
1740 assert!(contains_vector(&kernel, &expected_kernel_basis[1]));
1741 }
1742
1743 #[test]
1744 fn test_image_kernel_dependent_cols_row_major() {
1745 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1746 m.append_row(DynamicVector::from(vec![1.0, 2.0, 3.0]));
1750 m.append_row(DynamicVector::from(vec![2.0, 4.0, 6.0]));
1751
1752 let image = m.image();
1753 let expected_image_basis = [DynamicVector::from(vec![1.0, 2.0])];
1755 assert_eq!(image.len(), 1);
1756 assert!(contains_vector(&image, &expected_image_basis[0]));
1757
1758 let kernel = m.kernel();
1759 let expected_kernel_vector1 = DynamicVector::from(vec![-2.0, 1.0, 0.0]);
1764 let expected_kernel_vector2 = DynamicVector::from(vec![-3.0, 0.0, 1.0]);
1765 assert_eq!(kernel.len(), 2);
1766 assert!(
1767 contains_vector(&kernel, &expected_kernel_vector1)
1768 || contains_vector(&kernel, &DynamicVector::from(vec![2.0, -1.0, 0.0]))
1769 );
1770 assert!(
1771 contains_vector(&kernel, &expected_kernel_vector2)
1772 || contains_vector(&kernel, &DynamicVector::from(vec![3.0, 0.0, -1.0]))
1773 );
1774
1775 for k_vec in &kernel {
1776 let mut Ax_components = vec![0.0; m.num_rows()];
1777 (0..m.num_rows()).for_each(|r| {
1778 let mut sum = 0.0;
1779 for c in 0..m.num_cols() {
1780 sum += m.get_component(r, c) * k_vec.get_component(c);
1781 }
1782 Ax_components[r] = sum;
1783 });
1784 let Ax = DynamicVector::new(Ax_components);
1785 let zero_vec = DynamicVector::new(vec![0.0; m.num_rows()]);
1786 assert_eq!(Ax, zero_vec, "Kernel vector validation failed: Ax != 0");
1787 }
1788 }
1789
1790 #[test]
1791 fn test_image_kernel_col_major_identity() {
1792 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1793 m.append_column(DynamicVector::from(vec![1.0, 0.0]));
1794 m.append_column(DynamicVector::from(vec![0.0, 1.0]));
1795
1796 let image = m.image();
1797 let expected_image_basis =
1798 [DynamicVector::from(vec![1.0, 0.0]), DynamicVector::from(vec![0.0, 1.0])];
1799 assert_eq!(image.len(), 2);
1800 assert!(contains_vector(&image, &expected_image_basis[0]));
1801 assert!(contains_vector(&image, &expected_image_basis[1]));
1802
1803 let kernel = m.kernel();
1804 assert_eq!(kernel.len(), 0, "Kernel of identity matrix should be trivial");
1805 }
1806
1807 #[test]
1808 fn test_image_kernel_col_major_zero_matrix() {
1809 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1810 m.append_column(DynamicVector::from(vec![0.0, 0.0]));
1811 m.append_column(DynamicVector::from(vec![0.0, 0.0])); let image = m.image();
1814 assert_eq!(image.len(), 0, "Image of zero matrix should be trivial");
1815
1816 let kernel = m.kernel();
1817 let expected_kernel_basis =
1818 [DynamicVector::from(vec![1.0, 0.0]), DynamicVector::from(vec![0.0, 1.0])];
1819 assert_eq!(kernel.len(), 2);
1820 assert!(contains_vector(&kernel, &expected_kernel_basis[0]));
1821 assert!(contains_vector(&kernel, &expected_kernel_basis[1]));
1822 }
1823
1824 #[test]
1825 fn test_empty_matrix_0x0_row_major() {
1826 let m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1827 assert_eq!(m.num_rows(), 0);
1828 assert_eq!(m.num_cols(), 0);
1829 assert_eq!(m.image().len(), 0);
1830 assert_eq!(m.kernel().len(), 0);
1831 }
1832
1833 #[test]
1834 fn test_matrix_3x0_row_major() {
1835 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1836 m.append_row(DynamicVector::from(vec![]));
1837 m.append_row(DynamicVector::from(vec![]));
1838 m.append_row(DynamicVector::from(vec![]));
1839 assert_eq!(m.num_rows(), 3);
1840 assert_eq!(m.num_cols(), 0);
1841 assert_eq!(m.image().len(), 0);
1842 assert_eq!(m.kernel().len(), 0);
1843 }
1844
1845 #[test]
1846 fn test_empty_matrix_0x0_col_major() {
1847 let m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1848 assert_eq!(m.num_rows(), 0);
1849 assert_eq!(m.num_cols(), 0);
1850 assert_eq!(m.image().len(), 0);
1851 assert_eq!(m.kernel().len(), 0);
1852 }
1853
1854 #[test]
1855 fn test_matrix_0x3_col_major() {
1856 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1857 m.append_column(DynamicVector::from(vec![]));
1858 m.append_column(DynamicVector::from(vec![]));
1859 m.append_column(DynamicVector::from(vec![]));
1860 assert_eq!(m.num_rows(), 0);
1861 assert_eq!(m.num_cols(), 3);
1862 assert_eq!(m.image().len(), 0);
1863 let kernel = m.kernel();
1865 assert_eq!(kernel.len(), 3);
1866 assert!(contains_vector(&kernel, &DynamicVector::from(vec![1.0, 0.0, 0.0])));
1867 assert!(contains_vector(&kernel, &DynamicVector::from(vec![0.0, 1.0, 0.0])));
1868 assert!(contains_vector(&kernel, &DynamicVector::from(vec![0.0, 0.0, 1.0])));
1869 }
1870
1871 #[test]
1872 fn test_matrix_vector_mul_row_major() {
1873 let mut m: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1874 m.append_row(DynamicVector::from(vec![1.0, 2.0, 3.0]));
1875 m.append_row(DynamicVector::from(vec![4.0, 5.0, 6.0]));
1876 m.append_row(DynamicVector::from(vec![7.0, 8.0, 9.0]));
1877 let v = DynamicVector::from(vec![1.0, 2.0, 3.0]);
1878 let result = m * v;
1879 assert_eq!(result, DynamicVector::from(vec![14.0, 32.0, 50.0]));
1880 }
1881
1882 #[test]
1883 fn test_matrix_vector_mul_col_major() {
1884 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1885 m.append_row(&DynamicVector::from(vec![1.0, 2.0, 3.0]));
1886 m.append_row(&DynamicVector::from(vec![4.0, 5.0, 6.0]));
1887 m.append_row(&DynamicVector::from(vec![7.0, 8.0, 9.0]));
1888 let v = DynamicVector::from(vec![1.0, 2.0, 3.0]);
1889 let result = m * v;
1890 assert_eq!(result, DynamicVector::from(vec![14.0, 32.0, 50.0]));
1891 }
1892
1893 #[test]
1894 fn test_matrix_zeros() {
1895 let m = DynamicDenseMatrix::<f64, RowMajor>::zeros(2, 3);
1896 assert_eq!(m.num_rows(), 2);
1897 assert_eq!(m.num_cols(), 3);
1898 assert_eq!(m.image().len(), 0);
1899 assert_eq!(m.kernel().len(), 3);
1900
1901 let m = DynamicDenseMatrix::<f64, ColumnMajor>::zeros(2, 3);
1902 assert_eq!(m.num_rows(), 2);
1903 assert_eq!(m.num_cols(), 3);
1904 assert_eq!(m.image().len(), 0);
1905 assert_eq!(m.kernel().len(), 3);
1906 }
1907
1908 #[test]
1909 fn test_matrix_matmul() {
1910 let mut m: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1911 m.append_column(DynamicVector::from(vec![1.0, 4.0]));
1915 m.append_column(DynamicVector::from(vec![2.0, 5.0]));
1916 m.append_column(DynamicVector::from(vec![3.0, 6.0]));
1917
1918 let mut n: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1919 n.append_row(DynamicVector::from(vec![9.0, 10.0]));
1924 n.append_row(DynamicVector::from(vec![11.0, 12.0]));
1925 n.append_row(DynamicVector::from(vec![13.0, 14.0]));
1926
1927 let result = m * n;
1929 assert_eq!(result.num_rows(), 2);
1930 assert_eq!(result.num_cols(), 2);
1931 assert_eq!(*result.get_component(0, 0), 1.0 * 9.0 + 2.0 * 11.0 + 3.0 * 13.0);
1935 assert_eq!(*result.get_component(0, 1), 1.0 * 10.0 + 2.0 * 12.0 + 3.0 * 14.0);
1936 assert_eq!(*result.get_component(1, 0), 4.0 * 9.0 + 5.0 * 11.0 + 6.0 * 13.0);
1937 assert_eq!(*result.get_component(1, 1), 4.0 * 10.0 + 5.0 * 12.0 + 6.0 * 14.0);
1938 }
1939
1940 #[test]
1941 fn test_matrix_matmul_rm_rm() {
1942 let mut a_rm: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1946 a_rm.append_row(DynamicVector::from(vec![1.0, 2.0]));
1947 a_rm.append_row(DynamicVector::from(vec![3.0, 4.0]));
1948
1949 let mut b_rm: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
1953 b_rm.append_row(DynamicVector::from(vec![5.0, 6.0]));
1954 b_rm.append_row(DynamicVector::from(vec![7.0, 8.0]));
1955
1956 let result = a_rm * b_rm;
1960 assert_eq!(result.num_rows(), 2);
1961 assert_eq!(result.num_cols(), 2);
1962 assert_eq!(*result.get_component(0, 0), 1.0 * 5.0 + 2.0 * 7.0);
1963 assert_eq!(*result.get_component(0, 1), 1.0 * 6.0 + 2.0 * 8.0);
1964 assert_eq!(*result.get_component(1, 0), 3.0 * 5.0 + 4.0 * 7.0);
1965 assert_eq!(*result.get_component(1, 1), 3.0 * 6.0 + 4.0 * 8.0);
1966 }
1967
1968 #[test]
1969 fn test_matrix_matmul_cm_cm() {
1970 let mut a_cm: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1974 a_cm.append_column(DynamicVector::from(vec![1.0, 3.0]));
1975 a_cm.append_column(DynamicVector::from(vec![2.0, 4.0]));
1976
1977 let mut b_cm: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
1981 b_cm.append_column(DynamicVector::from(vec![5.0, 7.0]));
1982 b_cm.append_column(DynamicVector::from(vec![6.0, 8.0]));
1983
1984 let result = a_cm * b_cm; assert_eq!(result.num_rows(), 2);
2003 assert_eq!(result.num_cols(), 2);
2004
2005 assert_eq!(*result.get_component(0, 0), 1.0 * 5.0 + 2.0 * 7.0); assert_eq!(*result.get_component(0, 1), 1.0 * 6.0 + 2.0 * 8.0); assert_eq!(*result.get_component(1, 0), 3.0 * 5.0 + 4.0 * 7.0); assert_eq!(*result.get_component(1, 1), 3.0 * 6.0 + 4.0 * 8.0); }
2011
2012 #[test]
2013 fn test_display_formatting() {
2014 let empty_rm: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
2016 println!("Empty RowMajor matrix: \n{empty_rm}");
2017
2018 let mut small_rm: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
2020 small_rm.append_row(DynamicVector::from([1.0, 2.0]));
2021 small_rm.append_row(DynamicVector::from([3.0, 4.0]));
2022 println!("Small RowMajor matrix: \n{small_rm}");
2023
2024 let mut large_rm: DynamicDenseMatrix<f64, RowMajor> = DynamicDenseMatrix::new();
2026 large_rm.append_row(DynamicVector::from([1.0, 123.456, -5.0]));
2027 large_rm.append_row(DynamicVector::from([42.0, 0.0, -999.123]));
2028 large_rm.append_row(DynamicVector::from([7.8, 100.0, 2.5]));
2029 println!("Large RowMajor matrix: \n{large_rm}");
2030
2031 let mut col_major: DynamicDenseMatrix<f64, ColumnMajor> = DynamicDenseMatrix::new();
2033 col_major.append_column(DynamicVector::from([10.0, 20.0]));
2034 col_major.append_column(DynamicVector::from([30.0, 40.0]));
2035 col_major.append_column(DynamicVector::from([50.0, 60.0]));
2036 println!("ColumnMajor matrix: \n{col_major}");
2037 }
2038}