fix: cargo fmt
This commit is contained in:
+110
-108
@@ -1,75 +1,64 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use num::complex::Complex;
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
use num::complex::Complex;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EVD<T: FloatExt, M: BaseMatrix<T>> {
|
||||
pub struct EVD<T: FloatExt, M: BaseMatrix<T>> {
|
||||
pub d: Vec<T>,
|
||||
pub e: Vec<T>,
|
||||
pub V: M
|
||||
pub V: M,
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: BaseMatrix<T>> EVD<T, M> {
|
||||
pub fn new(V: M, d: Vec<T>, e: Vec<T>) -> EVD<T, M> {
|
||||
EVD {
|
||||
d: d,
|
||||
e: e,
|
||||
V: V
|
||||
}
|
||||
EVD { d: d, e: e, V: V }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
fn evd(&self, symmetric: bool) -> EVD<T, Self>{
|
||||
pub trait EVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
fn evd(&self, symmetric: bool) -> EVD<T, Self> {
|
||||
self.clone().evd_mut(symmetric)
|
||||
}
|
||||
|
||||
fn evd_mut(mut self, symmetric: bool) -> EVD<T, Self>{
|
||||
let(nrows, ncols) = self.shape();
|
||||
fn evd_mut(mut self, symmetric: bool) -> EVD<T, Self> {
|
||||
let (nrows, ncols) = self.shape();
|
||||
if ncols != nrows {
|
||||
panic!("Matrix is not square: {} x {}", nrows, ncols);
|
||||
}
|
||||
|
||||
let n = nrows;
|
||||
let mut d = vec![T::zero(); n];
|
||||
let mut e = vec![T::zero(); n];
|
||||
|
||||
let mut e = vec![T::zero(); n];
|
||||
|
||||
let mut V;
|
||||
if symmetric {
|
||||
if symmetric {
|
||||
V = self;
|
||||
// Tridiagonalize.
|
||||
tred2(&mut V, &mut d, &mut e);
|
||||
// Diagonalize.
|
||||
tql2(&mut V, &mut d, &mut e);
|
||||
|
||||
} else {
|
||||
let scale = balance(&mut self);
|
||||
|
||||
let perm = elmhes(&mut self);
|
||||
let scale = balance(&mut self);
|
||||
|
||||
V = Self::eye(n);
|
||||
let perm = elmhes(&mut self);
|
||||
|
||||
eltran(&self, &mut V, &perm);
|
||||
V = Self::eye(n);
|
||||
|
||||
eltran(&self, &mut V, &perm);
|
||||
|
||||
hqr2(&mut self, &mut V, &mut d, &mut e);
|
||||
balbak(&mut V, &scale);
|
||||
sort(&mut d, &mut e, &mut V);
|
||||
}
|
||||
|
||||
EVD {
|
||||
V: V,
|
||||
d: d,
|
||||
e: e
|
||||
}
|
||||
EVD { V: V, d: d, e: e }
|
||||
}
|
||||
}
|
||||
|
||||
fn tred2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>) {
|
||||
|
||||
let (n, _) = V.shape();
|
||||
for i in 0..n {
|
||||
d[i] = V.get(n - 1, i);
|
||||
@@ -131,7 +120,7 @@ fn tred2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T
|
||||
for j in 0..i {
|
||||
f = d[j];
|
||||
g = e[j];
|
||||
for k in j..=i-1 {
|
||||
for k in j..=i - 1 {
|
||||
V.sub_element_mut(k, j, f * e[k] + g * d[k]);
|
||||
}
|
||||
d[j] = V.get(i - 1, j);
|
||||
@@ -139,10 +128,10 @@ fn tred2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T
|
||||
}
|
||||
}
|
||||
d[i] = h;
|
||||
}
|
||||
}
|
||||
|
||||
// Accumulate transformations.
|
||||
for i in 0..n-1 {
|
||||
for i in 0..n - 1 {
|
||||
V.set(n - 1, i, V.get(i, i));
|
||||
V.set(i, i, T::one());
|
||||
let h = d[i + 1];
|
||||
@@ -156,7 +145,7 @@ fn tred2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T
|
||||
g = g + V.get(k, i + 1) * V.get(k, j);
|
||||
}
|
||||
for k in 0..=i {
|
||||
V.sub_element_mut(k, j, g * d[k]);
|
||||
V.sub_element_mut(k, j, g * d[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,7 +182,7 @@ fn tql2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>
|
||||
break;
|
||||
}
|
||||
m += 1;
|
||||
} else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -219,7 +208,7 @@ fn tql2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>
|
||||
d[l + 1] = e[l] * (p + r);
|
||||
let dl1 = d[l + 1];
|
||||
let mut h = g - d[l];
|
||||
for i in l+2..n {
|
||||
for i in l + 2..n {
|
||||
d[i] = d[i] - h;
|
||||
}
|
||||
f = f + h;
|
||||
@@ -249,7 +238,7 @@ fn tql2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>
|
||||
for k in 0..n {
|
||||
h = V.get(k, i + 1);
|
||||
V.set(k, i + 1, s * V.get(k, i) + c * h);
|
||||
V.set(k, i, c * V.get(k, i) - s * h);
|
||||
V.set(k, i, c * V.get(k, i) - s * h);
|
||||
}
|
||||
}
|
||||
p = -s * s2 * c3 * el1 * e[l] / dl1;
|
||||
@@ -267,7 +256,7 @@ fn tql2<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>
|
||||
}
|
||||
|
||||
// Sort eigenvalues and corresponding vectors.
|
||||
for i in 0..n-1 {
|
||||
for i in 0..n - 1 {
|
||||
let mut k = i;
|
||||
let mut p = d[i];
|
||||
for j in i + 1..n {
|
||||
@@ -294,8 +283,8 @@ fn balance<T: FloatExt, M: BaseMatrix<T>>(A: &mut M) -> Vec<T> {
|
||||
|
||||
let (n, _) = A.shape();
|
||||
|
||||
let mut scale = vec![T::one(); n];
|
||||
|
||||
let mut scale = vec![T::one(); n];
|
||||
|
||||
let t = T::from(0.95).unwrap();
|
||||
|
||||
let mut done = false;
|
||||
@@ -345,7 +334,7 @@ fn elmhes<T: FloatExt, M: BaseMatrix<T>>(A: &mut M) -> Vec<usize> {
|
||||
let (n, _) = A.shape();
|
||||
let mut perm = vec![0; n];
|
||||
|
||||
for m in 1..n-1 {
|
||||
for m in 1..n - 1 {
|
||||
let mut x = T::zero();
|
||||
let mut i = m;
|
||||
for j in m..n {
|
||||
@@ -353,10 +342,10 @@ fn elmhes<T: FloatExt, M: BaseMatrix<T>>(A: &mut M) -> Vec<usize> {
|
||||
x = A.get(j, m - 1);
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
perm[m] = i;
|
||||
if i != m {
|
||||
for j in (m-1)..n {
|
||||
for j in (m - 1)..n {
|
||||
let swap = A.get(i, j);
|
||||
A.set(i, j, A.get(m, j));
|
||||
A.set(m, j, swap);
|
||||
@@ -366,7 +355,7 @@ fn elmhes<T: FloatExt, M: BaseMatrix<T>>(A: &mut M) -> Vec<usize> {
|
||||
A.set(j, i, A.get(j, m));
|
||||
A.set(j, m, swap);
|
||||
}
|
||||
}
|
||||
}
|
||||
if x != T::zero() {
|
||||
for i in (m + 1)..n {
|
||||
let mut y = A.get(i, m - 1);
|
||||
@@ -381,11 +370,11 @@ fn elmhes<T: FloatExt, M: BaseMatrix<T>>(A: &mut M) -> Vec<usize> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return perm;
|
||||
}
|
||||
}
|
||||
|
||||
fn eltran<T: FloatExt, M: BaseMatrix<T>>(A: &M, V: &mut M, perm: &Vec<usize>) {
|
||||
let (n, _) = A.shape();
|
||||
@@ -405,27 +394,27 @@ fn eltran<T: FloatExt, M: BaseMatrix<T>>(A: &M, V: &mut M, perm: &Vec<usize>) {
|
||||
}
|
||||
|
||||
fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>) {
|
||||
let (n, _) = A.shape();
|
||||
let mut z = T::zero();
|
||||
let (n, _) = A.shape();
|
||||
let mut z = T::zero();
|
||||
let mut s = T::zero();
|
||||
let mut r = T::zero();
|
||||
let mut q = T::zero();
|
||||
let mut p = T::zero();
|
||||
let mut anorm = T::zero();
|
||||
|
||||
for i in 0..n {
|
||||
|
||||
for i in 0..n {
|
||||
for j in i32::max(i as i32 - 1, 0)..n as i32 {
|
||||
anorm = anorm + A.get(i, j as usize).abs();
|
||||
anorm = anorm + A.get(i, j as usize).abs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut nn = n - 1;
|
||||
let mut t = T::zero();
|
||||
'outer: loop {
|
||||
'outer: loop {
|
||||
let mut its = 0;
|
||||
loop {
|
||||
let mut l = nn;
|
||||
while l > 0 {
|
||||
while l > 0 {
|
||||
s = A.get(l - 1, l - 1).abs() + A.get(l, l).abs();
|
||||
if s == T::zero() {
|
||||
s = anorm;
|
||||
@@ -433,8 +422,8 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
if A.get(l, l - 1).abs() <= T::epsilon() * s {
|
||||
A.set(l, l - 1, T::zero());
|
||||
break;
|
||||
}
|
||||
l -= 1;
|
||||
}
|
||||
l -= 1;
|
||||
}
|
||||
let mut x = A.get(nn, nn);
|
||||
if l == nn {
|
||||
@@ -444,7 +433,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
break 'outer;
|
||||
} else {
|
||||
nn -= 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut y = A.get(nn - 1, nn - 1);
|
||||
let mut w = A.get(nn, nn - 1) * A.get(nn - 1, nn);
|
||||
@@ -453,7 +442,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
q = p * p + w;
|
||||
z = q.abs().sqrt();
|
||||
x = x + t;
|
||||
A.set(nn, nn, x );
|
||||
A.set(nn, nn, x);
|
||||
A.set(nn - 1, nn - 1, y + t);
|
||||
if q >= T::zero() {
|
||||
z = p + z.copysign(p);
|
||||
@@ -469,7 +458,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
r = (p * p + q * q).sqrt();
|
||||
p = p / r;
|
||||
q = q / r;
|
||||
for j in nn-1..n {
|
||||
for j in nn - 1..n {
|
||||
z = A.get(nn - 1, j);
|
||||
A.set(nn - 1, j, q * z + p * A.get(nn, j));
|
||||
A.set(nn, j, q * A.get(nn, j) - p * z);
|
||||
@@ -490,19 +479,19 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
d[nn - 1] = d[nn];
|
||||
e[nn - 1] = -e[nn];
|
||||
}
|
||||
|
||||
|
||||
if nn <= 1 {
|
||||
break 'outer;
|
||||
} else {
|
||||
nn -= 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if its == 30 {
|
||||
panic!("Too many iterations in hqr");
|
||||
}
|
||||
if its == 10 || its == 20 {
|
||||
t = t + x;
|
||||
for i in 0..nn+1 {
|
||||
for i in 0..nn + 1 {
|
||||
A.sub_element_mut(i, i, x);
|
||||
}
|
||||
s = A.get(nn, nn - 1).abs() + A.get(nn - 1, nn - 2).abs();
|
||||
@@ -527,14 +516,15 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
break;
|
||||
}
|
||||
let u = A.get(m, m - 1).abs() * (q.abs() + r.abs());
|
||||
let v = p.abs() * (A.get(m - 1, m - 1).abs() + z.abs() + A.get(m + 1, m + 1).abs());
|
||||
let v = p.abs()
|
||||
* (A.get(m - 1, m - 1).abs() + z.abs() + A.get(m + 1, m + 1).abs());
|
||||
if u <= T::epsilon() * v {
|
||||
break;
|
||||
}
|
||||
m -= 1;
|
||||
}
|
||||
for i in m..nn-1 {
|
||||
A.set(i + 2, i , T::zero());
|
||||
for i in m..nn - 1 {
|
||||
A.set(i + 2, i, T::zero());
|
||||
if i != m {
|
||||
A.set(i + 2, i - 1, T::zero());
|
||||
}
|
||||
@@ -547,7 +537,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
if k + 1 != nn {
|
||||
r = A.get(k + 2, k - 1);
|
||||
}
|
||||
x = p.abs() + q.abs() +r.abs();
|
||||
x = p.abs() + q.abs() + r.abs();
|
||||
if x != T::zero() {
|
||||
p = p / x;
|
||||
q = q / x;
|
||||
@@ -583,8 +573,8 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
mmin = nn;
|
||||
} else {
|
||||
mmin = k + 3;
|
||||
}
|
||||
for i in 0..mmin+1 {
|
||||
}
|
||||
for i in 0..mmin + 1 {
|
||||
p = x * A.get(i, k) + y * A.get(i, k + 1);
|
||||
if k + 1 != nn {
|
||||
p = p + z * A.get(i, k + 2);
|
||||
@@ -609,7 +599,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
if l + 1 >= nn {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if anorm != T::zero() {
|
||||
@@ -659,7 +649,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
}
|
||||
}
|
||||
}
|
||||
if i == 0{
|
||||
if i == 0 {
|
||||
break;
|
||||
} else {
|
||||
i -= 1;
|
||||
@@ -672,13 +662,14 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
A.set(na, na, q / A.get(nn, na));
|
||||
A.set(na, nn, -(A.get(nn, nn) - p) / A.get(nn, na));
|
||||
} else {
|
||||
let temp = Complex::new(T::zero(), -A.get(na, nn)) / Complex::new(A.get(na, na) - p, q);
|
||||
let temp = Complex::new(T::zero(), -A.get(na, nn))
|
||||
/ Complex::new(A.get(na, na) - p, q);
|
||||
A.set(na, na, temp.re);
|
||||
A.set(na, nn, temp.im);
|
||||
}
|
||||
A.set(nn, na, T::zero());
|
||||
A.set(nn, nn, T::one());
|
||||
if nn >= 2 {
|
||||
if nn >= 2 {
|
||||
for i in (0..nn - 1).rev() {
|
||||
let w = A.get(i, i) - p;
|
||||
let mut ra = T::zero();
|
||||
@@ -694,25 +685,40 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
} else {
|
||||
m = i;
|
||||
if e[i] == T::zero() {
|
||||
let temp = Complex::new(-ra, -sa) / Complex::new(w, q);
|
||||
let temp = Complex::new(-ra, -sa) / Complex::new(w, q);
|
||||
A.set(i, na, temp.re);
|
||||
A.set(i, nn, temp.im);
|
||||
} else {
|
||||
let x = A.get(i, i + 1);
|
||||
let y = A.get(i + 1, i);
|
||||
let mut vr = (d[i] - p).powf(T::two()) + (e[i]).powf(T::two()) - q * q;
|
||||
let mut vr =
|
||||
(d[i] - p).powf(T::two()) + (e[i]).powf(T::two()) - q * q;
|
||||
let vi = T::two() * q * (d[i] - p);
|
||||
if vr == T::zero() && vi == T::zero() {
|
||||
vr = T::epsilon() * anorm * (w.abs() + q.abs() + x.abs() + y.abs() + z.abs());
|
||||
vr = T::epsilon()
|
||||
* anorm
|
||||
* (w.abs() + q.abs() + x.abs() + y.abs() + z.abs());
|
||||
}
|
||||
let temp = Complex::new(x * r - z * ra + q * sa, x * s - z * sa - q * ra) / Complex::new(vr, vi);
|
||||
let temp =
|
||||
Complex::new(x * r - z * ra + q * sa, x * s - z * sa - q * ra)
|
||||
/ Complex::new(vr, vi);
|
||||
A.set(i, na, temp.re);
|
||||
A.set(i, nn, temp.im);
|
||||
if x.abs() > z.abs() + q.abs() {
|
||||
A.set(i + 1, na, (-ra - w * A.get(i, na) + q * A.get(i, nn)) / x);
|
||||
A.set(i + 1, nn, (-sa - w * A.get(i, nn) - q * A.get(i, na)) / x);
|
||||
A.set(
|
||||
i + 1,
|
||||
na,
|
||||
(-ra - w * A.get(i, na) + q * A.get(i, nn)) / x,
|
||||
);
|
||||
A.set(
|
||||
i + 1,
|
||||
nn,
|
||||
(-sa - w * A.get(i, nn) - q * A.get(i, na)) / x,
|
||||
);
|
||||
} else {
|
||||
let temp = Complex::new(-r - y * A.get(i, na), -s - y * A.get(i, nn)) / Complex::new(z, q);
|
||||
let temp =
|
||||
Complex::new(-r - y * A.get(i, na), -s - y * A.get(i, nn))
|
||||
/ Complex::new(z, q);
|
||||
A.set(i + 1, na, temp.re);
|
||||
A.set(i + 1, nn, temp.im);
|
||||
}
|
||||
@@ -728,7 +734,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for j in (0..n).rev() {
|
||||
for i in 0..n {
|
||||
@@ -739,7 +745,7 @@ fn hqr2<T: FloatExt, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e:
|
||||
V.set(i, j, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn balbak<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, scale: &Vec<T>) {
|
||||
@@ -751,7 +757,7 @@ fn balbak<T: FloatExt, M: BaseMatrix<T>>(V: &mut M, scale: &Vec<T>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn sort<T: FloatExt, M: BaseMatrix<T>>(d: &mut Vec<T>, e: &mut Vec<T>, V: &mut M) {
|
||||
fn sort<T: FloatExt, M: BaseMatrix<T>>(d: &mut Vec<T>, e: &mut Vec<T>, V: &mut M) {
|
||||
let n = d.len();
|
||||
let mut temp = vec![T::zero(); n];
|
||||
for j in 1..n {
|
||||
@@ -781,74 +787,72 @@ fn sort<T: FloatExt, M: BaseMatrix<T>>(d: &mut Vec<T>, e: &mut Vec<T>, V: &mut M
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::linalg::naive::dense_matrix::DenseMatrix;
|
||||
|
||||
#[test]
|
||||
fn decompose_symmetric() {
|
||||
|
||||
fn decompose_symmetric() {
|
||||
let A = DenseMatrix::from_array(&[
|
||||
&[0.9000, 0.4000, 0.7000],
|
||||
&[0.4000, 0.5000, 0.3000],
|
||||
&[0.7000, 0.3000, 0.8000]]);
|
||||
&[0.7000, 0.3000, 0.8000],
|
||||
]);
|
||||
|
||||
let eigen_values: Vec<f64> = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
|
||||
let eigen_vectors = DenseMatrix::from_array(&[
|
||||
&[0.6881997, -0.07121225, 0.7220180],
|
||||
&[0.3700456, 0.89044952, -0.2648886],
|
||||
&[0.6240573, -0.44947578, -0.6391588]
|
||||
&[0.6240573, -0.44947578, -0.6391588],
|
||||
]);
|
||||
|
||||
let evd = A.evd(true);
|
||||
let evd = A.evd(true);
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
for i in 0..eigen_values.len() {
|
||||
assert!((eigen_values[i] - evd.d[i]).abs() < 1e-4);
|
||||
}
|
||||
for i in 0..eigen_values.len() {
|
||||
assert!((0f64 - evd.e[i]).abs() < std::f64::EPSILON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decompose_asymmetric() {
|
||||
|
||||
fn decompose_asymmetric() {
|
||||
let A = DenseMatrix::from_array(&[
|
||||
&[0.9000, 0.4000, 0.7000],
|
||||
&[0.4000, 0.5000, 0.3000],
|
||||
&[0.8000, 0.3000, 0.8000]]);
|
||||
&[0.8000, 0.3000, 0.8000],
|
||||
]);
|
||||
|
||||
let eigen_values: Vec<f64> = vec![1.79171122, 0.31908143, 0.08920735];
|
||||
|
||||
let eigen_vectors = DenseMatrix::from_array(&[
|
||||
&[0.7178958, 0.05322098, 0.6812010],
|
||||
&[0.7178958, 0.05322098, 0.6812010],
|
||||
&[0.3837711, -0.84702111, -0.1494582],
|
||||
&[0.6952105, 0.43984484, -0.7036135]
|
||||
&[0.6952105, 0.43984484, -0.7036135],
|
||||
]);
|
||||
|
||||
let evd = A.evd(false);
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
let evd = A.evd(false);
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
for i in 0..eigen_values.len() {
|
||||
assert!((eigen_values[i] - evd.d[i]).abs() < 1e-4);
|
||||
}
|
||||
for i in 0..eigen_values.len() {
|
||||
assert!((0f64 - evd.e[i]).abs() < std::f64::EPSILON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decompose_complex() {
|
||||
|
||||
fn decompose_complex() {
|
||||
let A = DenseMatrix::from_array(&[
|
||||
&[3.0, -2.0, 1.0, 1.0],
|
||||
&[4.0, -1.0, 1.0, 1.0],
|
||||
&[1.0, 1.0, 3.0, -2.0],
|
||||
&[1.0, 1.0, 4.0, -1.0]]);
|
||||
&[1.0, 1.0, 4.0, -1.0],
|
||||
]);
|
||||
|
||||
let eigen_values_d: Vec<f64> = vec![0.0, 2.0, 2.0, 0.0];
|
||||
let eigen_values_e: Vec<f64> = vec![2.2361, 0.9999, -0.9999, -2.2361];
|
||||
@@ -857,19 +861,17 @@ mod tests {
|
||||
&[-0.9159, -0.1378, 0.3816, -0.0806],
|
||||
&[-0.6707, 0.1059, 0.901, 0.6289],
|
||||
&[0.9159, -0.1378, 0.3816, 0.0806],
|
||||
&[0.6707, 0.1059, 0.901, -0.6289]
|
||||
&[0.6707, 0.1059, 0.901, -0.6289],
|
||||
]);
|
||||
|
||||
let evd = A.evd(false);
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
let evd = A.evd(false);
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
for i in 0..eigen_values_d.len() {
|
||||
assert!((eigen_values_d[i] - evd.d[i]).abs() < 1e-4);
|
||||
}
|
||||
for i in 0..eigen_values_e.len() {
|
||||
assert!((eigen_values_e[i] - evd.e[i]).abs() < 1e-4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user