ndarray_linalg/eig.rs
1//! Eigenvalue decomposition for non-symmetric square matrices
2
3use crate::error::*;
4use crate::layout::*;
5use crate::types::*;
6use ndarray::*;
7
8/// Eigenvalue decomposition of general matrix reference
9pub trait Eig {
10 /// EigVec is the right eivenvector
11 type EigVal;
12 type EigVec;
13 /// Calculate eigenvalues with the right eigenvector
14 ///
15 /// $$ A u_i = \lambda_i u_i $$
16 ///
17 /// ```
18 /// use ndarray::*;
19 /// use ndarray_linalg::*;
20 ///
21 /// let a: Array2<f64> = array![
22 /// [-1.01, 0.86, -4.60, 3.31, -4.81],
23 /// [ 3.98, 0.53, -7.04, 5.29, 3.55],
24 /// [ 3.30, 8.26, -3.89, 8.20, -1.51],
25 /// [ 4.43, 4.96, -7.66, -7.33, 6.18],
26 /// [ 7.31, -6.43, -6.16, 2.47, 5.58],
27 /// ];
28 /// let (eigs, vecs) = a.eig().unwrap();
29 ///
30 /// let a = a.map(|v| v.as_c());
31 /// for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
32 /// let ev = vec.map(|v| v * e);
33 /// let av = a.dot(&vec);
34 /// assert_close_l2!(&av, &ev, 1e-5);
35 /// }
36 /// ```
37 fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
38}
39
40impl<A, S> Eig for ArrayBase<S, Ix2>
41where
42 A: Scalar + Lapack,
43 S: Data<Elem = A>,
44{
45 type EigVal = Array1<A::Complex>;
46 type EigVec = Array2<A::Complex>;
47
48 fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
49 let mut a = self.to_owned();
50 let layout = a.square_layout()?;
51 let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?;
52 let n = layout.len() as usize;
53 Ok((
54 ArrayBase::from(s),
55 Array2::from_shape_vec((n, n).f(), t).unwrap(),
56 ))
57 }
58}
59
60/// Calculate eigenvalues without eigenvectors
61pub trait EigVals {
62 type EigVal;
63 fn eigvals(&self) -> Result<Self::EigVal>;
64}
65
66impl<A, S> EigVals for ArrayBase<S, Ix2>
67where
68 A: Scalar + Lapack,
69 S: Data<Elem = A>,
70{
71 type EigVal = Array1<A::Complex>;
72
73 fn eigvals(&self) -> Result<Self::EigVal> {
74 let mut a = self.to_owned();
75 let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?;
76 Ok(ArrayBase::from(s))
77 }
78}