use crate::types::*;
use core::arch::aarch64::*;
#[inline]
pub fn _mm_add_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vaddq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_add_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vaddq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_add_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s32(unsafe { vaddq_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_add_epi64(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vaddq_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_sub_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vsubq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_sub_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vsubq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_sub_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s32(unsafe { vsubq_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_sub_epi64(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vsubq_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_adds_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vqaddq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_adds_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vqaddq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_adds_epu8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vqaddq_u8(a.u8(), b.u8()) })
}
#[inline]
pub fn _mm_adds_epu16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vqaddq_u16(a.u16(), b.u16()) })
}
#[inline]
pub fn _mm_subs_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vqsubq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_subs_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vqsubq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_subs_epu8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vqsubq_u8(a.u8(), b.u8()) })
}
#[inline]
pub fn _mm_subs_epu16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vqsubq_u16(a.u16(), b.u16()) })
}
#[inline]
pub fn _mm_mullo_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vmulq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_mulhi_epi16(a: __m128i, b: __m128i) -> __m128i {
unsafe {
let al = vget_low_s16(a.s16());
let ah = vget_high_s16(a.s16());
let bl = vget_low_s16(b.s16());
let bh = vget_high_s16(b.s16());
let lo = vmull_s16(al, bl);
let hi = vmull_s16(ah, bh);
let r = vuzp2q_s16(vreinterpretq_s16_s32(lo), vreinterpretq_s16_s32(hi));
__m128i::from_s16(r)
}
}
#[inline]
pub fn _mm_mulhi_epu16(a: __m128i, b: __m128i) -> __m128i {
unsafe {
let al = vget_low_u16(a.u16());
let ah = vget_high_u16(a.u16());
let bl = vget_low_u16(b.u16());
let bh = vget_high_u16(b.u16());
let lo = vmull_u16(al, bl);
let hi = vmull_u16(ah, bh);
let r = vuzp2q_u16(vreinterpretq_u16_u32(lo), vreinterpretq_u16_u32(hi));
__m128i::from_u16(r)
}
}
#[inline]
pub fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i {
unsafe {
let al = vget_low_s16(a.s16());
let ah = vget_high_s16(a.s16());
let bl = vget_low_s16(b.s16());
let bh = vget_high_s16(b.s16());
let lo = vmull_s16(al, bl);
let hi = vmull_s16(ah, bh);
__m128i::from_s32(vpaddq_s32(lo, hi))
}
}
#[inline]
pub fn _mm_mul_epu32(a: __m128i, b: __m128i) -> __m128i {
unsafe {
let al = vmovn_u64(a.u64());
let bl = vmovn_u64(b.u64());
__m128i::from_u64(vmull_u32(al, bl))
}
}
#[inline]
pub fn _mm_and_si128(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vandq_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_or_si128(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vorrq_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_xor_si128(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { veorq_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_andnot_si128(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vbicq_s64(b.s64(), a.s64()) })
}
#[inline]
pub fn _mm_avg_epu8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vrhaddq_u8(a.u8(), b.u8()) })
}
#[inline]
pub fn _mm_avg_epu16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vrhaddq_u16(a.u16(), b.u16()) })
}
#[inline]
pub fn _mm_min_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vminq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_max_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vmaxq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_min_epu8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vminq_u8(a.u8(), b.u8()) })
}
#[inline]
pub fn _mm_max_epu8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vmaxq_u8(a.u8(), b.u8()) })
}
#[inline]
pub fn _mm_cmpeq_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vceqq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_cmpeq_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vceqq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_cmpeq_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u32(unsafe { vceqq_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_cmpgt_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vcgtq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_cmpgt_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vcgtq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_cmpgt_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u32(unsafe { vcgtq_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_cmplt_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vcltq_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_cmplt_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u16(unsafe { vcltq_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_cmplt_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u32(unsafe { vcltq_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_slli_epi16<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..16).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_s16(unsafe { vshlq_s16(a.s16(), vdupq_n_s16(IMM as i16)) })
}
#[inline]
pub fn _mm_slli_epi32<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..32).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_s32(unsafe { vshlq_s32(a.s32(), vdupq_n_s32(IMM)) })
}
#[inline]
pub fn _mm_slli_epi64<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..64).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_s64(unsafe { vshlq_s64(a.s64(), vdupq_n_s64(IMM as i64)) })
}
#[inline]
pub fn _mm_srli_epi16<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..16).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_u16(unsafe { vshlq_u16(a.u16(), vdupq_n_s16(-(IMM as i16))) })
}
#[inline]
pub fn _mm_srli_epi32<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..32).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_u32(unsafe { vshlq_u32(a.u32(), vdupq_n_s32(-IMM)) })
}
#[inline]
pub fn _mm_srli_epi64<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if !(0..64).contains(&IMM) {
return _mm_setzero_si128();
}
__m128i::from_u64(unsafe { vshlq_u64(a.u64(), vdupq_n_s64(-(IMM as i64))) })
}
#[inline]
pub fn _mm_srai_epi16<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
let sh = IMM.clamp(0, 15);
__m128i::from_s16(unsafe { vshlq_s16(a.s16(), vdupq_n_s16(-(sh as i16))) })
}
#[inline]
pub fn _mm_srai_epi32<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
let sh = IMM.clamp(0, 31);
__m128i::from_s32(unsafe { vshlq_s32(a.s32(), vdupq_n_s32(-sh)) })
}
#[inline]
pub fn _mm_slli_si128<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if IMM == 0 {
return a;
}
if !(0..16).contains(&IMM) {
return _mm_setzero_si128();
}
let mut bytes = [0u8; 16];
let av = to_u8_array(a);
for i in 0..(16 - IMM as usize) {
bytes[i + IMM as usize] = av[i];
}
__m128i::from_u8(unsafe { vld1q_u8(bytes.as_ptr()) })
}
#[inline]
pub fn _mm_srli_si128<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
if IMM == 0 {
return a;
}
if !(0..16).contains(&IMM) {
return _mm_setzero_si128();
}
let mut bytes = [0u8; 16];
let av = to_u8_array(a);
for i in 0..(16 - IMM as usize) {
bytes[i] = av[i + IMM as usize];
}
__m128i::from_u8(unsafe { vld1q_u8(bytes.as_ptr()) })
}
#[inline]
pub fn _mm_bslli_si128<const IMM: i32>(a: __m128i) -> __m128i {
_mm_slli_si128::<IMM>(a)
}
#[inline]
pub fn _mm_bsrli_si128<const IMM: i32>(a: __m128i) -> __m128i {
_mm_srli_si128::<IMM>(a)
}
#[inline]
pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vcombine_s8(vqmovn_s16(a.s16()), vqmovn_s16(b.s16())) })
}
#[inline]
pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vcombine_s16(vqmovn_s32(a.s32()), vqmovn_s32(b.s32())) })
}
#[inline]
pub fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_u8(unsafe { vcombine_u8(vqmovun_s16(a.s16()), vqmovun_s16(b.s16())) })
}
#[inline]
pub fn _mm_unpackhi_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vzip2q_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_unpackhi_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vzip2q_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_unpackhi_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s32(unsafe { vzip2q_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_unpackhi_epi64(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vzip2q_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_unpacklo_epi8(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s8(unsafe { vzip1q_s8(a.s8(), b.s8()) })
}
#[inline]
pub fn _mm_unpacklo_epi16(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s16(unsafe { vzip1q_s16(a.s16(), b.s16()) })
}
#[inline]
pub fn _mm_unpacklo_epi32(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s32(unsafe { vzip1q_s32(a.s32(), b.s32()) })
}
#[inline]
pub fn _mm_unpacklo_epi64(a: __m128i, b: __m128i) -> __m128i {
__m128i::from_s64(unsafe { vzip1q_s64(a.s64(), b.s64()) })
}
#[inline]
pub fn _mm_move_epi64(a: __m128i) -> __m128i {
unsafe {
let lo = vgetq_lane_s64(a.s64(), 0);
__m128i::from_s64(vsetq_lane_s64(0, vdupq_n_s64(lo), 1))
}
}
#[inline]
pub fn _mm_shuffle_epi32<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
let av = to_i32_array(a);
let out = [
av[(IMM & 0x3) as usize],
av[((IMM >> 2) & 0x3) as usize],
av[((IMM >> 4) & 0x3) as usize],
av[((IMM >> 6) & 0x3) as usize],
];
__m128i::from_s32(unsafe { vld1q_s32(out.as_ptr()) })
}
#[inline]
pub fn _mm_shufflehi_epi16<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
let av = to_i16_array(a);
let mut out = av;
out[4] = av[4 + (IMM & 0x3) as usize];
out[5] = av[4 + ((IMM >> 2) & 0x3) as usize];
out[6] = av[4 + ((IMM >> 4) & 0x3) as usize];
out[7] = av[4 + ((IMM >> 6) & 0x3) as usize];
__m128i::from_s16(unsafe { vld1q_s16(out.as_ptr()) })
}
#[inline]
pub fn _mm_shufflelo_epi16<const IMM: i32>(a: __m128i) -> __m128i {
const { assert!(IMM >= 0 && IMM < 256, "IMM must be in 0..256") };
let av = to_i16_array(a);
let mut out = av;
out[0] = av[(IMM & 0x3) as usize];
out[1] = av[((IMM >> 2) & 0x3) as usize];
out[2] = av[((IMM >> 4) & 0x3) as usize];
out[3] = av[((IMM >> 6) & 0x3) as usize];
__m128i::from_s16(unsafe { vld1q_s16(out.as_ptr()) })
}
#[inline]
pub fn _mm_movemask_epi8(a: __m128i) -> i32 {
unsafe {
let msbs = vshrq_n_u8::<7>(a.u8());
let shift_table: [i8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7];
let shifts = vld1q_s8(shift_table.as_ptr());
let positioned = vshlq_u8(msbs, shifts);
let lo = vaddv_u8(vget_low_u8(positioned)) as i32;
let hi = vaddv_u8(vget_high_u8(positioned)) as i32;
lo | (hi << 8)
}
}
#[inline]
pub fn _mm_sad_epu8(a: __m128i, b: __m128i) -> __m128i {
unsafe {
let t = vpaddlq_u8(vabdq_u8(a.u8(), b.u8()));
__m128i::from_u64(vpaddlq_u32(vpaddlq_u16(t)))
}
}
#[inline]
pub fn _mm_setzero_si128() -> __m128i {
__m128i::from_s64(unsafe { vdupq_n_s64(0) })
}
#[inline]
pub fn _mm_set1_epi8(w: i8) -> __m128i {
__m128i::from_s8(unsafe { vdupq_n_s8(w) })
}
#[inline]
pub fn _mm_set1_epi16(w: i16) -> __m128i {
__m128i::from_s16(unsafe { vdupq_n_s16(w) })
}
#[inline]
pub fn _mm_set1_epi32(w: i32) -> __m128i {
__m128i::from_s32(unsafe { vdupq_n_s32(w) })
}
#[inline]
pub fn _mm_set1_epi64x(w: i64) -> __m128i {
__m128i::from_s64(unsafe { vdupq_n_s64(w) })
}
#[inline]
pub fn _mm_set_epi32(e3: i32, e2: i32, e1: i32, e0: i32) -> __m128i {
let data = [e0, e1, e2, e3];
__m128i::from_s32(unsafe { vld1q_s32(data.as_ptr()) })
}
#[inline]
pub fn _mm_setr_epi32(e3: i32, e2: i32, e1: i32, e0: i32) -> __m128i {
_mm_set_epi32(e0, e1, e2, e3)
}
#[inline]
pub fn _mm_set_epi64x(e1: i64, e0: i64) -> __m128i {
let data = [e0, e1];
__m128i::from_s64(unsafe { vld1q_s64(data.as_ptr()) })
}
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn _mm_set_epi16(
e7: i16,
e6: i16,
e5: i16,
e4: i16,
e3: i16,
e2: i16,
e1: i16,
e0: i16,
) -> __m128i {
let data = [e0, e1, e2, e3, e4, e5, e6, e7];
__m128i::from_s16(unsafe { vld1q_s16(data.as_ptr()) })
}
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn _mm_set_epi8(
e15: i8,
e14: i8,
e13: i8,
e12: i8,
e11: i8,
e10: i8,
e9: i8,
e8: i8,
e7: i8,
e6: i8,
e5: i8,
e4: i8,
e3: i8,
e2: i8,
e1: i8,
e0: i8,
) -> __m128i {
let data = [
e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15,
];
__m128i::from_s8(unsafe { vld1q_s8(data.as_ptr()) })
}
#[inline]
pub unsafe fn _mm_load_si128(p: *const __m128i) -> __m128i {
__m128i::from_s64(vld1q_s64(p as *const i64))
}
#[inline]
pub unsafe fn _mm_loadu_si128(p: *const __m128i) -> __m128i {
__m128i::from_s64(vld1q_s64(p as *const i64))
}
#[inline]
pub unsafe fn _mm_loadl_epi64(p: *const __m128i) -> __m128i {
let lo = core::ptr::read_unaligned(p as *const i64);
__m128i::from_s64(vsetq_lane_s64(0, vdupq_n_s64(lo), 1))
}
#[inline]
pub unsafe fn _mm_store_si128(p: *mut __m128i, a: __m128i) {
vst1q_s64(p as *mut i64, a.s64());
}
#[inline]
pub unsafe fn _mm_storeu_si128(p: *mut __m128i, a: __m128i) {
vst1q_s64(p as *mut i64, a.s64());
}
#[inline]
pub unsafe fn _mm_storel_epi64(p: *mut __m128i, a: __m128i) {
core::ptr::write_unaligned(p as *mut i64, vgetq_lane_s64(a.s64(), 0));
}
#[inline]
pub fn _mm_cvtsi128_si32(a: __m128i) -> i32 {
unsafe { vgetq_lane_s32(a.s32(), 0) }
}
#[inline]
pub fn _mm_cvtsi128_si64(a: __m128i) -> i64 {
unsafe { vgetq_lane_s64(a.s64(), 0) }
}
#[inline]
pub fn _mm_cvtsi32_si128(w: i32) -> __m128i {
__m128i::from_s32(unsafe { vsetq_lane_s32(w, vdupq_n_s32(0), 0) })
}
#[inline]
pub fn _mm_cvtsi64_si128(w: i64) -> __m128i {
__m128i::from_s64(unsafe { vsetq_lane_s64(w, vdupq_n_s64(0), 0) })
}
pub(crate) fn to_u8_array(a: __m128i) -> [u8; 16] {
let mut out = [0u8; 16];
unsafe { vst1q_u8(out.as_mut_ptr(), a.u8()) };
out
}
pub(crate) fn to_i16_array(a: __m128i) -> [i16; 8] {
let mut out = [0i16; 8];
unsafe { vst1q_s16(out.as_mut_ptr(), a.s16()) };
out
}
pub(crate) fn to_i32_array(a: __m128i) -> [i32; 4] {
let mut out = [0i32; 4];
unsafe { vst1q_s32(out.as_mut_ptr(), a.s32()) };
out
}
#[inline]
pub fn _mm_add_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vaddq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_sub_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vsubq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_mul_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vmulq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_div_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vdivq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_sqrt_pd(a: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vsqrtq_f64(a.f64()) })
}
#[inline]
pub fn _mm_max_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vmaxq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_min_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vminq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_add_sd(a: __m128d, b: __m128d) -> __m128d {
_mm_move_sd(a, _mm_add_pd(a, b))
}
#[inline]
pub fn _mm_sub_sd(a: __m128d, b: __m128d) -> __m128d {
_mm_move_sd(a, _mm_sub_pd(a, b))
}
#[inline]
pub fn _mm_mul_sd(a: __m128d, b: __m128d) -> __m128d {
_mm_move_sd(a, _mm_mul_pd(a, b))
}
#[inline]
pub fn _mm_div_sd(a: __m128d, b: __m128d) -> __m128d {
_mm_move_sd(a, _mm_div_pd(a, b))
}
#[inline]
pub fn _mm_and_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vandq_u64(a.u64(), b.u64()) })
}
#[inline]
pub fn _mm_or_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vorrq_u64(a.u64(), b.u64()) })
}
#[inline]
pub fn _mm_xor_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { veorq_u64(a.u64(), b.u64()) })
}
#[inline]
pub fn _mm_andnot_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vbicq_u64(b.u64(), a.u64()) })
}
#[inline]
pub fn _mm_cmpeq_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vceqq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_cmplt_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vcltq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_cmple_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vcleq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_cmpgt_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vcgtq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_cmpge_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe { vcgeq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_cmpneq_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_u64(unsafe {
let eq = vceqq_f64(a.f64(), b.f64());
vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(eq)))
})
}
#[inline]
pub fn _mm_cmpord_pd(a: __m128d, b: __m128d) -> __m128d {
unsafe {
let a_ord = vceqq_f64(a.f64(), a.f64());
let b_ord = vceqq_f64(b.f64(), b.f64());
__m128d::from_u64(vandq_u64(a_ord, b_ord))
}
}
#[inline]
pub fn _mm_cmpunord_pd(a: __m128d, b: __m128d) -> __m128d {
unsafe {
let a_ord = vceqq_f64(a.f64(), a.f64());
let b_ord = vceqq_f64(b.f64(), b.f64());
let ord = vandq_u64(a_ord, b_ord);
__m128d::from_u64(vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(ord))))
}
}
#[inline]
pub fn _mm_move_sd(a: __m128d, b: __m128d) -> __m128d {
unsafe {
let lo = vgetq_lane_f64(b.f64(), 0);
__m128d::from_f64(vsetq_lane_f64(lo, a.f64(), 0))
}
}
#[inline]
pub fn _mm_unpackhi_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vzip2q_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_unpacklo_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vzip1q_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_movemask_pd(a: __m128d) -> i32 {
unsafe {
let bits = vshrq_n_u64::<63>(a.u64());
let lo = vgetq_lane_u64(bits, 0) as i32;
let hi = vgetq_lane_u64(bits, 1) as i32;
lo | (hi << 1)
}
}
#[inline]
pub fn _mm_setzero_pd() -> __m128d {
__m128d::from_f64(unsafe { vdupq_n_f64(0.0) })
}
#[inline]
pub fn _mm_set1_pd(w: f64) -> __m128d {
__m128d::from_f64(unsafe { vdupq_n_f64(w) })
}
#[inline]
pub fn _mm_set_pd(e1: f64, e0: f64) -> __m128d {
let data = [e0, e1];
__m128d::from_f64(unsafe { vld1q_f64(data.as_ptr()) })
}
#[inline]
pub fn _mm_setr_pd(e1: f64, e0: f64) -> __m128d {
_mm_set_pd(e0, e1)
}
#[inline]
pub fn _mm_set_sd(w: f64) -> __m128d {
let data = [w, 0.0];
__m128d::from_f64(unsafe { vld1q_f64(data.as_ptr()) })
}
#[inline]
pub fn _mm_cvtsd_f64(a: __m128d) -> f64 {
unsafe { vgetq_lane_f64(a.f64(), 0) }
}
#[inline]
pub unsafe fn _mm_load_pd(p: *const f64) -> __m128d {
__m128d::from_f64(vld1q_f64(p))
}
#[inline]
pub unsafe fn _mm_loadu_pd(p: *const f64) -> __m128d {
__m128d::from_f64(vld1q_f64(p))
}
#[inline]
pub unsafe fn _mm_store_pd(p: *mut f64, a: __m128d) {
vst1q_f64(p, a.f64());
}
#[inline]
pub unsafe fn _mm_storeu_pd(p: *mut f64, a: __m128d) {
vst1q_f64(p, a.f64());
}
const OVERFLOW_F32: f32 = 2147483648.0;
#[inline]
fn cvtps_epi32_fixup(f: float32x4_t, cvt: int32x4_t) -> int32x4_t {
unsafe {
let overflow = vcgeq_f32(f, vdupq_n_f32(OVERFLOW_F32));
let is_nan = vmvnq_u32(vceqq_f32(f, f));
let need = vorrq_u32(overflow, is_nan);
vbslq_s32(need, vdupq_n_s32(i32::MIN), cvt)
}
}
#[inline]
pub fn _mm_cvtps_epi32(a: __m128) -> __m128i {
use crate::mxcsr::_MM_GET_ROUNDING_MODE;
unsafe {
let f = a.f32();
let cvt = match _MM_GET_ROUNDING_MODE() {
crate::constants::_MM_ROUND_NEAREST => vcvtnq_s32_f32(f),
crate::constants::_MM_ROUND_DOWN => vcvtmq_s32_f32(f),
crate::constants::_MM_ROUND_UP => vcvtpq_s32_f32(f),
_ => vcvtq_s32_f32(f),
};
__m128i::from_s32(cvtps_epi32_fixup(f, cvt))
}
}
#[inline]
pub fn _mm_cvttps_epi32(a: __m128) -> __m128i {
unsafe {
let f = a.f32();
let cvt = vcvtq_s32_f32(f);
__m128i::from_s32(cvtps_epi32_fixup(f, cvt))
}
}
#[inline]
pub fn _mm_cvtepi32_ps(a: __m128i) -> __m128 {
__m128::from_f32(unsafe { vcvtq_f32_s32(a.s32()) })
}
#[inline]
pub fn _mm_cvtepi32_pd(a: __m128i) -> __m128d {
unsafe {
let lo = vget_low_s32(a.s32());
__m128d::from_f64(vcvtq_f64_s64(vmovl_s32(lo)))
}
}
#[inline]
pub fn _mm_cvtpd_ps(a: __m128d) -> __m128 {
unsafe {
let lo = vcvt_f32_f64(a.f64());
__m128::from_f32(vcombine_f32(lo, vdup_n_f32(0.0)))
}
}
#[inline]
pub fn _mm_cvtps_pd(a: __m128) -> __m128d {
unsafe {
let lo = vget_low_f32(a.f32());
__m128d::from_f64(vcvt_f64_f32(lo))
}
}
#[inline]
pub fn _mm_cvtpd_epi32(a: __m128d) -> __m128i {
let lo = cvtd_s32(round_cur(_mm_cvtsd_f64(a)));
let hi = cvtd_s32(round_cur(unsafe { vgetq_lane_f64(a.f64(), 1) }));
_mm_set_epi32(0, 0, hi, lo)
}
#[inline]
pub fn _mm_cvttpd_epi32(a: __m128d) -> __m128i {
let lo = cvtd_s32(_mm_cvtsd_f64(a));
let hi = cvtd_s32(unsafe { vgetq_lane_f64(a.f64(), 1) });
_mm_set_epi32(0, 0, hi, lo)
}
#[inline]
pub fn _mm_cvtsd_si32(a: __m128d) -> i32 {
cvtd_s32(round_cur(_mm_cvtsd_f64(a)))
}
#[inline]
pub fn _mm_cvttsd_si32(a: __m128d) -> i32 {
cvtd_s32(_mm_cvtsd_f64(a))
}
#[inline]
fn round_cur(v: f64) -> f64 {
unsafe { vget_lane_f64(vrndi_f64(vdup_n_f64(v)), 0) }
}
#[inline]
fn cvtd_s32(v: f64) -> i32 {
if v.is_nan() || v.is_infinite() || !(-2147483648.0..2147483648.0).contains(&v) {
i32::MIN
} else {
v as i32
}
}
#[inline]
pub fn _mm_cvtsd_ss(a: __m128, b: __m128d) -> __m128 {
let v = unsafe { vget_lane_f32(vcvt_f32_f64(vdupq_n_f64(_mm_cvtsd_f64(b))), 0) };
unsafe { __m128::from_f32(vsetq_lane_f32(v, a.f32(), 0)) }
}
#[inline]
pub fn _mm_cvtss_sd(a: __m128d, b: __m128) -> __m128d {
let v = crate::sse::_mm_cvtss_f32(b) as f64;
unsafe { __m128d::from_f64(vsetq_lane_f64(v, a.f64(), 0)) }
}
#[inline]
pub fn _mm_cvtsi32_sd(a: __m128d, b: i32) -> __m128d {
unsafe { __m128d::from_f64(vsetq_lane_f64(b as f64, a.f64(), 0)) }
}
#[inline]
pub fn _mm_cvtsi64_sd(a: __m128d, b: i64) -> __m128d {
unsafe { __m128d::from_f64(vsetq_lane_f64(b as f64, a.f64(), 0)) }
}