1pub mod gf2_matrix;
2pub mod matrix;
3pub mod packed_gf2_matrix;
4pub use gf2_matrix::GF2Matrix;
5pub mod convert;
6
7#[cfg(test)]
8mod tests {
9 use crate::matrix::{MatrixCommon, MatrixTrait};
10
11 use super::*;
12
13 #[test]
14 fn instantiate_matrix() {
15 let mat = GF2Matrix::new(vec![vec![1, 0], vec![1, 1]]);
16 let el = mat.elements;
17 assert_eq!(el, vec![vec![1, 0], vec![1, 1]]);
18 }
19
20 #[test]
21 fn echelon_form_matrix() {
22 let mat = GF2Matrix::new(vec![vec![1, 0], vec![1, 1]]);
23 let (ech_form, _) = mat.echelon_form();
24 assert_eq!(ech_form.elements, vec![vec![1, 0], vec![0, 1]]);
25 let mat = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1], vec![0, 1, 0, 1]]);
26 let (ech_form, _) = mat.echelon_form();
27 assert_eq!(
28 ech_form.elements,
29 vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1], vec![0, 0, 0, 0]]
30 );
31 }
32
33 #[test]
34 fn echelon_form_ops() {
35 let mat = GF2Matrix::new(vec![vec![1, 0], vec![1, 1]]);
36 let (_, ops) = mat.echelon_form();
37 assert_eq!(ops, vec![(1, 0)])
38 }
39
40 #[test]
41 fn ncols_nrows() {
42 let mat = GF2Matrix::new(vec![vec![1, 0, 1], vec![1, 1, 0]]);
43 assert_eq!(mat.nrows(), 2);
44 assert_eq!(mat.ncols(), 3)
45 }
46
47 #[test]
48 fn get_pivot() {
49 assert_eq!(GF2Matrix::get_pivot(&vec![1, 0, 0, 1]).unwrap(), 0);
50 assert_eq!(GF2Matrix::get_pivot(&vec![0, 1, 1, 0]).unwrap(), 1);
51 assert_eq!(GF2Matrix::get_pivot(&vec![0, 0, 1, 1]).unwrap(), 2);
52 assert_eq!(GF2Matrix::get_pivot(&vec![0, 0, 0, 1]).unwrap(), 3);
53 assert!(GF2Matrix::get_pivot(&vec![0, 0, 0, 0]).is_none());
54 }
55
56 #[test]
57 fn is_reduced_echelon() {
58 assert_eq!(
59 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![1, 1, 0, 1]]).is_reduced_echelon(),
60 false
61 );
62 assert_eq!(
63 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![1, 1, 0, 1]]).is_reduced_echelon(),
64 false
65 );
66 assert_eq!(
67 GF2Matrix::new(vec![vec![1, 1, 0, 1], vec![0, 1, 0, 1]]).is_reduced_echelon(),
68 false
69 );
70 assert_eq!(
71 GF2Matrix::new(vec![vec![1, 0, 0, 1], vec![0, 1, 0, 1]]).is_reduced_echelon(),
72 true
73 );
74 assert_eq!(
75 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![1, 1, 0, 1], vec![0, 0, 1, 1]])
76 .is_reduced_echelon(),
77 false
78 );
79 assert_eq!(
80 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 0], vec![0, 0, 1, 1]])
81 .is_reduced_echelon(),
82 true
83 );
84 assert_eq!(
85 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1], vec![0, 1, 0, 1]])
86 .is_reduced_echelon(),
87 false
88 );
89 assert_eq!(
90 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 1, 0, 1]])
91 .is_reduced_echelon(),
92 false
93 );
94 }
95
96 #[test]
97 fn is_reduced_echelon_zero_row() {
98 assert_eq!(
99 GF2Matrix::new(vec![vec![0, 0, 0, 0], vec![1, 0, 0, 0], vec![0, 1, 0, 1]])
100 .is_reduced_echelon(),
101 false
102 );
103 assert_eq!(
104 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 1, 0, 1]])
105 .is_reduced_echelon(),
106 false
107 );
108 assert_eq!(
109 GF2Matrix::new(vec![vec![1, 0, 1, 0], vec![0, 0, 0, 0]]).is_reduced_echelon(),
110 true
111 );
112 }
113
114 #[test]
115 fn rank() {
116 assert_eq!(
117 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1]]).rank(),
118 2
119 );
120 assert_eq!(
121 GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![1, 0, 0, 0]]).rank(),
122 1
123 );
124 }
125
126 #[test]
127 fn image() {
128 let mat_1 = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1]]);
129 assert_eq!(mat_1.image(), mat_1.elements);
130 let mat_2 = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1], vec![0, 1, 0, 1]]);
131 assert_eq!(mat_2.image(), mat_1.elements);
132 let mat = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 0, 0, 0]]);
133 assert_eq!(mat.image(), vec![vec![1, 0, 0, 0]]);
134 }
135
136 #[test]
137 fn kernel() {
138 let mat = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 1, 0, 1]]);
139 assert_eq!(mat.kernel(), vec![vec![0, 0, 1, 0], vec![0, 1, 0, 1]]);
140 let mat = GF2Matrix::new(vec![vec![1, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 1, 0, 1]]);
141 assert_eq!(mat.kernel(), vec![vec![0, 0, 1, 0], vec![0, 1, 0, 1]])
142 }
143
144 #[test]
145 fn test_solve_matrix_system() {
146 let left_elements = vec![vec![1, 0, 0], vec![0, 1, 1], vec![1, 0, 1]];
147
148 let right_elements = vec![vec![0, 0, 1], vec![0, 1, 1], vec![1, 1, 1]];
149
150 let m = GF2Matrix::new(left_elements);
151 let rm = GF2Matrix::new(right_elements);
152 let r = m.solve_matrix_system(&rm);
153 assert_eq!(
154 r.elements,
155 vec![vec![0, 0, 1], vec![1, 0, 1], vec![1, 1, 0]]
156 );
157 }
158
159 #[test]
160 fn test_solve_matrix_system_linear_dependence() {
161 let left_elements = vec![vec![1, 0, 0], vec![0, 1, 1], vec![1, 0, 1], vec![1, 1, 1]];
162
163 let right_elements = vec![vec![0, 0, 1], vec![0, 1, 1], vec![1, 1, 1], vec![1, 1, 0]];
164
165 let m = GF2Matrix::new(left_elements);
166 let rm = GF2Matrix::new(right_elements);
167 let r = m.solve_matrix_system(&rm);
168 assert_eq!(
169 r.elements,
170 vec![vec![0, 0, 1], vec![1, 0, 1], vec![1, 1, 0]]
171 );
172 }
173
174 #[test]
175 #[should_panic(expected = "Matrix must have full rank")]
176 fn test_solve_matrix_system_no_full_rank() {
177 let left_elements = vec![vec![1, 0, 0], vec![0, 1, 1]];
178
179 let right_elements = vec![vec![0, 0, 1], vec![0, 1, 1], vec![1, 1, 1]];
180
181 let m = GF2Matrix::new(left_elements);
182 let rm = GF2Matrix::new(right_elements);
183 m.solve_matrix_system(&rm);
184 }
185
186 #[test]
187 fn test_solve() {
188 let left_elements = vec![vec![1, 0, 0], vec![0, 1, 1], vec![1, 0, 1]];
189
190 let b = vec![0, 0, 1];
191
192 let m = GF2Matrix::new(left_elements);
193 let r = m.solve(&b);
194 assert_eq!(r, vec![0, 1, 1]);
195 }
196
197 #[test]
198 #[should_panic(expected = "Matrix must have full rank")]
199 fn test_solve_no_full_rank() {
200 let left_elements = vec![vec![1, 0, 0], vec![0, 1, 1]];
201
202 let b = vec![0, 0, 1];
203
204 let m = GF2Matrix::new(left_elements);
205 m.solve(&b);
206 }
207}