use core::ops::{Add, Index, IndexMut, Mul};
use crate::Vec3;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Mat3x3 {
pub data: [f32; 9],
}
impl Mat3x3 {
pub fn new(data: [f32; 9]) -> Self {
Self { data }
}
pub fn zeros() -> Self {
Self { data: [0.0; 9] }
}
pub fn identity() -> Self {
Self {
data: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
}
}
pub fn skew_symmetric(q: Vec3<f32>) -> Mat3x3 {
Self {
data: [0.0, -q.z, q.y, q.z, 0.0, -q.x, -q.y, q.x, 0.0],
}
}
pub fn outer_product(a: Vec3<f32>, b: Vec3<f32>) -> Mat3x3 {
let mut data = [0.0; 9];
data[0] = a.x * b.x;
data[1] = a.x * b.y;
data[2] = a.x * b.z;
data[3] = a.y * b.x;
data[4] = a.y * b.y;
data[5] = a.y * b.z;
data[6] = a.z * b.x;
data[7] = a.z * b.y;
data[8] = a.z * b.z;
Self { data }
}
pub fn transpose(&self) -> Self {
Self {
data: [
self.data[0],
self.data[3],
self.data[6],
self.data[1],
self.data[4],
self.data[7],
self.data[2],
self.data[5],
self.data[8],
],
}
}
pub fn determinant(&self) -> f32 {
let data = &self.data;
data[0] * (data[4] * data[8] - data[7] * data[5])
- data[3] * (data[1] * data[8] - data[7] * data[2])
+ data[6] * (data[1] * data[5] - data[4] * data[2])
}
pub fn trace(&self) -> f32 {
self.data[0] + self.data[4] + self.data[8]
}
pub fn is_finite(&self) -> bool {
self.data.iter().all(|&x| x.is_finite())
}
}
impl Index<[usize; 2]> for Mat3x3 {
type Output = f32;
fn index(&self, ndx: [usize; 2]) -> &Self::Output {
&self.data[ndx[0] * 3 + ndx[1]]
}
}
impl IndexMut<[usize; 2]> for Mat3x3 {
fn index_mut(&mut self, idx: [usize; 2]) -> &mut f32 {
&mut self.data[idx[0] * 3 + idx[1]]
}
}
impl Mul<f32> for Mat3x3 {
type Output = Mat3x3;
fn mul(self, scalar: f32) -> Mat3x3 {
let mut data = [0.0; 9];
for (i, item) in data.iter_mut().enumerate() {
*item = self.data[i] * scalar;
}
Mat3x3 { data }
}
}
impl Add<Mat3x3> for Mat3x3 {
type Output = Mat3x3;
fn add(self, rhs: Mat3x3) -> Mat3x3 {
let mut data = [0.0; 9];
for (i, item) in data.iter_mut().enumerate() {
*item = self.data[i] + rhs.data[i];
}
Mat3x3 { data }
}
}
impl Mul<Mat3x3> for Mat3x3 {
type Output = Mat3x3;
fn mul(self, rhs: Mat3x3) -> Mat3x3 {
let mut data = [0.0; 9];
for i in 0..3 {
for j in 0..3 {
let mut sum = 0.0;
for k in 0..3 {
sum += self[[i, k]] * rhs[[k, j]];
}
data[i * 3 + j] = sum;
}
}
Mat3x3 { data }
}
}