inverse works but rel equal doesn't
This commit is contained in:
@@ -3,7 +3,7 @@ extern crate approx;
|
||||
|
||||
use structs::Tuple;
|
||||
|
||||
use std::ops::Index;
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Matrix {
|
||||
@@ -97,6 +97,29 @@ impl Matrix {
|
||||
}
|
||||
Matrix::from_vec(m)
|
||||
}
|
||||
|
||||
pub fn is_invertable(&self) -> bool {
|
||||
self.determinant() != 0.0
|
||||
}
|
||||
|
||||
pub fn inverse(&self) -> Matrix {
|
||||
// seems dangerous
|
||||
if !self.is_invertable() {
|
||||
panic!("We can't invert {:?}", self.matrix);
|
||||
}
|
||||
|
||||
//let mut matrix: Vec<Vec<f32>> = Vec::with_capacity(self.matrix.len());
|
||||
let mut matrix = Matrix::default(self.matrix.len(), self.matrix[0].len());
|
||||
let det = self.determinant();
|
||||
for (row_idx, row) in self.matrix.iter().enumerate().take(self.matrix.len()) {
|
||||
for (col_idx, _) in row.iter().enumerate().take(row.len()) {
|
||||
let c = self.cofactor(row_idx, col_idx);
|
||||
let val = c / det;
|
||||
matrix[col_idx][row_idx] = val;
|
||||
}
|
||||
}
|
||||
matrix
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Matrix {
|
||||
@@ -106,6 +129,12 @@ impl Index<usize> for Matrix {
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Matrix {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
&mut self.matrix[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Matrix {
|
||||
fn eq(&self, _rhs: &Self) -> bool {
|
||||
if self.matrix.len() != _rhs.matrix.len() {
|
||||
@@ -479,4 +508,56 @@ mod tests {
|
||||
assert_eq!(-4071.0, m.determinant());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_invert_invertable() {
|
||||
let m = Matrix::from_array([
|
||||
[6.0, 4.0, 4.0, 4.0],
|
||||
[5.0, 5.0, 7.0, 6.0],
|
||||
[4.0, -9.0, 3.0, -7.0],
|
||||
[9.0, 1.0, 7.0, -6.0],
|
||||
]);
|
||||
|
||||
assert_eq!(-2120.0, m.determinant());
|
||||
assert_eq!(true, m.is_invertable());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_invert_not_invertable() {
|
||||
let m = Matrix::from_array([
|
||||
[-4.0, 2.0, -2.0, -3.0],
|
||||
[9.0, 6.0, 2.0, 6.0],
|
||||
[0.0, -5.0, 1.0, -5.0],
|
||||
[0.0, 0.0, 0.0, 0.0],
|
||||
]);
|
||||
|
||||
assert_eq!(0.0, m.determinant());
|
||||
assert_eq!(false, m.is_invertable());
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inverse() {
|
||||
let m = Matrix::from_array([
|
||||
[-5.0, 2.0, 6.0, -8.0],
|
||||
[1.0, -5.0, 1.0, 8.0],
|
||||
[7.0, 7.0, -6.0, -7.0],
|
||||
[1.0, -3.0, 7.0, 4.0],
|
||||
]);
|
||||
|
||||
let b = m.inverse();
|
||||
assert_eq!(532.0, m.determinant());
|
||||
assert_eq!(-160.0, m.cofactor(2, 3));
|
||||
assert_eq!(-160.0/532.0, b[3][2]);
|
||||
assert_eq!(105.0, m.cofactor(3, 2));
|
||||
assert_eq!(105.0/532.0, b[2][3]);
|
||||
|
||||
let expected = Matrix::from_array([
|
||||
[0.21805, 0.45113, 0.24060, -0.04511],
|
||||
[-0.80827, -1.45677, -0.44361, 0.52068],
|
||||
[-0.07895, -0.22368, -0.05263, 0.19737],
|
||||
[-0.52256, -0.81392, -0.30075, 0.30639],
|
||||
]);
|
||||
|
||||
assert_eq!(expected, b);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user