1use std::fmt::Display;
2
3use crate::ring::*;
4
5mod owned;
6mod submatrix;
7mod transpose;
8
9pub use owned::*;
10pub use submatrix::*;
11#[allow(unused_imports)]
12pub use transpose::*;
13
14pub mod transform;
17
18#[stability::unstable(feature = "enable")]
19pub fn format_matrix<'a, M, R>(row_count: usize, col_count: usize, matrix: M, ring: R) -> impl 'a + Display
20where
21 R: 'a + RingStore,
22 El<R>: 'a,
23 M: 'a + Fn(usize, usize) -> &'a El<R>,
24{
25 struct DisplayWrapper<'a, R: 'a + RingStore, M: Fn(usize, usize) -> &'a El<R>> {
26 matrix: M,
27 ring: R,
28 row_count: usize,
29 col_count: usize,
30 }
31
32 impl<'a, R: 'a + RingStore, M: Fn(usize, usize) -> &'a El<R>> Display for DisplayWrapper<'a, R, M> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 let strings = (0..self.row_count)
35 .flat_map(|i| (0..self.col_count).map(move |j| (i, j)))
36 .map(|(i, j)| format!("{}", self.ring.format((self.matrix)(i, j))))
37 .collect::<Vec<_>>();
38 let max_len = strings.iter().map(|s| s.chars().count()).chain([2]).max().unwrap();
39 let mut strings = strings.into_iter();
40 for i in 0..self.row_count {
41 write!(f, "|")?;
42 if self.col_count > 0 {
43 write!(f, "{:>width$}", strings.next().unwrap(), width = max_len)?;
44 }
45 for _ in 1..self.col_count {
46 write!(f, ",{:>width$}", strings.next().unwrap(), width = max_len)?;
47 }
48 if i + 1 != self.row_count {
49 writeln!(f, "|")?;
50 } else {
51 write!(f, "|")?;
52 }
53 }
54 return Ok(());
55 }
56 }
57
58 DisplayWrapper {
59 matrix,
60 ring,
61 col_count,
62 row_count,
63 }
64}
65
66pub mod matrix_compare {
70 use super::*;
71
72 pub trait MatrixCompare<T> {
75 fn row_count(&self) -> usize;
77
78 fn col_count(&self) -> usize;
80
81 fn at(&self, i: usize, j: usize) -> &T;
83 }
84
85 impl<T, const ROWS: usize, const COLS: usize> MatrixCompare<T> for [[T; COLS]; ROWS] {
86 fn col_count(&self) -> usize { COLS }
87 fn row_count(&self) -> usize { ROWS }
88 fn at(&self, i: usize, j: usize) -> &T { &self[i][j] }
89 }
90
91 #[allow(deprecated)]
92 impl<T, const ROWS: usize, const COLS: usize> MatrixCompare<T> for [DerefArray<T, COLS>; ROWS] {
93 fn col_count(&self) -> usize { COLS }
94 fn row_count(&self) -> usize { ROWS }
95 fn at(&self, i: usize, j: usize) -> &T { &self[i][j] }
96 }
97
98 impl<T, const COLS: usize> MatrixCompare<T> for [[T; COLS]] {
99 fn col_count(&self) -> usize { COLS }
100 fn row_count(&self) -> usize { self.len() }
101 fn at(&self, i: usize, j: usize) -> &T { &self[i][j] }
102 }
103
104 impl<T> MatrixCompare<T> for [Vec<T>] {
105 fn col_count(&self) -> usize {
106 assert!(self.iter().all(|x| x.len() == self[0].len()));
107 self[0].len()
108 }
109 fn row_count(&self) -> usize { self.len() }
110 fn at(&self, i: usize, j: usize) -> &T { &self[i][j] }
111 }
112
113 impl<T, const ROWS: usize> MatrixCompare<T> for [Vec<T>; ROWS] {
114 fn col_count(&self) -> usize {
115 assert!(self.iter().all(|x| x.len() == self[0].len()));
116 self[0].len()
117 }
118 fn row_count(&self) -> usize { self.len() }
119 fn at(&self, i: usize, j: usize) -> &T { &self[i][j] }
120 }
121
122 impl<'a, V: AsPointerToSlice<T>, T> MatrixCompare<T> for Submatrix<'a, V, T> {
123 fn col_count(&self) -> usize { Submatrix::col_count(self) }
124 fn row_count(&self) -> usize { Submatrix::row_count(self) }
125 fn at(&self, i: usize, j: usize) -> &T { Submatrix::at(self, i, j) }
126 }
127
128 impl<'a, V: AsPointerToSlice<T>, T> MatrixCompare<T> for SubmatrixMut<'a, V, T> {
129 fn col_count(&self) -> usize { SubmatrixMut::col_count(self) }
130 fn row_count(&self) -> usize { SubmatrixMut::row_count(self) }
131 fn at(&self, i: usize, j: usize) -> &T { self.as_const().into_at(i, j) }
132 }
133
134 impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> MatrixCompare<T>
135 for TransposableSubmatrix<'a, V, T, TRANSPOSED>
136 {
137 fn col_count(&self) -> usize { TransposableSubmatrix::col_count(self) }
138 fn row_count(&self) -> usize { TransposableSubmatrix::row_count(self) }
139 fn at(&self, i: usize, j: usize) -> &T { TransposableSubmatrix::at(self, i, j) }
140 }
141
142 impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> MatrixCompare<T>
143 for TransposableSubmatrixMut<'a, V, T, TRANSPOSED>
144 {
145 fn col_count(&self) -> usize { TransposableSubmatrixMut::col_count(self) }
146 fn row_count(&self) -> usize { TransposableSubmatrixMut::row_count(self) }
147 fn at(&self, i: usize, j: usize) -> &T { self.as_const().into_at(i, j) }
148 }
149
150 impl<T> MatrixCompare<T> for OwnedMatrix<T> {
151 fn col_count(&self) -> usize { OwnedMatrix::col_count(self) }
152 fn row_count(&self) -> usize { OwnedMatrix::row_count(self) }
153 fn at(&self, i: usize, j: usize) -> &T { OwnedMatrix::at(self, i, j) }
154 }
155
156 impl<T, M: MatrixCompare<T>> MatrixCompare<T> for &M {
157 fn col_count(&self) -> usize { (**self).col_count() }
158 fn row_count(&self) -> usize { (**self).row_count() }
159 fn at(&self, i: usize, j: usize) -> &T { (**self).at(i, j) }
160 }
161
162 pub fn is_matrix_eq<R: ?Sized + RingBase, M1: MatrixCompare<R::Element>, M2: MatrixCompare<R::Element>>(
167 ring: &R,
168 lhs: &M1,
169 rhs: &M2,
170 ) -> bool {
171 if lhs.row_count() != rhs.row_count() || lhs.col_count() != rhs.col_count() {
172 return false;
173 }
174 for i in 0..lhs.row_count() {
175 for j in 0..lhs.col_count() {
176 if !ring.eq_el(lhs.at(i, j), rhs.at(i, j)) {
177 return false;
178 }
179 }
180 }
181 return true;
182 }
183}
184
185#[macro_export]
203macro_rules! assert_matrix_eq {
204 ($ring:expr,$lhs:expr,$rhs:expr) => {
205 match (&$ring, &$lhs, &$rhs) {
206 (ring_val, lhs_val, rhs_val) => {
207 assert!(
208 $crate::matrix::matrix_compare::is_matrix_eq(ring_val.get_ring(), lhs_val, rhs_val),
209 "Assertion failed: Expected\n{}\nto be\n{}",
210 $crate::matrix::format_matrix(
211 <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::row_count(lhs_val),
212 <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::col_count(lhs_val),
213 |i, j| <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::at(lhs_val, i, j),
214 ring_val
215 ),
216 $crate::matrix::format_matrix(
217 <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::row_count(rhs_val),
218 <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::col_count(rhs_val),
219 |i, j| <_ as $crate::matrix::matrix_compare::MatrixCompare<_>>::at(rhs_val, i, j),
220 ring_val
221 )
222 );
223 }
224 }
225 };
226}