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}