use p3_binary_field::TowerLevel;
use p3_matrix::dense::RowMajorMatrix;
pub trait AdditiveNtt<F: TowerLevel> {
fn shifted_ntt_batch(&self, mat: RowMajorMatrix<F>, shift: F) -> RowMajorMatrix<F>;
fn shifted_intt_batch(&self, mat: RowMajorMatrix<F>, shift: F) -> RowMajorMatrix<F>;
fn ntt_batch(&self, mat: RowMajorMatrix<F>) -> RowMajorMatrix<F> {
self.shifted_ntt_batch(mat, F::ZERO)
}
fn intt_batch(&self, mat: RowMajorMatrix<F>) -> RowMajorMatrix<F> {
self.shifted_intt_batch(mat, F::ZERO)
}
fn lde_batch(&self, mat: RowMajorMatrix<F>, added_bits: usize) -> RowMajorMatrix<F> {
self.shifted_lde_batch(mat, added_bits, F::ZERO)
}
fn shifted_lde_batch(
&self,
mat: RowMajorMatrix<F>,
added_bits: usize,
shift: F,
) -> RowMajorMatrix<F> {
let coeffs = self.shifted_intt_batch(mat, shift);
let width = coeffs.width;
let len = coeffs.values.len();
let padded_len = u32::try_from(added_bits)
.ok()
.and_then(|bits| len.checked_shl(bits))
.filter(|&padded| padded >> added_bits == len)
.expect("extended codeword length overflows usize");
let mut values = F::zero_vec(padded_len);
values[..len].copy_from_slice(&coeffs.values);
self.shifted_ntt_batch(RowMajorMatrix::new(values, width), shift)
}
}