#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
pub(crate) mod matrix;
pub(crate) mod single;
#[archmage::rite(v4)]
fn subtract_p(r: __m512i, p: __m512i) -> __m512i {
let ge = _mm512_cmp_epu64_mask::<{ _MM_CMPINT_NLT }>(r, p);
_mm512_mask_sub_epi64(r, ge, r, p)
}
#[archmage::rite(v4)]
pub(super) fn narrow_avx512(t: __m512i, mu: __m512i, p: __m512i, shift: i32) -> __m512i {
let mid = _mm512_add_epi64(
_mm512_srli_epi64::<32>(_mm512_mul_epu32(t, mu)),
_mm512_mul_epu32(_mm512_srli_epi64::<32>(t), mu),
);
let q = _mm512_srl_epi64(mid, _mm_cvtsi32_si128(shift));
let r = _mm512_sub_epi64(t, _mm512_mul_epu32(q, p));
subtract_p(subtract_p(r, p), p)
}
#[archmage::rite(v4)]
pub(super) fn normalize_avx512(x: __m512i, norm_mu: __m512i, p32: __m512i) -> __m512i {
let e = _mm512_srli_epi64::<32>(_mm512_mul_epu32(x, norm_mu));
let o = _mm512_srli_epi64::<32>(_mm512_mul_epu32(_mm512_srli_epi64::<32>(x), norm_mu));
let q = _mm512_or_si512(e, _mm512_slli_epi64::<32>(o));
let r = _mm512_sub_epi32(x, _mm512_mullo_epi32(q, p32));
_mm512_min_epu32(r, _mm512_sub_epi32(r, p32))
}
#[archmage::rite(v4)]
#[must_use]
pub(super) fn combine_halves_avx512(ev: __m512i, od: __m512i) -> __m512i {
_mm512_or_si512(ev, _mm512_slli_epi64::<32>(od))
}
#[archmage::rite(v4)]
pub(super) fn widen_add_avx512(a: __m512i, b: __m512i, p64: __m512i, p_m1: __m512i) -> __m512i {
let ae = _mm512_mul_epu32(a, _mm512_set1_epi64(1));
let ao = _mm512_mul_epu32(_mm512_shuffle_epi32::<0xB1>(a), _mm512_set1_epi64(1));
let be = _mm512_mul_epu32(b, _mm512_set1_epi64(1));
let bo = _mm512_mul_epu32(_mm512_shuffle_epi32::<0xB1>(b), _mm512_set1_epi64(1));
let se = _mm512_add_epi64(ae, be);
let so = _mm512_add_epi64(ao, bo);
let se = _mm512_mask_sub_epi64(
se,
_mm512_cmp_epu64_mask::<{ _MM_CMPINT_NLE }>(se, p_m1),
se,
p64,
);
let so = _mm512_mask_sub_epi64(
so,
_mm512_cmp_epu64_mask::<{ _MM_CMPINT_NLE }>(so, p_m1),
so,
p64,
);
combine_halves_avx512(se, so)
}