use crate::{Dvec4, Mat4};
use std::arch::x86_64::*;
#[repr(C)]
#[derive(Copy, Clone, Default, PartialEq)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct Dmat4 {
pub(crate) inner: [Dvec4; 4],
}
impl std::fmt::Debug for Dmat4 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.as_array().fmt(f)
}
}
impl Mat4<f64, Dvec4> for Dmat4 {
#[inline]
fn from_columns(x: Dvec4, y: Dvec4, z: Dvec4, w: Dvec4) -> Dmat4 {
Dmat4 {
inner: [x, y, z, w],
}
}
#[inline]
fn as_array(&self) -> &[Dvec4; 4] {
&self.inner
}
#[inline]
fn as_mut_array(&mut self) -> &mut [Dvec4; 4] {
&mut self.inner
}
#[inline]
fn mul_vector(&self, rhs: Dvec4) -> Dvec4 {
unsafe {
let mut result = _mm256_mul_pd(
self.inner[0].inner,
_mm256_permute4x64_pd::<0b_00_00_00_00>(rhs.inner),
);
result = _mm256_fmadd_pd(
self.inner[1].inner,
_mm256_permute4x64_pd::<0b_01_01_01_01>(rhs.inner),
result,
);
result = _mm256_fmadd_pd(
self.inner[2].inner,
_mm256_permute4x64_pd::<0b_10_10_10_10>(rhs.inner),
result,
);
result = _mm256_fmadd_pd(
self.inner[3].inner,
_mm256_permute4x64_pd::<0b_11_11_11_11>(rhs.inner),
result,
);
Dvec4 { inner: result }
}
}
#[inline]
fn transpose(&self) -> Dmat4 {
unsafe {
let c0 = _mm256_unpacklo_pd(self.inner[0].inner, self.inner[1].inner);
let c1 = _mm256_unpackhi_pd(self.inner[0].inner, self.inner[1].inner);
let c2 = _mm256_unpacklo_pd(self.inner[2].inner, self.inner[3].inner);
let c3 = _mm256_unpackhi_pd(self.inner[2].inner, self.inner[3].inner);
let d0 = _mm256_permute2f128_pd::<0b_00_10_00_00>(c0, c2);
let d1 = _mm256_permute2f128_pd::<0b_00_10_00_00>(c1, c3);
let d2 = _mm256_permute2f128_pd::<0b_00_11_00_01>(c0, c2);
let d3 = _mm256_permute2f128_pd::<0b_00_11_00_01>(c1, c3);
Dmat4::from_columns(
Dvec4 { inner: d0 },
Dvec4 { inner: d1 },
Dvec4 { inner: d2 },
Dvec4 { inner: d3 },
)
}
}
}
implement_matops!(Dmat4, Dvec4, f64);