binius_math/
deinterleave.rsuse binius_field::PackedField;
use itertools::Either;
use std::iter;
pub fn deinterleave<P: PackedField>(
log_scalar_count: usize,
interleaved: &[P],
) -> impl Iterator<Item = (usize, P, P)> + '_ {
assert_eq!(interleaved.len(), 1 << (log_scalar_count + 1).saturating_sub(P::LOG_WIDTH));
if log_scalar_count < P::LOG_WIDTH {
let mut even = P::zero();
let mut odd = P::zero();
for i in 0..1 << log_scalar_count {
even.set(i, interleaved[0].get(2 * i));
odd.set(i, interleaved[0].get(2 * i + 1));
}
return Either::Left(iter::once((0, even, odd)));
}
let deinterleaved = (0..1 << (log_scalar_count - P::LOG_WIDTH)).map(|i| {
let mut even = interleaved[2 * i];
let mut odd = interleaved[2 * i + 1];
for log_block_len in (0..P::LOG_WIDTH).rev() {
let (even_interleaved, odd_interleaved) = even.interleave(odd, log_block_len);
even = even_interleaved;
odd = odd_interleaved;
}
(i, even, odd)
});
Either::Right(deinterleaved)
}