use super::super::gfni::{
ISO_11D_TO_11B, mul_elementwise_assign_gfni, mul_elementwise_assign_gfni_8d,
mul_elementwise_gfni, mul_elementwise_gfni_8d,
};
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_avx512(token: archmage::X64V4xToken, dst: &mut [u8], a: &[u8], b: &[u8]) {
assert_eq!(
dst.len(),
a.len(),
"mul_elementwise_avx512: dst and a differ in length"
);
assert_eq!(
dst.len(),
b.len(),
"mul_elementwise_avx512: dst and b differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<64>();
let (a_lanes, a_rest) = a.as_chunks::<64>();
let (b_lanes, b_rest) = b.as_chunks::<64>();
for ((dlane, alane), blane) in dst_lanes.iter_mut().zip(a_lanes).zip(b_lanes) {
let x = _mm512_loadu_si512(alane);
let y = _mm512_loadu_si512(blane);
_mm512_storeu_si512(dlane, _mm512_gf2p8mul_epi8(x, y));
}
mul_elementwise_gfni(token.v3_gfni_crypto(), dst_rest, a_rest, b_rest);
}
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_assign_avx512(token: archmage::X64V4xToken, dst: &mut [u8], src: &[u8]) {
assert_eq!(
dst.len(),
src.len(),
"mul_elementwise_assign_avx512: dst and src differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<64>();
let (src_lanes, src_rest) = src.as_chunks::<64>();
for (dlane, slane) in dst_lanes.iter_mut().zip(src_lanes) {
let x = _mm512_loadu_si512(&*dlane);
let y = _mm512_loadu_si512(slane);
_mm512_storeu_si512(dlane, _mm512_gf2p8mul_epi8(x, y));
}
mul_elementwise_assign_gfni(token.v3_gfni_crypto(), dst_rest, src_rest);
}
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_avx512_8d(token: archmage::X64V4xToken, dst: &mut [u8], a: &[u8], b: &[u8]) {
assert_eq!(
dst.len(),
a.len(),
"mul_elementwise_avx512_8d: dst and a differ in length"
);
assert_eq!(
dst.len(),
b.len(),
"mul_elementwise_avx512_8d: dst and b differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<64>();
let (a_lanes, a_rest) = a.as_chunks::<64>();
let (b_lanes, b_rest) = b.as_chunks::<64>();
for ((dlane, alane), blane) in dst_lanes.iter_mut().zip(a_lanes).zip(b_lanes) {
let x = _mm512_loadu_si512(alane);
let y = _mm512_loadu_si512(blane);
_mm512_storeu_si512(dlane, multiply_vectors_8d(x, y));
}
mul_elementwise_gfni_8d(token.v3_gfni_crypto(), dst_rest, a_rest, b_rest);
}
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_assign_avx512_8d(token: archmage::X64V4xToken, dst: &mut [u8], src: &[u8]) {
assert_eq!(
dst.len(),
src.len(),
"mul_elementwise_assign_avx512_8d: dst and src differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<64>();
let (src_lanes, src_rest) = src.as_chunks::<64>();
for (dlane, slane) in dst_lanes.iter_mut().zip(src_lanes) {
let x = _mm512_loadu_si512(&*dlane);
let y = _mm512_loadu_si512(slane);
_mm512_storeu_si512(dlane, multiply_vectors_8d(x, y));
}
mul_elementwise_assign_gfni_8d(token.v3_gfni_crypto(), dst_rest, src_rest);
}
#[inline]
#[archmage::rite(v4x, import_intrinsics)]
fn multiply_vectors_8d(x: __m512i, y: __m512i) -> __m512i {
let phi = _mm512_set1_epi64(ISO_11D_TO_11B.cast_signed());
let px = _mm512_gf2p8affine_epi64_epi8::<0>(x, phi);
let py = _mm512_gf2p8affine_epi64_epi8::<0>(y, phi);
_mm512_gf2p8affine_epi64_epi8::<0>(_mm512_gf2p8mul_epi8(px, py), phi)
}