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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+46
-52
@@ -3,22 +3,21 @@
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LU<T: FloatExt, M: BaseMatrix<T>> {
|
||||
LU: M,
|
||||
pub struct LU<T: FloatExt, M: BaseMatrix<T>> {
|
||||
LU: M,
|
||||
pivot: Vec<usize>,
|
||||
pivot_sign: i8,
|
||||
singular: bool,
|
||||
phantom: PhantomData<T>
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
pub fn new(LU: M, pivot: Vec<usize>, pivot_sign: i8) -> LU<T, M> {
|
||||
|
||||
let (_, n) = LU.shape();
|
||||
let (_, n) = LU.shape();
|
||||
|
||||
let mut singular = false;
|
||||
for j in 0..n {
|
||||
@@ -33,7 +32,7 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
pivot: pivot,
|
||||
pivot_sign: pivot_sign,
|
||||
singular: singular,
|
||||
phantom: PhantomData
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,24 +62,24 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
for i in 0..n_rows {
|
||||
for j in 0..n_cols {
|
||||
if i <= j {
|
||||
U.set(i, j, self.LU.get(i, j));
|
||||
U.set(i, j, self.LU.get(i, j));
|
||||
} else {
|
||||
U.set(i, j, T::zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U
|
||||
}
|
||||
|
||||
pub fn pivot(&self) -> M {
|
||||
let (_, n) = self.LU.shape();
|
||||
let mut piv = M::zeros(n, n);
|
||||
|
||||
|
||||
for i in 0..n {
|
||||
piv.set(i, self.pivot[i], T::one());
|
||||
}
|
||||
|
||||
|
||||
piv
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
}
|
||||
|
||||
let mut inv = M::zeros(n, n);
|
||||
|
||||
|
||||
for i in 0..n {
|
||||
inv.set(i, i, T::one());
|
||||
}
|
||||
@@ -106,7 +105,10 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
let (b_m, b_n) = b.shape();
|
||||
|
||||
if b_m != m {
|
||||
panic!("Row dimensions do not agree: A is {} x {}, but B is {} x {}", m, n, b_m, b_n);
|
||||
panic!(
|
||||
"Row dimensions do not agree: A is {} x {}, but B is {} x {}",
|
||||
m, n, b_m, b_n
|
||||
);
|
||||
}
|
||||
|
||||
if self.singular {
|
||||
@@ -120,9 +122,9 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
X.set(i, j, b.get(self.pivot[i], j));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for k in 0..n {
|
||||
for i in k+1..n {
|
||||
for i in k + 1..n {
|
||||
for j in 0..b_n {
|
||||
X.sub_element_mut(i, j, X.get(k, j) * self.LU.get(i, k));
|
||||
}
|
||||
@@ -140,7 +142,7 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for j in 0..b_n {
|
||||
for i in 0..m {
|
||||
b.set(i, j, X.get(i, j));
|
||||
@@ -148,20 +150,16 @@ impl<T: FloatExt, M: BaseMatrix<T>> LU<T, M> {
|
||||
}
|
||||
|
||||
b
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub trait LUDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
pub trait LUDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
fn lu(&self) -> LU<T, Self> {
|
||||
self.clone().lu_mut()
|
||||
}
|
||||
|
||||
fn lu_mut(mut self) -> LU<T, Self> {
|
||||
|
||||
let (m, n) = self.shape();
|
||||
let (m, n) = self.shape();
|
||||
|
||||
let mut piv = vec![0; m];
|
||||
for i in 0..m {
|
||||
@@ -172,7 +170,6 @@ pub trait LUDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
let mut LUcolj = vec![T::zero(); m];
|
||||
|
||||
for j in 0..n {
|
||||
|
||||
for i in 0..m {
|
||||
LUcolj[i] = self.get(i, j);
|
||||
}
|
||||
@@ -189,7 +186,7 @@ pub trait LUDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
|
||||
let mut p = j;
|
||||
for i in j+1..m {
|
||||
for i in j + 1..m {
|
||||
if LUcolj[i].abs() > LUcolj[p].abs() {
|
||||
p = i;
|
||||
}
|
||||
@@ -205,50 +202,47 @@ pub trait LUDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
piv[j] = k;
|
||||
pivsign = -pivsign;
|
||||
}
|
||||
|
||||
|
||||
if j < m && self.get(j, j) != T::zero() {
|
||||
for i in j+1..m {
|
||||
for i in j + 1..m {
|
||||
self.div_element_mut(i, j, self.get(j, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LU::new(self, piv, pivsign)
|
||||
|
||||
}
|
||||
|
||||
fn lu_solve_mut(self, b: Self) -> Self {
|
||||
|
||||
self.lu_mut().solve(b)
|
||||
|
||||
}
|
||||
self.lu_mut().solve(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::linalg::naive::dense_matrix::*;
|
||||
use crate::linalg::naive::dense_matrix::*;
|
||||
|
||||
#[test]
|
||||
fn decompose() {
|
||||
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[0., 1., 5.], &[5., 6., 0.]]);
|
||||
let expected_L = DenseMatrix::from_array(&[&[1. , 0. , 0. ], &[0. , 1. , 0. ], &[0.2, 0.8, 1. ]]);
|
||||
let expected_U = DenseMatrix::from_array(&[&[ 5., 6., 0.], &[ 0., 1., 5.], &[ 0., 0., -1.]]);
|
||||
let expected_pivot = DenseMatrix::from_array(&[&[0., 0., 1.], &[0., 1., 0.], &[1., 0., 0.]]);
|
||||
let lu = a.lu();
|
||||
assert!(lu.L().approximate_eq(&expected_L, 1e-4));
|
||||
assert!(lu.U().approximate_eq(&expected_U, 1e-4));
|
||||
assert!(lu.pivot().approximate_eq(&expected_pivot, 1e-4));
|
||||
fn decompose() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[0., 1., 5.], &[5., 6., 0.]]);
|
||||
let expected_L = DenseMatrix::from_array(&[&[1., 0., 0.], &[0., 1., 0.], &[0.2, 0.8, 1.]]);
|
||||
let expected_U = DenseMatrix::from_array(&[&[5., 6., 0.], &[0., 1., 5.], &[0., 0., -1.]]);
|
||||
let expected_pivot =
|
||||
DenseMatrix::from_array(&[&[0., 0., 1.], &[0., 1., 0.], &[1., 0., 0.]]);
|
||||
let lu = a.lu();
|
||||
assert!(lu.L().approximate_eq(&expected_L, 1e-4));
|
||||
assert!(lu.U().approximate_eq(&expected_U, 1e-4));
|
||||
assert!(lu.pivot().approximate_eq(&expected_pivot, 1e-4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inverse() {
|
||||
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[0., 1., 5.], &[5., 6., 0.]]);
|
||||
let expected = DenseMatrix::from_array(&[&[-6.0, 3.6, 1.4], &[5.0, -3.0, -1.0], &[-1.0, 0.8, 0.2]]);
|
||||
let a_inv = a.lu().inverse();
|
||||
println!("{}", a_inv);
|
||||
assert!(a_inv.approximate_eq(&expected, 1e-4));
|
||||
fn inverse() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[0., 1., 5.], &[5., 6., 0.]]);
|
||||
let expected =
|
||||
DenseMatrix::from_array(&[&[-6.0, 3.6, 1.4], &[5.0, -3.0, -1.0], &[-1.0, 0.8, 0.2]]);
|
||||
let a_inv = a.lu().inverse();
|
||||
println!("{}", a_inv);
|
||||
assert!(a_inv.approximate_eq(&expected, 1e-4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
-42
@@ -1,45 +1,43 @@
|
||||
pub mod naive;
|
||||
pub mod qr;
|
||||
pub mod svd;
|
||||
pub mod evd;
|
||||
pub mod lu;
|
||||
pub mod ndarray_bindings;
|
||||
pub mod naive;
|
||||
pub mod nalgebra_bindings;
|
||||
pub mod ndarray_bindings;
|
||||
pub mod qr;
|
||||
pub mod svd;
|
||||
|
||||
use std::ops::Range;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use svd::SVDDecomposableMatrix;
|
||||
use evd::EVDDecomposableMatrix;
|
||||
use qr::QRDecomposableMatrix;
|
||||
use lu::LUDecomposableMatrix;
|
||||
use qr::QRDecomposableMatrix;
|
||||
use svd::SVDDecomposableMatrix;
|
||||
|
||||
pub trait BaseVector<T: FloatExt>: Clone + Debug {
|
||||
|
||||
fn get(&self, i: usize) -> T;
|
||||
pub trait BaseVector<T: FloatExt>: Clone + Debug {
|
||||
fn get(&self, i: usize) -> T;
|
||||
|
||||
fn set(&mut self, i: usize, x: T);
|
||||
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
|
||||
type RowVector: BaseVector<T> + Clone + Debug;
|
||||
pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
type RowVector: BaseVector<T> + Clone + Debug;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self;
|
||||
|
||||
fn to_row_vector(self) -> Self::RowVector;
|
||||
|
||||
fn get(&self, row: usize, col: usize) -> T;
|
||||
fn get(&self, row: usize, col: usize) -> T;
|
||||
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<T>;
|
||||
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T>;
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T>;
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: T);
|
||||
fn set(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn eye(size: usize) -> Self;
|
||||
|
||||
@@ -51,17 +49,17 @@ pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
|
||||
fn fill(nrows: usize, ncols: usize, value: T) -> Self;
|
||||
|
||||
fn shape(&self) -> (usize, usize);
|
||||
fn shape(&self) -> (usize, usize);
|
||||
|
||||
fn v_stack(&self, other: &Self) -> Self;
|
||||
|
||||
fn h_stack(&self, other: &Self) -> Self;
|
||||
|
||||
fn dot(&self, other: &Self) -> Self;
|
||||
fn dot(&self, other: &Self) -> Self;
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> T;
|
||||
fn vector_dot(&self, other: &Self) -> T;
|
||||
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self;
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self;
|
||||
|
||||
fn approximate_eq(&self, other: &Self, error: T) -> bool;
|
||||
|
||||
@@ -113,37 +111,37 @@ pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self;
|
||||
|
||||
fn add_scalar(&self, scalar: T) -> Self{
|
||||
fn add_scalar(&self, scalar: T) -> Self {
|
||||
let mut r = self.clone();
|
||||
r.add_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn sub_scalar(&self, scalar: T) -> Self{
|
||||
fn sub_scalar(&self, scalar: T) -> Self {
|
||||
let mut r = self.clone();
|
||||
r.sub_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn mul_scalar(&self, scalar: T) -> Self{
|
||||
fn mul_scalar(&self, scalar: T) -> Self {
|
||||
let mut r = self.clone();
|
||||
r.mul_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn div_scalar(&self, scalar: T) -> Self{
|
||||
fn div_scalar(&self, scalar: T) -> Self {
|
||||
let mut r = self.clone();
|
||||
r.div_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self;
|
||||
fn transpose(&self) -> Self;
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
fn norm2(&self) -> T;
|
||||
|
||||
fn norm(&self, p:T) -> T;
|
||||
fn norm(&self, p: T) -> T;
|
||||
|
||||
fn column_mean(&self) -> Vec<T>;
|
||||
|
||||
@@ -153,7 +151,7 @@ pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
let mut result = self.clone();
|
||||
result.negative_mut();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
@@ -169,9 +167,9 @@ pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
|
||||
fn sum(&self) -> T;
|
||||
|
||||
fn max_diff(&self, other: &Self) -> T;
|
||||
|
||||
fn softmax_mut(&mut self);
|
||||
fn max_diff(&self, other: &Self) -> T;
|
||||
|
||||
fn softmax_mut(&mut self);
|
||||
|
||||
fn pow_mut(&mut self, p: T) -> &Self;
|
||||
|
||||
@@ -181,22 +179,30 @@ pub trait BaseMatrix<T: FloatExt>: Clone + Debug {
|
||||
result
|
||||
}
|
||||
|
||||
fn argmax(&self) -> Vec<usize>;
|
||||
|
||||
fn unique(&self) -> Vec<T>;
|
||||
|
||||
fn cov(&self) -> Self;
|
||||
fn argmax(&self) -> Vec<usize>;
|
||||
|
||||
fn unique(&self) -> Vec<T>;
|
||||
|
||||
fn cov(&self) -> Self;
|
||||
}
|
||||
|
||||
pub trait Matrix<T: FloatExt>: BaseMatrix<T> + SVDDecomposableMatrix<T> + EVDDecomposableMatrix<T> + QRDecomposableMatrix<T> + LUDecomposableMatrix<T> + PartialEq + Display {}
|
||||
pub trait Matrix<T: FloatExt>:
|
||||
BaseMatrix<T>
|
||||
+ SVDDecomposableMatrix<T>
|
||||
+ EVDDecomposableMatrix<T>
|
||||
+ QRDecomposableMatrix<T>
|
||||
+ LUDecomposableMatrix<T>
|
||||
+ PartialEq
|
||||
+ Display
|
||||
{
|
||||
}
|
||||
|
||||
pub fn row_iter<F: FloatExt, M: BaseMatrix<F>>(m: &M) -> RowIter<F, M> {
|
||||
RowIter{
|
||||
RowIter {
|
||||
m: m,
|
||||
pos: 0,
|
||||
max_pos: m.shape().0,
|
||||
phantom: PhantomData
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,11 +210,10 @@ pub struct RowIter<'a, T: FloatExt, M: BaseMatrix<T>> {
|
||||
m: &'a M,
|
||||
pos: usize,
|
||||
max_pos: usize,
|
||||
phantom: PhantomData<&'a T>
|
||||
phantom: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
impl<'a, T: FloatExt, M: BaseMatrix<T>> Iterator for RowIter<'a, T, M> {
|
||||
|
||||
type Item = Vec<T>;
|
||||
|
||||
fn next(&mut self) -> Option<Vec<T>> {
|
||||
@@ -221,5 +226,4 @@ impl<'a, T: FloatExt, M: BaseMatrix<T>> Iterator for RowIter<'a, T, M> {
|
||||
self.pos += 1;
|
||||
res
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+245
-259
@@ -1,26 +1,26 @@
|
||||
extern crate num;
|
||||
use std::ops::Range;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::ser::{Serializer, SerializeStruct};
|
||||
use serde::de::{Deserializer, Visitor, SeqAccess, MapAccess};
|
||||
use serde::de::{Deserializer, MapAccess, SeqAccess, Visitor};
|
||||
use serde::ser::{SerializeStruct, Serializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::lu::LUDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::Matrix;
|
||||
pub use crate::linalg::{BaseMatrix, BaseVector};
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::lu::LUDecomposableMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
impl<T: FloatExt> BaseVector<T> for Vec<T> {
|
||||
fn get(&self, i: usize) -> T {
|
||||
self[i]
|
||||
}
|
||||
fn set(&mut self, i: usize, x: T){
|
||||
fn set(&mut self, i: usize, x: T) {
|
||||
self[i] = x
|
||||
}
|
||||
|
||||
@@ -31,32 +31,34 @@ impl<T: FloatExt> BaseVector<T> for Vec<T> {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DenseMatrix<T: FloatExt> {
|
||||
|
||||
ncols: usize,
|
||||
nrows: usize,
|
||||
values: Vec<T>
|
||||
|
||||
values: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: FloatExt> fmt::Display for DenseMatrix<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut rows: Vec<Vec<f64>> = Vec::new();
|
||||
for r in 0..self.nrows {
|
||||
rows.push(self.get_row_as_vec(r).iter().map(|x| (x.to_f64().unwrap() * 1e4).round() / 1e4 ).collect());
|
||||
}
|
||||
rows.push(
|
||||
self.get_row_as_vec(r)
|
||||
.iter()
|
||||
.map(|x| (x.to_f64().unwrap() * 1e4).round() / 1e4)
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
write!(f, "{:?}", rows)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt> DenseMatrix<T> {
|
||||
|
||||
impl<T: FloatExt> DenseMatrix<T> {
|
||||
fn new(nrows: usize, ncols: usize, values: Vec<T>) -> Self {
|
||||
DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
values: values
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_array(values: &[&[T]]) -> Self {
|
||||
DenseMatrix::from_vec(&values.into_iter().map(|row| Vec::from(*row)).collect())
|
||||
@@ -64,11 +66,14 @@ impl<T: FloatExt> DenseMatrix<T> {
|
||||
|
||||
pub fn from_vec(values: &Vec<Vec<T>>) -> DenseMatrix<T> {
|
||||
let nrows = values.len();
|
||||
let ncols = values.first().unwrap_or_else(|| panic!("Cannot create 2d matrix from an empty vector")).len();
|
||||
let ncols = values
|
||||
.first()
|
||||
.unwrap_or_else(|| panic!("Cannot create 2d matrix from an empty vector"))
|
||||
.len();
|
||||
let mut m = DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
values: vec![T::zero(); ncols*nrows]
|
||||
values: vec![T::zero(); ncols * nrows],
|
||||
};
|
||||
for row in 0..nrows {
|
||||
for col in 0..ncols {
|
||||
@@ -76,17 +81,17 @@ impl<T: FloatExt> DenseMatrix<T> {
|
||||
}
|
||||
}
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector_from_array(values: &[T]) -> Self {
|
||||
DenseMatrix::vector_from_vec(Vec::from(values))
|
||||
}
|
||||
DenseMatrix::vector_from_vec(Vec::from(values))
|
||||
}
|
||||
|
||||
pub fn vector_from_vec(values: Vec<T>) -> Self {
|
||||
DenseMatrix {
|
||||
ncols: values.len(),
|
||||
nrows: 1,
|
||||
values: values
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +103,11 @@ impl<T: FloatExt> DenseMatrix<T> {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = self.values[i] / b.values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_raw_values(&self) -> &Vec<T> {
|
||||
&self.values
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T: FloatExt + fmt::Debug + Deserialize<'de>> Deserialize<'de> for DenseMatrix<T> {
|
||||
@@ -111,31 +115,37 @@ impl<'de, T: FloatExt + fmt::Debug + Deserialize<'de>> Deserialize<'de> for Dens
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(field_identifier, rename_all = "lowercase")]
|
||||
enum Field { NRows, NCols, Values }
|
||||
|
||||
struct DenseMatrixVisitor<T: FloatExt + fmt::Debug>{
|
||||
t: PhantomData<T>
|
||||
enum Field {
|
||||
NRows,
|
||||
NCols,
|
||||
Values,
|
||||
}
|
||||
|
||||
|
||||
struct DenseMatrixVisitor<T: FloatExt + fmt::Debug> {
|
||||
t: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: FloatExt + fmt::Debug + Deserialize<'a>> Visitor<'a> for DenseMatrixVisitor<T> {
|
||||
type Value = DenseMatrix<T>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("struct DenseMatrix")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut seq: V) -> Result<DenseMatrix<T>, V::Error>
|
||||
where
|
||||
V: SeqAccess<'a>,
|
||||
{
|
||||
let nrows = seq.next_element()?
|
||||
let nrows = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
|
||||
let ncols = seq.next_element()?
|
||||
let ncols = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
|
||||
let values = seq.next_element()?
|
||||
let values = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| serde::de::Error::invalid_length(2, &self))?;
|
||||
Ok(DenseMatrix::new(nrows, ncols, values))
|
||||
}
|
||||
@@ -176,23 +186,26 @@ impl<'de, T: FloatExt + fmt::Debug + Deserialize<'de>> Deserialize<'de> for Dens
|
||||
}
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["nrows", "ncols", "values"];
|
||||
deserializer.deserialize_struct("DenseMatrix", FIELDS, DenseMatrixVisitor {
|
||||
t: PhantomData
|
||||
})
|
||||
const FIELDS: &'static [&'static str] = &["nrows", "ncols", "values"];
|
||||
deserializer.deserialize_struct(
|
||||
"DenseMatrix",
|
||||
FIELDS,
|
||||
DenseMatrixVisitor { t: PhantomData },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt + fmt::Debug + Serialize> Serialize for DenseMatrix<T> {
|
||||
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
|
||||
S: Serializer {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let (nrows, ncols) = self.shape();
|
||||
let mut state = serializer.serialize_struct("DenseMatrix", 3)?;
|
||||
state.serialize_field("nrows", &nrows)?;
|
||||
state.serialize_field("ncols", &ncols)?;
|
||||
state.serialize_field("ncols", &ncols)?;
|
||||
state.serialize_field("values", &self.values)?;
|
||||
state.end()
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +222,7 @@ impl<T: FloatExt> Matrix<T> for DenseMatrix<T> {}
|
||||
impl<T: FloatExt> PartialEq for DenseMatrix<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
let len = self.values.len();
|
||||
@@ -235,26 +248,28 @@ impl<T: FloatExt> Into<Vec<T>> for DenseMatrix<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
|
||||
impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
type RowVector = Vec<T>;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self{
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self {
|
||||
DenseMatrix::new(1, vec.len(), vec)
|
||||
}
|
||||
|
||||
fn to_row_vector(self) -> Self::RowVector{
|
||||
fn to_row_vector(self) -> Self::RowVector {
|
||||
self.to_raw_vector()
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, row: usize, col: usize) -> T {
|
||||
if row >= self.nrows || col >= self.ncols {
|
||||
panic!("Invalid index ({},{}) for {}x{} matrix", row, col, self.nrows, self.ncols);
|
||||
panic!(
|
||||
"Invalid index ({},{}) for {}x{} matrix",
|
||||
row, col, self.nrows, self.ncols
|
||||
);
|
||||
}
|
||||
self.values[col*self.nrows + row]
|
||||
self.values[col * self.nrows + row]
|
||||
}
|
||||
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<T>{
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<T> {
|
||||
let mut result = vec![T::zero(); self.ncols];
|
||||
for c in 0..self.ncols {
|
||||
result[c] = self.get(row, c);
|
||||
@@ -262,16 +277,16 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
result
|
||||
}
|
||||
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T>{
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T> {
|
||||
let mut result = vec![T::zero(); self.nrows];
|
||||
for r in 0..self.nrows {
|
||||
result[r] = self.get(r, col);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = x;
|
||||
self.values[col * self.nrows + row] = x;
|
||||
}
|
||||
|
||||
fn zeros(nrows: usize, ncols: usize) -> Self {
|
||||
@@ -280,7 +295,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
|
||||
fn ones(nrows: usize, ncols: usize) -> Self {
|
||||
DenseMatrix::fill(nrows, ncols, T::one())
|
||||
}
|
||||
}
|
||||
|
||||
fn eye(size: usize) -> Self {
|
||||
let mut matrix = Self::zeros(size, size);
|
||||
@@ -292,15 +307,15 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
fn to_raw_vector(&self) -> Vec<T>{
|
||||
fn to_raw_vector(&self) -> Vec<T> {
|
||||
let mut v = vec![T::zero(); self.nrows * self.ncols];
|
||||
|
||||
for r in 0..self.nrows{
|
||||
for r in 0..self.nrows {
|
||||
for c in 0..self.ncols {
|
||||
v[r * self.ncols + c] = self.get(r, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
@@ -314,25 +329,25 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
let mut result = Self::zeros(self.nrows + other.nrows, self.ncols);
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows+other.nrows {
|
||||
if r < self.nrows {
|
||||
for r in 0..self.nrows + other.nrows {
|
||||
if r < self.nrows {
|
||||
result.set(r, c, self.get(r, c));
|
||||
} else {
|
||||
result.set(r, c, other.get(r - self.nrows, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn v_stack(&self, other: &Self) -> Self{
|
||||
fn v_stack(&self, other: &Self) -> Self {
|
||||
if self.nrows != other.nrows {
|
||||
panic!("Number of rows in both matrices should be equal");
|
||||
}
|
||||
let mut result = Self::zeros(self.nrows, self.ncols + other.ncols);
|
||||
for r in 0..self.nrows {
|
||||
for c in 0..self.ncols+other.ncols {
|
||||
if c < self.ncols {
|
||||
for c in 0..self.ncols + other.ncols {
|
||||
if c < self.ncols {
|
||||
result.set(r, c, self.get(r, c));
|
||||
} else {
|
||||
result.set(r, c, other.get(r, c - self.ncols));
|
||||
@@ -343,7 +358,6 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn dot(&self, other: &Self) -> Self {
|
||||
|
||||
if self.ncols != other.nrows {
|
||||
panic!("Number of rows of A should equal number of columns of B");
|
||||
}
|
||||
@@ -361,7 +375,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> T {
|
||||
if (self.nrows != 1 || self.nrows != 1) && (other.nrows != 1 || other.ncols != 1) {
|
||||
@@ -369,18 +383,17 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
if self.nrows * self.ncols != other.nrows * other.ncols {
|
||||
panic!("A and B should have the same size");
|
||||
}
|
||||
}
|
||||
|
||||
let mut result = T::zero();
|
||||
for i in 0..(self.nrows * self.ncols) {
|
||||
result = result + self.values[i] * other.values[i];
|
||||
result = result + self.values[i] * other.values[i];
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self {
|
||||
|
||||
let ncols = cols.len();
|
||||
let nrows = rows.len();
|
||||
|
||||
@@ -388,22 +401,22 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
|
||||
for r in rows.start..rows.end {
|
||||
for c in cols.start..cols.end {
|
||||
m.set(r-rows.start, c-cols.start, self.get(r, c));
|
||||
m.set(r - rows.start, c - cols.start, self.get(r, c));
|
||||
}
|
||||
}
|
||||
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
fn approximate_eq(&self, other: &Self, error: T) -> bool {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
if (self.get(r, c) - other.get(r, c)).abs() > error {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,7 +431,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
fn add_mut(&mut self, other: &Self) -> &Self {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
panic!("A and B should have the same shape");
|
||||
}
|
||||
}
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
self.add_element_mut(r, c, other.get(r, c));
|
||||
@@ -431,7 +444,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
fn sub_mut(&mut self, other: &Self) -> &Self {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
panic!("A and B should have the same shape");
|
||||
}
|
||||
}
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
self.sub_element_mut(r, c, other.get(r, c));
|
||||
@@ -444,7 +457,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
fn mul_mut(&mut self, other: &Self) -> &Self {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
panic!("A and B should have the same shape");
|
||||
}
|
||||
}
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
self.mul_element_mut(r, c, other.get(r, c));
|
||||
@@ -457,7 +470,7 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
fn div_mut(&mut self, other: &Self) -> &Self {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
panic!("A and B should have the same shape");
|
||||
}
|
||||
}
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
self.div_element_mut(r, c, other.get(r, c));
|
||||
@@ -468,26 +481,26 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = self.values[col*self.nrows + row] / x;
|
||||
self.values[col * self.nrows + row] = self.values[col * self.nrows + row] / x;
|
||||
}
|
||||
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = self.values[col*self.nrows + row] * x;
|
||||
self.values[col * self.nrows + row] = self.values[col * self.nrows + row] * x;
|
||||
}
|
||||
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = self.values[col*self.nrows + row] + x
|
||||
self.values[col * self.nrows + row] = self.values[col * self.nrows + row] + x
|
||||
}
|
||||
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = self.values[col*self.nrows + row] - x;
|
||||
}
|
||||
self.values[col * self.nrows + row] = self.values[col * self.nrows + row] - x;
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self {
|
||||
let mut m = DenseMatrix {
|
||||
ncols: self.nrows,
|
||||
nrows: self.ncols,
|
||||
values: vec![T::zero(); self.ncols * self.nrows]
|
||||
values: vec![T::zero(); self.ncols * self.nrows],
|
||||
};
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
@@ -495,19 +508,16 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
}
|
||||
m
|
||||
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let values: Vec<T> = (0..nrows*ncols).map(|_| {
|
||||
T::rand()
|
||||
}).collect();
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let values: Vec<T> = (0..nrows * ncols).map(|_| T::rand()).collect();
|
||||
DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
values: values
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn norm2(&self) -> T {
|
||||
let mut norm = T::zero();
|
||||
@@ -519,21 +529,25 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
norm.sqrt()
|
||||
}
|
||||
|
||||
fn norm(&self, p:T) -> T {
|
||||
|
||||
fn norm(&self, p: T) -> T {
|
||||
if p.is_infinite() && p.is_sign_positive() {
|
||||
self.values.iter().map(|x| x.abs()).fold(T::neg_infinity(), |a, b| a.max(b))
|
||||
self.values
|
||||
.iter()
|
||||
.map(|x| x.abs())
|
||||
.fold(T::neg_infinity(), |a, b| a.max(b))
|
||||
} else if p.is_infinite() && p.is_sign_negative() {
|
||||
self.values.iter().map(|x| x.abs()).fold(T::infinity(), |a, b| a.min(b))
|
||||
self.values
|
||||
.iter()
|
||||
.map(|x| x.abs())
|
||||
.fold(T::infinity(), |a, b| a.min(b))
|
||||
} else {
|
||||
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.values.iter() {
|
||||
norm = norm + xi.abs().powf(p);
|
||||
}
|
||||
|
||||
norm.powf(T::one()/p)
|
||||
norm.powf(T::one() / p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,11 +599,14 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = -self.values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self {
|
||||
if self.nrows * self.ncols != nrows * ncols {
|
||||
panic!("Can't reshape {}x{} matrix into {}x{}.", self.nrows, self.ncols, nrows, ncols);
|
||||
panic!(
|
||||
"Can't reshape {}x{} matrix into {}x{}.",
|
||||
self.nrows, self.ncols, nrows, ncols
|
||||
);
|
||||
}
|
||||
let mut dst = DenseMatrix::zeros(nrows, ncols);
|
||||
let mut dst_r = 0;
|
||||
@@ -609,9 +626,11 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn copy_from(&mut self, other: &Self) {
|
||||
|
||||
if self.nrows != other.nrows || self.ncols != other.ncols {
|
||||
panic!("Can't copy {}x{} matrix into {}x{}.", self.nrows, self.ncols, other.nrows, other.ncols);
|
||||
panic!(
|
||||
"Can't copy {}x{} matrix into {}x{}.",
|
||||
self.nrows, self.ncols, other.nrows, other.ncols
|
||||
);
|
||||
}
|
||||
|
||||
for i in 0..self.values.len() {
|
||||
@@ -619,20 +638,19 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn abs_mut(&mut self) -> &Self{
|
||||
fn abs_mut(&mut self) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = self.values[i].abs();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn max_diff(&self, other: &Self) -> T{
|
||||
fn max_diff(&self, other: &Self) -> T {
|
||||
let mut max_diff = T::zero();
|
||||
for i in 0..self.values.len() {
|
||||
max_diff = max_diff.max((self.values[i] - other.values[i]).abs());
|
||||
}
|
||||
max_diff
|
||||
|
||||
}
|
||||
|
||||
fn sum(&self) -> T {
|
||||
@@ -644,7 +662,11 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn softmax_mut(&mut self) {
|
||||
let max = self.values.iter().map(|x| x.abs()).fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
let max = self
|
||||
.values
|
||||
.iter()
|
||||
.map(|x| x.abs())
|
||||
.fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
let mut z = T::zero();
|
||||
for r in 0..self.nrows {
|
||||
for c in 0..self.ncols {
|
||||
@@ -668,7 +690,6 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn argmax(&self) -> Vec<usize> {
|
||||
|
||||
let mut res = vec![0usize; self.nrows];
|
||||
|
||||
for r in 0..self.nrows {
|
||||
@@ -676,16 +697,15 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
let mut max_pos = 0usize;
|
||||
for c in 0..self.ncols {
|
||||
let v = self.get(r, c);
|
||||
if max < v{
|
||||
if max < v {
|
||||
max = v;
|
||||
max_pos = c;
|
||||
max_pos = c;
|
||||
}
|
||||
}
|
||||
res[r] = max_pos;
|
||||
}
|
||||
|
||||
res
|
||||
|
||||
}
|
||||
|
||||
fn unique(&self) -> Vec<T> {
|
||||
@@ -696,17 +716,16 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
}
|
||||
|
||||
fn cov(&self) -> Self {
|
||||
|
||||
let (m, n) = self.shape();
|
||||
|
||||
let mu = self.column_mean();
|
||||
let mu = self.column_mean();
|
||||
|
||||
let mut cov = Self::zeros(n, n);
|
||||
|
||||
for k in 0..m {
|
||||
for i in 0..n {
|
||||
for j in 0..=i {
|
||||
cov.add_element_mut(i, j, (self.get(k, i) - mu[i]) * (self.get(k, j) - mu[j]));
|
||||
cov.add_element_mut(i, j, (self.get(k, i) - mu[i]) * (self.get(k, j) - mu[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -715,127 +734,88 @@ impl<T: FloatExt> BaseMatrix<T> for DenseMatrix<T> {
|
||||
|
||||
for i in 0..n {
|
||||
for j in 0..=i {
|
||||
cov.div_element_mut(i, j, m_t);
|
||||
cov.div_element_mut(i, j, m_t);
|
||||
cov.set(j, i, cov.get(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
cov
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_to_row_vec() {
|
||||
|
||||
let vec = vec![ 1., 2., 3.];
|
||||
assert_eq!(DenseMatrix::from_row_vector(vec.clone()), DenseMatrix::new(1, 3, vec![1., 2., 3.]));
|
||||
assert_eq!(DenseMatrix::from_row_vector(vec.clone()).to_row_vector(), vec![1., 2., 3.]);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn h_stack() {
|
||||
|
||||
let a = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
&[7., 8., 9.]]);
|
||||
let b = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
&[7., 8., 9.],
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.]]);
|
||||
let result = a.h_stack(&b);
|
||||
assert_eq!(result, expected);
|
||||
fn from_to_row_vec() {
|
||||
let vec = vec![1., 2., 3.];
|
||||
assert_eq!(
|
||||
DenseMatrix::from_row_vector(vec.clone()),
|
||||
DenseMatrix::new(1, 3, vec![1., 2., 3.])
|
||||
);
|
||||
assert_eq!(
|
||||
DenseMatrix::from_row_vector(vec.clone()).to_row_vector(),
|
||||
vec![1., 2., 3.]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v_stack() {
|
||||
|
||||
let a = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
&[7., 8., 9.]]);
|
||||
let b = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2.],
|
||||
&[3., 4.],
|
||||
&[5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3., 1., 2.],
|
||||
&[4., 5., 6., 3., 4.],
|
||||
&[7., 8., 9., 5., 6.]]);
|
||||
let result = a.v_stack(&b);
|
||||
assert_eq!(result, expected);
|
||||
fn h_stack() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[4., 5., 6.], &[7., 8., 9.]]);
|
||||
let b = DenseMatrix::from_array(&[&[1., 2., 3.], &[4., 5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
&[7., 8., 9.],
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
]);
|
||||
let result = a.h_stack(&b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot() {
|
||||
|
||||
let a = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.]]);
|
||||
let b = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2.],
|
||||
&[3., 4.],
|
||||
&[5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(
|
||||
&[
|
||||
&[22., 28.],
|
||||
&[49., 64.]]);
|
||||
let result = a.dot(&b);
|
||||
assert_eq!(result, expected);
|
||||
fn v_stack() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[4., 5., 6.], &[7., 8., 9.]]);
|
||||
let b = DenseMatrix::from_array(&[&[1., 2.], &[3., 4.], &[5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(&[
|
||||
&[1., 2., 3., 1., 2.],
|
||||
&[4., 5., 6., 3., 4.],
|
||||
&[7., 8., 9., 5., 6.],
|
||||
]);
|
||||
let result = a.v_stack(&b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
|
||||
let m = DenseMatrix::from_array(
|
||||
&[
|
||||
&[1., 2., 3., 1., 2.],
|
||||
&[4., 5., 6., 3., 4.],
|
||||
&[7., 8., 9., 5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(
|
||||
&[
|
||||
&[2., 3.],
|
||||
&[5., 6.]]);
|
||||
let result = m.slice(0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
fn dot() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[4., 5., 6.]]);
|
||||
let b = DenseMatrix::from_array(&[&[1., 2.], &[3., 4.], &[5., 6.]]);
|
||||
let expected = DenseMatrix::from_array(&[&[22., 28.], &[49., 64.]]);
|
||||
let result = a.dot(&b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn approximate_eq() {
|
||||
let m = DenseMatrix::from_array(
|
||||
&[
|
||||
&[2., 3.],
|
||||
&[5., 6.]]);
|
||||
let m_eq = DenseMatrix::from_array(
|
||||
&[
|
||||
&[2.5, 3.0],
|
||||
&[5., 5.5]]);
|
||||
let m_neq = DenseMatrix::from_array(
|
||||
&[
|
||||
&[3.0, 3.0],
|
||||
&[5., 6.5]]);
|
||||
assert!(m.approximate_eq(&m_eq, 0.5));
|
||||
assert!(!m.approximate_eq(&m_neq, 0.5));
|
||||
fn slice() {
|
||||
let m = DenseMatrix::from_array(&[
|
||||
&[1., 2., 3., 1., 2.],
|
||||
&[4., 5., 6., 3., 4.],
|
||||
&[7., 8., 9., 5., 6.],
|
||||
]);
|
||||
let expected = DenseMatrix::from_array(&[&[2., 3.], &[5., 6.]]);
|
||||
let result = m.slice(0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approximate_eq() {
|
||||
let m = DenseMatrix::from_array(&[&[2., 3.], &[5., 6.]]);
|
||||
let m_eq = DenseMatrix::from_array(&[&[2.5, 3.0], &[5., 5.5]]);
|
||||
let m_neq = DenseMatrix::from_array(&[&[3.0, 3.0], &[5., 6.5]]);
|
||||
assert!(m.approximate_eq(&m_eq, 0.5));
|
||||
assert!(!m.approximate_eq(&m_neq, 0.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -864,7 +844,7 @@ mod tests {
|
||||
fn reshape() {
|
||||
let m_orig = DenseMatrix::vector_from_array(&[1., 2., 3., 4., 5., 6.]);
|
||||
let m_2_by_3 = m_orig.reshape(2, 3);
|
||||
let m_result = m_2_by_3.reshape(1, 6);
|
||||
let m_result = m_2_by_3.reshape(1, 6);
|
||||
assert_eq!(m_2_by_3.shape(), (2, 3));
|
||||
assert_eq!(m_2_by_3.get(1, 1), 5.);
|
||||
assert_eq!(m_result.get(0, 1), 2.);
|
||||
@@ -872,70 +852,76 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn norm() {
|
||||
|
||||
let v = DenseMatrix::vector_from_array(&[3., -2., 6.]);
|
||||
assert_eq!(v.norm(1.), 11.);
|
||||
assert_eq!(v.norm(2.), 7.);
|
||||
assert_eq!(v.norm(std::f64::INFINITY), 6.);
|
||||
assert_eq!(v.norm(std::f64::NEG_INFINITY), 2.);
|
||||
fn norm() {
|
||||
let v = DenseMatrix::vector_from_array(&[3., -2., 6.]);
|
||||
assert_eq!(v.norm(1.), 11.);
|
||||
assert_eq!(v.norm(2.), 7.);
|
||||
assert_eq!(v.norm(std::f64::INFINITY), 6.);
|
||||
assert_eq!(v.norm(std::f64::NEG_INFINITY), 2.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn softmax_mut() {
|
||||
fn softmax_mut() {
|
||||
let mut prob: DenseMatrix<f64> = DenseMatrix::vector_from_array(&[1., 2., 3.]);
|
||||
prob.softmax_mut();
|
||||
assert!((prob.get(0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((prob.get(0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((prob.get(0, 2) - 0.66).abs() < 0.01);
|
||||
}
|
||||
|
||||
let mut prob: DenseMatrix<f64> = DenseMatrix::vector_from_array(&[1., 2., 3.]);
|
||||
prob.softmax_mut();
|
||||
assert!((prob.get(0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((prob.get(0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((prob.get(0, 2) - 0.66).abs() < 0.01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn col_mean(){
|
||||
let a = DenseMatrix::from_array(&[
|
||||
&[1., 2., 3.],
|
||||
&[4., 5., 6.],
|
||||
&[7., 8., 9.]]);
|
||||
fn col_mean() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 2., 3.], &[4., 5., 6.], &[7., 8., 9.]]);
|
||||
let res = a.column_mean();
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eye(){
|
||||
let a = DenseMatrix::from_array(&[
|
||||
&[1., 0., 0.],
|
||||
&[0., 1., 0.],
|
||||
&[0., 0., 1.]]);
|
||||
fn eye() {
|
||||
let a = DenseMatrix::from_array(&[&[1., 0., 0.], &[0., 1., 0.], &[0., 0., 1.]]);
|
||||
let res = DenseMatrix::eye(3);
|
||||
assert_eq!(res, a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_from_json() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let deserialized_a: DenseMatrix<f64> = serde_json::from_str(&serde_json::to_string(&a).unwrap()).unwrap();
|
||||
assert_eq!(a, deserialized_a);
|
||||
fn to_from_json() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let deserialized_a: DenseMatrix<f64> =
|
||||
serde_json::from_str(&serde_json::to_string(&a).unwrap()).unwrap();
|
||||
assert_eq!(a, deserialized_a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_from_bincode() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let deserialized_a: DenseMatrix<f64> = bincode::deserialize(&bincode::serialize(&a).unwrap()).unwrap();
|
||||
assert_eq!(a, deserialized_a);
|
||||
fn to_from_bincode() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let deserialized_a: DenseMatrix<f64> =
|
||||
bincode::deserialize(&bincode::serialize(&a).unwrap()).unwrap();
|
||||
assert_eq!(a, deserialized_a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_string() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
assert_eq!(format!("{}", a), "[[0.9, 0.4, 0.7], [0.4, 0.5, 0.3], [0.7, 0.3, 0.8]]");
|
||||
fn to_string() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
assert_eq!(
|
||||
format!("{}", a),
|
||||
"[[0.9, 0.4, 0.7], [0.4, 0.5, 0.3], [0.7, 0.3, 0.8]]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cov() {
|
||||
let a = DenseMatrix::from_array(&[&[64.0, 580.0, 29.0], &[66.0, 570.0, 33.0], &[68.0, 590.0, 37.0], &[69.0, 660.0, 46.0], &[73.0, 600.0, 55.0]]);
|
||||
let expected = DenseMatrix::from_array(&[&[11.5, 50.0, 34.75], &[50.0, 1250.0, 205.0], &[34.75, 205.0, 110.0]]);
|
||||
assert_eq!(a.cov(), expected);
|
||||
fn cov() {
|
||||
let a = DenseMatrix::from_array(&[
|
||||
&[64.0, 580.0, 29.0],
|
||||
&[66.0, 570.0, 33.0],
|
||||
&[68.0, 590.0, 37.0],
|
||||
&[69.0, 660.0, 46.0],
|
||||
&[73.0, 600.0, 55.0],
|
||||
]);
|
||||
let expected = DenseMatrix::from_array(&[
|
||||
&[11.5, 50.0, 34.75],
|
||||
&[50.0, 1250.0, 205.0],
|
||||
&[34.75, 205.0, 110.0],
|
||||
]);
|
||||
assert_eq!(a.cov(), expected);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
pub mod dense_matrix;
|
||||
pub mod dense_matrix;
|
||||
|
||||
+185
-217
@@ -1,38 +1,39 @@
|
||||
use std::ops::{Range, AddAssign, SubAssign, MulAssign, DivAssign};
|
||||
use std::iter::Sum;
|
||||
use std::ops::{AddAssign, DivAssign, MulAssign, Range, SubAssign};
|
||||
|
||||
use nalgebra::{MatrixMN, DMatrix, Matrix, Scalar, Dynamic, U1, VecStorage};
|
||||
use nalgebra::{DMatrix, Dynamic, Matrix, MatrixMN, Scalar, VecStorage, U1};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::{BaseMatrix, BaseVector};
|
||||
use crate::linalg::Matrix as SmartCoreMatrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::lu::LUDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::Matrix as SmartCoreMatrix;
|
||||
use crate::linalg::{BaseMatrix, BaseVector};
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
impl<T: FloatExt + 'static> BaseVector<T> for MatrixMN<T, U1, Dynamic> {
|
||||
fn get(&self, i: usize) -> T {
|
||||
*self.get((0, i)).unwrap()
|
||||
}
|
||||
fn set(&mut self, i: usize, x: T){
|
||||
fn set(&mut self, i: usize, x: T) {
|
||||
*self.get_mut((0, i)).unwrap() = x;
|
||||
}
|
||||
|
||||
fn len(&self) -> usize{
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> BaseMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
BaseMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
type RowVector = MatrixMN<T, U1, Dynamic>;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self{
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self {
|
||||
Matrix::from_rows(&[vec])
|
||||
}
|
||||
|
||||
fn to_row_vector(self) -> Self::RowVector{
|
||||
fn to_row_vector(self) -> Self::RowVector {
|
||||
self.row(0).into_owned()
|
||||
}
|
||||
|
||||
@@ -50,13 +51,13 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: T) {
|
||||
*self.get_mut((row, col)).unwrap() = x;
|
||||
}
|
||||
}
|
||||
|
||||
fn eye(size: usize) -> Self {
|
||||
DMatrix::identity(size, size)
|
||||
}
|
||||
|
||||
fn zeros(nrows: usize, ncols: usize) -> Self {
|
||||
fn zeros(nrows: usize, ncols: usize) -> Self {
|
||||
DMatrix::zeros(nrows, ncols)
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
for (i, row) in self.row_iter().enumerate() {
|
||||
for (j, v) in row.iter().enumerate() {
|
||||
result[i * ncols + j] = *v;
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -83,25 +84,25 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
|
||||
fn shape(&self) -> (usize, usize) {
|
||||
self.shape()
|
||||
}
|
||||
}
|
||||
|
||||
fn v_stack(&self, other: &Self) -> Self {
|
||||
let mut columns = Vec::new();
|
||||
for r in 0..self.ncols(){
|
||||
fn v_stack(&self, other: &Self) -> Self {
|
||||
let mut columns = Vec::new();
|
||||
for r in 0..self.ncols() {
|
||||
columns.push(self.column(r));
|
||||
}
|
||||
for r in 0..other.ncols(){
|
||||
for r in 0..other.ncols() {
|
||||
columns.push(other.column(r));
|
||||
}
|
||||
Matrix::from_columns(&columns)
|
||||
}
|
||||
|
||||
fn h_stack(&self, other: &Self) -> Self {
|
||||
let mut rows = Vec::new();
|
||||
for r in 0..self.nrows(){
|
||||
let mut rows = Vec::new();
|
||||
for r in 0..self.nrows() {
|
||||
rows.push(self.row(r));
|
||||
}
|
||||
for r in 0..other.nrows(){
|
||||
for r in 0..other.nrows() {
|
||||
rows.push(other.row(r));
|
||||
}
|
||||
Matrix::from_rows(&rows)
|
||||
@@ -109,11 +110,11 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
|
||||
fn dot(&self, other: &Self) -> Self {
|
||||
self * other
|
||||
}
|
||||
}
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> T {
|
||||
self.dot(other)
|
||||
}
|
||||
}
|
||||
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self {
|
||||
self.slice_range(rows, cols).into_owned()
|
||||
@@ -141,46 +142,44 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
self
|
||||
}
|
||||
|
||||
fn div_mut(&mut self, other: &Self) -> &Self{
|
||||
fn div_mut(&mut self, other: &Self) -> &Self {
|
||||
self.component_div_assign(other);
|
||||
self
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
Matrix::add_scalar_mut(self, scalar);
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
Matrix::add_scalar_mut(self, -scalar);
|
||||
self
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self *= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self /= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self{
|
||||
fn transpose(&self) -> Self {
|
||||
self.transpose()
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self{
|
||||
DMatrix::from_iterator(nrows, ncols, (0..nrows*ncols).map(|_| {
|
||||
T::rand()
|
||||
}))
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
DMatrix::from_iterator(nrows, ncols, (0..nrows * ncols).map(|_| T::rand()))
|
||||
}
|
||||
|
||||
fn norm2(&self) -> T{
|
||||
fn norm2(&self) -> T {
|
||||
self.iter().map(|x| *x * *x).sum::<T>().sqrt()
|
||||
}
|
||||
|
||||
fn norm(&self, p:T) -> T {
|
||||
fn norm(&self, p: T) -> T {
|
||||
if p.is_infinite() && p.is_sign_positive() {
|
||||
self.iter().fold(T::neg_infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
@@ -189,7 +188,7 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
} else {
|
||||
v
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if p.is_infinite() && p.is_sign_negative() {
|
||||
self.iter().fold(T::infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
@@ -200,19 +199,17 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.iter() {
|
||||
norm = norm + xi.abs().powf(p);
|
||||
}
|
||||
|
||||
norm.powf(T::one()/p)
|
||||
norm.powf(T::one() / p)
|
||||
}
|
||||
}
|
||||
|
||||
fn column_mean(&self) -> Vec<T> {
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
for column in self.column_iter() {
|
||||
@@ -221,68 +218,71 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
for v in column.iter() {
|
||||
sum += *v;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
res.push(sum / T::from(count).unwrap());
|
||||
}
|
||||
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
*self.get_mut((row, col)).unwrap() = *self.get((row, col)).unwrap() / x;
|
||||
}
|
||||
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
*self.get_mut((row, col)).unwrap() = *self.get((row, col)).unwrap() * x;
|
||||
}
|
||||
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
*self.get_mut((row, col)).unwrap() = *self.get((row, col)).unwrap() + x;
|
||||
}
|
||||
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
*self.get_mut((row, col)).unwrap() = *self.get((row, col)).unwrap() - x;
|
||||
}
|
||||
|
||||
fn negative_mut(&mut self){
|
||||
fn negative_mut(&mut self) {
|
||||
*self *= -T::one();
|
||||
}
|
||||
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self{
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self {
|
||||
DMatrix::from_row_slice(nrows, ncols, &self.to_raw_vector())
|
||||
}
|
||||
|
||||
fn copy_from(&mut self, other: &Self){
|
||||
fn copy_from(&mut self, other: &Self) {
|
||||
Matrix::copy_from(self, other);
|
||||
}
|
||||
|
||||
fn abs_mut(&mut self) -> &Self{
|
||||
for v in self.iter_mut(){
|
||||
fn abs_mut(&mut self) -> &Self {
|
||||
for v in self.iter_mut() {
|
||||
*v = v.abs()
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn sum(&self) -> T{
|
||||
fn sum(&self) -> T {
|
||||
let mut sum = T::zero();
|
||||
for v in self.iter(){
|
||||
for v in self.iter() {
|
||||
sum += *v;
|
||||
}
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
fn max_diff(&self, other: &Self) -> T{
|
||||
fn max_diff(&self, other: &Self) -> T {
|
||||
let mut max_diff = T::zero();
|
||||
for r in 0..self.nrows() {
|
||||
for c in 0..self.ncols() {
|
||||
max_diff = max_diff.max((self[(r, c)] - other[(r, c)]).abs());
|
||||
}
|
||||
}
|
||||
max_diff
|
||||
max_diff
|
||||
}
|
||||
|
||||
fn softmax_mut(&mut self){
|
||||
let max = self.iter().map(|x| x.abs()).fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
|
||||
fn softmax_mut(&mut self) {
|
||||
let max = self
|
||||
.iter()
|
||||
.map(|x| x.abs())
|
||||
.fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
let mut z = T::zero();
|
||||
for r in 0..self.nrows() {
|
||||
for c in 0..self.ncols() {
|
||||
@@ -298,14 +298,14 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
}
|
||||
}
|
||||
|
||||
fn pow_mut(&mut self, p: T) -> &Self{
|
||||
for v in self.iter_mut(){
|
||||
fn pow_mut(&mut self, p: T) -> &Self {
|
||||
for v in self.iter_mut() {
|
||||
*v = v.powf(p)
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn argmax(&self) -> Vec<usize>{
|
||||
fn argmax(&self) -> Vec<usize> {
|
||||
let mut res = vec![0usize; self.nrows()];
|
||||
|
||||
for r in 0..self.nrows() {
|
||||
@@ -315,16 +315,15 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
let v = self[(r, c)];
|
||||
if max < v {
|
||||
max = v;
|
||||
max_pos = c;
|
||||
max_pos = c;
|
||||
}
|
||||
}
|
||||
res[r] = max_pos;
|
||||
}
|
||||
|
||||
res
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn unique(&self) -> Vec<T> {
|
||||
let mut result: Vec<T> = self.iter().map(|v| *v).collect();
|
||||
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
@@ -335,95 +334,96 @@ impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum
|
||||
fn cov(&self) -> Self {
|
||||
panic!("Not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> SVDDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>> {}
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
SVDDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> EVDDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>> {}
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
EVDDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> QRDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>> {}
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
QRDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> LUDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>> {}
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
LUDecomposableMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static> SmartCoreMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>> {}
|
||||
impl<T: FloatExt + Scalar + AddAssign + SubAssign + MulAssign + DivAssign + Sum + 'static>
|
||||
SmartCoreMatrix<T> for Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use nalgebra::{Matrix2x3, DMatrix, RowDVector};
|
||||
mod tests {
|
||||
use super::*;
|
||||
use nalgebra::{DMatrix, Matrix2x3, RowDVector};
|
||||
|
||||
#[test]
|
||||
fn vec_len() {
|
||||
let v = RowDVector::from_vec(vec!(1., 2., 3.));
|
||||
assert_eq!(3, v.len());
|
||||
let v = RowDVector::from_vec(vec![1., 2., 3.]);
|
||||
assert_eq!(3, v.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_set_vector() {
|
||||
let mut v = RowDVector::from_vec(vec!(1., 2., 3., 4.));
|
||||
let mut v = RowDVector::from_vec(vec![1., 2., 3., 4.]);
|
||||
|
||||
let expected = RowDVector::from_vec(vec!(1., 5., 3., 4.));
|
||||
let expected = RowDVector::from_vec(vec![1., 5., 3., 4.]);
|
||||
|
||||
v.set(1, 5.);
|
||||
|
||||
assert_eq!(v, expected);
|
||||
assert_eq!(5., BaseVector::get(&v, 1));
|
||||
assert_eq!(5., BaseVector::get(&v, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_set_dynamic() {
|
||||
let mut m = DMatrix::from_row_slice(
|
||||
2,
|
||||
3,
|
||||
&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
|
||||
);
|
||||
let mut m = DMatrix::from_row_slice(2, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
|
||||
|
||||
let expected = Matrix2x3::new(1., 2., 3., 4.,
|
||||
10., 6.);
|
||||
let expected = Matrix2x3::new(1., 2., 3., 4., 10., 6.);
|
||||
|
||||
m.set(1, 1, 10.);
|
||||
|
||||
assert_eq!(m, expected);
|
||||
assert_eq!(10., BaseMatrix::get(&m, 1, 1));
|
||||
}
|
||||
assert_eq!(10., BaseMatrix::get(&m, 1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zeros() {
|
||||
let expected = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[0., 0., 0., 0.],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[0., 0., 0., 0.]);
|
||||
|
||||
let m:DMatrix<f64> = BaseMatrix::zeros(2, 2);
|
||||
let m: DMatrix<f64> = BaseMatrix::zeros(2, 2);
|
||||
|
||||
assert_eq!(m, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ones() {
|
||||
let expected = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[1., 1., 1., 1.],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[1., 1., 1., 1.]);
|
||||
|
||||
let m:DMatrix<f64> = BaseMatrix::ones(2, 2);
|
||||
let m: DMatrix<f64> = BaseMatrix::ones(2, 2);
|
||||
|
||||
assert_eq!(m, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eye(){
|
||||
let expected = DMatrix::from_row_slice(3, 3, &[1., 0., 0., 0., 1., 0., 0., 0., 1.]);
|
||||
let m: DMatrix<f64> = BaseMatrix::eye(3);
|
||||
fn eye() {
|
||||
let expected = DMatrix::from_row_slice(3, 3, &[1., 0., 0., 0., 1., 0., 0., 0., 1.]);
|
||||
let m: DMatrix<f64> = BaseMatrix::eye(3);
|
||||
assert_eq!(m, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shape() {
|
||||
let m:DMatrix<f64> = BaseMatrix::zeros(5, 10);
|
||||
let m: DMatrix<f64> = BaseMatrix::zeros(5, 10);
|
||||
let (nrows, ncols) = m.shape();
|
||||
|
||||
assert_eq!(nrows, 5);
|
||||
@@ -431,18 +431,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_add_sub_mul_div(){
|
||||
let mut m = DMatrix::from_row_slice(
|
||||
2,
|
||||
3,
|
||||
&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
|
||||
);
|
||||
fn scalar_add_sub_mul_div() {
|
||||
let mut m = DMatrix::from_row_slice(2, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
|
||||
|
||||
let expected = DMatrix::from_row_slice(
|
||||
2,
|
||||
3,
|
||||
&[0.6, 0.8, 1., 1.2, 1.4, 1.6],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 3, &[0.6, 0.8, 1., 1.2, 1.4, 1.6]);
|
||||
|
||||
m.add_scalar_mut(3.0);
|
||||
m.sub_scalar_mut(1.0);
|
||||
@@ -452,79 +444,51 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_sub_mul_div(){
|
||||
let mut m = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[1.0, 2.0, 3.0, 4.0],
|
||||
);
|
||||
|
||||
let a = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[1.0, 2.0, 3.0, 4.0],
|
||||
);
|
||||
fn add_sub_mul_div() {
|
||||
let mut m = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]);
|
||||
|
||||
let a = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]);
|
||||
|
||||
let b: DMatrix<f64> = BaseMatrix::fill(2, 2, 10.);
|
||||
|
||||
let expected = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[0.1, 0.6, 1.5, 2.8],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[0.1, 0.6, 1.5, 2.8]);
|
||||
|
||||
m.add_mut(&a);
|
||||
m.mul_mut(&a);
|
||||
m.sub_mut(&a);
|
||||
m.div_mut(&b);
|
||||
|
||||
|
||||
assert_eq!(m, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_from_row_vector(){
|
||||
let v = RowDVector::from_vec(vec!(1., 2., 3., 4.));
|
||||
fn to_from_row_vector() {
|
||||
let v = RowDVector::from_vec(vec![1., 2., 3., 4.]);
|
||||
let expected = v.clone();
|
||||
let m: DMatrix<f64> = BaseMatrix::from_row_vector(v);
|
||||
assert_eq!(m.to_row_vector(), expected);
|
||||
assert_eq!(m.to_row_vector(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_row_col_as_vec(){
|
||||
let m = DMatrix::from_row_slice(
|
||||
3,
|
||||
3,
|
||||
&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
|
||||
);
|
||||
fn get_row_col_as_vec() {
|
||||
let m = DMatrix::from_row_slice(3, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]);
|
||||
|
||||
assert_eq!(m.get_row_as_vec(1), vec!(4., 5., 6.));
|
||||
assert_eq!(m.get_col_as_vec(1), vec!(2., 5., 8.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_raw_vector(){
|
||||
let m = DMatrix::from_row_slice(
|
||||
2,
|
||||
3,
|
||||
&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
|
||||
);
|
||||
fn to_raw_vector() {
|
||||
let m = DMatrix::from_row_slice(2, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
|
||||
|
||||
assert_eq!(m.to_raw_vector(), vec!(1., 2., 3., 4., 5., 6.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn element_add_sub_mul_div(){
|
||||
let mut m = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[1.0, 2.0, 3.0, 4.0],
|
||||
);
|
||||
fn element_add_sub_mul_div() {
|
||||
let mut m = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]);
|
||||
|
||||
let expected = DMatrix::from_row_slice(
|
||||
2,
|
||||
2,
|
||||
&[4., 1., 6., 0.4],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[4., 1., 6., 0.4]);
|
||||
|
||||
m.add_element_mut(0, 0, 3.0);
|
||||
m.sub_element_mut(0, 1, 1.0);
|
||||
@@ -534,60 +498,65 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vstack_hstack() {
|
||||
fn vstack_hstack() {
|
||||
let m1 = DMatrix::from_row_slice(2, 3, &[1., 2., 3., 4., 5., 6.]);
|
||||
let m2 = DMatrix::from_row_slice(2, 1, &[7., 8.]);
|
||||
|
||||
let m1 = DMatrix::from_row_slice(2, 3, &[1., 2., 3., 4., 5., 6.]);
|
||||
let m2 = DMatrix::from_row_slice(2, 1, &[ 7., 8.]);
|
||||
let m3 = DMatrix::from_row_slice(1, 4, &[9., 10., 11., 12.]);
|
||||
|
||||
let m3 = DMatrix::from_row_slice(1, 4, &[9., 10., 11., 12.]);
|
||||
let expected =
|
||||
DMatrix::from_row_slice(3, 4, &[1., 2., 3., 7., 4., 5., 6., 8., 9., 10., 11., 12.]);
|
||||
|
||||
let expected = DMatrix::from_row_slice(3, 4, &[1., 2., 3., 7., 4., 5., 6., 8., 9., 10., 11., 12.]);
|
||||
|
||||
let result = m1.v_stack(&m2).h_stack(&m3);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
let result = m1.v_stack(&m2).h_stack(&m3);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot() {
|
||||
|
||||
let a = DMatrix::from_row_slice(2, 3, &[1., 2., 3., 4., 5., 6.]);
|
||||
let b = DMatrix::from_row_slice(3, 2, &[1., 2., 3., 4., 5., 6.]);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[22., 28., 49., 64.]);
|
||||
let result = BaseMatrix::dot(&a, &b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vector_dot() {
|
||||
let a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
let b = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
assert_eq!(14., a.vector_dot(&b));
|
||||
fn dot() {
|
||||
let a = DMatrix::from_row_slice(2, 3, &[1., 2., 3., 4., 5., 6.]);
|
||||
let b = DMatrix::from_row_slice(3, 2, &[1., 2., 3., 4., 5., 6.]);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[22., 28., 49., 64.]);
|
||||
let result = BaseMatrix::dot(&a, &b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
fn vector_dot() {
|
||||
let a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
let b = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
assert_eq!(14., a.vector_dot(&b));
|
||||
}
|
||||
|
||||
let a = DMatrix::from_row_slice(3, 5, &[1., 2., 3., 1., 2., 4., 5., 6., 3., 4., 7., 8., 9., 5., 6.]);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[2., 3., 5., 6.]);
|
||||
let result = BaseMatrix::slice(&a, 0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
#[test]
|
||||
fn slice() {
|
||||
let a = DMatrix::from_row_slice(
|
||||
3,
|
||||
5,
|
||||
&[1., 2., 3., 1., 2., 4., 5., 6., 3., 4., 7., 8., 9., 5., 6.],
|
||||
);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[2., 3., 5., 6.]);
|
||||
let result = BaseMatrix::slice(&a, 0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approximate_eq() {
|
||||
let a = DMatrix::from_row_slice(3, 3, &[1., 2., 3., 4., 5., 6., 7., 8., 9.]);
|
||||
let noise = DMatrix::from_row_slice(3, 3, &[1e-5, 2e-5, 3e-5, 4e-5, 5e-5, 6e-5, 7e-5, 8e-5, 9e-5]);
|
||||
let noise = DMatrix::from_row_slice(
|
||||
3,
|
||||
3,
|
||||
&[1e-5, 2e-5, 3e-5, 4e-5, 5e-5, 6e-5, 7e-5, 8e-5, 9e-5],
|
||||
);
|
||||
assert!(a.approximate_eq(&(&noise + &a), 1e-4));
|
||||
assert!(!a.approximate_eq(&(&noise + &a), 1e-5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_mut() {
|
||||
let mut v = DMatrix::from_row_slice(1, 3, &[3., -2., 6.]);
|
||||
v.negative_mut();
|
||||
assert_eq!(v, DMatrix::from_row_slice(1, 3, &[-3., 2., -6.]));
|
||||
fn negative_mut() {
|
||||
let mut v = DMatrix::from_row_slice(1, 3, &[3., -2., 6.]);
|
||||
v.negative_mut();
|
||||
assert_eq!(v, DMatrix::from_row_slice(1, 3, &[-3., 2., -6.]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -595,7 +564,7 @@ mod tests {
|
||||
let m = DMatrix::from_row_slice(2, 2, &[1.0, 3.0, 2.0, 4.0]);
|
||||
let expected = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]);
|
||||
let m_transposed = m.transpose();
|
||||
assert_eq!(m_transposed, expected);
|
||||
assert_eq!(m_transposed, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -609,8 +578,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn norm() {
|
||||
let v = DMatrix::from_row_slice(1, 3, &[3., -2., 6.]);
|
||||
fn norm() {
|
||||
let v = DMatrix::from_row_slice(1, 3, &[3., -2., 6.]);
|
||||
assert_eq!(BaseMatrix::norm(&v, 1.), 11.);
|
||||
assert_eq!(BaseMatrix::norm(&v, 2.), 7.);
|
||||
assert_eq!(BaseMatrix::norm(&v, std::f64::INFINITY), 6.);
|
||||
@@ -618,17 +587,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn col_mean(){
|
||||
fn col_mean() {
|
||||
let a = DMatrix::from_row_slice(3, 3, &[1., 2., 3., 4., 5., 6., 7., 8., 9.]);
|
||||
let res = BaseMatrix::column_mean(&a);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
let res = BaseMatrix::column_mean(&a);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reshape() {
|
||||
let m_orig = DMatrix::from_row_slice(1, 6, &[1., 2., 3., 4., 5., 6.]);
|
||||
let m_2_by_3 = m_orig.reshape(2, 3);
|
||||
let m_result = m_2_by_3.reshape(1, 6);
|
||||
let m_orig = DMatrix::from_row_slice(1, 6, &[1., 2., 3., 4., 5., 6.]);
|
||||
let m_2_by_3 = m_orig.reshape(2, 3);
|
||||
let m_result = m_2_by_3.reshape(1, 6);
|
||||
assert_eq!(BaseMatrix::shape(&m_2_by_3), (2, 3));
|
||||
assert_eq!(BaseMatrix::get(&m_2_by_3, 1, 1), 5.);
|
||||
assert_eq!(BaseMatrix::get(&m_result, 0, 1), 2.);
|
||||
@@ -653,47 +622,46 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn sum() {
|
||||
let a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
let a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
assert_eq!(a.sum(), 6.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_diff() {
|
||||
let a1 = DMatrix::from_row_slice(2, 3, &[1., 2., 3., 4., -5., 6.]);
|
||||
let a2 = DMatrix::from_row_slice(2, 3, &[2., 3., 4., 1., 0., -12.]);
|
||||
let a2 = DMatrix::from_row_slice(2, 3, &[2., 3., 4., 1., 0., -12.]);
|
||||
assert_eq!(a1.max_diff(&a2), 18.);
|
||||
assert_eq!(a2.max_diff(&a2), 0.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn softmax_mut(){
|
||||
let mut prob: DMatrix<f64> = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
prob.softmax_mut();
|
||||
assert!((BaseMatrix::get(&prob, 0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 2) - 0.66).abs() < 0.01);
|
||||
fn softmax_mut() {
|
||||
let mut prob: DMatrix<f64> = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
prob.softmax_mut();
|
||||
assert!((BaseMatrix::get(&prob, 0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 2) - 0.66).abs() < 0.01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pow_mut(){
|
||||
let mut a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
fn pow_mut() {
|
||||
let mut a = DMatrix::from_row_slice(1, 3, &[1., 2., 3.]);
|
||||
a.pow_mut(3.);
|
||||
assert_eq!(a, DMatrix::from_row_slice(1, 3, &[1., 8., 27.]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argmax(){
|
||||
fn argmax() {
|
||||
let a = DMatrix::from_row_slice(3, 3, &[1., 2., 3., -5., -6., -7., 0.1, 0.2, 0.1]);
|
||||
let res = a.argmax();
|
||||
assert_eq!(res, vec![2, 0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unique(){
|
||||
fn unique() {
|
||||
let a = DMatrix::from_row_slice(3, 3, &[1., 2., 2., -2., -6., -7., 2., 3., 4.]);
|
||||
let res = a.unique();
|
||||
assert_eq!(res.len(), 7);
|
||||
assert_eq!(res, vec![-7., -6., -2., 1., 2., 3., 4.]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+191
-225
@@ -1,44 +1,45 @@
|
||||
use std::ops::Range;
|
||||
use std::iter::Sum;
|
||||
use std::ops::AddAssign;
|
||||
use std::ops::SubAssign;
|
||||
use std::ops::MulAssign;
|
||||
use std::ops::DivAssign;
|
||||
use std::ops::MulAssign;
|
||||
use std::ops::Range;
|
||||
use std::ops::SubAssign;
|
||||
|
||||
use ndarray::{Array, ArrayBase, OwnedRepr, Ix2, Ix1, Axis, stack, s};
|
||||
use ndarray::ScalarOperand;
|
||||
use ndarray::{s, stack, Array, ArrayBase, Axis, Ix1, Ix2, OwnedRepr};
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::{BaseMatrix, BaseVector};
|
||||
use crate::linalg::Matrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::lu::LUDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::Matrix;
|
||||
use crate::linalg::{BaseMatrix, BaseVector};
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
impl<T: FloatExt> BaseVector<T> for ArrayBase<OwnedRepr<T>, Ix1> {
|
||||
fn get(&self, i: usize) -> T {
|
||||
self[i]
|
||||
}
|
||||
fn set(&mut self, i: usize, x: T){
|
||||
fn set(&mut self, i: usize, x: T) {
|
||||
self[i] = x;
|
||||
}
|
||||
|
||||
fn len(&self) -> usize{
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> BaseMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>
|
||||
BaseMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
type RowVector = ArrayBase<OwnedRepr<T>, Ix1>;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self{
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self {
|
||||
let vec_size = vec.len();
|
||||
vec.into_shape((1, vec_size)).unwrap()
|
||||
}
|
||||
|
||||
fn to_row_vector(self) -> Self::RowVector{
|
||||
fn to_row_vector(self) -> Self::RowVector {
|
||||
let vec_size = self.nrows() * self.ncols();
|
||||
self.into_shape(vec_size).unwrap()
|
||||
}
|
||||
@@ -57,7 +58,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = x;
|
||||
}
|
||||
}
|
||||
|
||||
fn eye(size: usize) -> Self {
|
||||
Array::eye(size)
|
||||
@@ -81,7 +82,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
|
||||
fn shape(&self) -> (usize, usize) {
|
||||
(self.nrows(), self.ncols())
|
||||
}
|
||||
}
|
||||
|
||||
fn v_stack(&self, other: &Self) -> Self {
|
||||
stack(Axis(1), &[self.view(), other.view()]).unwrap()
|
||||
@@ -92,12 +93,12 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
}
|
||||
|
||||
fn dot(&self, other: &Self) -> Self {
|
||||
self.dot(other)
|
||||
}
|
||||
self.dot(other)
|
||||
}
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> T {
|
||||
self.dot(&other.view().reversed_axes())[[0, 0]]
|
||||
}
|
||||
}
|
||||
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self {
|
||||
self.slice(s![rows, cols]).to_owned()
|
||||
@@ -109,7 +110,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
|
||||
fn add_mut(&mut self, other: &Self) -> &Self {
|
||||
*self += other;
|
||||
self
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_mut(&mut self, other: &Self) -> &Self {
|
||||
@@ -119,50 +120,48 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
|
||||
fn mul_mut(&mut self, other: &Self) -> &Self {
|
||||
*self *= other;
|
||||
self
|
||||
self
|
||||
}
|
||||
|
||||
fn div_mut(&mut self, other: &Self) -> &Self{
|
||||
fn div_mut(&mut self, other: &Self) -> &Self {
|
||||
*self /= other;
|
||||
self
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self += scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self -= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self *= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
*self /= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self{
|
||||
fn transpose(&self) -> Self {
|
||||
self.clone().reversed_axes()
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self{
|
||||
let values: Vec<T> = (0..nrows*ncols).map(|_| {
|
||||
T::rand()
|
||||
}).collect();
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let values: Vec<T> = (0..nrows * ncols).map(|_| T::rand()).collect();
|
||||
Array::from_shape_vec((nrows, ncols), values).unwrap()
|
||||
}
|
||||
|
||||
fn norm2(&self) -> T{
|
||||
fn norm2(&self) -> T {
|
||||
self.iter().map(|x| *x * *x).sum::<T>().sqrt()
|
||||
}
|
||||
|
||||
fn norm(&self, p:T) -> T {
|
||||
fn norm(&self, p: T) -> T {
|
||||
if p.is_infinite() && p.is_sign_positive() {
|
||||
self.iter().fold(T::neg_infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
@@ -171,7 +170,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
} else {
|
||||
v
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if p.is_infinite() && p.is_sign_negative() {
|
||||
self.iter().fold(T::infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
@@ -182,14 +181,13 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.iter() {
|
||||
norm = norm + xi.abs().powf(p);
|
||||
}
|
||||
|
||||
norm.powf(T::one()/p)
|
||||
norm.powf(T::one() / p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,46 +195,46 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
self.mean_axis(Axis(0)).unwrap().to_vec()
|
||||
}
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = self[[row, col]] / x;
|
||||
}
|
||||
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = self[[row, col]] * x;
|
||||
}
|
||||
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = self[[row, col]] + x;
|
||||
}
|
||||
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = self[[row, col]] - x;
|
||||
}
|
||||
|
||||
fn negative_mut(&mut self){
|
||||
fn negative_mut(&mut self) {
|
||||
*self *= -T::one();
|
||||
}
|
||||
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self{
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self {
|
||||
self.clone().into_shape((nrows, ncols)).unwrap()
|
||||
}
|
||||
|
||||
fn copy_from(&mut self, other: &Self){
|
||||
fn copy_from(&mut self, other: &Self) {
|
||||
self.assign(&other);
|
||||
}
|
||||
|
||||
fn abs_mut(&mut self) -> &Self{
|
||||
for v in self.iter_mut(){
|
||||
fn abs_mut(&mut self) -> &Self {
|
||||
for v in self.iter_mut() {
|
||||
*v = v.abs()
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn sum(&self) -> T{
|
||||
fn sum(&self) -> T {
|
||||
self.sum()
|
||||
}
|
||||
|
||||
fn max_diff(&self, other: &Self) -> T{
|
||||
fn max_diff(&self, other: &Self) -> T {
|
||||
let mut max_diff = T::zero();
|
||||
for r in 0..self.nrows() {
|
||||
for c in 0..self.ncols() {
|
||||
@@ -245,9 +243,12 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
}
|
||||
max_diff
|
||||
}
|
||||
|
||||
fn softmax_mut(&mut self){
|
||||
let max = self.iter().map(|x| x.abs()).fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
|
||||
fn softmax_mut(&mut self) {
|
||||
let max = self
|
||||
.iter()
|
||||
.map(|x| x.abs())
|
||||
.fold(T::neg_infinity(), |a, b| a.max(b));
|
||||
let mut z = T::zero();
|
||||
for r in 0..self.nrows() {
|
||||
for c in 0..self.ncols() {
|
||||
@@ -263,7 +264,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
}
|
||||
}
|
||||
|
||||
fn pow_mut(&mut self, p: T) -> &Self{
|
||||
fn pow_mut(&mut self, p: T) -> &Self {
|
||||
for r in 0..self.nrows() {
|
||||
for c in 0..self.ncols() {
|
||||
self.set(r, c, self[(r, c)].powf(p));
|
||||
@@ -272,7 +273,7 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
self
|
||||
}
|
||||
|
||||
fn argmax(&self) -> Vec<usize>{
|
||||
fn argmax(&self) -> Vec<usize> {
|
||||
let mut res = vec![0usize; self.nrows()];
|
||||
|
||||
for r in 0..self.nrows() {
|
||||
@@ -282,16 +283,15 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
let v = self[(r, c)];
|
||||
if max < v {
|
||||
max = v;
|
||||
max_pos = c;
|
||||
max_pos = c;
|
||||
}
|
||||
}
|
||||
res[r] = max_pos;
|
||||
}
|
||||
|
||||
res
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn unique(&self) -> Vec<T> {
|
||||
let mut result = self.clone().into_raw_vec();
|
||||
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
@@ -302,231 +302,205 @@ impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign
|
||||
fn cov(&self) -> Self {
|
||||
panic!("Not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> SVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>
|
||||
SVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> EVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>
|
||||
EVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> QRDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>
|
||||
QRDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> LUDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum>
|
||||
LUDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> Matrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
impl<T: FloatExt + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> Matrix<T>
|
||||
for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ndarray::{arr1, arr2, Array2};
|
||||
|
||||
#[test]
|
||||
fn vec_get_set() {
|
||||
let mut result = arr1(&[1., 2., 3.]);
|
||||
let expected = arr1(&[1., 5., 3.]);
|
||||
let mut result = arr1(&[1., 2., 3.]);
|
||||
let expected = arr1(&[1., 5., 3.]);
|
||||
|
||||
result.set(1, 5.);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
assert_eq!(5., BaseVector::get(&result, 1));
|
||||
assert_eq!(5., BaseVector::get(&result, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_len() {
|
||||
let v = arr1(&[1., 2., 3.]);
|
||||
assert_eq!(3, v.len());
|
||||
let v = arr1(&[1., 2., 3.]);
|
||||
assert_eq!(3, v.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_to_row_vec() {
|
||||
|
||||
let vec = arr1(&[ 1., 2., 3.]);
|
||||
fn from_to_row_vec() {
|
||||
let vec = arr1(&[1., 2., 3.]);
|
||||
assert_eq!(Array2::from_row_vector(vec.clone()), arr2(&[[1., 2., 3.]]));
|
||||
assert_eq!(Array2::from_row_vector(vec.clone()).to_row_vector(), arr1(&[1., 2., 3.]));
|
||||
|
||||
assert_eq!(
|
||||
Array2::from_row_vector(vec.clone()).to_row_vector(),
|
||||
arr1(&[1., 2., 3.])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_mut() {
|
||||
|
||||
let mut a1 = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn add_mut() {
|
||||
let mut a1 = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let a2 = a1.clone();
|
||||
let a3 = a1.clone() + a2.clone();
|
||||
a1.add_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_mut() {
|
||||
|
||||
let mut a1 = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn sub_mut() {
|
||||
let mut a1 = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let a2 = a1.clone();
|
||||
let a3 = a1.clone() - a2.clone();
|
||||
a1.sub_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_mut() {
|
||||
|
||||
let mut a1 = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn mul_mut() {
|
||||
let mut a1 = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let a2 = a1.clone();
|
||||
let a3 = a1.clone() * a2.clone();
|
||||
a1.mul_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
a1.mul_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn div_mut() {
|
||||
|
||||
let mut a1 = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn div_mut() {
|
||||
let mut a1 = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let a2 = a1.clone();
|
||||
let a3 = a1.clone() / a2.clone();
|
||||
a1.div_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
a1.div_mut(&a2);
|
||||
|
||||
assert_eq!(a1, a3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn div_element_mut() {
|
||||
|
||||
let mut a = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn div_element_mut() {
|
||||
let mut a = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
a.div_element_mut(1, 1, 5.);
|
||||
|
||||
assert_eq!(BaseMatrix::get(&a, 1, 1), 1.);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul_element_mut() {
|
||||
|
||||
let mut a = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn mul_element_mut() {
|
||||
let mut a = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
a.mul_element_mut(1, 1, 5.);
|
||||
|
||||
assert_eq!(BaseMatrix::get(&a, 1, 1), 25.);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_element_mut() {
|
||||
|
||||
let mut a = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn add_element_mut() {
|
||||
let mut a = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
a.add_element_mut(1, 1, 5.);
|
||||
|
||||
assert_eq!(BaseMatrix::get(&a, 1, 1), 10.);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_element_mut() {
|
||||
|
||||
let mut a = arr2(&[[ 1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
fn sub_element_mut() {
|
||||
let mut a = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
a.sub_element_mut(1, 1, 5.);
|
||||
|
||||
assert_eq!(BaseMatrix::get(&a, 1, 1), 0.);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vstack_hstack() {
|
||||
|
||||
let a1 = arr2(&[[1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
let a2 = arr2(&[[ 7.], [8.]]);
|
||||
fn vstack_hstack() {
|
||||
let a1 = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let a2 = arr2(&[[7.], [8.]]);
|
||||
|
||||
let a3 = arr2(&[[9., 10., 11., 12.]]);
|
||||
|
||||
let expected = arr2(&[[1., 2., 3., 7.],
|
||||
[4., 5., 6., 8.],
|
||||
[9., 10., 11., 12.]]);
|
||||
let expected = arr2(&[[1., 2., 3., 7.], [4., 5., 6., 8.], [9., 10., 11., 12.]]);
|
||||
|
||||
let result = a1.v_stack(&a2).h_stack(&a3);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
let result = a1.v_stack(&a2).h_stack(&a3);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_raw_vector() {
|
||||
let result = arr2(&[[1., 2., 3.], [4., 5., 6.]]).to_raw_vector();
|
||||
let result = arr2(&[[1., 2., 3.], [4., 5., 6.]]).to_raw_vector();
|
||||
let expected = vec![1., 2., 3., 4., 5., 6.];
|
||||
|
||||
assert_eq!(result, expected);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_set() {
|
||||
let mut result = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let expected = arr2(&[[1., 2., 3.], [4., 10., 6.]]);
|
||||
let mut result = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let expected = arr2(&[[1., 2., 3.], [4., 10., 6.]]);
|
||||
|
||||
result.set(1, 1, 10.);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
assert_eq!(10., BaseMatrix::get(&result, 1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot() {
|
||||
|
||||
let a = arr2(&[
|
||||
[1., 2., 3.],
|
||||
[4., 5., 6.]]);
|
||||
let b = arr2(&[
|
||||
[1., 2.],
|
||||
[3., 4.],
|
||||
[5., 6.]]);
|
||||
let expected = arr2(&[
|
||||
[22., 28.],
|
||||
[49., 64.]]);
|
||||
let result = BaseMatrix::dot(&a, &b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vector_dot() {
|
||||
let a = arr2(&[[1., 2., 3.]]);
|
||||
let b = arr2(&[[1., 2., 3.]]);
|
||||
assert_eq!(14., a.vector_dot(&b));
|
||||
assert_eq!(10., BaseMatrix::get(&result, 1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
|
||||
let a = arr2(
|
||||
&[
|
||||
[1., 2., 3., 1., 2.],
|
||||
[4., 5., 6., 3., 4.],
|
||||
[7., 8., 9., 5., 6.]]);
|
||||
let expected = arr2(
|
||||
&[
|
||||
[2., 3.],
|
||||
[5., 6.]]);
|
||||
let result = BaseMatrix::slice(&a, 0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
fn dot() {
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.]]);
|
||||
let b = arr2(&[[1., 2.], [3., 4.], [5., 6.]]);
|
||||
let expected = arr2(&[[22., 28.], [49., 64.]]);
|
||||
let result = BaseMatrix::dot(&a, &b);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_ops() {
|
||||
let a = arr2(&[[1., 2., 3.]]);
|
||||
assert_eq!(&arr2(&[[2., 3., 4.]]), a.clone().add_scalar_mut(1.));
|
||||
assert_eq!(&arr2(&[[0., 1., 2.]]), a.clone().sub_scalar_mut(1.));
|
||||
assert_eq!(&arr2(&[[2., 4., 6.]]), a.clone().mul_scalar_mut(2.));
|
||||
assert_eq!(&arr2(&[[0.5, 1., 1.5]]), a.clone().div_scalar_mut(2.));
|
||||
fn vector_dot() {
|
||||
let a = arr2(&[[1., 2., 3.]]);
|
||||
let b = arr2(&[[1., 2., 3.]]);
|
||||
assert_eq!(14., a.vector_dot(&b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
let a = arr2(&[
|
||||
[1., 2., 3., 1., 2.],
|
||||
[4., 5., 6., 3., 4.],
|
||||
[7., 8., 9., 5., 6.],
|
||||
]);
|
||||
let expected = arr2(&[[2., 3.], [5., 6.]]);
|
||||
let result = BaseMatrix::slice(&a, 0..2, 1..3);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_ops() {
|
||||
let a = arr2(&[[1., 2., 3.]]);
|
||||
assert_eq!(&arr2(&[[2., 3., 4.]]), a.clone().add_scalar_mut(1.));
|
||||
assert_eq!(&arr2(&[[0., 1., 2.]]), a.clone().sub_scalar_mut(1.));
|
||||
assert_eq!(&arr2(&[[2., 4., 6.]]), a.clone().mul_scalar_mut(2.));
|
||||
assert_eq!(&arr2(&[[0.5, 1., 1.5]]), a.clone().div_scalar_mut(2.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -534,12 +508,12 @@ mod tests {
|
||||
let m = arr2(&[[1.0, 3.0], [2.0, 4.0]]);
|
||||
let expected = arr2(&[[1.0, 2.0], [3.0, 4.0]]);
|
||||
let m_transposed = m.transpose();
|
||||
assert_eq!(m_transposed, expected);
|
||||
assert_eq!(m_transposed, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn norm() {
|
||||
let v = arr2(&[[3., -2., 6.]]);
|
||||
fn norm() {
|
||||
let v = arr2(&[[3., -2., 6.]]);
|
||||
assert_eq!(v.norm(1.), 11.);
|
||||
assert_eq!(v.norm(2.), 7.);
|
||||
assert_eq!(v.norm(std::f64::INFINITY), 6.);
|
||||
@@ -547,17 +521,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_mut() {
|
||||
let mut v = arr2(&[[3., -2., 6.]]);
|
||||
v.negative_mut();
|
||||
assert_eq!(v, arr2(&[[-3., 2., -6.]]));
|
||||
fn negative_mut() {
|
||||
let mut v = arr2(&[[3., -2., 6.]]);
|
||||
v.negative_mut();
|
||||
assert_eq!(v, arr2(&[[-3., 2., -6.]]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reshape() {
|
||||
let m_orig = arr2(&[[1., 2., 3., 4., 5., 6.]]);
|
||||
let m_2_by_3 = BaseMatrix::reshape(&m_orig, 2, 3);
|
||||
let m_result = BaseMatrix::reshape(&m_2_by_3, 1, 6);
|
||||
let m_result = BaseMatrix::reshape(&m_2_by_3, 1, 6);
|
||||
assert_eq!(BaseMatrix::shape(&m_2_by_3), (2, 3));
|
||||
assert_eq!(BaseMatrix::get(&m_2_by_3, 1, 1), 5.);
|
||||
assert_eq!(BaseMatrix::get(&m_result, 0, 1), 2.);
|
||||
@@ -567,84 +541,80 @@ mod tests {
|
||||
#[test]
|
||||
fn copy_from() {
|
||||
let mut src = arr2(&[[1., 2., 3.]]);
|
||||
let dst = Array2::<f64>::zeros((1, 3));
|
||||
let dst = Array2::<f64>::zeros((1, 3));
|
||||
src.copy_from(&dst);
|
||||
assert_eq!(src, dst);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum() {
|
||||
let src = arr2(&[[1., 2., 3.]]);
|
||||
let src = arr2(&[[1., 2., 3.]]);
|
||||
assert_eq!(src.sum(), 6.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_diff() {
|
||||
let a1 = arr2(&[[1., 2., 3.], [4., -5., 6.]]);
|
||||
let a2 = arr2(&[[2., 3., 4.], [1., 0., -12.]]);
|
||||
let a1 = arr2(&[[1., 2., 3.], [4., -5., 6.]]);
|
||||
let a2 = arr2(&[[2., 3., 4.], [1., 0., -12.]]);
|
||||
assert_eq!(a1.max_diff(&a2), 18.);
|
||||
assert_eq!(a2.max_diff(&a2), 0.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn softmax_mut(){
|
||||
let mut prob: Array2<f64> = arr2(&[[1., 2., 3.]]);
|
||||
prob.softmax_mut();
|
||||
assert!((BaseMatrix::get(&prob, 0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 2) - 0.66).abs() < 0.01);
|
||||
fn softmax_mut() {
|
||||
let mut prob: Array2<f64> = arr2(&[[1., 2., 3.]]);
|
||||
prob.softmax_mut();
|
||||
assert!((BaseMatrix::get(&prob, 0, 0) - 0.09).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 1) - 0.24).abs() < 0.01);
|
||||
assert!((BaseMatrix::get(&prob, 0, 2) - 0.66).abs() < 0.01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pow_mut(){
|
||||
let mut a = arr2(&[[1., 2., 3.]]);
|
||||
fn pow_mut() {
|
||||
let mut a = arr2(&[[1., 2., 3.]]);
|
||||
a.pow_mut(3.);
|
||||
assert_eq!(a, arr2(&[[1., 8., 27.]]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argmax(){
|
||||
let a = arr2(&[[1., 2., 3.], [-5., -6., -7.], [0.1, 0.2, 0.1]]);
|
||||
fn argmax() {
|
||||
let a = arr2(&[[1., 2., 3.], [-5., -6., -7.], [0.1, 0.2, 0.1]]);
|
||||
let res = a.argmax();
|
||||
assert_eq!(res, vec![2, 0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unique(){
|
||||
let a = arr2(&[[1., 2., 2.], [-2., -6., -7.], [2., 3., 4.]]);
|
||||
fn unique() {
|
||||
let a = arr2(&[[1., 2., 2.], [-2., -6., -7.], [2., 3., 4.]]);
|
||||
let res = a.unique();
|
||||
assert_eq!(res.len(), 7);
|
||||
assert_eq!(res, vec![-7., -6., -2., 1., 2., 3., 4.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_row_as_vector(){
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
fn get_row_as_vector() {
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
let res = a.get_row_as_vec(1);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_col_as_vector(){
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
fn get_col_as_vector() {
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
let res = a.get_col_as_vec(1);
|
||||
assert_eq!(res, vec![2., 5., 8.]);
|
||||
assert_eq!(res, vec![2., 5., 8.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn col_mean(){
|
||||
let a = arr2(&[[1., 2., 3.],
|
||||
[4., 5., 6.],
|
||||
[7., 8., 9.]]);
|
||||
fn col_mean() {
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
let res = a.column_mean();
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
assert_eq!(res, vec![4., 5., 6.]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eye(){
|
||||
let a = arr2(&[[1., 0., 0.],
|
||||
[0., 1., 0.],
|
||||
[0., 0., 1.]]);
|
||||
fn eye() {
|
||||
let a = arr2(&[[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]);
|
||||
let res: Array2<f64> = BaseMatrix::eye(3);
|
||||
assert_eq!(res, a);
|
||||
}
|
||||
@@ -661,12 +631,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn approximate_eq() {
|
||||
let a = arr2(&[[1., 2., 3.],
|
||||
[4., 5., 6.],
|
||||
[7., 8., 9.]]);
|
||||
let noise = arr2(&[[1e-5, 2e-5, 3e-5],
|
||||
[4e-5, 5e-5, 6e-5],
|
||||
[7e-5, 8e-5, 9e-5]]);
|
||||
let a = arr2(&[[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
|
||||
let noise = arr2(&[[1e-5, 2e-5, 3e-5], [4e-5, 5e-5, 6e-5], [7e-5, 8e-5, 9e-5]]);
|
||||
assert!(a.approximate_eq(&(&noise + &a), 1e-4));
|
||||
assert!(!a.approximate_eq(&(&noise + &a), 1e-5));
|
||||
}
|
||||
@@ -678,4 +644,4 @@ mod tests {
|
||||
a.abs_mut();
|
||||
assert_eq!(a, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-55
@@ -2,19 +2,18 @@
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QR<T: FloatExt, M: BaseMatrix<T>> {
|
||||
pub struct QR<T: FloatExt, M: BaseMatrix<T>> {
|
||||
QR: M,
|
||||
tau: Vec<T>,
|
||||
singular: bool
|
||||
singular: bool,
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
pub fn new(QR: M, tau: Vec<T>) -> QR<T, M> {
|
||||
|
||||
let mut singular = false;
|
||||
for j in 0..tau.len() {
|
||||
if tau[j] == T::zero() {
|
||||
@@ -26,7 +25,7 @@ impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
QR {
|
||||
QR: QR,
|
||||
tau: tau,
|
||||
singular: singular
|
||||
singular: singular,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,13 +34,13 @@ impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
let mut R = M::zeros(n, n);
|
||||
for i in 0..n {
|
||||
R.set(i, i, self.tau[i]);
|
||||
for j in i+1..n {
|
||||
for j in i + 1..n {
|
||||
R.set(i, j, self.QR.get(i, j));
|
||||
}
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
pub fn Q(&self) -> M {
|
||||
let (m, n) = self.QR.shape();
|
||||
let mut Q = M::zeros(m, n);
|
||||
@@ -63,19 +62,21 @@ impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
if k == 0 {
|
||||
break;
|
||||
} else {
|
||||
k -= 1;
|
||||
k -= 1;
|
||||
}
|
||||
}
|
||||
return Q;
|
||||
}
|
||||
|
||||
fn solve(&self, mut b: M) -> M {
|
||||
|
||||
let (m, n) = self.QR.shape();
|
||||
let (b_nrows, b_ncols) = b.shape();
|
||||
|
||||
let (b_nrows, b_ncols) = b.shape();
|
||||
|
||||
if b_nrows != m {
|
||||
panic!("Row dimensions do not agree: A is {} x {}, but B is {} x {}", m, n, b_nrows, b_ncols);
|
||||
panic!(
|
||||
"Row dimensions do not agree: A is {} x {}, but B is {} x {}",
|
||||
m, n, b_nrows, b_ncols
|
||||
);
|
||||
}
|
||||
|
||||
if self.singular {
|
||||
@@ -93,13 +94,13 @@ impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
b.add_element_mut(i, j, s * self.QR.get(i, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k in (0..n).rev() {
|
||||
for j in 0..b_ncols {
|
||||
b.set(k, j, b.get(k, j) / self.tau[k]);
|
||||
}
|
||||
|
||||
|
||||
for i in 0..k {
|
||||
for j in 0..b_ncols {
|
||||
b.sub_element_mut(i, j, b.get(k, j) * self.QR.get(i, k));
|
||||
@@ -108,19 +109,16 @@ impl<T: FloatExt, M: BaseMatrix<T>> QR<T, M> {
|
||||
}
|
||||
|
||||
b
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub trait QRDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
pub trait QRDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
fn qr(&self) -> QR<T, Self> {
|
||||
self.clone().qr_mut()
|
||||
}
|
||||
|
||||
fn qr_mut(mut self) -> QR<T, Self> {
|
||||
|
||||
let (m, n) = self.shape();
|
||||
let (m, n) = self.shape();
|
||||
|
||||
let mut r_diagonal: Vec<T> = vec![T::zero(); n];
|
||||
|
||||
@@ -131,7 +129,6 @@ pub trait QRDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
|
||||
if nrm.abs() > T::epsilon() {
|
||||
|
||||
if self.get(k, k) < T::zero() {
|
||||
nrm = -nrm;
|
||||
}
|
||||
@@ -140,7 +137,7 @@ pub trait QRDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
self.add_element_mut(k, k, T::one());
|
||||
|
||||
for j in k+1..n {
|
||||
for j in k + 1..n {
|
||||
let mut s = T::zero();
|
||||
for i in k..m {
|
||||
s = s + self.get(i, k) * self.get(i, j);
|
||||
@@ -150,54 +147,51 @@ pub trait QRDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
self.add_element_mut(i, j, s * self.get(i, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r_diagonal[k] = -nrm;
|
||||
}
|
||||
|
||||
QR::new(self, r_diagonal)
|
||||
|
||||
}
|
||||
|
||||
fn qr_solve_mut(self, b: Self) -> Self {
|
||||
|
||||
self.qr_mut().solve(b)
|
||||
|
||||
}
|
||||
self.qr_mut().solve(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::linalg::naive::dense_matrix::*;
|
||||
use crate::linalg::naive::dense_matrix::*;
|
||||
|
||||
#[test]
|
||||
fn decompose() {
|
||||
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let q = DenseMatrix::from_array(&[
|
||||
&[-0.7448, 0.2436, 0.6212],
|
||||
&[-0.331, -0.9432, -0.027],
|
||||
&[-0.5793, 0.2257, -0.7832]]);
|
||||
let r = DenseMatrix::from_array(&[
|
||||
&[-1.2083, -0.6373, -1.0842],
|
||||
&[0.0, -0.3064, 0.0682],
|
||||
&[0.0, 0.0, -0.1999]]);
|
||||
let qr = a.qr();
|
||||
assert!(qr.Q().abs().approximate_eq(&q.abs(), 1e-4));
|
||||
assert!(qr.R().abs().approximate_eq(&r.abs(), 1e-4));
|
||||
fn decompose() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let q = DenseMatrix::from_array(&[
|
||||
&[-0.7448, 0.2436, 0.6212],
|
||||
&[-0.331, -0.9432, -0.027],
|
||||
&[-0.5793, 0.2257, -0.7832],
|
||||
]);
|
||||
let r = DenseMatrix::from_array(&[
|
||||
&[-1.2083, -0.6373, -1.0842],
|
||||
&[0.0, -0.3064, 0.0682],
|
||||
&[0.0, 0.0, -0.1999],
|
||||
]);
|
||||
let qr = a.qr();
|
||||
assert!(qr.Q().abs().approximate_eq(&q.abs(), 1e-4));
|
||||
assert!(qr.R().abs().approximate_eq(&r.abs(), 1e-4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qr_solve_mut() {
|
||||
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let b = DenseMatrix::from_array(&[&[0.5, 0.2],&[0.5, 0.8], &[0.5, 0.3]]);
|
||||
let expected_w = DenseMatrix::from_array(&[
|
||||
&[-0.2027027, -1.2837838],
|
||||
&[0.8783784, 2.2297297],
|
||||
&[0.4729730, 0.6621622]
|
||||
]);
|
||||
let w = a.qr_solve_mut(b);
|
||||
assert!(w.approximate_eq(&expected_w, 1e-2));
|
||||
fn qr_solve_mut() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let b = DenseMatrix::from_array(&[&[0.5, 0.2], &[0.5, 0.8], &[0.5, 0.3]]);
|
||||
let expected_w = DenseMatrix::from_array(&[
|
||||
&[-0.2027027, -1.2837838],
|
||||
&[0.8783784, 2.2297297],
|
||||
&[0.4729730, 0.6621622],
|
||||
]);
|
||||
let w = a.qr_solve_mut(b);
|
||||
assert!(w.approximate_eq(&expected_w, 1e-2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+221
-74
@@ -12,17 +12,16 @@ pub struct SVD<T: FloatExt, M: SVDDecomposableMatrix<T>> {
|
||||
full: bool,
|
||||
m: usize,
|
||||
n: usize,
|
||||
tol: T
|
||||
tol: T,
|
||||
}
|
||||
|
||||
pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
fn svd_solve_mut(self, b: Self) -> Self {
|
||||
self.svd_mut().solve(b)
|
||||
}
|
||||
|
||||
fn svd_solve(&self, b: Self) -> Self {
|
||||
self.svd().solve(b)
|
||||
self.svd().solve(b)
|
||||
}
|
||||
|
||||
fn svd(&self) -> SVD<T, Self> {
|
||||
@@ -30,14 +29,13 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
|
||||
fn svd_mut(self) -> SVD<T, Self> {
|
||||
let mut U = self;
|
||||
|
||||
let mut U = self;
|
||||
let (m, n) = U.shape();
|
||||
|
||||
let (m, n) = U.shape();
|
||||
|
||||
let (mut l, mut nm) = (0usize, 0usize);
|
||||
let (mut anorm, mut g, mut scale) = (T::zero(), T::zero(), T::zero());
|
||||
|
||||
let (mut anorm, mut g, mut scale) = (T::zero(), T::zero(), T::zero());
|
||||
|
||||
let mut v = Self::zeros(n, n);
|
||||
let mut w = vec![T::zero(); n];
|
||||
let mut rv1 = vec![T::zero(); n];
|
||||
@@ -55,7 +53,6 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
|
||||
if scale.abs() > T::epsilon() {
|
||||
|
||||
for k in i..m {
|
||||
U.div_element_mut(k, i, scale);
|
||||
s = s + U.get(k, i) * U.get(k, i);
|
||||
@@ -98,7 +95,7 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
|
||||
let f = U.get(i, l - 1);
|
||||
g = -s.sqrt().copysign(f);
|
||||
g = -s.sqrt().copysign(f);
|
||||
let h = f * g - s;
|
||||
U.set(i, l - 1, f - g);
|
||||
|
||||
@@ -123,7 +120,6 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
anorm = T::max(anorm, w[i].abs() + rv1[i].abs());
|
||||
}
|
||||
|
||||
@@ -186,11 +182,11 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
for k in (0..n).rev() {
|
||||
for iteration in 0..30 {
|
||||
let mut flag = true;
|
||||
let mut flag = true;
|
||||
l = k;
|
||||
while l != 0 {
|
||||
while l != 0 {
|
||||
if l == 0 || rv1[l].abs() <= T::epsilon() * anorm {
|
||||
flag = false;
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
nm = l - 1;
|
||||
@@ -203,7 +199,7 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
if flag {
|
||||
let mut c = T::zero();
|
||||
let mut s = T::one();
|
||||
for i in l..k+1 {
|
||||
for i in l..k + 1 {
|
||||
let f = s * rv1[i];
|
||||
rv1[i] = c * rv1[i];
|
||||
if f.abs() <= T::epsilon() * anorm {
|
||||
@@ -219,7 +215,7 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
let y = U.get(j, nm);
|
||||
let z = U.get(j, i);
|
||||
U.set(j, nm, y * c + z * s);
|
||||
U.set(j, i, z * c - y * s);
|
||||
U.set(j, i, z * c - y * s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,11 +291,11 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
w[k] = x;
|
||||
}
|
||||
}
|
||||
|
||||
let mut inc = 1usize;
|
||||
|
||||
let mut inc = 1usize;
|
||||
let mut su = vec![T::zero(); m];
|
||||
let mut sv = vec![T::zero(); n];
|
||||
|
||||
|
||||
loop {
|
||||
inc *= 3;
|
||||
inc += 1;
|
||||
@@ -310,7 +306,7 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
|
||||
loop {
|
||||
inc /= 3;
|
||||
for i in inc..n {
|
||||
for i in inc..n {
|
||||
let sw = w[i];
|
||||
for k in 0..m {
|
||||
su[k] = U.get(k, i);
|
||||
@@ -339,7 +335,6 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
for k in 0..n {
|
||||
v.set(k, j, sv[k]);
|
||||
}
|
||||
|
||||
}
|
||||
if inc <= 1 {
|
||||
break;
|
||||
@@ -366,18 +361,17 @@ pub trait SVDDecomposableMatrix<T: FloatExt>: BaseMatrix<T> {
|
||||
v.set(j, k, -v.get(j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SVD::new(U, v, w)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FloatExt, M: SVDDecomposableMatrix<T>> SVD<T, M> {
|
||||
pub fn new(U: M, V: M, s: Vec<T>) -> SVD<T, M> {
|
||||
let m = U.shape().0;
|
||||
let n = V.shape().0;
|
||||
let full = s.len() == m.min(n);
|
||||
let n = V.shape().0;
|
||||
let full = s.len() == m.min(n);
|
||||
let tol = T::half() * (T::from(m + n).unwrap() + T::one()).sqrt() * s[0] * T::epsilon();
|
||||
SVD {
|
||||
U: U,
|
||||
@@ -386,7 +380,7 @@ impl<T: FloatExt, M: SVDDecomposableMatrix<T>> SVD<T, M> {
|
||||
full: full,
|
||||
m: m,
|
||||
n: n,
|
||||
tol: tol
|
||||
tol: tol,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +388,11 @@ impl<T: FloatExt, M: SVDDecomposableMatrix<T>> SVD<T, M> {
|
||||
let p = b.shape().1;
|
||||
|
||||
if self.U.shape().0 != b.shape().0 {
|
||||
panic!("Dimensions do not agree. U.nrows should equal b.nrows but is {}, {}", self.U.shape().0, b.shape().0);
|
||||
panic!(
|
||||
"Dimensions do not agree. U.nrows should equal b.nrows but is {}, {}",
|
||||
self.U.shape().0,
|
||||
b.shape().0
|
||||
);
|
||||
}
|
||||
|
||||
for k in 0..p {
|
||||
@@ -424,30 +422,30 @@ impl<T: FloatExt, M: SVDDecomposableMatrix<T>> SVD<T, 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 s: Vec<f64> = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
|
||||
let U = DenseMatrix::from_array(&[
|
||||
&[0.6881997, -0.07121225, 0.7220180],
|
||||
&[0.3700456, 0.89044952, -0.2648886],
|
||||
&[0.6240573, -0.44947578, -0.639158]
|
||||
&[0.6240573, -0.44947578, -0.639158],
|
||||
]);
|
||||
|
||||
let V = 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 svd = A.svd();
|
||||
@@ -457,43 +455,199 @@ mod tests {
|
||||
for i in 0..s.len() {
|
||||
assert!((s[i] - svd.s[i]).abs() < 1e-4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decompose_asymmetric() {
|
||||
|
||||
fn decompose_asymmetric() {
|
||||
let A = DenseMatrix::from_array(&[
|
||||
&[1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433],
|
||||
&[0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340],
|
||||
&[-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051],
|
||||
&[-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563],
|
||||
&[-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502, -1.88207227],
|
||||
&[0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013, 1.63805985],
|
||||
&[0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535, -0.2158704, -0.27529472]
|
||||
&[
|
||||
1.19720880,
|
||||
-1.8391378,
|
||||
0.3019585,
|
||||
-1.1165701,
|
||||
-1.7210814,
|
||||
0.4918882,
|
||||
-0.04247433,
|
||||
],
|
||||
&[
|
||||
0.06605075,
|
||||
1.0315583,
|
||||
0.8294362,
|
||||
-0.3646043,
|
||||
-1.6038017,
|
||||
-0.9188110,
|
||||
-0.63760340,
|
||||
],
|
||||
&[
|
||||
-1.02637715,
|
||||
1.0747931,
|
||||
-0.8089055,
|
||||
-0.4726863,
|
||||
-0.2064826,
|
||||
-0.3325532,
|
||||
0.17966051,
|
||||
],
|
||||
&[
|
||||
-1.45817729,
|
||||
-0.8942353,
|
||||
0.3459245,
|
||||
1.5068363,
|
||||
-2.0180708,
|
||||
-0.3696350,
|
||||
-1.19575563,
|
||||
],
|
||||
&[
|
||||
-0.07318103,
|
||||
-0.2783787,
|
||||
1.2237598,
|
||||
0.1995332,
|
||||
0.2545336,
|
||||
-0.1392502,
|
||||
-1.88207227,
|
||||
],
|
||||
&[
|
||||
0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013, 1.63805985,
|
||||
],
|
||||
&[
|
||||
0.12641406,
|
||||
-0.8710055,
|
||||
-0.2712301,
|
||||
0.2296515,
|
||||
1.1781535,
|
||||
-0.2158704,
|
||||
-0.27529472,
|
||||
],
|
||||
]);
|
||||
|
||||
let s: Vec<f64> = vec![3.8589375, 3.4396766, 2.6487176, 2.2317399, 1.5165054, 0.8109055, 0.2706515];
|
||||
let s: Vec<f64> = vec![
|
||||
3.8589375, 3.4396766, 2.6487176, 2.2317399, 1.5165054, 0.8109055, 0.2706515,
|
||||
];
|
||||
|
||||
let U = DenseMatrix::from_array(&[
|
||||
&[-0.3082776, 0.77676231, 0.01330514, 0.23231424, -0.47682758, 0.13927109, 0.02640713],
|
||||
&[-0.4013477, -0.09112050, 0.48754440, 0.47371793, 0.40636608, 0.24600706, -0.37796295],
|
||||
&[0.0599719, -0.31406586, 0.45428229, -0.08071283, -0.38432597, 0.57320261, 0.45673993],
|
||||
&[-0.7694214, -0.12681435, -0.05536793, -0.62189972, -0.02075522, -0.01724911, -0.03681864],
|
||||
&[-0.3319069, -0.17984404, -0.54466777, 0.45335157, 0.19377726, 0.12333423, 0.55003852],
|
||||
&[0.1259351, 0.49087824, 0.16349687, -0.32080176, 0.64828744, 0.20643772, 0.38812467],
|
||||
&[0.1491884, 0.01768604, -0.47884363, -0.14108924, 0.03922507, 0.73034065, -0.43965505]
|
||||
&[
|
||||
-0.3082776,
|
||||
0.77676231,
|
||||
0.01330514,
|
||||
0.23231424,
|
||||
-0.47682758,
|
||||
0.13927109,
|
||||
0.02640713,
|
||||
],
|
||||
&[
|
||||
-0.4013477,
|
||||
-0.09112050,
|
||||
0.48754440,
|
||||
0.47371793,
|
||||
0.40636608,
|
||||
0.24600706,
|
||||
-0.37796295,
|
||||
],
|
||||
&[
|
||||
0.0599719,
|
||||
-0.31406586,
|
||||
0.45428229,
|
||||
-0.08071283,
|
||||
-0.38432597,
|
||||
0.57320261,
|
||||
0.45673993,
|
||||
],
|
||||
&[
|
||||
-0.7694214,
|
||||
-0.12681435,
|
||||
-0.05536793,
|
||||
-0.62189972,
|
||||
-0.02075522,
|
||||
-0.01724911,
|
||||
-0.03681864,
|
||||
],
|
||||
&[
|
||||
-0.3319069,
|
||||
-0.17984404,
|
||||
-0.54466777,
|
||||
0.45335157,
|
||||
0.19377726,
|
||||
0.12333423,
|
||||
0.55003852,
|
||||
],
|
||||
&[
|
||||
0.1259351,
|
||||
0.49087824,
|
||||
0.16349687,
|
||||
-0.32080176,
|
||||
0.64828744,
|
||||
0.20643772,
|
||||
0.38812467,
|
||||
],
|
||||
&[
|
||||
0.1491884,
|
||||
0.01768604,
|
||||
-0.47884363,
|
||||
-0.14108924,
|
||||
0.03922507,
|
||||
0.73034065,
|
||||
-0.43965505,
|
||||
],
|
||||
]);
|
||||
|
||||
let V = DenseMatrix::from_array(&[
|
||||
&[-0.2122609, -0.54650056, 0.08071332, -0.43239135, -0.2925067, 0.1414550, 0.59769207],
|
||||
&[-0.1943605, 0.63132116, -0.54059857, -0.37089970, -0.1363031, 0.2892641, 0.17774114],
|
||||
&[0.3031265, -0.06182488, 0.18579097, -0.38606409, -0.5364911, 0.2983466, -0.58642548],
|
||||
&[0.1844063, 0.24425278, 0.25923756, 0.59043765, -0.4435443, 0.3959057, 0.37019098],
|
||||
&[-0.7164205, 0.30694911, 0.58264743, -0.07458095, -0.1142140, -0.1311972, -0.13124764],
|
||||
&[-0.1103067, -0.10633600, 0.18257905, -0.03638501, 0.5722925, 0.7784398, -0.09153611],
|
||||
&[-0.5156083, -0.36573746, -0.47613340, 0.41342817, -0.2659765, 0.1654796, -0.32346758]
|
||||
]);
|
||||
&[
|
||||
-0.2122609,
|
||||
-0.54650056,
|
||||
0.08071332,
|
||||
-0.43239135,
|
||||
-0.2925067,
|
||||
0.1414550,
|
||||
0.59769207,
|
||||
],
|
||||
&[
|
||||
-0.1943605,
|
||||
0.63132116,
|
||||
-0.54059857,
|
||||
-0.37089970,
|
||||
-0.1363031,
|
||||
0.2892641,
|
||||
0.17774114,
|
||||
],
|
||||
&[
|
||||
0.3031265,
|
||||
-0.06182488,
|
||||
0.18579097,
|
||||
-0.38606409,
|
||||
-0.5364911,
|
||||
0.2983466,
|
||||
-0.58642548,
|
||||
],
|
||||
&[
|
||||
0.1844063, 0.24425278, 0.25923756, 0.59043765, -0.4435443, 0.3959057, 0.37019098,
|
||||
],
|
||||
&[
|
||||
-0.7164205,
|
||||
0.30694911,
|
||||
0.58264743,
|
||||
-0.07458095,
|
||||
-0.1142140,
|
||||
-0.1311972,
|
||||
-0.13124764,
|
||||
],
|
||||
&[
|
||||
-0.1103067,
|
||||
-0.10633600,
|
||||
0.18257905,
|
||||
-0.03638501,
|
||||
0.5722925,
|
||||
0.7784398,
|
||||
-0.09153611,
|
||||
],
|
||||
&[
|
||||
-0.5156083,
|
||||
-0.36573746,
|
||||
-0.47613340,
|
||||
0.41342817,
|
||||
-0.2659765,
|
||||
0.1654796,
|
||||
-0.32346758,
|
||||
],
|
||||
]);
|
||||
|
||||
let svd = A.svd();
|
||||
|
||||
@@ -502,21 +656,14 @@ mod tests {
|
||||
for i in 0..s.len() {
|
||||
assert!((s[i] - svd.s[i]).abs() < 1e-4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solve() {
|
||||
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let b = DenseMatrix::from_array(&[&[0.5, 0.2],&[0.5, 0.8], &[0.5, 0.3]]);
|
||||
let expected_w = DenseMatrix::from_array(&[
|
||||
&[-0.20, -1.28],
|
||||
&[0.87, 2.22],
|
||||
&[0.47, 0.66]
|
||||
]);
|
||||
let w = a.svd_solve_mut(b);
|
||||
assert!(w.approximate_eq(&expected_w, 1e-2));
|
||||
fn solve() {
|
||||
let a = DenseMatrix::from_array(&[&[0.9, 0.4, 0.7], &[0.4, 0.5, 0.3], &[0.7, 0.3, 0.8]]);
|
||||
let b = DenseMatrix::from_array(&[&[0.5, 0.2], &[0.5, 0.8], &[0.5, 0.3]]);
|
||||
let expected_w = DenseMatrix::from_array(&[&[-0.20, -1.28], &[0.87, 2.22], &[0.47, 0.66]]);
|
||||
let w = a.svd_solve_mut(b);
|
||||
assert!(w.approximate_eq(&expected_w, 1e-2));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user