use crate::field::{Elem, FieldElem};
use crate::kernel::{FieldKernels, RawDispatch};
use super::check_pair;
#[cfg(feature = "alloc")]
use super::CoeffVecRef;
pub fn mul_add_scatter<F: FieldKernels>(
rows: &mut [u8],
row_len: usize,
coeffs: &[Elem<F>],
src: &[u8],
) {
check_pair::<F>("mul_add_scatter", "row_len", row_len, "src", src.len());
let used = coeffs
.len()
.checked_mul(row_len)
.expect("mul_add_scatter: row geometry overflows");
assert!(
rows.len() >= used,
"mul_add_scatter: rows is {} bytes but {} rows of {row_len} bytes need {used}",
rows.len(),
coeffs.len(),
);
if row_len == 0 || coeffs.is_empty() || coeffs.iter().all(|c| c.is_zero()) {
return;
}
F::mul_add_scatter(RawDispatch, &mut rows[..used], row_len, coeffs, src);
}
pub fn mul_into_scatter<F: FieldKernels>(
rows: &mut [u8],
row_len: usize,
coeffs: &[Elem<F>],
src: &[u8],
) {
check_pair::<F>("mul_into_scatter", "row_len", row_len, "src", src.len());
let used = coeffs
.len()
.checked_mul(row_len)
.expect("mul_into_scatter: row geometry overflows");
assert!(
rows.len() >= used,
"mul_into_scatter: rows is {} bytes but {} rows of {row_len} bytes need {used}",
rows.len(),
coeffs.len(),
);
if row_len == 0 || coeffs.is_empty() {
return;
}
F::mul_into_scatter(RawDispatch, &mut rows[..used], row_len, coeffs, src);
}
#[cfg(feature = "alloc")]
pub fn mul_add_scatter_with<F: FieldKernels>(
rows: &mut [u8],
row_len: usize,
coeffs: CoeffVecRef<'_, F>,
src: &[u8],
) {
check_pair::<F>("mul_add_scatter_with", "row_len", row_len, "src", src.len());
let used = coeffs
.len()
.checked_mul(row_len)
.expect("mul_add_scatter_with: row geometry overflows");
assert!(
rows.len() >= used,
"mul_add_scatter_with: rows is {} bytes but {} rows of {row_len} bytes need {used}",
rows.len(),
coeffs.len(),
);
if row_len == 0 || coeffs.values().all(FieldElem::is_zero) {
return;
}
F::mul_add_scatter_plan(
RawDispatch,
&mut rows[..used],
row_len,
coeffs.values,
coeffs.prepared,
src,
);
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use super::*;
use crate::field::poly::AES;
use crate::field::{Elem as E8, FiniteField, Polynomial};
#[test]
#[should_panic(expected = "mul_add_scatter")]
fn zero_row_length_still_checks_pairing() {
let coeffs = [E8::<FiniteField<2, 8, Polynomial<AES>>>::from_raw(0x07); 3];
let mut rows = [0u8; 8];
mul_add_scatter::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, &coeffs, &[1, 2, 3]);
}
}