1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! Inverts matrices.
use crate::Matrix;
use crate::error::*;
use super::{
StdFunc,
GetMinors,
Transpose,
Determinant,
};
#[derive(Clone)]
pub struct Invert;
impl Invert {
/// Evaluates `Invert` while minimizing heap allocation.
pub fn evalpure(matrix: &Matrix) -> Matrix {
let mut output = matrix.clone();
let rows = matrix.rows();
let cols = matrix.cols();
// Compute the determinant of the input matrix
let original_det = Determinant::evalpure(matrix);
// Step 1: For each cell, compute the determinant of the matrix of minors
// determined with respect to that cell
for i in 0..rows {
for j in 0..cols {
let matrix_of_minors = GetMinors::evalpure(matrix, i, j);
let det = Determinant::evalpure(&matrix_of_minors);
output[[i, j]] = det;
}
}
// Step 2: For each cell, if `i + j` is odd, multiply the value by -1
// Step 4: Divide each value by the determinant of the original matrix
for i in 0..rows {
for j in 0..cols {
if (i + j)%2 != 0 {
output[[i, j]] = output[[i, j]] * -1.0f64;
}
output[[i, j]] = output[[i, j]] / original_det;
}
}
// Step 3: Transpose the matrix
output = Transpose::evalpure(&output);
// Did Step 4 above
// We're done!
output
}
}
impl StdFunc for Invert {
fn eval(&self, args: Vec<Matrix>) -> Matrix {
if args.len() != 1 {
throw(WrongNumberOfArgs);
return Matrix::new(0, 0, Vec::new());
}
Self::evalpure(&args[0])
}
}