array_matrix/matrix/
adj.rs

1use std::ops::Neg;
2
3use num_traits::{One};
4
5use crate::SquareMatrix;
6
7use super::matrix_init;
8use super::minor::Minor;
9
10pub trait Adj: SquareMatrix
11where
12    Self::Output: SquareMatrix
13{
14    type Output;
15
16    /// Returns the adjugate matrix of the given square matrix
17    /// 
18    /// adj(A)
19    /// 
20    /// # Examples
21    /// 
22    /// ```rust
23    /// let a = [
24    ///     [1.0, 2.0],
25    ///     [3.0, 4.0]
26    /// ];
27    /// let aa = [
28    ///     [4.0, -2.0],
29    ///     [-3.0, 1.0]
30    /// ];
31    /// assert_eq!(a.adj(), aa);
32    /// ```
33    fn adj(&self) -> Self::Output;
34}
35
36impl<F: One> Adj for [[F; 1]; 1]
37where
38    Self: SquareMatrix
39{
40    type Output = Self;
41
42    fn adj(&self) -> Self::Output
43    {
44        [[F::one()]]
45    }
46}
47
48impl<F: Neg<Output = F> + Clone> Adj for [[F; 2]; 2]
49where
50    Self: SquareMatrix
51{
52    type Output = Self;
53
54    fn adj(&self) -> Self::Output
55    {
56        [
57            [self[1][1].clone(), -self[0][1].clone()],
58            [-self[1][0].clone(), self[0][0].clone()]
59        ]
60    }
61}
62
63macro_rules! adj {
64    ($i:expr) => {
65        impl<F: One + Neg<Output = F>> Adj for [[F; $i]; $i]
66        where
67            Self: SquareMatrix + Minor<Output = F, Index = (usize, usize)>
68        {
69            type Output = Self;
70        
71            fn adj(&self) -> Self::Output
72            {
73                matrix_init(|r, c| if (r+c)%2 == 0 {F::one()} else {-F::one()}*self.minor((c, r)))
74            }
75        }
76    };
77}
78
79adj!(3);
80adj!(4);
81adj!(5);
82adj!(6);
83adj!(7);
84adj!(8);
85adj!(9);
86adj!(10);
87adj!(11);
88adj!(12);
89adj!(13);
90adj!(14);
91adj!(15);
92adj!(16);