#![allow(
clippy::erasing_op,
clippy::identity_op,
clippy::suspicious_op_assign_impl,
clippy::suspicious_arithmetic_impl
)]
use std::fmt;
use crate::fraction::Fraction;
use super::{Matrix, MatrixError, TransformVector};
use crate::vector::{ VectorError, vector3d::Vector3D };
pub struct Matrix4x4 {
pub data: [Fraction; 4 * 4],
}
impl Matrix for Matrix4x4 {
type Data = Fraction;
fn new() -> Self {
Matrix4x4 {
data: [
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
],
}
}
fn from(value: Self::Data) -> Self {
Matrix4x4 {
data: [
value, value, value, value, value, value, value, value, value, value, value, value,
value, value, value, value,
],
}
}
fn from_slice(values: &[Self::Data]) -> Self {
let mut new_matrix = Matrix4x4::new();
new_matrix.data[0] = values[0];
new_matrix.data[1] = values[1];
new_matrix.data[2] = values[2];
new_matrix.data[3] = values[3];
new_matrix.data[4] = values[4];
new_matrix.data[5] = values[5];
new_matrix.data[6] = values[6];
new_matrix.data[7] = values[7];
new_matrix.data[8] = values[8];
new_matrix.data[9] = values[9];
new_matrix.data[10] = values[10];
new_matrix.data[11] = values[11];
new_matrix.data[12] = values[12];
new_matrix.data[13] = values[13];
new_matrix.data[14] = values[14];
new_matrix.data[15] = values[15];
new_matrix
}
fn scale(&self, scale: Self::Data) -> Self {
let mut scaled_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
scaled_matrix.data[4 * i + j] = self.data[4 * i + j] * scale;
}
}
scaled_matrix
}
fn determinant(&self) -> Result<Self::Data, MatrixError> {
Ok(self.data[4 * 0 + 0]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 3]
+ self.data[4 * 0 + 0]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 1]
+ self.data[4 * 0 + 0]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 2]
+ self.data[4 * 0 + 1]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 2]
+ self.data[4 * 0 + 1]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 3]
+ self.data[4 * 0 + 1]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 0]
+ self.data[4 * 0 + 2]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 3]
+ self.data[4 * 0 + 2]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 0]
+ self.data[4 * 0 + 2]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 1]
+ self.data[4 * 0 + 3]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 1]
+ self.data[4 * 0 + 3]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 2]
+ self.data[4 * 0 + 3]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 0]
- self.data[4 * 0 + 0]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 2]
- self.data[4 * 0 + 0]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 3]
- self.data[4 * 0 + 0]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 1]
- self.data[4 * 0 + 1]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 3]
- self.data[4 * 0 + 1]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 0]
- self.data[4 * 0 + 1]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 2]
- self.data[4 * 0 + 2]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 3]
* self.data[4 * 3 + 1]
- self.data[4 * 0 + 2]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 3]
- self.data[4 * 0 + 2]
* self.data[4 * 1 + 3]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 0]
- self.data[4 * 0 + 3]
* self.data[4 * 1 + 0]
* self.data[4 * 2 + 1]
* self.data[4 * 3 + 2]
- self.data[4 * 0 + 3]
* self.data[4 * 1 + 1]
* self.data[4 * 2 + 2]
* self.data[4 * 3 + 0]
- self.data[4 * 0 + 3]
* self.data[4 * 1 + 2]
* self.data[4 * 2 + 0]
* self.data[4 * 3 + 1])
}
fn transpose(&self) -> Self {
let mut transposed_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
transposed_matrix.data[4 * i + j] = self.data[i + 4 * j];
}
}
transposed_matrix
}
fn cofactor(&self) -> Result<Self, MatrixError> {
let mut cofactor_matrix = Matrix4x4::new();
cofactor_matrix.data[4 * 0 + 0] = self.data[4 * 1 + 1]
* (self.data[4 * 2 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 1 + 2]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 1])
+ self.data[4 * 1 + 3]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 1]);
cofactor_matrix.data[4 * 0 + 1] = -(self.data[4 * 1 + 0]
* (self.data[4 * 2 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 1 + 2]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 1 + 3]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 0]));
cofactor_matrix.data[4 * 0 + 2] = self.data[4 * 1 + 0]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 1])
- self.data[4 * 1 + 1]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 1 + 3]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 2 + 1] * self.data[4 * 3 + 0]);
cofactor_matrix.data[4 * 0 + 3] = -(self.data[4 * 1 + 0]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 1])
- self.data[4 * 1 + 1]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 0])
+ self.data[4 * 1 + 2]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 2 + 1] * self.data[4 * 3 + 0]));
cofactor_matrix.data[4 * 1 + 0] = -(self.data[4 * 0 + 1]
* (self.data[4 * 2 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 1])
+ self.data[4 * 0 + 3]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 1]));
cofactor_matrix.data[4 * 1 + 1] = self.data[4 * 0 + 0]
* (self.data[4 * 2 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 0]);
cofactor_matrix.data[4 * 1 + 2] = -(self.data[4 * 0 + 0]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 2 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 2 + 1] * self.data[4 * 3 + 0]));
cofactor_matrix.data[4 * 1 + 3] = self.data[4 * 0 + 0]
* (self.data[4 * 2 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 2 + 2] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 2]
* (self.data[4 * 2 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 2 + 1] * self.data[4 * 3 + 0]);
cofactor_matrix.data[4 * 2 + 0] = self.data[4 * 0 + 1]
* (self.data[4 * 1 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 1 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 1])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 3 + 1]);
cofactor_matrix.data[4 * 2 + 1] = -(self.data[4 * 0 + 0]
* (self.data[4 * 1 + 2] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 3 + 0]));
cofactor_matrix.data[4 * 2 + 2] = self.data[4 * 0 + 0]
* (self.data[4 * 1 + 1] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 1 + 1] * self.data[4 * 3 + 0]);
cofactor_matrix.data[4 * 2 + 3] = -(self.data[4 * 0 + 0]
* (self.data[4 * 1 + 1] * self.data[4 * 3 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 3 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 3 + 0])
+ self.data[4 * 0 + 2]
* (self.data[4 * 1 + 0] * self.data[4 * 3 + 1]
- self.data[4 * 1 + 1] * self.data[4 * 3 + 0]));
cofactor_matrix.data[4 * 3 + 0] = -(self.data[4 * 0 + 1]
* (self.data[4 * 1 + 2] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 1 + 1] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 1])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 1] * self.data[4 * 2 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 2 + 1]));
cofactor_matrix.data[4 * 3 + 1] = self.data[4 * 0 + 0]
* (self.data[4 * 1 + 2] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 2])
- self.data[4 * 0 + 2]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 2 + 0]);
cofactor_matrix.data[4 * 3 + 2] = -(self.data[4 * 0 + 0]
* (self.data[4 * 1 + 1] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 3]
- self.data[4 * 1 + 3] * self.data[4 * 2 + 0])
+ self.data[4 * 0 + 3]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 1]
- self.data[4 * 1 + 1] * self.data[4 * 2 + 0]));
cofactor_matrix.data[4 * 3 + 3] = self.data[4 * 0 + 0]
* (self.data[4 * 1 + 1] * self.data[4 * 2 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 2 + 1])
- self.data[4 * 0 + 1]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 2]
- self.data[4 * 1 + 2] * self.data[4 * 2 + 0])
+ self.data[4 * 0 + 2]
* (self.data[4 * 1 + 0] * self.data[4 * 2 + 1]
- self.data[4 * 1 + 1] * self.data[4 * 2 + 0]);
Ok(cofactor_matrix)
}
fn adjugate(&self) -> Result<Self, MatrixError> {
Ok(self.cofactor().unwrap().transpose())
}
fn inverse(&self) -> Result<Self, MatrixError>
where
Self: Sized,
{
let determinant = self.determinant().unwrap();
if determinant == Self::Data::from(0_i16) {
return Err(MatrixError::ZeroDeterminantError);
}
let inverse_matrix = self
.adjugate()
.unwrap()
.scale(Self::Data::from(1_i16) / determinant);
Ok(inverse_matrix)
}
}
impl TransformVector<Vector3D> for Matrix4x4 {
fn transform_vector(&self, other: Vector3D) -> Result<Vector3D, VectorError> {
Ok(Vector3D {
data: [
other[0] * self.data[4 * 0 + 0] + other[1] * self.data[4 * 0 + 1] + other[2] * self.data[4 * 0 + 2] + self.data[4 * 0 + 3],
other[0] * self.data[4 * 1 + 0] + other[1] * self.data[4 * 1 + 1] + other[2] * self.data[4 * 1 + 2] + self.data[4 * 1 + 3],
other[0] * self.data[4 * 2 + 0] + other[1] * self.data[4 * 2 + 1] + other[2] * self.data[4 * 2 + 2] + self.data[4 * 2 + 3],
],
})
}
}
impl std::cmp::PartialEq for Matrix4x4 {
fn eq(&self, other: &Matrix4x4) -> bool {
for i in 0..4 {
for j in 0..4 {
if self.data[4 * i + j] != other[4 * i + j] {
return false;
}
}
}
true
}
}
impl std::cmp::Eq for Matrix4x4 {}
impl std::ops::Add for Matrix4x4 {
type Output = Matrix4x4;
fn add(self, other: Matrix4x4) -> Matrix4x4 {
let mut sum_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
sum_matrix[4 * i + j] = self.data[4 * i + j] + other[4 * i + j];
}
}
sum_matrix
}
}
impl std::ops::AddAssign for Matrix4x4 {
fn add_assign(&mut self, other: Matrix4x4) {
for i in 0..4 {
for j in 0..4 {
self.data[4 * i + j] += other[4 * i + j];
}
}
}
}
impl std::ops::Sub for Matrix4x4 {
type Output = Matrix4x4;
fn sub(self, other: Matrix4x4) -> Matrix4x4 {
let mut difference_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
difference_matrix[4 * i + j] = self.data[4 * i + j] - other[4 * i + j];
}
}
difference_matrix
}
}
impl std::ops::SubAssign for Matrix4x4 {
fn sub_assign(&mut self, other: Matrix4x4) {
for i in 0..4 {
for j in 0..4 {
self.data[4 * i + j] -= other[4 * i + j];
}
}
}
}
impl std::ops::Mul for Matrix4x4 {
type Output = Matrix4x4;
fn mul(self, other: Matrix4x4) -> Matrix4x4 {
let mut product_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
for m in 0..4 {
product_matrix[4 * i + j] += self.data[4 * i + m] * other[4 * m + j];
}
}
}
product_matrix
}
}
impl std::ops::MulAssign for Matrix4x4 {
fn mul_assign(&mut self, other: Matrix4x4) {
let mut product_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
for m in 0..4 {
product_matrix[4 * i + j] += self.data[4 * i + m] * other[4 * m + j];
}
}
}
self.data[0..16].clone_from_slice(&product_matrix.data[0..16]);
}
}
impl std::ops::Neg for Matrix4x4 {
type Output = Matrix4x4;
fn neg(self) -> Matrix4x4 {
let mut negated_matrix = Matrix4x4::new();
for i in 0..4 {
for j in 0..4 {
negated_matrix[4 * i + j] = -self.data[4 * i + j];
}
}
negated_matrix
}
}
impl std::ops::Index<usize> for Matrix4x4 {
type Output = Fraction;
fn index(&self, index: usize) -> &Fraction {
&self.data[index]
}
}
impl std::ops::IndexMut<usize> for Matrix4x4 {
fn index_mut(&mut self, index: usize) -> &mut Fraction {
&mut self.data[index]
}
}
impl Copy for Matrix4x4 {}
impl Clone for Matrix4x4 {
fn clone(&self) -> Matrix4x4 {
*self
}
}
impl fmt::Debug for Matrix4x4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"\n[{}, {}, {}, {}]\n[{}, {}, {}, {}]\n[{}, {}, {}, {}]\n[{}, {}, {}, {}]",
self.data[4 * 0 + 0],
self.data[4 * 0 + 1],
self.data[4 * 0 + 2],
self.data[4 * 0 + 3],
self.data[4 * 1 + 0],
self.data[4 * 1 + 1],
self.data[4 * 1 + 2],
self.data[4 * 1 + 3],
self.data[4 * 2 + 0],
self.data[4 * 2 + 1],
self.data[4 * 2 + 2],
self.data[4 * 2 + 3],
self.data[4 * 3 + 0],
self.data[4 * 3 + 1],
self.data[4 * 3 + 2],
self.data[4 * 3 + 3]
)
}
}
impl fmt::Display for Matrix4x4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"\n({}, {}, {}, {})\n({}, {}, {}, {})\n({}, {}, {}, {})\n({}, {}, {}, {})",
self.data[4 * 0 + 0],
self.data[4 * 0 + 1],
self.data[4 * 0 + 2],
self.data[4 * 0 + 3],
self.data[4 * 1 + 0],
self.data[4 * 1 + 1],
self.data[4 * 1 + 2],
self.data[4 * 1 + 3],
self.data[4 * 2 + 0],
self.data[4 * 2 + 1],
self.data[4 * 2 + 2],
self.data[4 * 2 + 3],
self.data[4 * 3 + 0],
self.data[4 * 3 + 1],
self.data[4 * 3 + 2],
self.data[4 * 3 + 3]
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_test() {
let values: [Fraction; 16] = [
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
];
let matrix1: Matrix4x4 = Matrix4x4 {
data: [
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(0, 1),
],
};
let matrix2 = Matrix4x4::new();
let matrix3 = Matrix::from(Fraction::new_denom(0, 1));
let matrix4 = Matrix4x4::from_slice(&values);
assert_eq!(matrix1, matrix2);
assert_eq!(matrix2, matrix3);
assert_eq!(matrix3, matrix4);
}
#[test]
fn addition_test() {
let matrix1: Matrix4x4 = Matrix::from(Fraction::new_denom(5, 1));
let matrix2 = Matrix::from(Fraction::new_denom(6, 1));
let result_matrix = Matrix::from(Fraction::new_denom(11, 1));
assert_eq!(matrix1 + matrix2, result_matrix);
assert_eq!(matrix2 + matrix1, result_matrix);
}
#[test]
fn subtraction_test() {
let matrix1: Matrix4x4 = Matrix::from(Fraction::new_denom(5, 1));
let matrix2 = Matrix::from(Fraction::new_denom(6, 1));
let result_matrix1 = Matrix::from(Fraction::new_denom(-1, 1));
let result_matrix2 = Matrix::from(Fraction::new_denom(1, 1));
assert_eq!(matrix1 - matrix2, result_matrix1);
assert_eq!(matrix2 - matrix1, result_matrix2);
}
#[test]
fn multiplication_test() {
let values1: [Fraction; 16] = [
Fraction::new_denom(4, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(3, 1),
];
let values2: [Fraction; 16] = [
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(3, 1),
];
let result_values1: [Fraction; 16] = [
Fraction::new_denom(92, 1),
Fraction::new_denom(48, 1),
Fraction::new_denom(84, 1),
Fraction::new_denom(79, 1),
Fraction::new_denom(75, 1),
Fraction::new_denom(37, 1),
Fraction::new_denom(67, 1),
Fraction::new_denom(68, 1),
Fraction::new_denom(64, 1),
Fraction::new_denom(28, 1),
Fraction::new_denom(49, 1),
Fraction::new_denom(58, 1),
Fraction::new_denom(90, 1),
Fraction::new_denom(48, 1),
Fraction::new_denom(84, 1),
Fraction::new_denom(85, 1),
];
let result_values2: [Fraction; 16] = [
Fraction::new_denom(94, 1),
Fraction::new_denom(32, 1),
Fraction::new_denom(78, 1),
Fraction::new_denom(59, 1),
Fraction::new_denom(72, 1),
Fraction::new_denom(25, 1),
Fraction::new_denom(63, 1),
Fraction::new_denom(54, 1),
Fraction::new_denom(125, 1),
Fraction::new_denom(40, 1),
Fraction::new_denom(89, 1),
Fraction::new_denom(73, 1),
Fraction::new_denom(80, 1),
Fraction::new_denom(28, 1),
Fraction::new_denom(66, 1),
Fraction::new_denom(55, 1),
];
let matrix1: Matrix4x4 = Matrix4x4::from_slice(&values1);
let matrix2 = Matrix4x4::from_slice(&values2);
let result_matrix1 = Matrix4x4::from_slice(&result_values1);
let result_matrix2 = Matrix4x4::from_slice(&result_values2);
assert_eq!(matrix1 * matrix2, result_matrix1);
assert_eq!(matrix2 * matrix1, result_matrix2);
}
#[test]
fn scale_test() {
let scale = Fraction::new_denom(5, 1);
let values: [Fraction; 16] = [
Fraction::new_denom(4, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(6, 1),
];
let result_values: [Fraction; 16] = [
Fraction::new_denom(4 * 5, 1),
Fraction::new_denom(2 * 5, 1),
Fraction::new_denom(6 * 5, 1),
Fraction::new_denom(5 * 5, 1),
Fraction::new_denom(5 * 5, 1),
Fraction::new_denom(1 * 5, 1),
Fraction::new_denom(3 * 5, 1),
Fraction::new_denom(4 * 5, 1),
Fraction::new_denom(7 * 5, 1),
Fraction::new_denom(4 * 5, 1),
Fraction::new_denom(2 * 5, 1),
Fraction::new_denom(2 * 5, 1),
Fraction::new_denom(7 * 5, 1),
Fraction::new_denom(2 * 5, 1),
Fraction::new_denom(1 * 5, 1),
Fraction::new_denom(6 * 5, 1),
];
let matrix = Matrix4x4::from_slice(&values);
let result_matrix = Matrix4x4::from_slice(&result_values);
assert_eq!(matrix.scale(scale), result_matrix);
}
#[test]
fn transpose_test() {
let values1: [Fraction; 16] = [
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(9, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(6, 1),
];
let result_values: [Fraction; 16] = [
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(9, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(6, 1),
];
let matrix = Matrix4x4::from_slice(&values1);
let result_matrix = Matrix4x4::from_slice(&result_values);
assert_eq!(matrix.transpose(), result_matrix);
}
#[test]
fn cofactor_test() {
let values: [Fraction; 16] = [
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(9, 1),
];
let result_values: [Fraction; 16] = [
Fraction::new_denom(-30, 1),
Fraction::new_denom(66, 1),
Fraction::new_denom(26, 1),
Fraction::new_denom(-26, 1),
Fraction::new_denom(90, 1),
Fraction::new_denom(-264, 1),
Fraction::new_denom(-54, 1),
Fraction::new_denom(114, 1),
Fraction::new_denom(-60, 1),
Fraction::new_denom(210, 1),
Fraction::new_denom(40, 1),
Fraction::new_denom(-100, 1),
Fraction::new_denom(0, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(-4, 1),
Fraction::new_denom(4, 1),
];
let matrix = Matrix4x4::from_slice(&values);
let result_matrix = Matrix4x4::from_slice(&result_values);
assert_eq!(matrix.cofactor().unwrap(), result_matrix);
}
#[test]
fn adjugate_test() {
let values: [Fraction; 16] = [
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(9, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(8, 1),
];
let result_values: [Fraction; 16] = [
Fraction::new_denom(68, 1),
Fraction::new_denom(-36, 1),
Fraction::new_denom(-95, 1),
Fraction::new_denom(14, 1),
Fraction::new_denom(92, 1),
Fraction::new_denom(-110, 1),
Fraction::new_denom(86, 1),
Fraction::new_denom(-73, 1),
Fraction::new_denom(-110, 1),
Fraction::new_denom(-95, 1),
Fraction::new_denom(169, 1),
Fraction::new_denom(8, 1),
Fraction::new_denom(-55, 1),
Fraction::new_denom(213, 1),
Fraction::new_denom(-176, 1),
Fraction::new_denom(4, 1),
];
let matrix = Matrix4x4::from_slice(&values);
let result_matrix = Matrix4x4::from_slice(&result_values);
assert_eq!(matrix.adjugate().unwrap(), result_matrix);
}
#[test]
fn determinant_test() {
let values: [Fraction; 16] = [
Fraction::new_denom(4, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(5, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(6, 1),
];
let matrix = Matrix4x4::from_slice(&values);
let determinant = Fraction::new_denom(45, 1);
assert_eq!(matrix.determinant().unwrap(), determinant);
}
#[test]
fn inverse_test() {
let values: [Fraction; 16] = [
Fraction::new_denom(5, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(2, 1),
Fraction::new_denom(4, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(1, 1),
Fraction::new_denom(7, 1),
Fraction::new_denom(3, 1),
Fraction::new_denom(6, 1),
Fraction::new_denom(8, 1),
];
let result_values: [Fraction; 16] = [
Fraction::new_denom(252, 555),
Fraction::new_denom(-63, 555),
Fraction::new_denom(102, 555),
Fraction::new_denom(-123, 555),
Fraction::new_denom(-82, 555),
Fraction::new_denom(113, 555),
Fraction::new_denom(-42, 555),
Fraction::new_denom(18, 555),
Fraction::new_denom(-109, 555),
Fraction::new_denom(-19, 555),
Fraction::new_denom(66, 555),
Fraction::new_denom(51, 555),
Fraction::new_denom(-108, 555),
Fraction::new_denom(27, 555),
Fraction::new_denom(-123, 555),
Fraction::new_denom(132, 555),
];
let matrix = Matrix4x4::from_slice(&values);
let result_matrix = Matrix4x4::from_slice(&result_values);
assert_eq!(matrix.inverse().unwrap(), result_matrix);
}
}