#![allow(clippy::inline_always)]
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "simd")] {
use core::simd::{f32x4,f32x8,num::SimdFloat};
const _: () = assert!(core::mem::size_of::<Matrix3x3<f32>>() == 64);
const _: () = assert!(core::mem::align_of::<Matrix3x3<f32>>() == 32);
} else if #[cfg(feature = "no_align")] {
const _: () = assert!(core::mem::size_of::<Matrix3x3<f32>>() == 36);
const _: () = assert!(core::mem::align_of::<Matrix3x3<f32>>() == 4);
} else {
const _: () = assert!(core::mem::size_of::<Matrix3x3<f32>>() == 64);
const _: () = assert!(core::mem::align_of::<Matrix3x3<f32>>() == 32);
}
}
use crate::{Matrix3x3, Vector3d};
pub trait Matrix3x3Math: Sized {
fn m3x3_neg(this: Matrix3x3<Self>) -> Matrix3x3<Self>;
fn m3x3_abs(this: Matrix3x3<Self>) -> Matrix3x3<Self>;
fn m3x3_add(this: Matrix3x3<Self>, this: Matrix3x3<Self>) -> Matrix3x3<Self>;
fn m3x3_mul_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self>;
fn m3x3_div_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self>;
fn m3x3_mul_add(this: Matrix3x3<Self>, k: Self, other: Matrix3x3<Self>) -> Matrix3x3<Self>;
fn m3x3_mul_vector(this: Matrix3x3<Self>, other: Vector3d<Self>) -> Vector3d<Self>;
fn m3x3_vector_mul(this: Vector3d<Self>, other: Matrix3x3<Self>) -> Vector3d<Self>;
fn m3x3_mul(this: Matrix3x3<Self>, other: Matrix3x3<Self>) -> Matrix3x3<Self>;
fn m3x3_trace(this: Matrix3x3<Self>) -> Self;
fn m3x3_trace_sum_squares(this: Matrix3x3<Self>) -> Self;
fn m3x3_sum(this: Matrix3x3<Self>) -> Self;
fn m3x3_mean(this: Matrix3x3<Self>) -> Self;
fn m3x3_product(this: Matrix3x3<Self>) -> Self;
fn m3x3_top_right_determinant(this: Matrix3x3<Self>) -> Self;
fn m3x3_top_right_sum_squares(this: Matrix3x3<Self>) -> Self;
fn m3x3_determinant(this: Matrix3x3<Self>) -> Self;
fn m3x3_adjugate(this: Matrix3x3<Self>) -> (Matrix3x3<Self>, Self);
}
impl Matrix3x3Math for f32 {
#[inline(always)]
fn m3x3_neg(this: Matrix3x3<Self>) -> Matrix3x3<Self> {
let ret = core::array::from_fn(|ii| -this.a[ii]);
Matrix3x3::from(ret)
}
#[inline(always)]
fn m3x3_abs(this: Matrix3x3<Self>) -> Matrix3x3<Self> {
let ret = core::array::from_fn(|ii| this.a[ii].abs());
Matrix3x3::from(ret)
}
#[inline(always)]
fn m3x3_add(this: Matrix3x3<Self>, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
let ret = core::array::from_fn(|ii| this.a[ii] + other.a[ii]);
Matrix3x3::from(ret)
}
#[inline(always)]
fn m3x3_mul_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self> {
let ret = core::array::from_fn(|ii| this.a[ii] * other);
Matrix3x3::from(ret)
}
#[inline(always)]
fn m3x3_div_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self> {
Self::m3x3_mul_scalar(this, 1.0 / other)
}
#[inline(always)]
fn m3x3_mul_add(this: Matrix3x3<Self>, k: Self, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
Self::m3x3_add(Self::m3x3_mul_scalar(this, k), other)
}
#[inline]
fn m3x3_mul_vector(this: Matrix3x3<Self>, other: Vector3d<Self>) -> Vector3d<Self> {
let mut rx = this.a[0] * other.x;
let mut ry = this.a[3] * other.x;
let mut rz = this.a[6] * other.x;
rx += this.a[1] * other.y;
ry += this.a[4] * other.y;
rz += this.a[7] * other.y;
rx += this.a[2] * other.z;
ry += this.a[5] * other.z;
rz += this.a[8] * other.z;
Vector3d { x: rx, y: ry, z: rz }
}
fn m3x3_vector_mul(this: Vector3d<Self>, other: Matrix3x3<Self>) -> Vector3d<Self> {
Vector3d {
x: this.x * other.a[0] + this.y * other.a[3] + this.z * other.a[6],
y: this.x * other.a[1] + this.y * other.a[4] + this.z * other.a[7],
z: this.x * other.a[2] + this.y * other.a[5] + this.z * other.a[8],
}
}
#[inline(always)]
fn m3x3_mul(this: Matrix3x3<Self>, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
#[cfg(feature = "simd")]
{
let a0_simd = f32x4::from_array([this.a[0], this.a[1], this.a[2], 0.0]);
let a3_simd = f32x4::from_array([this.a[3], this.a[4], this.a[5], 0.0]);
let a6_simd = f32x4::from_array([this.a[6], this.a[7], this.a[8], 0.0]);
let b0_simd = f32x4::from_array([other.a[0], other.a[3], other.a[6], 0.0]);
let b1_simd = f32x4::from_array([other.a[1], other.a[4], other.a[7], 0.0]);
let b2_simd = f32x4::from_array([other.a[2], other.a[5], other.a[8], 0.0]);
let a = [
(a0_simd * b0_simd).reduce_sum(),
(a0_simd * b1_simd).reduce_sum(),
(a0_simd * b2_simd).reduce_sum(),
(a3_simd * b0_simd).reduce_sum(),
(a3_simd * b1_simd).reduce_sum(),
(a3_simd * b2_simd).reduce_sum(),
(a6_simd * b0_simd).reduce_sum(),
(a6_simd * b1_simd).reduce_sum(),
(a6_simd * b2_simd).reduce_sum(),
];
Matrix3x3::from(a)
}
#[cfg(not(feature = "simd"))]
{
let a = [
this.a[0] * other.a[0] + this.a[1] * other.a[3] + this.a[2] * other.a[6],
this.a[0] * other.a[1] + this.a[1] * other.a[4] + this.a[2] * other.a[7],
this.a[0] * other.a[2] + this.a[1] * other.a[5] + this.a[2] * other.a[8],
this.a[3] * other.a[0] + this.a[4] * other.a[3] + this.a[5] * other.a[6],
this.a[3] * other.a[1] + this.a[4] * other.a[4] + this.a[5] * other.a[7],
this.a[3] * other.a[2] + this.a[4] * other.a[5] + this.a[5] * other.a[8],
this.a[6] * other.a[0] + this.a[7] * other.a[3] + this.a[8] * other.a[6],
this.a[6] * other.a[1] + this.a[7] * other.a[4] + this.a[8] * other.a[7],
this.a[6] * other.a[2] + this.a[7] * other.a[5] + this.a[8] * other.a[8],
];
Matrix3x3::from(a)
}
}
#[inline(always)]
fn m3x3_trace(this: Matrix3x3<Self>) -> Self {
this.a[0] + this.a[4] + this.a[8]
}
#[inline(always)]
fn m3x3_trace_sum_squares(this: Matrix3x3<Self>) -> Self {
#[cfg(feature = "simd")]
{
let trace_simd = f32x4::from_array([this.a[0], this.a[4], this.a[8], 0.0]);
(trace_simd * trace_simd).reduce_sum()
}
#[cfg(not(feature = "simd"))]
{
this.a[0] * this.a[0] + this.a[4] * this.a[4] + this.a[8] * this.a[8]
}
}
#[inline(always)]
fn m3x3_sum(this: Matrix3x3<Self>) -> Self {
this.a.iter().sum()
}
#[inline(always)]
fn m3x3_mean(this: Matrix3x3<Self>) -> Self {
this.sum() / 9.0
}
#[inline(always)]
fn m3x3_product(this: Matrix3x3<Self>) -> Self {
this.a.iter().product()
}
#[inline(always)]
fn m3x3_top_right_sum_squares(this: Matrix3x3<Self>) -> Self {
#[cfg(feature = "simd")]
{
let top_right_simd = f32x4::from_array([this.a[1], this.a[2], this.a[5], 0.0]);
(top_right_simd * top_right_simd).reduce_sum()
}
#[cfg(not(feature = "simd"))]
{
this.a[1] * this.a[1] + this.a[2] * this.a[2] + this.a[5] * this.a[5]
}
}
#[inline(always)]
fn m3x3_top_right_determinant(this: Matrix3x3<Self>) -> Self {
#[cfg(feature = "simd")]
{
let a_simd = f32x4::from_array([this.a[0], -this.a[1], this.a[2], 0.0]);
let d = [
this.a[4] * this.a[8] - this.a[5] * this.a[5],
this.a[1] * this.a[8] - this.a[5] * this.a[2],
this.a[1] * this.a[5] - this.a[4] * this.a[2],
0.0,
];
let d_simd = f32x4::from_array(d);
(a_simd * d_simd).reduce_sum()
}
#[cfg(not(feature = "simd"))]
{
this.a[0] * (this.a[4] * this.a[8] - this.a[5] * this.a[5])
- this.a[1] * (this.a[1] * this.a[8] - this.a[5] * this.a[2])
+ this.a[2] * (this.a[1] * this.a[5] - this.a[4] * this.a[2])
}
}
#[inline(always)]
fn m3x3_determinant(this: Matrix3x3<Self>) -> Self {
#[cfg(feature = "simd")]
{
let a_simd = f32x4::from_array([this.a[0], -this.a[1], this.a[2], 0.0]);
let d = [
this.a[4] * this.a[8] - this.a[5] * this.a[7],
this.a[3] * this.a[8] - this.a[5] * this.a[6],
this.a[3] * this.a[7] - this.a[4] * this.a[6],
0.0,
];
let d_simd = f32x4::from_array(d);
(a_simd * d_simd).reduce_sum()
}
#[cfg(not(feature = "simd"))]
{
this.a[0] * (this.a[4] * this.a[8] - this.a[5] * this.a[7])
- this.a[1] * (this.a[3] * this.a[8] - this.a[5] * this.a[6])
+ this.a[2] * (this.a[3] * this.a[7] - this.a[4] * this.a[6])
}
}
#[rustfmt::skip]
#[inline]
fn m3x3_adjugate(this: Matrix3x3<Self>) -> (Matrix3x3<Self>, Self) {
let ei_fh = this.a[4] * this.a[8] - this.a[5] * this.a[7];
let di_fg = this.a[3] * this.a[8] - this.a[5] * this.a[6];
let dh_eg = this.a[3] * this.a[7] - this.a[4] * this.a[6];
let determinant = this.a[0] * ei_fh - this.a[1]*di_fg + this.a[2]* dh_eg;
let a = [
ei_fh, -(this.a[1] * this.a[8] - this.a[2] * this.a[7]), this.a[1] * this.a[5] - this.a[2] * this.a[4], - di_fg, this.a[0] * this.a[8] - this.a[2] * this.a[6], -(this.a[0] * this.a[5] - this.a[2] * this.a[3]), dh_eg, -(this.a[0] * this.a[7] - this.a[1] * this.a[6]), this.a[0] * this.a[4] - this.a[1] * this.a[3], ];
(Matrix3x3::from(a), determinant)
}
}
impl Matrix3x3Math for f64 {
#[inline(always)]
fn m3x3_neg(this: Matrix3x3<Self>) -> Matrix3x3<Self> {
let mut a = this.a;
for r in &mut a {
*r = -*r;
}
Matrix3x3::from(a)
}
#[inline(always)]
fn m3x3_abs(this: Matrix3x3<Self>) -> Matrix3x3<Self> {
let mut a = this.a;
for r in &mut a {
*r = r.abs();
}
Matrix3x3::from(a)
}
#[inline(always)]
fn m3x3_add(this: Matrix3x3<Self>, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
let mut a = this.a;
for (ii, r) in a.iter_mut().enumerate() {
*r += other.a[ii];
}
Matrix3x3::from(a)
}
#[inline(always)]
fn m3x3_mul_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self> {
let mut a = this.a;
for r in &mut a {
*r *= other;
}
Matrix3x3::from(a)
}
#[inline(always)]
fn m3x3_div_scalar(this: Matrix3x3<Self>, other: Self) -> Matrix3x3<Self> {
Self::m3x3_mul_scalar(this, 1.0 / other)
}
#[inline(always)]
fn m3x3_mul_add(this: Matrix3x3<Self>, k: Self, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
Self::m3x3_add(Self::m3x3_mul_scalar(this, k), other)
}
#[inline(always)]
fn m3x3_mul_vector(this: Matrix3x3<Self>, other: Vector3d<Self>) -> Vector3d<Self> {
Vector3d {
x: this.a[0] * other.x + this.a[1] * other.y + this.a[2] * other.z,
y: this.a[3] * other.x + this.a[4] * other.y + this.a[5] * other.z,
z: this.a[6] * other.x + this.a[7] * other.y + this.a[8] * other.z,
}
}
#[inline(always)]
fn m3x3_vector_mul(this: Vector3d<Self>, other: Matrix3x3<Self>) -> Vector3d<Self> {
Vector3d {
x: this.x * other.a[0] + this.y * other.a[3] + this.z * other.a[6],
y: this.x * other.a[1] + this.y * other.a[4] + this.z * other.a[7],
z: this.x * other.a[2] + this.y * other.a[5] + this.z * other.a[8],
}
}
#[inline(always)]
fn m3x3_mul(this: Matrix3x3<Self>, other: Matrix3x3<Self>) -> Matrix3x3<Self> {
let a = [
this.a[0] * other.a[0] + this.a[1] * other.a[3] + this.a[2] * other.a[6],
this.a[0] * other.a[1] + this.a[1] * other.a[4] + this.a[2] * other.a[7],
this.a[0] * other.a[2] + this.a[1] * other.a[5] + this.a[2] * other.a[8],
this.a[3] * other.a[0] + this.a[4] * other.a[3] + this.a[5] * other.a[6],
this.a[3] * other.a[1] + this.a[4] * other.a[4] + this.a[5] * other.a[7],
this.a[3] * other.a[2] + this.a[4] * other.a[5] + this.a[5] * other.a[8],
this.a[6] * other.a[0] + this.a[7] * other.a[3] + this.a[8] * other.a[6],
this.a[6] * other.a[1] + this.a[7] * other.a[4] + this.a[8] * other.a[7],
this.a[6] * other.a[2] + this.a[7] * other.a[5] + this.a[8] * other.a[8],
];
Matrix3x3::from(a)
}
#[inline(always)]
fn m3x3_trace(this: Matrix3x3<Self>) -> Self {
this.a[0] + this.a[4] + this.a[8]
}
#[inline(always)]
fn m3x3_trace_sum_squares(this: Matrix3x3<Self>) -> Self {
this.a[0] * this.a[0] + this.a[4] * this.a[4] + this.a[8] * this.a[8]
}
#[inline(always)]
fn m3x3_sum(this: Matrix3x3<Self>) -> Self {
this.a.iter().sum()
}
#[inline(always)]
fn m3x3_mean(this: Matrix3x3<Self>) -> Self {
this.sum() / 9.0
}
#[inline(always)]
fn m3x3_product(this: Matrix3x3<Self>) -> Self {
this.a.iter().product()
}
#[inline(always)]
fn m3x3_top_right_sum_squares(this: Matrix3x3<Self>) -> Self {
this.a[1] * this.a[1] + this.a[2] * this.a[2] + this.a[5] * this.a[5]
}
#[rustfmt::skip]
#[inline(always)]
fn m3x3_top_right_determinant(this: Matrix3x3<Self>) -> Self {
this.a[0] * (this.a[4] * this.a[8] - this.a[5] * this.a[5])
- this.a[1] * (this.a[1] * this.a[8] - this.a[5] * this.a[2])
+ this.a[2] * (this.a[1] * this.a[5] - this.a[4] * this.a[2])
}
#[rustfmt::skip]
#[inline(always)]
fn m3x3_determinant(this: Matrix3x3<Self>) -> Self {
this.a[0] * (this.a[4] * this.a[8] - this.a[5] * this.a[7])
-this.a[1] * (this.a[3] * this.a[8] - this.a[5] * this.a[6])
+this.a[2] * (this.a[3] * this.a[7] - this.a[4] * this.a[6])
}
#[rustfmt::skip]
#[inline(always)]
fn m3x3_adjugate(this: Matrix3x3<Self>) -> (Matrix3x3<Self>, Self) {
let ei_fh = this.a[4] * this.a[8] - this.a[5] * this.a[7];
let di_fg = this.a[3] * this.a[8] - this.a[5] * this.a[6];
let dh_eg = this.a[3] * this.a[7] - this.a[4] * this.a[6];
let determinant = this.a[0] * ei_fh - this.a[1]*di_fg + this.a[2]* dh_eg;
let a = [
ei_fh, -(this.a[1] * this.a[8] - this.a[2] * this.a[7]), this.a[1] * this.a[5] - this.a[2] * this.a[4], - di_fg, this.a[0] * this.a[8] - this.a[2] * this.a[6], -(this.a[0] * this.a[5] - this.a[2] * this.a[3]), dh_eg, -(this.a[0] * this.a[7] - this.a[1] * this.a[6]), this.a[0] * this.a[4] - this.a[1] * this.a[3], ];
(Matrix3x3::from(a), determinant)
}
}