Skip to main content

lin_algebra/
lib.rs

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}