use crate::register::ZeroUpper;
use super::*;
#[inline(always)]
pub unsafe fn _mm_srai_epi64x_v1(v: __m128i, cnt: i32) -> __m128i {
let m = _mm_set1_epi64x(1i64 << (63 - cnt));
_mm_sub_epi64(_mm_xor_si128(_mm_srl_epi64(v, _mm_cvtsi32_si128(cnt)), m), m)
}
#[inline(always)]
pub unsafe fn _mm_srlv_epi64x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let count_high = _mm_unpackhi_epi64(shifts, shifts);
let shifted_low = _mm_srl_epi64(value, shifts); let mut shifted_high = _mm_srl_epi64(value, count_high);
shifted_high = _mm_unpackhi_epi64(shifted_high, shifted_high);
_mm_unpacklo_epi64(shifted_low, shifted_high) }
#[target_feature(enable = "sse2")] #[inline]
pub unsafe fn _mm_srlv_epi32x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let shifts: [u32; 4] = core::mem::transmute(shifts);
let mut value: [u32; 4] = core::mem::transmute(value);
for (value, shift) in value.iter_mut().zip(shifts) {
*value >>= shift;
}
core::mem::transmute(value)
}
#[inline(always)]
pub unsafe fn _mm_sllv_epi64x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let count_high = _mm_unpackhi_epi64(shifts, shifts);
let shifted_low = _mm_sll_epi64(value, shifts); let mut shifted_high = _mm_sll_epi64(value, count_high);
shifted_high = _mm_unpackhi_epi64(shifted_high, shifted_high);
_mm_unpacklo_epi64(shifted_low, shifted_high) }
#[target_feature(enable = "sse2")]
#[inline]
pub unsafe fn _mm_sllv_epi32x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let shifts: [u32; 4] = core::mem::transmute(shifts);
let mut value: [u32; 4] = core::mem::transmute(value);
for (value, shift) in value.iter_mut().zip(shifts) {
*value <<= shift;
}
core::mem::transmute(value)
}
#[inline(always)]
pub unsafe fn _mm_srav_epi64x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let m = _mm_srlv_epi64x_v1(_mm_set1_epu64x(1 << 63), shifts);
_mm_sub_epi64(_mm_xor_si128(_mm_srlv_epi64x_v1(value, shifts), m), m)
}
#[target_feature(enable = "sse2")]
#[inline]
pub unsafe fn _mm_srav_epi32x_v1(value: __m128i, shifts: __m128i) -> __m128i {
let shifts: [u32; 4] = core::mem::transmute(shifts);
let mut value: [i32; 4] = core::mem::transmute(value);
for (value, shift) in value.iter_mut().zip(shifts) {
*value >>= shift;
}
core::mem::transmute(value)
}
#[inline(always)]
pub unsafe fn _mm_popcnt_epi8x_v1(v: __m128i) -> __m128i {
let v = _mm_sub_epi8(v, _mm_and_si128(_mm_srli_epi16(v, 1), _mm_set1_epi8(0x55)));
let v = _mm_add_epi8(
_mm_and_si128(v, _mm_set1_epi8(0x33)),
_mm_and_si128(_mm_srli_epi16(v, 2), _mm_set1_epi8(0x33)),
);
_mm_and_si128(_mm_add_epi8(v, _mm_srli_epi16(v, 4)), _mm_set1_epi8(0x0F))
}
#[inline(always)]
pub unsafe fn _mm_popcnt_epi16x_v1(v: __m128i) -> __m128i {
let bytes = _mm_popcnt_epi8x_v1(v);
_mm_add_epi16(_mm_and_si128(bytes, _mm_set1_epi16(0x00FF)), _mm_srli_epi16(bytes, 8))
}
#[inline(always)]
pub unsafe fn _mm_bswap_epi16x_v1(v: __m128i) -> __m128i {
_mm_or_si128(_mm_slli_epi16(v, 8), _mm_srli_epi16(v, 8))
}
#[inline(always)]
pub unsafe fn _mm_popcnt_epi32x_v1(v: __m128i) -> __m128i {
let bytes = _mm_popcnt_epi8x_v1(v);
let sum16 = _mm_add_epi16(_mm_and_si128(bytes, _mm_set1_epi16(0x00FF)), _mm_srli_epi16(bytes, 8));
_mm_add_epi32(
_mm_and_si128(sum16, _mm_set1_epi32(0x0000FFFF)),
_mm_srli_epi32(sum16, 16),
)
}
#[inline(always)]
pub unsafe fn _mm_popcnt_epi64x_v1(v: __m128i) -> __m128i {
_mm_sad_epu8(_mm_popcnt_epi8x_v1(v), _mm_setzero_si128())
}
#[inline(always)]
pub unsafe fn _mm_bswap_epi32x_v1(x: __m128i) -> __m128i {
let t = _mm_or_si128(_mm_slli_epi16(x, 8), _mm_srli_epi16(x, 8));
_mm_or_si128(_mm_slli_epi32(t, 16), _mm_srli_epi32(t, 16))
}
#[inline(always)]
pub unsafe fn _mm_bswap_epi64x_v1(x: __m128i) -> __m128i {
_mm_shuffle_epi32::<{ MM_SHUFFLE!(2, 3, 0, 1) }>(_mm_bswap_epi32x_v1(x))
}
#[inline(always)]
pub unsafe fn _mm_bswap_psx_v1(x: __m128) -> __m128 {
_mm_castsi128_ps(_mm_bswap_epi32x_v1(_mm_castps_si128(x)))
}
#[inline(always)]
pub unsafe fn _mm_bswap_pdx_v1(x: __m128d) -> __m128d {
_mm_castsi128_pd(_mm_bswap_epi64x_v1(_mm_castpd_si128(x)))
}
#[inline(always)]
pub unsafe fn _mm_zeroupper_mask_epi32<Z: ZeroUpper>() -> __m128i {
use crate::element::MaskElement;
_mm_setr_epi32(
i32::from_bool(0 < Z::N),
i32::from_bool(1 < Z::N),
i32::from_bool(2 < Z::N),
i32::from_bool(3 < Z::N),
)
}
#[inline(always)]
pub unsafe fn _mm_slli_epi8x_v1<const IMM8: i32>(v: __m128i) -> __m128i {
let keep = 0xFFu8.wrapping_shl(IMM8 as u32) as i8; _mm_and_si128(_mm_slli_epi16(v, IMM8), _mm_set1_epi8(keep))
}
#[inline(always)]
pub unsafe fn _mm_srli_epi8x_v1<const IMM8: i32>(v: __m128i) -> __m128i {
let keep = (0xFFu8 >> IMM8) as i8;
_mm_and_si128(_mm_srli_epi16(v, IMM8), _mm_set1_epi8(keep))
}
#[inline(always)]
pub unsafe fn _mm_srai_epi8x_v1<const IMM8: i32>(v: __m128i) -> __m128i {
let logical = _mm_srli_epi8x_v1::<IMM8>(v);
let m = _mm_set1_epi8((0x80u8 >> IMM8) as i8);
_mm_sub_epi8(_mm_xor_si128(logical, m), m)
}
#[inline(always)]
pub unsafe fn _mm_sll_epi8x_v1(v: __m128i, shift: u32) -> __m128i {
let keep = (0xFFu32.wrapping_shl(shift) as u8) as i8;
_mm_and_si128(_mm_sll_epi16(v, _mm_cvtsi32_si128(shift as i32)), _mm_set1_epi8(keep))
}
#[inline(always)]
pub unsafe fn _mm_srl_epi8x_v1(v: __m128i, shift: u32) -> __m128i {
let keep = ((0xFFu32 >> shift.min(31)) as u8) as i8;
_mm_and_si128(_mm_srl_epi16(v, _mm_cvtsi32_si128(shift as i32)), _mm_set1_epi8(keep))
}
#[inline(always)]
pub unsafe fn _mm_sra_epi8x_v1(v: __m128i, shift: u32) -> __m128i {
let logical = _mm_srl_epi8x_v1(v, shift);
let m = _mm_set1_epi8(((0x80u32 >> shift.min(31)) as u8) as i8);
_mm_sub_epi8(_mm_xor_si128(logical, m), m)
}
#[inline(always)]
pub unsafe fn _mm_mullo_epi8x_v1(a: __m128i, b: __m128i) -> __m128i {
let lo_mask = _mm_set1_epi16(0x00FF);
let even = _mm_mullo_epi16(_mm_and_si128(a, lo_mask), _mm_and_si128(b, lo_mask));
let odd = _mm_mullo_epi16(_mm_srli_epi16(a, 8), _mm_srli_epi16(b, 8));
_mm_or_si128(_mm_and_si128(even, lo_mask), _mm_slli_epi16(odd, 8))
}
#[inline(always)]
pub unsafe fn _mm_mulhi_epi8x_v1(a: __m128i, b: __m128i) -> __m128i {
let zero = _mm_setzero_si128();
let a_lo = _mm_srai_epi16(_mm_unpacklo_epi8(zero, a), 8);
let b_lo = _mm_srai_epi16(_mm_unpacklo_epi8(zero, b), 8);
let a_hi = _mm_srai_epi16(_mm_unpackhi_epi8(zero, a), 8);
let b_hi = _mm_srai_epi16(_mm_unpackhi_epi8(zero, b), 8);
let p_lo = _mm_srai_epi16(_mm_mullo_epi16(a_lo, b_lo), 8);
let p_hi = _mm_srai_epi16(_mm_mullo_epi16(a_hi, b_hi), 8);
_mm_packs_epi16(p_lo, p_hi)
}
#[inline(always)]
pub unsafe fn _mm_mulhi_epu8x_v1(a: __m128i, b: __m128i) -> __m128i {
let zero = _mm_setzero_si128();
let a_lo = _mm_unpacklo_epi8(a, zero); let b_lo = _mm_unpacklo_epi8(b, zero);
let a_hi = _mm_unpackhi_epi8(a, zero);
let b_hi = _mm_unpackhi_epi8(b, zero);
let p_lo = _mm_srli_epi16(_mm_mullo_epi16(a_lo, b_lo), 8);
let p_hi = _mm_srli_epi16(_mm_mullo_epi16(a_hi, b_hi), 8);
_mm_packus_epi16(p_lo, p_hi)
}
#[inline(always)]
pub unsafe fn _mm_count_mask2_epi32x_v1(a: __m128i, b: __m128i) -> usize {
(_mm_movemask_epi8(_mm_packs_epi32(a, b)) as u32).count_ones() as usize / 2
}
#[inline(always)]
pub unsafe fn _mm_count_mask4_epi32x_v1(a: __m128i, b: __m128i, c: __m128i, d: __m128i) -> usize {
let lo = _mm_packs_epi32(a, b);
let hi = _mm_packs_epi32(c, d);
(_mm_movemask_epi8(_mm_packs_epi16(lo, hi)) as u32).count_ones() as usize
}
#[inline(always)]
pub unsafe fn _mm_count_mask2_epi16x_v1(a: __m128i, b: __m128i) -> usize {
(_mm_movemask_epi8(_mm_packs_epi16(a, b)) as u32).count_ones() as usize
}
#[inline(always)]
pub unsafe fn _mm_count_mask_epi32x_v1<const N: usize>(values: [__m128i; N]) -> usize {
let mut total = 0;
let mut i = 0;
while i + 3 < N {
total += _mm_count_mask4_epi32x_v1(values[i], values[i + 1], values[i + 2], values[i + 3]);
i += 4;
}
if i + 1 < N {
total += _mm_count_mask2_epi32x_v1(values[i], values[i + 1]);
i += 2;
}
if i < N {
total += (_mm_movemask_ps(_mm_castsi128_ps(values[i])) as u32).count_ones() as usize;
}
total
}
#[inline(always)]
pub unsafe fn _mm_count_mask_epi16x_v1<const N: usize>(values: [__m128i; N]) -> usize {
let mut total = 0;
let mut i = 0;
while i + 1 < N {
total += _mm_count_mask2_epi16x_v1(values[i], values[i + 1]);
i += 2;
}
if i < N {
total += (_mm_movemask_epi8(values[i]) as u32).count_ones() as usize / 2;
}
total
}
#[inline(always)]
pub unsafe fn _mm_count_mask_ps_v1<const N: usize>(values: [__m128; N]) -> usize {
let mut ints = [_mm_setzero_si128(); N];
let mut i = 0;
while i < N {
ints[i] = _mm_castps_si128(values[i]);
i += 1;
}
_mm_count_mask_epi32x_v1(ints)
}