use super::super::check_scattered;
use super::rows::{matrix_rows1, matrix_rows2, matrix_rows4};
use super::{Affine8D, Blocked, Gfni};
use crate::field::gf8b::Elem;
use crate::field::gf8d;
use crate::kernel::Matrix;
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_gfni(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &[(&[Elem], &[u8])],
) {
for (t, (coeffs, _)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
nrows,
"mul_add_matrix_gfni: term {t} needs {nrows} coefficients"
);
}
mul_add_matrix_gfni_with(_token, rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_gfni_with<M: Matrix<Elem> + ?Sized>(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &M,
) {
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|needed| needed <= rows.len()),
"mul_add_matrix_gfni: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
for term in 0..terms.len() {
assert_eq!(terms.source(term).len(), row_len);
}
if terms.len() == 0 {
return;
}
mul_add_matrix_impl::<Gfni, M, false>(rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_gfni_8d(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &[(&[gf8d::Elem], &[u8])],
) {
for (t, (coeffs, _)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
nrows,
"mul_add_matrix_gfni_8d: term {t} needs {nrows} coefficients"
);
}
mul_add_matrix_gfni_8d_with(_token, rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_gfni_8d_with<M: Matrix<gf8d::Elem> + ?Sized>(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &M,
) {
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|needed| needed <= rows.len()),
"mul_add_matrix_gfni_8d: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
for term in 0..terms.len() {
assert_eq!(terms.source(term).len(), row_len);
}
if terms.len() == 0 {
return;
}
mul_add_matrix_impl::<Affine8D, M, false>(rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_gfni(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &[(&[Elem], &[u8])],
) {
for (t, (coeffs, _)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
nrows,
"mul_into_matrix_gfni: term {t} needs {nrows} coefficients"
);
}
mul_into_matrix_gfni_with(_token, rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_gfni_with<M: Matrix<Elem> + ?Sized>(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &M,
) {
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|needed| needed <= rows.len()),
"mul_into_matrix_gfni: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
for term in 0..terms.len() {
assert_eq!(terms.source(term).len(), row_len);
}
mul_add_matrix_impl::<Gfni, M, true>(rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_gfni_8d(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &[(&[gf8d::Elem], &[u8])],
) {
for (t, (coeffs, _)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
nrows,
"mul_into_matrix_gfni_8d: term {t} needs {nrows} coefficients"
);
}
mul_into_matrix_gfni_8d_with(_token, rows, row_len, nrows, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_gfni_8d_with<M: Matrix<gf8d::Elem> + ?Sized>(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &M,
) {
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|needed| needed <= rows.len()),
"mul_into_matrix_gfni_8d: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
for term in 0..terms.len() {
assert_eq!(terms.source(term).len(), row_len);
}
mul_add_matrix_impl::<Affine8D, M, true>(rows, row_len, nrows, terms);
}
#[allow(unsafe_code)]
#[archmage::rite(v3_gfni_crypto)]
fn mul_add_matrix_impl<S: Blocked, M: Matrix<S::Coeff> + ?Sized, const OVERWRITE: bool>(
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &M,
) {
let base = rows.as_mut_ptr();
let mut g = 0;
while g + 4 <= nrows {
let ptrs = unsafe {
[
base.add(g * row_len),
base.add((g + 1) * row_len),
base.add((g + 2) * row_len),
base.add((g + 3) * row_len),
]
};
matrix_rows4::<S, M, OVERWRITE>(ptrs, row_len, g, terms);
g += 4;
}
if g + 2 <= nrows {
let ptrs = unsafe { [base.add(g * row_len), base.add((g + 1) * row_len)] };
matrix_rows2::<S, M, OVERWRITE>(ptrs, row_len, g, terms);
g += 2;
}
if g < nrows {
let ptr = unsafe { base.add(g * row_len) };
matrix_rows1::<S, M, OVERWRITE>(ptr, row_len, g, terms);
}
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_at_gfni(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
row_len: usize,
row_starts: &[usize],
terms: &[(&[Elem], &[u8])],
) {
check_scattered("mul_add_matrix_at_gfni", dst.len(), row_len, row_starts);
for (t, (coeffs, src)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
row_starts.len(),
"mul_add_matrix_at_gfni: term {t} needs {} coefficients",
row_starts.len()
);
assert_eq!(src.len(), row_len);
}
if terms.is_empty() || row_starts.is_empty() {
return;
}
mul_add_matrix_at_impl::<Gfni, _>(dst, row_len, row_starts, terms);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_add_matrix_at_gfni_8d(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
row_len: usize,
row_starts: &[usize],
terms: &[(&[gf8d::Elem], &[u8])],
) {
check_scattered("mul_add_matrix_at_gfni_8d", dst.len(), row_len, row_starts);
for (t, (coeffs, src)) in terms.iter().enumerate() {
assert_eq!(
coeffs.len(),
row_starts.len(),
"mul_add_matrix_at_gfni_8d: term {t} needs {} coefficients",
row_starts.len()
);
assert_eq!(src.len(), row_len);
}
if terms.is_empty() || row_starts.is_empty() {
return;
}
mul_add_matrix_at_impl::<Affine8D, _>(dst, row_len, row_starts, terms);
}
#[allow(unsafe_code)]
#[archmage::rite(v3_gfni_crypto)]
fn mul_add_matrix_at_impl<S: Blocked, M: Matrix<S::Coeff> + ?Sized>(
dst: &mut [u8],
row_len: usize,
row_starts: &[usize],
terms: &M,
) {
let base = dst.as_mut_ptr();
let nrows = row_starts.len();
let mut g = 0;
while g + 4 <= nrows {
let ptrs = unsafe {
[
base.add(row_starts[g]),
base.add(row_starts[g + 1]),
base.add(row_starts[g + 2]),
base.add(row_starts[g + 3]),
]
};
matrix_rows4::<S, M, false>(ptrs, row_len, g, terms);
g += 4;
}
if g + 2 <= nrows {
let ptrs = unsafe { [base.add(row_starts[g]), base.add(row_starts[g + 1])] };
matrix_rows2::<S, M, false>(ptrs, row_len, g, terms);
g += 2;
}
if g < nrows {
let ptr = unsafe { base.add(row_starts[g]) };
matrix_rows1::<S, M, false>(ptr, row_len, g, terms);
}
}