pub fn reconstruct_sub(
codewords: &[Option<Additive>],
erasures: &[bool],
n: usize,
k: usize,
error_poly: &[Multiplier; FIELD_SIZE],
) -> Result<Vec<u8>> {
assert!(is_power_of_2(n), "Algorithm only works for 2^i sizes for N");
assert!(is_power_of_2(k), "Algorithm only works for 2^i sizes for K");
assert_eq!(codewords.len(), n);
assert!(k <= n / 2);
let recover_up_to = k; let mut recovered = vec![Additive(0); recover_up_to];
let mut codeword = codewords
.iter()
.enumerate()
.map(|(idx, sym)| {
if let Some(sym) = sym {
(idx, *sym)
} else {
(idx, Additive(0))
}
})
.map(|(idx, codeword)| {
if idx < recovered.len() {
recovered[idx] = codeword;
}
codeword
})
.collect::<Vec<Additive>>();
assert_eq!(codeword.len(), n);
decode_main(&mut codeword[..], recover_up_to, erasures, &error_poly[..], n);
for idx in 0..recover_up_to {
if erasures[idx] {
recovered[idx] = codeword[idx];
};
}
let mut recovered_bytes = Vec::with_capacity(recover_up_to * 2);
recovered.into_iter().take(k).for_each(|x| recovered_bytes.extend_from_slice(&x.0.to_be_bytes()[..]));
Ok(recovered_bytes)
}
pub(crate) fn decode_main(
codeword: &mut [Additive],
recover_up_to: usize,
erasure: &[bool],
log_walsh2: &[Multiplier],
n: usize,
) {
assert_eq!(codeword.len(), n);
assert!(n >= recover_up_to);
assert_eq!(erasure.len(), n);
for i in 0..codeword.len() {
codeword[i] = if erasure[i] { Additive(0) } else { codeword[i].mul(log_walsh2[i]) };
}
inverse_afft(codeword, n, 0);
tweaked_formal_derivative(codeword);
afft(codeword, n, 0);
for i in 0..recover_up_to {
codeword[i] = if erasure[i] { codeword[i].mul(log_walsh2[i]) } else { Additive(0) };
}
}
pub fn eval_error_polynomial(erasure: &[bool], log_walsh2: &mut [Multiplier], n: usize) {
let z = std::cmp::min(n, erasure.len());
assert!(z <= erasure.len());
assert!(n <= log_walsh2.len());
assert!(z <= log_walsh2.len());
for i in 0..z {
log_walsh2[i] = Multiplier(erasure[i] as Elt);
}
for i in z..n {
log_walsh2[i] = Multiplier(0);
}
walsh(log_walsh2, FIELD_SIZE);
for i in 0..n {
let tmp = log_walsh2[i].to_wide() * LOG_WALSH[i].to_wide();
log_walsh2[i] = Multiplier((tmp % ONEMASK as Wide) as Elt);
}
walsh(log_walsh2, FIELD_SIZE);
for i in 0..z {
if erasure[i] {
log_walsh2[i] = Multiplier(ONEMASK) - log_walsh2[i];
}
}
}