use num_traits::MulAdd;
use std::arch::aarch64::*;
use std::ops::{Add, Mul, Neg, Sub};
#[repr(transparent)]
#[derive(Copy, Clone, Debug)]
pub(crate) struct NeonStoreD {
pub(crate) v: float64x2_t,
}
impl Default for NeonStoreD {
#[inline(always)]
fn default() -> Self {
unsafe { NeonStoreD::raw(vdupq_n_f64(0.)) }
}
}
impl NeonStoreD {
#[inline(always)]
pub(crate) fn set_values(v0: f64, v1: f64) -> Self {
NeonStoreD {
v: unsafe { vld1q_f64([v0, v1].as_ptr()) },
}
}
#[inline(always)]
pub(crate) fn raw(v: float64x2_t) -> Self {
NeonStoreD { v }
}
#[inline(always)]
pub(crate) fn load(ptr: &[f64]) -> Self {
NeonStoreD::raw(unsafe { vld1q_f64(ptr.as_ptr()) })
}
#[inline(always)]
pub(crate) fn load1(ptr: &[f64]) -> Self {
NeonStoreD::raw(unsafe { vld1q_lane_f64::<0>(ptr.as_ptr(), vdupq_n_f64(0.)) })
}
#[inline(always)]
pub(crate) fn write(self, ptr: &mut [f64]) {
unsafe { vst1q_f64(ptr.as_mut_ptr(), self.v) }
}
#[inline(always)]
pub(crate) fn write1(self, ptr: &mut [f64]) {
unsafe { vst1q_lane_f64::<0>(ptr.as_mut_ptr(), self.v) }
}
#[inline(always)]
pub(crate) fn reverse(self) -> Self {
unsafe { NeonStoreD::raw(vcombine_f64(vget_high_f64(self.v), vget_low_f64(self.v))) }
}
#[inline(always)]
pub(crate) fn f64_mul_add(q: f64, a: NeonStoreD, b: Self) -> Self {
NeonStoreD::raw(unsafe { vfmaq_n_f64(b.v, a.v, q) })
}
#[inline(always)]
pub(crate) fn f64_mul_nadd(q: f64, a: NeonStoreD, b: NeonStoreD) -> NeonStoreD {
NeonStoreD::raw(unsafe { vfmsq_n_f64(b.v, a.v, q) })
}
#[inline(always)]
pub(crate) fn xor(&self, p0: NeonStoreD) -> NeonStoreD {
NeonStoreD::raw(unsafe {
vreinterpretq_f64_u64(veorq_u64(
vreinterpretq_u64_f64(self.v),
vreinterpretq_u64_f64(p0.v),
))
})
}
#[inline(always)]
pub(crate) fn zip(self, other: Self) -> [Self; 2] {
[
NeonStoreD::raw(unsafe { vzip1q_f64(self.v, other.v) }),
NeonStoreD::raw(unsafe { vzip2q_f64(self.v, other.v) }),
]
}
}
impl Add<NeonStoreD> for NeonStoreD {
type Output = Self;
#[inline(always)]
fn add(self, rhs: NeonStoreD) -> Self::Output {
NeonStoreD::raw(unsafe { vaddq_f64(self.v, rhs.v) })
}
}
impl Sub<NeonStoreD> for NeonStoreD {
type Output = Self;
#[inline(always)]
fn sub(self, rhs: NeonStoreD) -> Self::Output {
NeonStoreD::raw(unsafe { vsubq_f64(self.v, rhs.v) })
}
}
impl Neg for NeonStoreD {
type Output = Self;
#[inline(always)]
fn neg(self) -> Self::Output {
NeonStoreD::raw(unsafe { vnegq_f64(self.v) })
}
}
impl Mul<NeonStoreD> for NeonStoreD {
type Output = Self;
#[inline(always)]
fn mul(self, rhs: NeonStoreD) -> Self::Output {
NeonStoreD::raw(unsafe { vmulq_f64(self.v, rhs.v) })
}
}
impl Mul<f64> for NeonStoreD {
type Output = Self;
#[inline(always)]
fn mul(self, rhs: f64) -> Self::Output {
NeonStoreD::raw(unsafe { vmulq_n_f64(self.v, rhs) })
}
}
impl Mul<NeonStoreD> for f64 {
type Output = NeonStoreD;
#[inline(always)]
fn mul(self, rhs: NeonStoreD) -> Self::Output {
NeonStoreD::raw(unsafe { vmulq_n_f64(rhs.v, self) })
}
}
impl MulAdd<NeonStoreD> for NeonStoreD {
type Output = Self;
#[inline(always)]
fn mul_add(self, a: NeonStoreD, b: Self) -> Self::Output {
Self::raw(unsafe { vfmaq_f64(b.v, self.v, a.v) })
}
}