use crate::field::{Elem, FieldBuffer};
use crate::kernel::{FieldKernels, KernelDispatch, RawDispatch};
mod coefficient;
mod dot;
mod gather;
#[cfg(feature = "alloc")]
pub mod map;
#[cfg(feature = "alloc")]
pub mod map_bits;
mod matrix;
mod packing;
mod recip;
mod scatter;
mod single;
pub use coefficient::Coeff;
pub use dot::dot_product;
pub use gather::{add_gather_offsets, mul_add_gather, mul_into_gather};
pub use matrix::{mul_add_matrix, mul_add_matrix_at, mul_into_matrix, mul_into_matrix_at};
pub use packing::{pack, unpack};
pub use recip::{div_elementwise, div_elementwise_assign, inv_assign, inv_into};
pub use scatter::{mul_add_scatter, mul_into_scatter};
pub use single::{
add_assign, add_assign_rows, add_assign_scalar, mul_add, mul_add_with, mul_assign,
mul_assign_with, mul_elementwise, mul_elementwise_assign, mul_into, mul_into_with, sub_assign,
sub_assign_rows, sub_assign_scalar,
};
#[cfg(feature = "alloc")]
pub use coefficient::{CoeffMatrix, CoeffRef, CoeffVec, CoeffVecRef};
#[cfg(feature = "alloc")]
pub use gather::{mul_add_gather_with, mul_into_gather_with};
#[cfg(feature = "alloc")]
pub use map::{
apply_into_with, contains_into_with, embed_into_with, frobenius_assign_with,
frobenius_into_with, norm_into_with, restrict_into_with, trace_into_with, unapply_into_with,
};
#[cfg(feature = "alloc")]
pub use matrix::{
mul_add_matrix_at_with, mul_add_matrix_with, mul_into_matrix_at_with, mul_into_matrix_with,
};
#[cfg(feature = "alloc")]
pub use packing::{pack_to_vec, unpack_to_vec};
#[cfg(feature = "alloc")]
pub use scatter::mul_add_scatter_with;
mod private {
pub trait Sealed {}
}
#[allow(private_bounds)]
pub trait PreparedCoefficient<F: FieldKernels>: private::Sealed + PreparedRepr<F> {
fn value(&self) -> Elem<F>;
}
pub(crate) trait PreparedRepr<F: FieldKernels>: private::Sealed {
fn repr(&self, _proof: RawDispatch) -> &<F as KernelDispatch>::Prepared;
}
#[inline]
fn check_width<F: FieldBuffer>(name: &str, len: usize) {
assert!(
len.is_multiple_of(F::BYTES),
"{name}: buffer of {len} bytes is not a whole number of {} elements",
F::NAME
);
}
#[inline]
fn check_pair<F: FieldBuffer>(
name: &str,
left_name: &str,
left: usize,
right_name: &str,
right: usize,
) {
assert_eq!(
left, right,
"{name}: {left_name} is {left} bytes but {right_name} is {right} bytes"
);
check_width::<F>(name, left);
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use super::*;
use crate::field::binary::tower::Rijndael16Field;
use crate::field::poly::AES;
use crate::field::{Elem as E8, FiniteField, Polynomial};
#[test]
#[allow(clippy::type_complexity)]
fn zero_row_length_is_a_no_op() {
let coeffs = [E8::<FiniteField<2, 8, Polynomial<AES>>>::from_raw(0x07); 3];
let mut rows = [0xA5u8; 8];
mul_add_scatter::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, &coeffs, &[]);
assert_eq!(rows, [0xA5; 8]);
let coeffs_vec = CoeffVec::<FiniteField<2, 8, Polynomial<AES>>>::new(&coeffs);
mul_add_scatter_with::<FiniteField<2, 8, Polynomial<AES>>>(
&mut rows,
0,
coeffs_vec.as_ref(),
&[],
);
assert_eq!(rows, [0xA5; 8]);
let terms: &[(&[E8<FiniteField<2, 8, Polynomial<AES>>>], &[u8])] = &[(&coeffs, &[])];
mul_add_matrix::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, 3, terms);
assert_eq!(rows, [0xA5; 8]);
mul_into_matrix::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, 3, terms);
assert_eq!(rows, [0xA5; 8]);
mul_add_matrix_at::<FiniteField<2, 8, Polynomial<AES>>>(
&mut rows,
0,
&[1, 4],
&[(&coeffs[..2], &[])],
);
assert_eq!(rows, [0xA5; 8]);
let matrix =
CoeffMatrix::<FiniteField<2, 8, Polynomial<AES>>>::from_source_major(1, 3, &coeffs);
mul_add_matrix_with::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, &matrix, &[&[]]);
assert_eq!(rows, [0xA5; 8]);
mul_into_matrix_with::<FiniteField<2, 8, Polynomial<AES>>>(&mut rows, 0, &matrix, &[&[]]);
assert_eq!(rows, [0xA5; 8]);
let wide = [Elem::<Rijndael16Field>::from_raw(0x0103); 2];
let mut rows16 = [0x5Au8; 4];
mul_add_scatter::<Rijndael16Field>(&mut rows16, 0, &wide, &[]);
assert_eq!(rows16, [0x5A; 4]);
}
}