#[cfg(not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
)))]
mod avx2;
#[cfg(target_feature = "avx512f")]
mod avx512;
#[cfg(not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
)))]
mod triples;
#[cfg(not(target_feature = "avx512f"))]
pub(crate) use avx2::*;
#[cfg(target_feature = "avx512f")]
pub(crate) use avx512::*;
#[cfg(not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
)))]
use crate::clmul::wide::{Lanes64, TOP_NIBBLE_FOLD};
use crate::packed::split::Lanes;
const SWAP_QUADWORDS: i32 = 0x4e;
#[cfg(all(
target_feature = "avx512vl",
not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
))
))]
const XOR3: i32 = 0x96;
#[cfg(not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
)))]
pub(crate) mod gf64 {
use core::array;
pub(crate) use super::avx2::{Reg, interleave_64};
use super::avx2::{WIDTH, deinterleave_3, interleave_3, load, store};
pub(crate) const WIDTH_64: usize = 2 * WIDTH;
#[inline(always)]
pub(crate) unsafe fn gather_3(from: *const u64) -> [Reg; 3] {
let rows = unsafe { array::from_fn(|r| load(from.add(r * WIDTH_64).cast())) };
deinterleave_3(rows)
}
#[inline(always)]
pub(crate) unsafe fn scatter_3(to: *mut u64, coordinates: [Reg; 3]) {
for (r, row) in interleave_3(coordinates).into_iter().enumerate() {
unsafe { store(to.add(r * WIDTH_64).cast(), row) };
}
}
}
impl Lanes for Reg {
#[inline(always)]
fn zero() -> Self {
zero()
}
#[inline(always)]
fn broadcast(value: u128) -> Self {
broadcast(value)
}
#[inline(always)]
fn xor(self, other: Self) -> Self {
xor(self, other)
}
#[inline(always)]
fn unpack_low_64(self, other: Self) -> Self {
unpack_low_64(self, other)
}
#[inline(always)]
fn clmul<const IMM: i32>(self, other: Self) -> Self {
clmul::<IMM>(self, other)
}
}
#[cfg(not(all(
feature = "wide-poly",
target_feature = "avx512f",
target_feature = "avx512bw"
)))]
impl Lanes64 for avx2::Reg {
#[inline(always)]
fn zero() -> Self {
avx2::zero()
}
#[inline(always)]
fn xor(self, other: Self) -> Self {
avx2::xor(self, other)
}
#[inline(always)]
fn xor3(self, b: Self, c: Self) -> Self {
avx2::xor3(self, b, c)
}
#[inline(always)]
fn clmul<const IMM: i32>(self, other: Self) -> Self {
avx2::clmul::<IMM>(self, other)
}
#[inline(always)]
fn unpack_low(self, other: Self) -> Self {
avx2::unpack_low_64(self, other)
}
#[inline(always)]
fn unpack_high(self, other: Self) -> Self {
avx2::unpack_high_64(self, other)
}
#[inline(always)]
fn shl<const N: i32>(self) -> Self {
avx2::shl_64::<N>(self)
}
#[inline(always)]
fn shr<const N: i32>(self) -> Self {
avx2::shr_64::<N>(self)
}
#[inline(always)]
fn fold_top_nibble(self) -> Self {
let table = avx2::broadcast(u128::from_le_bytes(TOP_NIBBLE_FOLD));
avx2::shuffle_bytes(table, avx2::shr_64::<60>(self))
}
}
#[cfg(all(
target_feature = "avx512f",
not(all(feature = "wide-poly", target_feature = "avx512bw"))
))]
impl Lanes64 for avx512::Reg {
#[inline(always)]
fn zero() -> Self {
avx512::zero()
}
#[inline(always)]
fn xor(self, other: Self) -> Self {
avx512::xor(self, other)
}
#[inline(always)]
fn clmul<const IMM: i32>(self, other: Self) -> Self {
avx512::clmul::<IMM>(self, other)
}
#[inline(always)]
fn unpack_low(self, other: Self) -> Self {
avx512::unpack_low_64(self, other)
}
#[inline(always)]
fn unpack_high(self, other: Self) -> Self {
avx512::unpack_high_64(self, other)
}
#[inline(always)]
fn shl<const N: i32>(self) -> Self {
avx512::shl_64::<N>(self)
}
#[inline(always)]
fn shr<const N: i32>(self) -> Self {
avx512::shr_64::<N>(self)
}
}