use super::super::Affine8D;
use super::super::rows::rows_resolved_chunked;
use super::rows_external_chunked;
use crate::field::gf8d;
#[allow(clippy::used_underscore_binding)]
#[allow(unsafe_code)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_chunk_8d(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
terms: &[(&[gf8d::Elem], &[u8])],
chunk: usize,
) {
type Terms<'a> = [(&'a [gf8d::Elem], &'a [u8])];
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|used| used <= rows.len()),
"matrix_overwrite_chunk: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
for (coeffs, src) in terms {
assert_eq!(src.len(), row_len);
assert_eq!(
coeffs.len(),
nrows,
"matrix_overwrite_chunk: term needs {nrows} coefficients"
);
}
assert!(
matches!(chunk, 32 | 64 | 96),
"matrix_overwrite_chunk: chunk must be 32, 64 or 96"
);
let base = rows.as_mut_ptr();
unsafe {
let mut g = 0;
while g + 4 <= nrows {
let ptrs = [
base.add(g * row_len),
base.add((g + 1) * row_len),
base.add((g + 2) * row_len),
base.add((g + 3) * row_len),
];
match chunk {
32 => rows_resolved_chunked::<Affine8D, Terms, 4, 2, true, 32, false>(
ptrs, row_len, g, terms,
),
64 => rows_resolved_chunked::<Affine8D, Terms, 4, 2, true, 64, false>(
ptrs, row_len, g, terms,
),
_ => rows_resolved_chunked::<Affine8D, Terms, 4, 2, true, 96, false>(
ptrs, row_len, g, terms,
),
}
g += 4;
}
if g + 2 <= nrows {
let ptrs = [base.add(g * row_len), base.add((g + 1) * row_len)];
match chunk {
32 => rows_resolved_chunked::<Affine8D, Terms, 2, 4, true, 32, false>(
ptrs, row_len, g, terms,
),
64 => rows_resolved_chunked::<Affine8D, Terms, 2, 4, true, 64, false>(
ptrs, row_len, g, terms,
),
_ => rows_resolved_chunked::<Affine8D, Terms, 2, 4, true, 96, false>(
ptrs, row_len, g, terms,
),
}
g += 2;
}
if g < nrows {
let ptrs = [base.add(g * row_len)];
match chunk {
32 => rows_resolved_chunked::<Affine8D, Terms, 1, 4, true, 32, false>(
ptrs, row_len, g, terms,
),
64 => rows_resolved_chunked::<Affine8D, Terms, 1, 4, true, 64, false>(
ptrs, row_len, g, terms,
),
_ => rows_resolved_chunked::<Affine8D, Terms, 1, 4, true, 96, false>(
ptrs, row_len, g, terms,
),
}
}
}
}
#[allow(clippy::used_underscore_binding)]
#[allow(unsafe_code)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_into_matrix_external_grouped_8d(
_token: archmage::X64V3GfniCryptoToken,
rows: &mut [u8],
row_len: usize,
nrows: usize,
maps: &[u64],
srcs: &[&[u8]],
chunk: usize,
) {
assert_eq!(
row_len % 32,
0,
"matrix_overwrite_external_grouped: needs a 32-byte-multiple row"
);
assert!(
nrows
.checked_mul(row_len)
.is_some_and(|used| used <= rows.len()),
"matrix_overwrite_external_grouped: rows buffer does not hold {nrows} rows of {row_len} bytes"
);
assert_eq!(
maps.len(),
nrows * srcs.len(),
"matrix_overwrite_external_grouped: one map word per (term, row)"
);
for src in srcs {
assert_eq!(src.len(), row_len);
}
assert!(
matches!(chunk, 0 | 32 | 64 | 96),
"matrix_overwrite_external_grouped: chunk must be 0, 32, 64 or 96"
);
let terms = srcs.len();
if terms == 0 {
rows[..nrows * row_len].fill(0);
return;
}
let base = rows.as_mut_ptr();
unsafe {
let mut cursor = 0;
let mut g = 0;
while g + 4 <= nrows {
let (group, rest) = maps[cursor..cursor + terms * 4].as_chunks::<4>();
debug_assert!(rest.is_empty());
rows_external_chunked::<4, 2>(
[
base.add(g * row_len),
base.add((g + 1) * row_len),
base.add((g + 2) * row_len),
base.add((g + 3) * row_len),
],
row_len,
group,
srcs,
chunk,
);
cursor += terms * 4;
g += 4;
}
if g + 2 <= nrows {
let (group, rest) = maps[cursor..cursor + terms * 2].as_chunks::<2>();
debug_assert!(rest.is_empty());
rows_external_chunked::<2, 4>(
[base.add(g * row_len), base.add((g + 1) * row_len)],
row_len,
group,
srcs,
chunk,
);
cursor += terms * 2;
g += 2;
}
if g < nrows {
let (group, rest) = maps[cursor..cursor + terms].as_chunks::<1>();
debug_assert!(rest.is_empty());
rows_external_chunked::<1, 4>([base.add(g * row_len)], row_len, group, srcs, chunk);
}
}
}