use crate::modules::field::Field;
pub type Mat = Vec<Vec<Field>>;
pub type VecF = Vec<Field>;
pub struct CompanionMatrix {
pub k: usize,
pub mat: Mat,
}
impl CompanionMatrix {
pub fn from_coeffs(coeffs: &[u64]) -> Self {
let k = coeffs.len();
let mut m: Mat = vec![vec![Field::zero(); k]; k];
for (i, row) in m.iter_mut().enumerate().take(k - 1) {
row[i + 1] = Field::one();
}
for (j, &c) in coeffs.iter().enumerate().take(k) {
let neg = Field::new(
(Field::MOD as u128 - (c as u128 % Field::MOD as u128)) % (Field::MOD as u128),
);
m[k - 1][j] = neg;
}
CompanionMatrix { k, mat: m }
}
pub fn mat_vec_mul(&self, v: &VecF) -> VecF {
assert_eq!(v.len(), self.k);
let mut out = vec![Field::zero(); self.k];
for (i, row) in self.mat.iter().enumerate() {
let mut acc = Field::zero();
for (val, &vj) in row.iter().zip(v.iter()) {
acc = acc + (*val * vj);
}
out[i] = acc;
}
out
}
pub fn mat_mul(&self, other: &Mat) -> Mat {
assert_eq!(other.len(), self.k);
let mut res = vec![vec![Field::zero(); self.k]; self.k];
for (i, row_a) in self.mat.iter().enumerate() {
for (j, _col_b) in (0..self.k).enumerate() {
let mut acc = Field::zero();
for (t, &val_a) in row_a.iter().enumerate() {
acc = acc + (val_a * other[t][j]);
}
res[i][j] = acc;
}
}
res
}
pub fn mat_pow(&self, mut exp: u64) -> Mat {
let mut base = self.mat.clone();
let mut res = identity(self.k);
while exp > 0 {
if exp & 1 == 1 {
res = multiply_mat(&res, &base);
}
base = multiply_mat(&base, &base);
exp >>= 1;
}
res
}
}
pub fn identity(k: usize) -> Mat {
let mut id = vec![vec![Field::zero(); k]; k];
for (i, row) in id.iter_mut().enumerate().take(k) {
row[i] = Field::one();
}
id
}
pub fn multiply_mat(a: &Mat, b: &Mat) -> Mat {
let k = a.len();
let mut res = vec![vec![Field::zero(); k]; k];
for (i, row_a) in a.iter().enumerate().take(k) {
for j in 0..k {
let mut acc = Field::zero();
for (t, &val_a) in row_a.iter().enumerate().take(k) {
acc = acc + (val_a * b[t][j]);
}
res[i][j] = acc;
}
}
res
}