opis/matrix/
inverse.rs

1use crate::Matrix;
2use std::error::Error;
3
4impl<T> Matrix<T>
5where T: std::ops::Mul<Output=T>
6+ std::ops::Sub<Output=T>
7+ Clone
8+ std::cmp::PartialOrd
9+ std::ops::Div<Output=Result<T, Box<dyn Error>>>
10+ std::ops::Add<Output=T> + std::fmt::Debug {
11    
12    pub fn inverse_div_err(&self, neg_one: T, zero: T, one: T) -> Result<Matrix<T>, Box<dyn Error>> {
13
14        let (rows, columns) = self.dimensions()?;
15
16        if rows == columns {
17
18            let determinant = self.determinant(neg_one.clone())?;
19
20            if determinant != zero {
21
22                let minors_matrix = self.minors(neg_one.clone())?;
23
24                let cofactors_matrix = minors_matrix.cofactors(neg_one)?;
25
26                let transpose_matrix = cofactors_matrix.transpose()?;
27
28                let inv_det = (one / determinant)?;
29
30                let inverse_matrix = transpose_matrix * inv_det;
31                
32                Ok(inverse_matrix)
33
34            } else {
35
36                Err("Matrix is not invertible!")?
37
38            }
39
40        } else {
41            
42            Err("Non Square matrix!")?
43
44        }
45
46    }
47
48}
49
50impl<T> Matrix<T>
51where T: std::ops::Mul<Output=T>
52+ std::ops::Sub<Output=T>
53+ Clone
54+ std::cmp::PartialOrd
55+ std::ops::Div<Output=T>
56+ std::ops::Add<Output=T> + std::fmt::Debug {
57    
58    pub fn inverse(&self, neg_one: T, zero: T, one: T) -> Result<Matrix<T>, Box<dyn Error>> {
59
60        let (rows, columns) = self.dimensions()?;
61
62        if rows == columns {
63
64            let determinant = self.determinant(neg_one.clone())?;
65
66            if determinant != zero {
67
68                let minors_matrix = self.minors(neg_one.clone())?;
69
70                let cofactors_matrix = minors_matrix.cofactors(neg_one)?;
71
72                let transpose_matrix = cofactors_matrix.transpose()?;
73
74                let inv_det = one / determinant;
75
76                let inverse_matrix = transpose_matrix * inv_det;
77                
78                Ok(inverse_matrix)
79
80            } else {
81
82                Err("Matrix is not invertible!")?
83
84            }
85
86        } else {
87            
88            Err("Non Square matrix!")?
89
90        }
91
92    }
93
94}
95
96#[cfg(test)]
97mod tests {
98    
99    use crate::Fraction;
100    use super::*;
101
102    #[test]
103    fn test_matrix_inverse_0() {
104
105        let a = Matrix(vec![
106            vec![Fraction::from(&1_u8), (&2_u8).into(), (&3_u8).into()],
107            vec![(&4_u8).into(), (&5_u8).into(), (&6_u8).into()],
108            vec![(&7_u8).into(), (&2_u8).into(), (&9_u8).into()],
109        ]);
110
111        let i = Matrix(vec![
112            vec![("-11/12").try_into().unwrap(), ("1/3").try_into().unwrap(), ("1/12").try_into().unwrap()],
113            vec![("-1/6").try_into().unwrap(), ("1/3").try_into().unwrap(), ("-1/6").try_into().unwrap()],
114            vec![("3/4").try_into().unwrap(), ("-1/3").try_into().unwrap(), ("1/12").try_into().unwrap()],
115        ]);
116
117        assert_eq!(
118            a.inverse_div_err(
119                ("-1/1").try_into().unwrap(),
120                (&0_u8).into(),
121                (&1_u8).into()
122            ).unwrap(),
123            i
124        );
125         
126    }
127
128    // #[test]
129    // fn test_matrix_inverse_for_i8() {
130
131    //     let a = Matrix(vec![vec![1,2], vec![1,3]]);
132
133    //     let i = Matrix(vec![vec![3,-2], vec![-1,1]]);
134
135    //     assert_eq!(a.inverse(-1,0,1).unwrap(), i);
136         
137    // }
138
139    // #[test]
140    // fn test_matrix_inverse_for_fraction() {
141
142    //     let a = Matrix(vec![
143    //         vec![Fraction::from(&2_u8), (&3_u8).into(), (&3_u8).into()],
144    //         vec![(&2_u8).into(), (&4_u8).into(), (&5_u8).into()],
145    //         vec![(&1_u8).into(), (&1_u8).into(), (&2_u8).into()],
146    //     ]);
147
148    //     let i = Matrix(vec![
149    //         vec![(&1_u8).into(), ("-1/1").try_into().unwrap(), (&1_u8).into()],
150    //         vec![("1/3").try_into().unwrap(), ("1/3").try_into().unwrap(), ("-4/3").try_into().unwrap()],
151    //         vec![("-2/3").try_into().unwrap(), ("1/3").try_into().unwrap(), ("2/3").try_into().unwrap()],
152    //     ]);
153
154    //     assert_eq!(
155    //         a.inverse_div_err(
156    //             ("-1/1").try_into().unwrap(),
157    //             (&0_u8).into(),
158    //             (&1_u8).into()
159    //         ).unwrap(),
160    //         i
161    //     );
162         
163    // }
164
165}