134 lines
3.5 KiB
Rust
134 lines
3.5 KiB
Rust
#[derive(Clone, Debug)]
|
|
pub struct MatrixGF2 {
|
|
pub rows: usize,
|
|
pub cols: usize,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
impl MatrixGF2 {
|
|
pub fn new(rows: usize, cols: usize, data: Vec<u8>) -> Self {
|
|
assert_eq!(data.len(), rows * cols, "Taille incorrecte.");
|
|
Self { rows, cols, data }
|
|
}
|
|
|
|
pub fn get(&self, i: usize, j: usize) -> u8 {
|
|
self.data[i * self.cols + j]
|
|
}
|
|
|
|
pub fn set(&mut self, i: usize, j: usize, val: u8) {
|
|
self.data[i * self.cols + j] = val;
|
|
}
|
|
|
|
pub fn print(&self) {
|
|
for i in 0..self.rows {
|
|
let start = i * self.cols;
|
|
let end = start + self.cols;
|
|
println!("{:?}", &self.data[start..end]);
|
|
}
|
|
}
|
|
|
|
pub fn swap_rows(&mut self, r1: usize, r2: usize) {
|
|
if r1 == r2 {
|
|
return;
|
|
}
|
|
for c in 0..self.cols {
|
|
let v1 = self.get(r1, c);
|
|
let v2 = self.get(r2, c);
|
|
self.set(r1, c, v2);
|
|
self.set(r2, c, v1);
|
|
}
|
|
}
|
|
|
|
pub fn swap_cols(&mut self, c1: usize, c2: usize) {
|
|
if c1 == c2 {
|
|
return;
|
|
}
|
|
for r in 0..self.rows {
|
|
let v1 = self.get(r, c1);
|
|
let v2 = self.get(r, c2);
|
|
self.set(r, c1, v2);
|
|
self.set(r, c2, v1);
|
|
}
|
|
}
|
|
|
|
pub fn xor_rows(&mut self, src: usize, dest: usize) {
|
|
for c in 0..self.cols {
|
|
let v_src = self.get(src, c);
|
|
let v_dest = self.get(dest, c);
|
|
self.set(dest, c, v_src ^ v_dest);
|
|
}
|
|
}
|
|
|
|
pub fn gauss_jordan(&mut self) {
|
|
let mut l = 0;
|
|
for r in 0..self.rows {
|
|
if l >= self.cols {
|
|
return;
|
|
}
|
|
let mut i = r;
|
|
while self.get(i, l) == 0 {
|
|
i += 1;
|
|
if i == self.rows {
|
|
i = r;
|
|
l += 1;
|
|
if l == self.cols {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
self.swap_rows(i, r);
|
|
for i in 0..self.rows {
|
|
if i != r && self.get(i, l) == 1 {
|
|
self.xor_rows(r, i);
|
|
}
|
|
}
|
|
l += 1;
|
|
}
|
|
}
|
|
|
|
pub fn gauss_jordan_swap_cols(&mut self) -> (usize, Vec<(usize, usize)>) {
|
|
let mut rank = 0;
|
|
let mut col_swaps = Vec::new();
|
|
let rows = self.rows;
|
|
let cols = self.cols;
|
|
|
|
for c in 0..cols {
|
|
if rank >= rows {
|
|
break;
|
|
}
|
|
let mut pivot_r = rank;
|
|
while pivot_r < rows && self.get(pivot_r, c) == 0 {
|
|
pivot_r += 1;
|
|
}
|
|
if pivot_r == rows {
|
|
let mut found_swap = false;
|
|
for c2 in (c + 1)..cols {
|
|
let mut pr2 = rank;
|
|
while pr2 < rows && self.get(pr2, c2) == 0 {
|
|
pr2 += 1;
|
|
}
|
|
if pr2 < rows {
|
|
self.swap_cols(c, c2);
|
|
col_swaps.push((c, c2));
|
|
pivot_r = pr2;
|
|
found_swap = true;
|
|
break;
|
|
}
|
|
}
|
|
if !found_swap {
|
|
break;
|
|
}
|
|
}
|
|
self.swap_rows(rank, pivot_r);
|
|
|
|
for i in 0..rows {
|
|
if i != rank && self.get(i, c) == 1 {
|
|
self.xor_rows(rank, i);
|
|
}
|
|
}
|
|
rank += 1;
|
|
}
|
|
(rank, col_swaps)
|
|
}
|
|
}
|