mod avx2;
#[cfg(feature = "simd512")]
mod avx512;
mod gfni;
mod ssse3;
pub use avx2::{
mul_add_avx2, mul_add_scatter_avx2, mul_assign_avx2, mul_elementwise_assign_avx2,
mul_elementwise_avx2, mul_into_avx2,
};
#[cfg(all(test, feature = "simd512"))]
pub(crate) use avx512::MUL_ADD_PEEL_MIN;
#[cfg(feature = "simd512")]
pub use avx512::{
mul_add_avx512, mul_add_matrix_avx512, mul_add_matrix_avx512_with, mul_assign_avx512,
mul_elementwise_assign_avx512, mul_elementwise_avx512, mul_into_avx512,
};
pub use gfni::{
mul_add_gather_gfni, mul_add_gfni, mul_add_matrix_gfni, mul_add_matrix_gfni_with,
mul_add_scatter_gfni, mul_assign_gfni, mul_elementwise_assign_gfni, mul_elementwise_gfni,
mul_into_gfni,
};
pub use ssse3::{
mul_add_gather_ssse3, mul_add_matrix_ssse3, mul_add_matrix_ssse3_with, mul_add_scatter_ssse3,
mul_add_ssse3, mul_assign_ssse3, mul_elementwise_assign_ssse3, mul_elementwise_ssse3,
mul_into_ssse3,
};
pub(crate) use avx2::{NibbleAvx2, nibble_avx2, scale_avx2};
pub(crate) use ssse3::{nibble_ssse3, scale_ssse3};
use crate::kernel::tables::TowerCoeff;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[inline]
fn check_elements(name: &str, bytes: usize) {
assert!(
bytes.is_multiple_of(2),
"{name}: buffer of {bytes} bytes ends with a partial GF(2^16) element",
);
}
const SWAP_ADJACENT: [u8; 16] = [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14];
const SWAP_ADJACENT_AVX2: [u8; 32] = {
let mut wide = [0u8; 32];
let mut i = 0;
while i < 32 {
wide[i] = SWAP_ADJACENT[i & 15];
i += 1;
}
wide
};
#[inline]
fn broadcast_words(coeff: TowerCoeff) -> (i16, i16) {
(
i16::from_ne_bytes(coeff.same.to_ne_bytes()),
i16::from_ne_bytes(coeff.cross.to_ne_bytes()),
)
}
#[archmage::rite(v3, import_intrinsics)]
fn swap_mask_avx2() -> __m256i {
_mm256_loadu_si256(&SWAP_ADJACENT_AVX2)
}
#[archmage::rite(v2, import_intrinsics)]
fn swap_mask_ssse3() -> __m128i {
_mm_loadu_si128(&SWAP_ADJACENT)
}
const TERM_TILE: usize = 8;