array_matrix/matrix/inv.rs
1use num_traits::Inv;
2use num_traits::Zero;
3
4use crate::MMul;
5use crate::Adj;
6use crate::Det;
7use crate::SquareMatrix;
8
9pub trait MInv: SquareMatrix
10where
11 Self::Output: SquareMatrix
12{
13 type Output;
14
15 /// Returns the inverted matrix if the matrix is non-singular
16 ///
17 /// A⁻¹
18 ///
19 /// # Examples
20 ///
21 /// ```rust
22 /// // Returns none if matrix is singular
23 /// let a = [
24 /// [1.0, 2.0],
25 /// [2.0, 4.0]
26 /// ];
27 /// assert_eq!(a.inv(), None);
28 ///
29 /// // Otherwise equals adjunct matrix divided by determinant
30 /// let a = [
31 /// [1.0, 2.0],
32 /// [3.0, 4.0]
33 /// ];
34 /// let ai = a.adj().dot(a.det().recip());
35 /// assert_eq!(a.inv(), Some(ai));
36 /// ```
37 fn inv(&self) -> Option<Self::Output>;
38}
39
40impl<F, M> MInv for M
41where
42 F: Inv<Output = F> + Zero,
43 Self: Adj + Det<Output = F>,
44 <Self as Adj>::Output: MMul<F>,
45 <<Self as Adj>::Output as MMul<F>>::Output: SquareMatrix
46{
47 type Output = <<Self as Adj>::Output as MMul<F>>::Output;
48
49 fn inv(&self) -> Option<Self::Output>
50 {
51 let det = self.det();
52 if det.is_zero()
53 {
54 None
55 }
56 else
57 {
58 Some(self.adj().mul(det.inv()))
59 }
60 }
61}