Skip to content

Commit 5f658d2

Browse files
committed
rewrite a function collecting right eigenvector
1 parent a2bb5e2 commit 5f658d2

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

src/lapack/eig.rs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,40 @@ macro_rules! impl_eig_real {
4242
let mut vr = vec![Self::Real::zero(); (n * n) as usize];
4343
let info = $ev(l.lapacke_layout(), b'N', jobvr, n, &mut a, n, &mut wr, &mut wi, &mut vl, n, &mut vr, n);
4444
let w: Vec<Self::Complex> = wr.iter().zip(wi.iter()).map(|(&r, &i)| Self::Complex::new(r, i)).collect();
45+
// If the j-th eigenvalue is real, then
46+
// eigenvector = [ vr[j], vr[j+n], vr[j+2*n], ... ].
47+
//
48+
// If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
49+
// eigenvector(j) = [ vr[j] + i*vr[j+1], vr[j+n] + i*vr[j+n+1], vr[j+2*n] + i*vr[j+2*n+1], ... ] and
50+
// eigenvector(j+1) = [ vr[j] - i*vr[j+1], vr[j+n] - i*vr[j+n+1], vr[j+2*n] - i*vr[j+2*n+1], ... ].
51+
//
52+
// Therefore, if eigenvector(j) is written as [ v_{j0}, v_{j1}, v_{j2}, ... ],
53+
// you have to make
54+
// v = vec![ v_{00}, v_{10}, v_{20}, ..., v_{jk}, v_{(j+1)k}, v_{(j+2)k}, ... ] (v.len() = n*n)
55+
// based on wi and vr.
56+
// After that, v is converted to Array2 (see ../eig.rs).
4557
let n = n as usize;
46-
let mut conj = false;
47-
let mut v = vec![Self::Complex::zero(); n * n];
48-
for (i, c) in w.iter().enumerate() {
49-
if conj {
50-
for j in 0..n {
51-
v[n*j+i] = Self::Complex::new(vr[n*j+i-1], -vr[n*j+i]);
52-
}
53-
conj = false;
54-
} else if c.im != 0.0 {
55-
conj = true;
56-
for j in 0..n {
57-
v[n*j+i] = Self::Complex::new(vr[n*j+i], vr[n*j+i+1]);
58-
}
58+
let mut flg = false;
59+
let conj: Vec<i8> = wi.iter().map(|&i| {
60+
if flg {
61+
flg = false;
62+
-1
63+
} else if i != 0.0 {
64+
flg = true;
65+
1
5966
} else {
60-
for j in 0..n {
61-
v[n*j+i] = Self::Complex::new(vr[n*j+i], 0.0);
62-
}
67+
0
6368
}
64-
}
69+
}).collect();
70+
let v: Vec<Self::Complex> = (0..n*n).map(|i| {
71+
let j = i % n;
72+
match conj[j] {
73+
1 => Self::Complex::new(vr[i], vr[i+1]),
74+
-1 => Self::Complex::new(vr[i-1], -vr[i]),
75+
_ => Self::Complex::new(vr[i], 0.0),
76+
}
77+
}).collect();
78+
6579
into_result(info, (w, v))
6680
}
6781
}

0 commit comments

Comments
 (0)