mod elementwise;
mod experiments;
mod gather;
mod gfni;
mod matrix;
mod nibble;
mod nibble_rows;
mod rows;
mod scatter;
pub use elementwise::*;
pub use experiments::*;
pub use gather::*;
pub use gfni::*;
pub use matrix::*;
pub use nibble::*;
pub use nibble_rows::*;
pub use scatter::*;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
use crate::field::gf8b::Elem;
use crate::field::gf8d;
use crate::kernel::Matrix;
use crate::kernel::tables::affine_8b;
use crate::kernel::tables::{ScaleTable, affine_8d, scale_table, scale_table_8d};
pub(super) trait Blocked {
type Coeff: Copy;
fn zero() -> Self::Coeff;
const AFFINE: bool;
fn byte(coeff: Self::Coeff) -> u8;
fn map(coeff: Self::Coeff) -> u64;
fn table(coeff: Self::Coeff) -> &'static ScaleTable;
}
pub(super) enum Gfni {}
impl Blocked for Gfni {
type Coeff = Elem;
const AFFINE: bool = false;
#[inline]
fn zero() -> Elem {
Elem(0)
}
#[inline]
fn byte(coeff: Elem) -> u8 {
coeff.0
}
#[inline]
fn map(_coeff: Elem) -> u64 {
0
}
#[inline]
fn table(coeff: Elem) -> &'static ScaleTable {
scale_table(coeff)
}
}
#[derive(Clone, Copy)]
pub struct Affine8BFactor {
map: u64,
table: &'static ScaleTable,
}
#[inline]
#[must_use]
pub fn prepare_affine_8b(coeff: Elem) -> Affine8BFactor {
Affine8BFactor {
map: affine_8b(coeff),
table: scale_table(coeff),
}
}
enum Affine8B {}
impl Blocked for Affine8B {
type Coeff = Affine8BFactor;
const AFFINE: bool = true;
#[inline]
fn zero() -> Affine8BFactor {
prepare_affine_8b(Elem(0))
}
#[inline]
fn byte(coeff: Affine8BFactor) -> u8 {
coeff.table.coeff.0
}
#[inline]
fn map(coeff: Affine8BFactor) -> u64 {
coeff.map
}
#[inline]
fn table(coeff: Affine8BFactor) -> &'static ScaleTable {
coeff.table
}
}
pub(super) enum Affine8D {}
impl Blocked for Affine8D {
type Coeff = gf8d::Elem;
const AFFINE: bool = true;
#[inline]
fn zero() -> gf8d::Elem {
gf8d::Elem(0)
}
#[inline]
fn byte(coeff: gf8d::Elem) -> u8 {
coeff.0
}
#[inline]
fn map(coeff: gf8d::Elem) -> u64 {
affine_8d(coeff)
}
#[inline]
fn table(coeff: gf8d::Elem) -> &'static ScaleTable {
scale_table_8d(coeff)
}
}
pub(super) enum Affine8DPrepared {}
impl Blocked for Affine8DPrepared {
type Coeff = crate::kernel::gf8::Prepared8D;
const AFFINE: bool = true;
#[inline]
fn zero() -> Self::Coeff {
crate::kernel::gf8::Prepared8D {
table: scale_table_8d(gf8d::Elem(0)),
affine: affine_8d(gf8d::Elem(0)),
}
}
#[inline]
fn byte(coeff: Self::Coeff) -> u8 {
coeff.table.coeff.0
}
#[inline]
fn map(coeff: Self::Coeff) -> u64 {
coeff.affine
}
#[inline]
fn table(coeff: Self::Coeff) -> &'static ScaleTable {
coeff.table
}
}
pub(super) struct PreparedMatrix<'a> {
pub(super) prepared: &'a [crate::kernel::gf8::Prepared8D],
pub(super) nrows: usize,
pub(super) sources: &'a [&'a [u8]],
}
impl Matrix<crate::kernel::gf8::Prepared8D> for PreparedMatrix<'_> {
#[inline]
fn len(&self) -> usize {
self.sources.len()
}
#[inline]
fn coefficient(&self, term: usize, row: usize) -> &crate::kernel::gf8::Prepared8D {
&self.prepared[term * self.nrows + row]
}
#[inline]
fn source(&self, term: usize) -> &[u8] {
self.sources[term]
}
}
#[inline]
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn bfactor<S: Blocked>(coeff: S::Coeff) -> __m256i {
if S::AFFINE {
_mm256_set1_epi64x(S::map(coeff).cast_signed())
} else {
_mm256_set1_epi8(S::byte(coeff).cast_signed())
}
}
#[inline]
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn bfactor128<S: Blocked>(coeff: S::Coeff) -> __m128i {
if S::AFFINE {
_mm_set1_epi64x(S::map(coeff).cast_signed())
} else {
_mm_set1_epi8(S::byte(coeff).cast_signed())
}
}
#[inline]
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn bmul<S: Blocked>(x: __m256i, factor: __m256i) -> __m256i {
if S::AFFINE {
_mm256_gf2p8affine_epi64_epi8::<0>(x, factor)
} else {
_mm256_gf2p8mul_epi8(x, factor)
}
}
#[inline]
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn bmul128<S: Blocked>(x: __m128i, factor: __m128i) -> __m128i {
if S::AFFINE {
_mm_gf2p8affine_epi64_epi8::<0>(x, factor)
} else {
_mm_gf2p8mul_epi8(x, factor)
}
}
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn brem<S: Blocked>(dst: &mut [u8], coeff: S::Coeff, src: &[u8]) {
if S::AFFINE {
gfni::mul_add_affine_impl(dst, S::map(coeff), S::table(coeff), src);
} else {
gfni::mul_add_gfni_impl(dst, Elem(S::byte(coeff)), src);
}
}
#[inline]
fn factor_word<S: Blocked>(coeff: S::Coeff) -> u64 {
if S::AFFINE {
S::map(coeff)
} else {
u64::from(S::byte(coeff))
}
}
#[inline]
#[archmage::rite(v3_gfni_crypto)]
pub(super) fn wfactor<S: Blocked>(word: u64) -> __m256i {
if S::AFFINE {
_mm256_set1_epi64x(word.cast_signed())
} else {
_mm256_set1_epi8(word.to_le_bytes()[0].cast_signed())
}
}