use crate::sse::*;
use crate::types::*;
use core::arch::aarch64::*;
#[inline]
pub fn _mm_hadd_ps(a: __m128, b: __m128) -> __m128 {
__m128::from_f32(unsafe { vpaddq_f32(a.f32(), b.f32()) })
}
#[inline]
pub fn _mm_hsub_ps(a: __m128, b: __m128) -> __m128 {
unsafe {
let even = vuzp1q_f32(a.f32(), b.f32());
let odd = vuzp2q_f32(a.f32(), b.f32());
__m128::from_f32(vsubq_f32(even, odd))
}
}
#[inline]
pub fn _mm_addsub_ps(a: __m128, b: __m128) -> __m128 {
unsafe {
let mask = _mm_setr_ps(-0.0, 0.0, -0.0, 0.0);
let flipped = veorq_u32(b.u32(), mask.u32());
__m128::from_f32(vaddq_f32(a.f32(), vreinterpretq_f32_u32(flipped)))
}
}
#[inline]
pub fn _mm_hadd_pd(a: __m128d, b: __m128d) -> __m128d {
__m128d::from_f64(unsafe { vpaddq_f64(a.f64(), b.f64()) })
}
#[inline]
pub fn _mm_hsub_pd(a: __m128d, b: __m128d) -> __m128d {
unsafe {
let a0 = vgetq_lane_f64(a.f64(), 0);
let a1 = vgetq_lane_f64(a.f64(), 1);
let b0 = vgetq_lane_f64(b.f64(), 0);
let b1 = vgetq_lane_f64(b.f64(), 1);
crate::sse2::_mm_set_pd(b0 - b1, a0 - a1)
}
}
#[inline]
pub fn _mm_addsub_pd(a: __m128d, b: __m128d) -> __m128d {
unsafe {
let a0 = vgetq_lane_f64(a.f64(), 0);
let a1 = vgetq_lane_f64(a.f64(), 1);
let b0 = vgetq_lane_f64(b.f64(), 0);
let b1 = vgetq_lane_f64(b.f64(), 1);
crate::sse2::_mm_set_pd(a1 + b1, a0 - b0)
}
}
#[inline]
pub fn _mm_movedup_pd(a: __m128d) -> __m128d {
unsafe {
let lo = vgetq_lane_f64(a.f64(), 0);
__m128d::from_f64(vdupq_n_f64(lo))
}
}
#[inline]
pub fn _mm_movehdup_ps(a: __m128) -> __m128 {
__m128::from_f32(unsafe { vtrn2q_f32(a.f32(), a.f32()) })
}
#[inline]
pub fn _mm_moveldup_ps(a: __m128) -> __m128 {
__m128::from_f32(unsafe { vtrn1q_f32(a.f32(), a.f32()) })
}