use lin_algebra::gf2_matrix::GF2Matrix;
use lin_algebra::matrix::MatrixCommon;
use std::ops::{Deref, DerefMut};
#[derive(Clone)]
pub struct VanderMonde {
pub matrix: GF2Matrix,
}
impl From<GF2Matrix> for VanderMonde {
fn from(matrix: GF2Matrix) -> Self {
Self { matrix }
}
}
impl Deref for VanderMonde {
type Target = GF2Matrix;
fn deref(&self) -> &Self::Target {
&self.matrix
}
}
impl DerefMut for VanderMonde {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.matrix
}
}
impl VanderMonde {
pub fn new(elements: Vec<Vec<u8>>) -> Self {
VanderMonde {
matrix: GF2Matrix::new(elements),
}
}
pub fn __repr__(&self) -> String {
let rows: Vec<String> = self
.elements
.iter()
.map(|row| format!("{:?}", row))
.collect();
format!("[{}]", rows.join(", "))
}
fn append_row(&mut self, v: Vec<u8>) {
self.elements.push(v)
}
fn append_column(&mut self, v: Vec<u8>) {
for i in 0..self.nrows() {
self.elements[i].push(v[i]);
}
}
pub fn compute_next(
&self,
monom_slice: Vec<usize>,
support_slice: Vec<usize>,
idx: usize,
operations: &Vec<(usize, usize)>,
) -> Self {
let mut m_copy = self.clone();
let row: Vec<u8> = (0..=idx)
.map(|i| monomo_eval(support_slice[support_slice.len() - 1], monom_slice[i]) as u8)
.collect();
let column: Vec<u8> = (0..idx)
.map(|i| monomo_eval(support_slice[i], monom_slice[monom_slice.len() - 1]) as u8)
.collect();
let n_vect: Vec<u8> = apply_operations(&operations, column);
m_copy.append_column(n_vect);
m_copy.append_row(row);
m_copy
}
pub fn compute_vandermonde(support: Vec<usize>, monomials: Vec<usize>) -> Self {
let result: Vec<Vec<u8>> = support
.iter()
.map(|zi| monomials.iter().map(|ej| monomo_eval(*zi, *ej)).collect())
.collect();
Self::new(result)
}
pub fn fill_rows(&self, support_slice: Vec<usize>, monom_slice: Vec<usize>) -> Self {
let mut m_copy = self.clone();
for j in 0..support_slice.len() {
let row: Vec<u8> = (0..monom_slice.len())
.map(|i| monomo_eval(support_slice[j], monom_slice[i]) as u8)
.collect();
m_copy.append_row(row)
}
m_copy
}
pub fn construct_and_add_column(
&self,
support: &Vec<usize>,
monom: usize,
operations: &Vec<(usize, usize)>,
) -> Self {
let mut m_copy = self.clone();
let column: Vec<u8> = (0..m_copy.nrows())
.map(|i| monomo_eval(support[i], monom))
.collect();
let n_vect: Vec<u8> = apply_operations(&operations, column);
m_copy.append_column(n_vect);
m_copy
}
}
pub fn monomo_eval(x: usize, u: usize) -> u8 {
((x & u) == u) as u8
}
fn apply_operations(operations: &Vec<(usize, usize)>, v: Vec<u8>) -> Vec<u8> {
let mut result = v.clone();
for &(op1, op2) in operations.iter() {
result[op1] = (result[op1] + result[op2]) % 2;
}
result
}
fn is_submonomial(sub_monom: usize, monom: usize) -> bool {
(sub_monom & monom) == sub_monom
}
pub fn verify(z: &Vec<usize>, g: &Vec<u8>, mapping: &Vec<usize>) -> (bool, Option<(usize, usize)>) {
for (idx, &item) in z.iter().enumerate() {
let anf: Vec<u8> = (0..g.len())
.filter(|&i| is_submonomial(mapping[i], item))
.map(|i| g[i])
.collect();
if anf.iter().copied().sum::<u8>() % 2 == 1 {
return (false, Some((idx, item)));
}
}
(true, None)
}