use crate::modular::mod_q;
use crate::params::Params;
pub fn bit_decomp(v: &[u64], params: &Params) -> Vec<u64> {
let l = params.l;
let mut result = Vec::with_capacity(v.len() * l);
for &vi in v {
for i in 0..l {
result.push(((vi >> i) & 1) as u64);
}
}
result
}
pub fn bit_decomp_inverse(bits: &[u64], params: &Params) -> Vec<u64> {
let l = params.l;
let k = bits.len() / l;
let q = params.q;
let mut result = Vec::with_capacity(k);
for j in 0..k {
let mut sum: i64 = 0;
for i in 0..l {
sum += (bits[j * l + i] as i64) * (1i64 << i);
}
result.push(mod_q(sum, q));
}
result
}
pub fn flatten(v: &[u64], params: &Params) -> Vec<u64> {
let decomposed = bit_decomp_inverse(v, params);
bit_decomp(&decomposed, params)
}
pub fn powers_of_2(b: &[u64], params: &Params) -> Vec<u64> {
let l = params.l;
let q = params.q;
let mut result = Vec::with_capacity(b.len() * l);
for &bi in b {
for i in 0..l {
let p = 1u64 << i;
result.push(mod_q((bi as i64) * (p as i64), q));
}
}
result
}
pub fn g_inverse_matrix(matrix: &[Vec<u64>], params: &Params) -> Vec<Vec<u64>> {
matrix
.iter()
.map(|row| {
let decomp = bit_decomp(row, params);
decomp
})
.collect()
}
pub fn flatten_matrix(matrix: &[Vec<u64>], params: &Params) -> Vec<Vec<u64>> {
matrix
.iter()
.map(|row| {
let flat = flatten(row, params);
flat
})
.collect()
}