feat: extends interface of Matrix to support for broad range of types
This commit is contained in:
+156
-150
@@ -2,16 +2,18 @@
|
||||
|
||||
use num::complex::Complex;
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EVD<M: BaseMatrix> {
|
||||
pub d: Vec<f64>,
|
||||
pub e: Vec<f64>,
|
||||
pub struct EVD<T: FloatExt + Debug, M: BaseMatrix<T>> {
|
||||
pub d: Vec<T>,
|
||||
pub e: Vec<T>,
|
||||
pub V: M
|
||||
}
|
||||
|
||||
impl<M: BaseMatrix> EVD<M> {
|
||||
pub fn new(V: M, d: Vec<f64>, e: Vec<f64>) -> EVD<M> {
|
||||
impl<T: FloatExt + Debug, 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,
|
||||
@@ -20,21 +22,21 @@ impl<M: BaseMatrix> EVD<M> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EVDDecomposableMatrix: BaseMatrix {
|
||||
pub trait EVDDecomposableMatrix<T: FloatExt + Debug>: BaseMatrix<T> {
|
||||
|
||||
fn evd(&self, symmetric: bool) -> EVD<Self>{
|
||||
fn evd(&self, symmetric: bool) -> EVD<T, Self>{
|
||||
self.clone().evd_mut(symmetric)
|
||||
}
|
||||
|
||||
fn evd_mut(mut self, symmetric: bool) -> EVD<Self>{
|
||||
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![0f64; n];
|
||||
let mut e = vec![0f64; n];
|
||||
let mut d = vec![T::zero(); n];
|
||||
let mut e = vec![T::zero(); n];
|
||||
|
||||
let mut V;
|
||||
if symmetric {
|
||||
@@ -66,7 +68,7 @@ pub trait EVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
fn tred2<T: FloatExt + Debug, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>) {
|
||||
|
||||
let (n, _) = V.shape();
|
||||
for i in 0..n {
|
||||
@@ -76,34 +78,34 @@ fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
// Householder reduction to tridiagonal form.
|
||||
for i in (1..n).rev() {
|
||||
// Scale to avoid under/overflow.
|
||||
let mut scale = 0f64;
|
||||
let mut h = 0f64;
|
||||
let mut scale = T::zero();
|
||||
let mut h = T::zero();
|
||||
for k in 0..i {
|
||||
scale = scale + d[k].abs();
|
||||
}
|
||||
if scale == 0f64 {
|
||||
if scale == T::zero() {
|
||||
e[i] = d[i - 1];
|
||||
for j in 0..i {
|
||||
d[j] = V.get(i - 1, j);
|
||||
V.set(i, j, 0.0);
|
||||
V.set(j, i, 0.0);
|
||||
V.set(i, j, T::zero());
|
||||
V.set(j, i, T::zero());
|
||||
}
|
||||
} else {
|
||||
// Generate Householder vector.
|
||||
for k in 0..i {
|
||||
d[k] /= scale;
|
||||
h += d[k] * d[k];
|
||||
d[k] = d[k] / scale;
|
||||
h = h + d[k] * d[k];
|
||||
}
|
||||
let mut f = d[i - 1];
|
||||
let mut g = h.sqrt();
|
||||
if f > 0f64 {
|
||||
if f > T::zero() {
|
||||
g = -g;
|
||||
}
|
||||
e[i] = scale * g;
|
||||
h = h - f * g;
|
||||
d[i - 1] = f - g;
|
||||
for j in 0..i {
|
||||
e[j] = 0f64;
|
||||
e[j] = T::zero();
|
||||
}
|
||||
|
||||
// Apply similarity transformation to remaining columns.
|
||||
@@ -112,19 +114,19 @@ fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
V.set(j, i, f);
|
||||
g = e[j] + V.get(j, j) * f;
|
||||
for k in j + 1..=i - 1 {
|
||||
g += V.get(k, j) * d[k];
|
||||
e[k] += V.get(k, j) * f;
|
||||
g = g + V.get(k, j) * d[k];
|
||||
e[k] = e[k] + V.get(k, j) * f;
|
||||
}
|
||||
e[j] = g;
|
||||
}
|
||||
f = 0.0;
|
||||
f = T::zero();
|
||||
for j in 0..i {
|
||||
e[j] /= h;
|
||||
f += e[j] * d[j];
|
||||
e[j] = e[j] / h;
|
||||
f = f + e[j] * d[j];
|
||||
}
|
||||
let hh = f / (h + h);
|
||||
for j in 0..i {
|
||||
e[j] -= hh * d[j];
|
||||
e[j] = e[j] - hh * d[j];
|
||||
}
|
||||
for j in 0..i {
|
||||
f = d[j];
|
||||
@@ -133,7 +135,7 @@ fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
V.sub_element_mut(k, j, f * e[k] + g * d[k]);
|
||||
}
|
||||
d[j] = V.get(i - 1, j);
|
||||
V.set(i, j, 0.0);
|
||||
V.set(i, j, T::zero());
|
||||
}
|
||||
}
|
||||
d[i] = h;
|
||||
@@ -142,16 +144,16 @@ fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
// Accumulate transformations.
|
||||
for i in 0..n-1 {
|
||||
V.set(n - 1, i, V.get(i, i));
|
||||
V.set(i, i, 1.0);
|
||||
V.set(i, i, T::one());
|
||||
let h = d[i + 1];
|
||||
if h != 0f64 {
|
||||
if h != T::zero() {
|
||||
for k in 0..=i {
|
||||
d[k] = V.get(k, i + 1) / h;
|
||||
}
|
||||
for j in 0..=i {
|
||||
let mut g = 0f64;
|
||||
let mut g = T::zero();
|
||||
for k in 0..=i {
|
||||
g += V.get(k, i + 1) * V.get(k, j);
|
||||
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]);
|
||||
@@ -159,35 +161,35 @@ fn tred2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
}
|
||||
}
|
||||
for k in 0..=i {
|
||||
V.set(k, i + 1, 0.0);
|
||||
V.set(k, i + 1, T::zero());
|
||||
}
|
||||
}
|
||||
for j in 0..n {
|
||||
d[j] = V.get(n - 1, j);
|
||||
V.set(n - 1, j, 0.0);
|
||||
V.set(n - 1, j, T::zero());
|
||||
}
|
||||
V.set(n - 1, n - 1, 1.0);
|
||||
e[0] = 0.0;
|
||||
V.set(n - 1, n - 1, T::one());
|
||||
e[0] = T::zero();
|
||||
}
|
||||
|
||||
fn tql2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
fn tql2<T: FloatExt + Debug, M: BaseMatrix<T>>(V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>) {
|
||||
let (n, _) = V.shape();
|
||||
for i in 1..n {
|
||||
e[i - 1] = e[i];
|
||||
}
|
||||
e[n - 1] = 0f64;
|
||||
e[n - 1] = T::zero();
|
||||
|
||||
let mut f = 0f64;
|
||||
let mut tst1 = 0f64;
|
||||
let mut f = T::zero();
|
||||
let mut tst1 = T::zero();
|
||||
for l in 0..n {
|
||||
// Find small subdiagonal element
|
||||
tst1 = f64::max(tst1, d[l].abs() + e[l].abs());
|
||||
tst1 = T::max(tst1, d[l].abs() + e[l].abs());
|
||||
|
||||
let mut m = l;
|
||||
|
||||
loop {
|
||||
if m < n {
|
||||
if e[m].abs() <= tst1 * std::f64::EPSILON {
|
||||
if e[m].abs() <= tst1 * T::epsilon() {
|
||||
break;
|
||||
}
|
||||
m += 1;
|
||||
@@ -208,9 +210,9 @@ fn tql2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
|
||||
// Compute implicit shift
|
||||
let mut g = d[l];
|
||||
let mut p = (d[l + 1] - g) / (2.0 * e[l]);
|
||||
let mut r = p.hypot(1.0);
|
||||
if p < 0f64 {
|
||||
let mut p = (d[l + 1] - g) / (T::two() * e[l]);
|
||||
let mut r = p.hypot(T::one());
|
||||
if p < T::zero() {
|
||||
r = -r;
|
||||
}
|
||||
d[l] = e[l] / (p + r);
|
||||
@@ -218,18 +220,18 @@ fn tql2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
let dl1 = d[l + 1];
|
||||
let mut h = g - d[l];
|
||||
for i in l+2..n {
|
||||
d[i] -= h;
|
||||
d[i] = d[i] - h;
|
||||
}
|
||||
f = f + h;
|
||||
|
||||
// Implicit QL transformation.
|
||||
p = d[m];
|
||||
let mut c = 1.0;
|
||||
let mut c = T::one();
|
||||
let mut c2 = c;
|
||||
let mut c3 = c;
|
||||
let el1 = e[l + 1];
|
||||
let mut s = 0.0;
|
||||
let mut s2 = 0.0;
|
||||
let mut s = T::zero();
|
||||
let mut s2 = T::zero();
|
||||
for i in (l..m).rev() {
|
||||
c3 = c2;
|
||||
c2 = c;
|
||||
@@ -255,13 +257,13 @@ fn tql2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
d[l] = c * p;
|
||||
|
||||
// Check for convergence.
|
||||
if e[l].abs() <= tst1 * std::f64::EPSILON {
|
||||
if e[l].abs() <= tst1 * T::epsilon() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
d[l] = d[l] + f;
|
||||
e[l] = 0f64;
|
||||
e[l] = T::zero();
|
||||
}
|
||||
|
||||
// Sort eigenvalues and corresponding vectors.
|
||||
@@ -286,43 +288,45 @@ fn tql2<M: BaseMatrix>(V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn balance<M: BaseMatrix>(A: &mut M) -> Vec<f64> {
|
||||
let radix = 2f64;
|
||||
fn balance<T: FloatExt + Debug, M: BaseMatrix<T>>(A: &mut M) -> Vec<T> {
|
||||
let radix = T::two();
|
||||
let sqrdx = radix * radix;
|
||||
|
||||
let (n, _) = A.shape();
|
||||
|
||||
let mut scale = vec![1f64; n];
|
||||
let mut scale = vec![T::one(); n];
|
||||
|
||||
let t = T::from(0.95).unwrap();
|
||||
|
||||
let mut done = false;
|
||||
while !done {
|
||||
done = true;
|
||||
for i in 0..n {
|
||||
let mut r = 0f64;
|
||||
let mut c = 0f64;
|
||||
let mut r = T::zero();
|
||||
let mut c = T::zero();
|
||||
for j in 0..n {
|
||||
if j != i {
|
||||
c += A.get(j, i).abs();
|
||||
r += A.get(i, j).abs();
|
||||
c = c + A.get(j, i).abs();
|
||||
r = r + A.get(i, j).abs();
|
||||
}
|
||||
}
|
||||
if c != 0f64 && r != 0f64 {
|
||||
if c != T::zero() && r != T::zero() {
|
||||
let mut g = r / radix;
|
||||
let mut f = 1.0;
|
||||
let mut f = T::one();
|
||||
let s = c + r;
|
||||
while c < g {
|
||||
f *= radix;
|
||||
c *= sqrdx;
|
||||
f = f * radix;
|
||||
c = c * sqrdx;
|
||||
}
|
||||
g = r * radix;
|
||||
while c > g {
|
||||
f /= radix;
|
||||
c /= sqrdx;
|
||||
f = f / radix;
|
||||
c = c / sqrdx;
|
||||
}
|
||||
if (c + r) / f < 0.95 * s {
|
||||
if (c + r) / f < t * s {
|
||||
done = false;
|
||||
g = 1.0 / f;
|
||||
scale[i] *= f;
|
||||
g = T::one() / f;
|
||||
scale[i] = scale[i] * f;
|
||||
for j in 0..n {
|
||||
A.mul_element_mut(i, j, g);
|
||||
}
|
||||
@@ -337,12 +341,12 @@ fn balance<M: BaseMatrix>(A: &mut M) -> Vec<f64> {
|
||||
return scale;
|
||||
}
|
||||
|
||||
fn elmhes<M: BaseMatrix>(A: &mut M) -> Vec<usize> {
|
||||
fn elmhes<T: FloatExt + Debug, M: BaseMatrix<T>>(A: &mut M) -> Vec<usize> {
|
||||
let (n, _) = A.shape();
|
||||
let mut perm = vec![0; n];
|
||||
|
||||
for m in 1..n-1 {
|
||||
let mut x = 0f64;
|
||||
let mut x = T::zero();
|
||||
let mut i = m;
|
||||
for j in m..n {
|
||||
if A.get(j, m - 1).abs() > x.abs() {
|
||||
@@ -363,11 +367,11 @@ fn elmhes<M: BaseMatrix>(A: &mut M) -> Vec<usize> {
|
||||
A.set(j, m, swap);
|
||||
}
|
||||
}
|
||||
if x != 0f64 {
|
||||
if x != T::zero() {
|
||||
for i in (m + 1)..n {
|
||||
let mut y = A.get(i, m - 1);
|
||||
if y != 0f64 {
|
||||
y /= x;
|
||||
if y != T::zero() {
|
||||
y = y / x;
|
||||
A.set(i, m - 1, y);
|
||||
for j in m..n {
|
||||
A.sub_element_mut(i, j, y * A.get(m, j));
|
||||
@@ -383,7 +387,7 @@ fn elmhes<M: BaseMatrix>(A: &mut M) -> Vec<usize> {
|
||||
return perm;
|
||||
}
|
||||
|
||||
fn eltran<M: BaseMatrix>(A: &M, V: &mut M, perm: &Vec<usize>) {
|
||||
fn eltran<T: FloatExt + Debug, M: BaseMatrix<T>>(A: &M, V: &mut M, perm: &Vec<usize>) {
|
||||
let (n, _) = A.shape();
|
||||
for mp in (1..n - 1).rev() {
|
||||
for k in mp + 1..n {
|
||||
@@ -393,41 +397,41 @@ fn eltran<M: BaseMatrix>(A: &M, V: &mut M, perm: &Vec<usize>) {
|
||||
if i != mp {
|
||||
for j in mp..n {
|
||||
V.set(mp, j, V.get(i, j));
|
||||
V.set(i, j, 0.0);
|
||||
V.set(i, j, T::zero());
|
||||
}
|
||||
V.set(i, mp, 1.0);
|
||||
V.set(i, mp, T::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>) {
|
||||
fn hqr2<T: FloatExt + Debug, M: BaseMatrix<T>>(A: &mut M, V: &mut M, d: &mut Vec<T>, e: &mut Vec<T>) {
|
||||
let (n, _) = A.shape();
|
||||
let mut z = 0f64;
|
||||
let mut s = 0f64;
|
||||
let mut r = 0f64;
|
||||
let mut q = 0f64;
|
||||
let mut p = 0f64;
|
||||
let mut anorm = 0f64;
|
||||
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 j in i32::max(i as i32 - 1, 0)..n as i32 {
|
||||
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 = 0.0;
|
||||
let mut t = T::zero();
|
||||
'outer: loop {
|
||||
let mut its = 0;
|
||||
loop {
|
||||
let mut l = nn;
|
||||
while l > 0 {
|
||||
s = A.get(l - 1, l - 1).abs() + A.get(l, l).abs();
|
||||
if s == 0.0 {
|
||||
if s == T::zero() {
|
||||
s = anorm;
|
||||
}
|
||||
if A.get(l, l - 1).abs() <= std::f64::EPSILON * s {
|
||||
A.set(l, l - 1, 0.0);
|
||||
if A.get(l, l - 1).abs() <= T::epsilon() * s {
|
||||
A.set(l, l - 1, T::zero());
|
||||
break;
|
||||
}
|
||||
l -= 1;
|
||||
@@ -445,17 +449,17 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
let mut y = A.get(nn - 1, nn - 1);
|
||||
let mut w = A.get(nn, nn - 1) * A.get(nn - 1, nn);
|
||||
if l == nn - 1 {
|
||||
p = 0.5 * (y - x);
|
||||
p = T::half() * (y - x);
|
||||
q = p * p + w;
|
||||
z = q.abs().sqrt();
|
||||
x += t;
|
||||
x = x + t;
|
||||
A.set(nn, nn, x );
|
||||
A.set(nn - 1, nn - 1, y + t);
|
||||
if q >= 0.0 {
|
||||
if q >= T::zero() {
|
||||
z = p + z.copysign(p);
|
||||
d[nn - 1] = x + z;
|
||||
d[nn] = x + z;
|
||||
if z != 0.0 {
|
||||
if z != T::zero() {
|
||||
d[nn] = x - w / z;
|
||||
}
|
||||
x = A.get(nn, nn - 1);
|
||||
@@ -463,8 +467,8 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
p = x / s;
|
||||
q = z / s;
|
||||
r = (p * p + q * q).sqrt();
|
||||
p /= r;
|
||||
q /= r;
|
||||
p = p / r;
|
||||
q = q / r;
|
||||
for j in nn-1..n {
|
||||
z = A.get(nn - 1, j);
|
||||
A.set(nn - 1, j, q * z + p * A.get(nn, j));
|
||||
@@ -497,14 +501,14 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
panic!("Too many iterations in hqr");
|
||||
}
|
||||
if its == 10 || its == 20 {
|
||||
t += x;
|
||||
t = t + x;
|
||||
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();
|
||||
y = 0.75 * s;
|
||||
x = 0.75 * s;
|
||||
w = -0.4375 * s * s;
|
||||
y = T::from(0.75).unwrap() * s;
|
||||
x = T::from(0.75).unwrap() * s;
|
||||
w = T::from(-0.4375).unwrap() * s * s;
|
||||
}
|
||||
its += 1;
|
||||
let mut m = nn - 2;
|
||||
@@ -516,42 +520,42 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
q = A.get(m + 1, m + 1) - z - r - s;
|
||||
r = A.get(m + 2, m + 1);
|
||||
s = p.abs() + q.abs() + r.abs();
|
||||
p /= s;
|
||||
q /= s;
|
||||
r /= s;
|
||||
p = p / s;
|
||||
q = q / s;
|
||||
r = r / s;
|
||||
if m == l {
|
||||
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());
|
||||
if u <= std::f64::EPSILON * v {
|
||||
if u <= T::epsilon() * v {
|
||||
break;
|
||||
}
|
||||
m -= 1;
|
||||
}
|
||||
for i in m..nn-1 {
|
||||
A.set(i + 2, i , 0.0);
|
||||
A.set(i + 2, i , T::zero());
|
||||
if i != m {
|
||||
A.set(i + 2, i - 1, 0.0);
|
||||
A.set(i + 2, i - 1, T::zero());
|
||||
}
|
||||
}
|
||||
for k in m..nn {
|
||||
if k != m {
|
||||
p = A.get(k, k - 1);
|
||||
q = A.get(k + 1, k - 1);
|
||||
r = 0.0;
|
||||
r = T::zero();
|
||||
if k + 1 != nn {
|
||||
r = A.get(k + 2, k - 1);
|
||||
}
|
||||
x = p.abs() + q.abs() +r.abs();
|
||||
if x != 0.0 {
|
||||
p /= x;
|
||||
q /= x;
|
||||
r /= x;
|
||||
if x != T::zero() {
|
||||
p = p / x;
|
||||
q = q / x;
|
||||
r = r / x;
|
||||
}
|
||||
}
|
||||
let s = (p * p + q * q + r * r).sqrt().copysign(p);
|
||||
if s != 0.0 {
|
||||
if s != T::zero() {
|
||||
if k == m {
|
||||
if l != m {
|
||||
A.set(k, k - 1, -A.get(k, k - 1));
|
||||
@@ -559,16 +563,16 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
} else {
|
||||
A.set(k, k - 1, -s * x);
|
||||
}
|
||||
p += s;
|
||||
p = p + s;
|
||||
x = p / s;
|
||||
y = q / s;
|
||||
z = r / s;
|
||||
q /= p;
|
||||
r /= p;
|
||||
q = q / p;
|
||||
r = r / p;
|
||||
for j in k..n {
|
||||
p = A.get(k, j) + q * A.get(k + 1, j);
|
||||
if k + 1 != nn {
|
||||
p += r * A.get(k + 2, j);
|
||||
p = p + r * A.get(k + 2, j);
|
||||
A.sub_element_mut(k + 2, j, p * z);
|
||||
}
|
||||
A.sub_element_mut(k + 1, j, p * y);
|
||||
@@ -583,7 +587,7 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
for i in 0..mmin+1 {
|
||||
p = x * A.get(i, k) + y * A.get(i, k + 1);
|
||||
if k + 1 != nn {
|
||||
p += z * A.get(i, k + 2);
|
||||
p = p + z * A.get(i, k + 2);
|
||||
A.sub_element_mut(i, k + 2, p * r);
|
||||
}
|
||||
A.sub_element_mut(i, k + 1, p * q);
|
||||
@@ -592,7 +596,7 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
for i in 0..n {
|
||||
p = x * V.get(i, k) + y * V.get(i, k + 1);
|
||||
if k + 1 != nn {
|
||||
p += z * V.get(i, k + 2);
|
||||
p = p + z * V.get(i, k + 2);
|
||||
V.sub_element_mut(i, k + 2, p * r);
|
||||
}
|
||||
V.sub_element_mut(i, k + 1, p * q);
|
||||
@@ -608,38 +612,38 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
};
|
||||
}
|
||||
|
||||
if anorm != 0f64 {
|
||||
if anorm != T::zero() {
|
||||
for nn in (0..n).rev() {
|
||||
p = d[nn];
|
||||
q = e[nn];
|
||||
let na = nn.wrapping_sub(1);
|
||||
if q == 0f64 {
|
||||
if q == T::zero() {
|
||||
let mut m = nn;
|
||||
A.set(nn, nn, 1.0);
|
||||
A.set(nn, nn, T::one());
|
||||
if nn > 0 {
|
||||
let mut i = nn - 1;
|
||||
loop {
|
||||
let w = A.get(i, i) - p;
|
||||
r = 0.0;
|
||||
r = T::zero();
|
||||
for j in m..=nn {
|
||||
r += A.get(i, j) * A.get(j, nn);
|
||||
r = r + A.get(i, j) * A.get(j, nn);
|
||||
}
|
||||
if e[i] < 0.0 {
|
||||
if e[i] < T::zero() {
|
||||
z = w;
|
||||
s = r;
|
||||
} else {
|
||||
m = i;
|
||||
|
||||
if e[i] == 0.0 {
|
||||
if e[i] == T::zero() {
|
||||
t = w;
|
||||
if t == 0.0 {
|
||||
t = std::f64::EPSILON * anorm;
|
||||
if t == T::zero() {
|
||||
t = T::epsilon() * anorm;
|
||||
}
|
||||
A.set(i, nn, -r / t);
|
||||
} else {
|
||||
let x = A.get(i, i + 1);
|
||||
let y = A.get(i + 1, i);
|
||||
q = (d[i] - p).powf(2f64) + e[i].powf(2f64);
|
||||
q = (d[i] - p).powf(T::two()) + e[i].powf(T::two());
|
||||
t = (x * s - z * r) / q;
|
||||
A.set(i, nn, t);
|
||||
if x.abs() > z.abs() {
|
||||
@@ -649,7 +653,7 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
}
|
||||
}
|
||||
t = A.get(i, nn).abs();
|
||||
if std::f64::EPSILON * t * t > 1f64 {
|
||||
if T::epsilon() * t * t > T::one() {
|
||||
for j in i..=nn {
|
||||
A.div_element_mut(j, nn, t);
|
||||
}
|
||||
@@ -662,44 +666,44 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if q < 0f64 {
|
||||
} else if q < T::zero() {
|
||||
let mut m = na;
|
||||
if A.get(nn, na).abs() > A.get(na, nn).abs() {
|
||||
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(0.0, -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, 0.0);
|
||||
A.set(nn, nn, 1.0);
|
||||
A.set(nn, na, T::zero());
|
||||
A.set(nn, nn, T::one());
|
||||
if nn >= 2 {
|
||||
for i in (0..nn - 1).rev() {
|
||||
let w = A.get(i, i) - p;
|
||||
let mut ra = 0f64;
|
||||
let mut sa = 0f64;
|
||||
let mut ra = T::zero();
|
||||
let mut sa = T::zero();
|
||||
for j in m..=nn {
|
||||
ra += A.get(i, j) * A.get(j, na);
|
||||
sa += A.get(i, j) * A.get(j, nn);
|
||||
ra = ra + A.get(i, j) * A.get(j, na);
|
||||
sa = sa + A.get(i, j) * A.get(j, nn);
|
||||
}
|
||||
if e[i] < 0.0 {
|
||||
if e[i] < T::zero() {
|
||||
z = w;
|
||||
r = ra;
|
||||
s = sa;
|
||||
} else {
|
||||
m = i;
|
||||
if e[i] == 0.0 {
|
||||
if e[i] == T::zero() {
|
||||
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(2f64) + (e[i]).powf(2.0) - q * q;
|
||||
let vi = 2.0 * q * (d[i] - p);
|
||||
if vr == 0.0 && vi == 0.0 {
|
||||
vr = std::f64::EPSILON * anorm * (w.abs() + q.abs() + x.abs() + y.abs() + z.abs());
|
||||
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());
|
||||
}
|
||||
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);
|
||||
@@ -714,8 +718,8 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
}
|
||||
}
|
||||
}
|
||||
t = f64::max(A.get(i, na).abs(), A.get(i, nn).abs());
|
||||
if std::f64::EPSILON * t * t > 1f64 {
|
||||
t = T::max(A.get(i, na).abs(), A.get(i, nn).abs());
|
||||
if T::epsilon() * t * t > T::one() {
|
||||
for j in i..=nn {
|
||||
A.div_element_mut(j, na, t);
|
||||
A.div_element_mut(j, nn, t);
|
||||
@@ -728,9 +732,9 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
|
||||
for j in (0..n).rev() {
|
||||
for i in 0..n {
|
||||
z = 0f64;
|
||||
z = T::zero();
|
||||
for k in 0..=j {
|
||||
z += V.get(i, k) * A.get(k, j);
|
||||
z = z + V.get(i, k) * A.get(k, j);
|
||||
}
|
||||
V.set(i, j, z);
|
||||
}
|
||||
@@ -738,7 +742,7 @@ fn hqr2<M: BaseMatrix>(A: &mut M, V: &mut M, d: &mut Vec<f64>, e: &mut Vec<f64>)
|
||||
}
|
||||
}
|
||||
|
||||
fn balbak<M: BaseMatrix>(V: &mut M, scale: &Vec<f64>) {
|
||||
fn balbak<T: FloatExt + Debug, M: BaseMatrix<T>>(V: &mut M, scale: &Vec<T>) {
|
||||
let (n, _) = V.shape();
|
||||
for i in 0..n {
|
||||
for j in 0..n {
|
||||
@@ -747,9 +751,9 @@ fn balbak<M: BaseMatrix>(V: &mut M, scale: &Vec<f64>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn sort<M: BaseMatrix>(d: &mut Vec<f64>, e: &mut Vec<f64>, V: &mut M) {
|
||||
fn sort<T: FloatExt + Debug, M: BaseMatrix<T>>(d: &mut Vec<T>, e: &mut Vec<T>, V: &mut M) {
|
||||
let n = d.len();
|
||||
let mut temp = vec![0f64; n];
|
||||
let mut temp = vec![T::zero(); n];
|
||||
for j in 1..n {
|
||||
let real = d[j];
|
||||
let img = e[j];
|
||||
@@ -789,7 +793,7 @@ mod tests {
|
||||
&[0.4000, 0.5000, 0.3000],
|
||||
&[0.7000, 0.3000, 0.8000]]);
|
||||
|
||||
let eigen_values = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
let eigen_values: Vec<f64> = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
|
||||
let eigen_vectors = DenseMatrix::from_array(&[
|
||||
&[0.6881997, -0.07121225, 0.7220180],
|
||||
@@ -817,7 +821,7 @@ mod tests {
|
||||
&[0.4000, 0.5000, 0.3000],
|
||||
&[0.8000, 0.3000, 0.8000]]);
|
||||
|
||||
let eigen_values = vec![1.79171122, 0.31908143, 0.08920735];
|
||||
let eigen_values: Vec<f64> = vec![1.79171122, 0.31908143, 0.08920735];
|
||||
|
||||
let eigen_vectors = DenseMatrix::from_array(&[
|
||||
&[0.7178958, 0.05322098, 0.6812010],
|
||||
@@ -826,6 +830,8 @@ mod tests {
|
||||
]);
|
||||
|
||||
let evd = A.evd(false);
|
||||
|
||||
println!("{}", &evd.V.abs());
|
||||
|
||||
assert!(eigen_vectors.abs().approximate_eq(&evd.V.abs(), 1e-4));
|
||||
for i in 0..eigen_values.len() {
|
||||
@@ -846,8 +852,8 @@ mod tests {
|
||||
&[1.0, 1.0, 3.0, -2.0],
|
||||
&[1.0, 1.0, 4.0, -1.0]]);
|
||||
|
||||
let eigen_values_d = vec![0.0, 2.0, 2.0, 0.0];
|
||||
let eigen_values_e = vec![2.2361, 0.9999, -0.9999, -2.2361];
|
||||
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];
|
||||
|
||||
let eigen_vectors = DenseMatrix::from_array(&[
|
||||
&[-0.9159, -0.1378, 0.3816, -0.0806],
|
||||
|
||||
+42
-37
@@ -6,11 +6,14 @@ pub mod ndarray_bindings;
|
||||
|
||||
use std::ops::Range;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use svd::SVDDecomposableMatrix;
|
||||
use evd::EVDDecomposableMatrix;
|
||||
use qr::QRDecomposableMatrix;
|
||||
|
||||
pub trait BaseMatrix: Clone + Debug {
|
||||
pub trait BaseMatrix<T: FloatExt + Debug>: Clone + Debug {
|
||||
|
||||
type RowVector: Clone + Debug;
|
||||
|
||||
@@ -18,13 +21,13 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn to_row_vector(self) -> Self::RowVector;
|
||||
|
||||
fn get(&self, row: usize, col: usize) -> f64;
|
||||
fn get(&self, row: usize, col: usize) -> T;
|
||||
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<f64>;
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<T>;
|
||||
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<f64>;
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T>;
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: f64);
|
||||
fn set(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn eye(size: usize) -> Self;
|
||||
|
||||
@@ -32,9 +35,9 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn ones(nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
fn to_raw_vector(&self) -> Vec<f64>;
|
||||
fn to_raw_vector(&self) -> Vec<T>;
|
||||
|
||||
fn fill(nrows: usize, ncols: usize, value: f64) -> Self;
|
||||
fn fill(nrows: usize, ncols: usize, value: T) -> Self;
|
||||
|
||||
fn shape(&self) -> (usize, usize);
|
||||
|
||||
@@ -44,11 +47,11 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn dot(&self, other: &Self) -> Self;
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> f64;
|
||||
fn vector_dot(&self, other: &Self) -> T;
|
||||
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self;
|
||||
|
||||
fn approximate_eq(&self, other: &Self, error: f64) -> bool;
|
||||
fn approximate_eq(&self, other: &Self, error: T) -> bool;
|
||||
|
||||
fn add_mut(&mut self, other: &Self) -> &Self;
|
||||
|
||||
@@ -58,13 +61,13 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn div_mut(&mut self, other: &Self) -> &Self;
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: f64);
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: f64);
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: f64);
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: f64);
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T);
|
||||
|
||||
fn add(&self, other: &Self) -> Self {
|
||||
let mut r = self.clone();
|
||||
@@ -90,33 +93,33 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
r
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self;
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self;
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self;
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self;
|
||||
|
||||
fn add_scalar(&self, scalar: f64) -> Self{
|
||||
fn add_scalar(&self, scalar: T) -> Self{
|
||||
let mut r = self.clone();
|
||||
r.add_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn sub_scalar(&self, scalar: f64) -> Self{
|
||||
fn sub_scalar(&self, scalar: T) -> Self{
|
||||
let mut r = self.clone();
|
||||
r.sub_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn mul_scalar(&self, scalar: f64) -> Self{
|
||||
fn mul_scalar(&self, scalar: T) -> Self{
|
||||
let mut r = self.clone();
|
||||
r.mul_scalar_mut(scalar);
|
||||
r
|
||||
}
|
||||
|
||||
fn div_scalar(&self, scalar: f64) -> Self{
|
||||
fn div_scalar(&self, scalar: T) -> Self{
|
||||
let mut r = self.clone();
|
||||
r.div_scalar_mut(scalar);
|
||||
r
|
||||
@@ -126,11 +129,11 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
fn norm2(&self) -> f64;
|
||||
fn norm2(&self) -> T;
|
||||
|
||||
fn norm(&self, p:f64) -> f64;
|
||||
fn norm(&self, p:T) -> T;
|
||||
|
||||
fn column_mean(&self) -> Vec<f64>;
|
||||
fn column_mean(&self) -> Vec<T>;
|
||||
|
||||
fn negative_mut(&mut self);
|
||||
|
||||
@@ -152,15 +155,15 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
result
|
||||
}
|
||||
|
||||
fn sum(&self) -> f64;
|
||||
fn sum(&self) -> T;
|
||||
|
||||
fn max_diff(&self, other: &Self) -> f64;
|
||||
fn max_diff(&self, other: &Self) -> T;
|
||||
|
||||
fn softmax_mut(&mut self);
|
||||
|
||||
fn pow_mut(&mut self, p: f64) -> &Self;
|
||||
fn pow_mut(&mut self, p: T) -> &Self;
|
||||
|
||||
fn pow(&mut self, p: f64) -> Self {
|
||||
fn pow(&mut self, p: T) -> Self {
|
||||
let mut result = self.clone();
|
||||
result.pow_mut(p);
|
||||
result
|
||||
@@ -168,31 +171,33 @@ pub trait BaseMatrix: Clone + Debug {
|
||||
|
||||
fn argmax(&self) -> Vec<usize>;
|
||||
|
||||
fn unique(&self) -> Vec<f64>;
|
||||
fn unique(&self) -> Vec<T>;
|
||||
|
||||
}
|
||||
|
||||
pub trait Matrix: BaseMatrix + SVDDecomposableMatrix + EVDDecomposableMatrix + QRDecomposableMatrix {}
|
||||
pub trait Matrix<T: FloatExt + Debug>: BaseMatrix<T> + SVDDecomposableMatrix<T> + EVDDecomposableMatrix<T> + QRDecomposableMatrix<T> {}
|
||||
|
||||
pub fn row_iter<M: Matrix>(m: &M) -> RowIter<M> {
|
||||
pub fn row_iter<F: FloatExt + Debug, M: Matrix<F>>(m: &M) -> RowIter<F, M> {
|
||||
RowIter{
|
||||
m: m,
|
||||
pos: 0,
|
||||
max_pos: m.shape().0
|
||||
max_pos: m.shape().0,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RowIter<'a, M: Matrix> {
|
||||
pub struct RowIter<'a, T: FloatExt + Debug, M: Matrix<T>> {
|
||||
m: &'a M,
|
||||
pos: usize,
|
||||
max_pos: usize
|
||||
max_pos: usize,
|
||||
phantom: PhantomData<&'a T>
|
||||
}
|
||||
|
||||
impl<'a, M: Matrix> Iterator for RowIter<'a, M> {
|
||||
impl<'a, T: FloatExt + Debug, M: Matrix<T>> Iterator for RowIter<'a, T, M> {
|
||||
|
||||
type Item = Vec<f64>;
|
||||
type Item = Vec<T>;
|
||||
|
||||
fn next(&mut self) -> Option<Vec<f64>> {
|
||||
fn next(&mut self) -> Option<Vec<T>> {
|
||||
let res;
|
||||
if self.pos < self.max_pos {
|
||||
res = Some(self.m.get_row_as_vec(self.pos))
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
extern crate num;
|
||||
use std::ops::Range;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::linalg::Matrix;
|
||||
pub use crate::linalg::BaseMatrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use crate::math;
|
||||
use rand::prelude::*;
|
||||
use crate::math::num::FloatExt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DenseMatrix {
|
||||
pub struct DenseMatrix<T: FloatExt + Debug> {
|
||||
|
||||
ncols: usize,
|
||||
nrows: usize,
|
||||
values: Vec<f64>
|
||||
values: Vec<T>
|
||||
|
||||
}
|
||||
|
||||
impl fmt::Display for DenseMatrix {
|
||||
impl<T: FloatExt + Debug> 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 * 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 DenseMatrix {
|
||||
impl<T: FloatExt + Debug> DenseMatrix<T> {
|
||||
|
||||
fn new(nrows: usize, ncols: usize, values: Vec<f64>) -> DenseMatrix {
|
||||
fn new(nrows: usize, ncols: usize, values: Vec<T>) -> Self {
|
||||
DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
@@ -38,17 +39,17 @@ impl DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_array(values: &[&[f64]]) -> DenseMatrix {
|
||||
pub fn from_array(values: &[&[T]]) -> Self {
|
||||
DenseMatrix::from_vec(&values.into_iter().map(|row| Vec::from(*row)).collect())
|
||||
}
|
||||
|
||||
pub fn from_vec(values: &Vec<Vec<f64>>) -> DenseMatrix {
|
||||
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 mut m = DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
values: vec![0f64; ncols*nrows]
|
||||
values: vec![T::zero(); ncols*nrows]
|
||||
};
|
||||
for row in 0..nrows {
|
||||
for col in 0..ncols {
|
||||
@@ -58,11 +59,11 @@ impl DenseMatrix {
|
||||
m
|
||||
}
|
||||
|
||||
pub fn vector_from_array(values: &[f64]) -> DenseMatrix {
|
||||
pub fn vector_from_array(values: &[T]) -> Self {
|
||||
DenseMatrix::vector_from_vec(Vec::from(values))
|
||||
}
|
||||
|
||||
pub fn vector_from_vec(values: Vec<f64>) -> DenseMatrix {
|
||||
pub fn vector_from_vec(values: Vec<T>) -> Self {
|
||||
DenseMatrix {
|
||||
ncols: values.len(),
|
||||
nrows: 1,
|
||||
@@ -70,31 +71,31 @@ impl DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn div_mut(&mut self, b: DenseMatrix) -> () {
|
||||
pub fn div_mut(&mut self, b: Self) -> () {
|
||||
if self.nrows != b.nrows || self.ncols != b.ncols {
|
||||
panic!("Can't divide matrices of different sizes.");
|
||||
}
|
||||
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] /= b.values[i];
|
||||
self.values[i] = self.values[i] / b.values[i];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_raw_values(&self) -> &Vec<f64> {
|
||||
pub fn get_raw_values(&self) -> &Vec<T> {
|
||||
&self.values
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl SVDDecomposableMatrix for DenseMatrix {}
|
||||
impl<T: FloatExt + Debug> SVDDecomposableMatrix<T> for DenseMatrix<T> {}
|
||||
|
||||
impl EVDDecomposableMatrix for DenseMatrix {}
|
||||
impl<T: FloatExt + Debug> EVDDecomposableMatrix<T> for DenseMatrix<T> {}
|
||||
|
||||
impl QRDecomposableMatrix for DenseMatrix {}
|
||||
impl<T: FloatExt + Debug> QRDecomposableMatrix<T> for DenseMatrix<T> {}
|
||||
|
||||
impl Matrix for DenseMatrix {}
|
||||
impl<T: FloatExt + Debug> Matrix<T> for DenseMatrix<T> {}
|
||||
|
||||
impl PartialEq for DenseMatrix {
|
||||
impl<T: FloatExt + Debug> PartialEq for DenseMatrix<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
return false
|
||||
@@ -108,7 +109,7 @@ impl PartialEq for DenseMatrix {
|
||||
}
|
||||
|
||||
for i in 0..len {
|
||||
if (self.values[i] - other.values[i]).abs() > math::EPSILON {
|
||||
if (self.values[i] - other.values[i]).abs() > T::epsilon() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -117,15 +118,15 @@ impl PartialEq for DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Vec<f64>> for DenseMatrix {
|
||||
fn into(self) -> Vec<f64> {
|
||||
impl<T: FloatExt + Debug> Into<Vec<T>> for DenseMatrix<T> {
|
||||
fn into(self) -> Vec<T> {
|
||||
self.values
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseMatrix for DenseMatrix {
|
||||
impl<T: FloatExt + Debug> BaseMatrix<T> for DenseMatrix<T> {
|
||||
|
||||
type RowVector = Vec<f64>;
|
||||
type RowVector = Vec<T>;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self{
|
||||
DenseMatrix::new(1, vec.len(), vec)
|
||||
@@ -135,50 +136,50 @@ impl BaseMatrix for DenseMatrix {
|
||||
self.to_raw_vector()
|
||||
}
|
||||
|
||||
fn get(&self, row: usize, col: usize) -> f64 {
|
||||
fn get(&self, row: usize, col: usize) -> T {
|
||||
self.values[col*self.nrows + row]
|
||||
}
|
||||
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<f64>{
|
||||
let mut result = vec![0f64; self.ncols];
|
||||
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);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<f64>{
|
||||
let mut result = vec![0f64; self.nrows];
|
||||
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: f64) {
|
||||
fn set(&mut self, row: usize, col: usize, x: T) {
|
||||
self.values[col*self.nrows + row] = x;
|
||||
}
|
||||
|
||||
fn zeros(nrows: usize, ncols: usize) -> DenseMatrix {
|
||||
DenseMatrix::fill(nrows, ncols, 0f64)
|
||||
fn zeros(nrows: usize, ncols: usize) -> Self {
|
||||
DenseMatrix::fill(nrows, ncols, T::zero())
|
||||
}
|
||||
|
||||
fn ones(nrows: usize, ncols: usize) -> DenseMatrix {
|
||||
DenseMatrix::fill(nrows, ncols, 1f64)
|
||||
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);
|
||||
|
||||
for i in 0..size {
|
||||
matrix.set(i, i, 1.0);
|
||||
matrix.set(i, i, T::one());
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
fn to_raw_vector(&self) -> Vec<f64>{
|
||||
let mut v = vec![0.; self.nrows * self.ncols];
|
||||
fn to_raw_vector(&self) -> Vec<T>{
|
||||
let mut v = vec![T::zero(); self.nrows * self.ncols];
|
||||
|
||||
for r in 0..self.nrows{
|
||||
for c in 0..self.ncols {
|
||||
@@ -197,7 +198,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
if self.ncols != other.ncols {
|
||||
panic!("Number of columns in both matrices should be equal");
|
||||
}
|
||||
let mut result = DenseMatrix::zeros(self.nrows + other.nrows, self.ncols);
|
||||
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 {
|
||||
@@ -214,7 +215,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
if self.nrows != other.nrows {
|
||||
panic!("Number of rows in both matrices should be equal");
|
||||
}
|
||||
let mut result = DenseMatrix::zeros(self.nrows, self.ncols + other.ncols);
|
||||
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 {
|
||||
@@ -233,13 +234,13 @@ impl BaseMatrix for DenseMatrix {
|
||||
panic!("Number of rows of A should equal number of columns of B");
|
||||
}
|
||||
let inner_d = self.ncols;
|
||||
let mut result = DenseMatrix::zeros(self.nrows, other.ncols);
|
||||
let mut result = Self::zeros(self.nrows, other.ncols);
|
||||
|
||||
for r in 0..self.nrows {
|
||||
for c in 0..other.ncols {
|
||||
let mut s = 0f64;
|
||||
let mut s = T::zero();
|
||||
for i in 0..inner_d {
|
||||
s += self.get(r, i) * other.get(i, c);
|
||||
s = s + self.get(r, i) * other.get(i, c);
|
||||
}
|
||||
result.set(r, c, s);
|
||||
}
|
||||
@@ -248,7 +249,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
result
|
||||
}
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> f64 {
|
||||
fn vector_dot(&self, other: &Self) -> T {
|
||||
if (self.nrows != 1 || self.nrows != 1) && (other.nrows != 1 || other.ncols != 1) {
|
||||
panic!("A and B should both be 1-dimentional vectors.");
|
||||
}
|
||||
@@ -256,20 +257,20 @@ impl BaseMatrix for DenseMatrix {
|
||||
panic!("A and B should have the same size");
|
||||
}
|
||||
|
||||
let mut result = 0f64;
|
||||
let mut result = T::zero();
|
||||
for i in 0..(self.nrows * self.ncols) {
|
||||
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>) -> DenseMatrix {
|
||||
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self {
|
||||
|
||||
let ncols = cols.len();
|
||||
let nrows = rows.len();
|
||||
|
||||
let mut m = DenseMatrix::new(nrows, ncols, vec![0f64; nrows * ncols]);
|
||||
let mut m = DenseMatrix::new(nrows, ncols, vec![T::zero(); nrows * ncols]);
|
||||
|
||||
for r in rows.start..rows.end {
|
||||
for c in cols.start..cols.end {
|
||||
@@ -280,7 +281,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
m
|
||||
}
|
||||
|
||||
fn approximate_eq(&self, other: &Self, error: f64) -> bool {
|
||||
fn approximate_eq(&self, other: &Self, error: T) -> bool {
|
||||
if self.ncols != other.ncols || self.nrows != other.nrows {
|
||||
return false
|
||||
}
|
||||
@@ -296,7 +297,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
true
|
||||
}
|
||||
|
||||
fn fill(nrows: usize, ncols: usize, value: f64) -> Self {
|
||||
fn fill(nrows: usize, ncols: usize, value: T) -> Self {
|
||||
DenseMatrix::new(nrows, ncols, vec![value; ncols * nrows])
|
||||
}
|
||||
|
||||
@@ -352,27 +353,27 @@ impl BaseMatrix for DenseMatrix {
|
||||
self
|
||||
}
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: f64) {
|
||||
self.values[col*self.nrows + row] /= x;
|
||||
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;
|
||||
}
|
||||
|
||||
fn mul_element_mut(&mut self, row: usize, col: usize, x: f64) {
|
||||
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;
|
||||
}
|
||||
|
||||
fn add_element_mut(&mut self, row: usize, col: usize, x: f64) {
|
||||
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
|
||||
}
|
||||
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: f64) {
|
||||
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;
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self {
|
||||
let mut m = DenseMatrix {
|
||||
ncols: self.nrows,
|
||||
nrows: self.ncols,
|
||||
values: vec![0f64; self.ncols * self.nrows]
|
||||
values: vec![T::zero(); self.ncols * self.nrows]
|
||||
};
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
@@ -383,10 +384,9 @@ impl BaseMatrix for DenseMatrix {
|
||||
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
let values: Vec<f64> = (0..nrows*ncols).map(|_| {
|
||||
rng.gen()
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let values: Vec<T> = (0..nrows*ncols).map(|_| {
|
||||
T::rand()
|
||||
}).collect();
|
||||
DenseMatrix {
|
||||
ncols: ncols,
|
||||
@@ -395,74 +395,74 @@ impl BaseMatrix for DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
fn norm2(&self) -> f64 {
|
||||
let mut norm = 0f64;
|
||||
fn norm2(&self) -> T {
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.values.iter() {
|
||||
norm += xi * xi;
|
||||
norm = norm + *xi * *xi;
|
||||
}
|
||||
|
||||
norm.sqrt()
|
||||
}
|
||||
|
||||
fn norm(&self, p:f64) -> f64 {
|
||||
fn norm(&self, p:T) -> T {
|
||||
|
||||
if p.is_infinite() && p.is_sign_positive() {
|
||||
self.values.iter().map(|x| x.abs()).fold(std::f64::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(std::f64::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 = 0f64;
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.values.iter() {
|
||||
norm += xi.abs().powf(p);
|
||||
norm = norm + xi.abs().powf(p);
|
||||
}
|
||||
|
||||
norm.powf(1.0/p)
|
||||
norm.powf(T::one()/p)
|
||||
}
|
||||
}
|
||||
|
||||
fn column_mean(&self) -> Vec<f64> {
|
||||
let mut mean = vec![0f64; self.ncols];
|
||||
fn column_mean(&self) -> Vec<T> {
|
||||
let mut mean = vec![T::zero(); self.ncols];
|
||||
|
||||
for r in 0..self.nrows {
|
||||
for c in 0..self.ncols {
|
||||
mean[c] += self.get(r, c);
|
||||
mean[c] = mean[c] + self.get(r, c);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..mean.len() {
|
||||
mean[i] /= self.nrows as f64;
|
||||
mean[i] = mean[i] / T::from(self.nrows).unwrap();
|
||||
}
|
||||
|
||||
mean
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] += scalar;
|
||||
self.values[i] = self.values[i] + scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] -= scalar;
|
||||
self.values[i] = self.values[i] - scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] *= scalar;
|
||||
self.values[i] = self.values[i] * scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] /= scalar;
|
||||
self.values[i] = self.values[i] / scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
@@ -512,8 +512,8 @@ impl BaseMatrix for DenseMatrix {
|
||||
self
|
||||
}
|
||||
|
||||
fn max_diff(&self, other: &Self) -> f64{
|
||||
let mut max_diff = 0f64;
|
||||
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());
|
||||
}
|
||||
@@ -521,22 +521,22 @@ impl BaseMatrix for DenseMatrix {
|
||||
|
||||
}
|
||||
|
||||
fn sum(&self) -> f64 {
|
||||
let mut sum = 0.;
|
||||
fn sum(&self) -> T {
|
||||
let mut sum = T::zero();
|
||||
for i in 0..self.values.len() {
|
||||
sum += self.values[i];
|
||||
sum = sum + self.values[i];
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
fn softmax_mut(&mut self) {
|
||||
let max = self.values.iter().map(|x| x.abs()).fold(std::f64::NEG_INFINITY, |a, b| a.max(b));
|
||||
let mut z = 0.;
|
||||
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 {
|
||||
let p = (self.get(r, c) - max).exp();
|
||||
self.set(r, c, p);
|
||||
z += p;
|
||||
z = z + p;
|
||||
}
|
||||
}
|
||||
for r in 0..self.nrows {
|
||||
@@ -546,7 +546,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
fn pow_mut(&mut self, p: f64) -> &Self {
|
||||
fn pow_mut(&mut self, p: T) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = self.values[i].powf(p);
|
||||
}
|
||||
@@ -558,7 +558,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
let mut res = vec![0usize; self.nrows];
|
||||
|
||||
for r in 0..self.nrows {
|
||||
let mut max = std::f64::NEG_INFINITY;
|
||||
let mut max = T::neg_infinity();
|
||||
let mut max_pos = 0usize;
|
||||
for c in 0..self.ncols {
|
||||
let v = self.get(r, c);
|
||||
@@ -574,7 +574,7 @@ impl BaseMatrix for DenseMatrix {
|
||||
|
||||
}
|
||||
|
||||
fn unique(&self) -> Vec<f64> {
|
||||
fn unique(&self) -> Vec<T> {
|
||||
let mut result = self.values.clone();
|
||||
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
result.dedup();
|
||||
@@ -698,7 +698,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rand() {
|
||||
let m = DenseMatrix::rand(3, 3);
|
||||
let m: DenseMatrix<f64> = DenseMatrix::rand(3, 3);
|
||||
for c in 0..3 {
|
||||
for r in 0..3 {
|
||||
assert!(m.get(r, c) != 0f64);
|
||||
@@ -742,7 +742,7 @@ mod tests {
|
||||
#[test]
|
||||
fn softmax_mut() {
|
||||
|
||||
let mut prob = DenseMatrix::vector_from_array(&[1., 2., 3.]);
|
||||
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);
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
use std::ops::Range;
|
||||
use std::fmt::Debug;
|
||||
use std::iter::Sum;
|
||||
use std::ops::AddAssign;
|
||||
use std::ops::SubAssign;
|
||||
use std::ops::MulAssign;
|
||||
use std::ops::DivAssign;
|
||||
|
||||
use ndarray::{Array, ArrayBase, OwnedRepr, Ix2, Ix1, Axis, stack, s};
|
||||
use ndarray::ScalarOperand;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::linalg::Matrix;
|
||||
use crate::linalg::svd::SVDDecomposableMatrix;
|
||||
use crate::linalg::evd::EVDDecomposableMatrix;
|
||||
use crate::linalg::qr::QRDecomposableMatrix;
|
||||
use ndarray::{Array, ArrayBase, OwnedRepr, Ix2, Ix1, Axis, stack, s};
|
||||
use rand::prelude::*;
|
||||
|
||||
impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
|
||||
impl<T: FloatExt + Debug + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> BaseMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2>
|
||||
{
|
||||
type RowVector = ArrayBase<OwnedRepr<f64>, Ix1>;
|
||||
type RowVector = ArrayBase<OwnedRepr<T>, Ix1>;
|
||||
|
||||
fn from_row_vector(vec: Self::RowVector) -> Self{
|
||||
let vec_size = vec.len();
|
||||
@@ -21,19 +31,19 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self.into_shape(vec_size).unwrap()
|
||||
}
|
||||
|
||||
fn get(&self, row: usize, col: usize) -> f64 {
|
||||
fn get(&self, row: usize, col: usize) -> T {
|
||||
self[[row, col]]
|
||||
}
|
||||
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<f64> {
|
||||
fn get_row_as_vec(&self, row: usize) -> Vec<T> {
|
||||
self.row(row).to_vec()
|
||||
}
|
||||
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<f64> {
|
||||
fn get_col_as_vec(&self, col: usize) -> Vec<T> {
|
||||
self.column(col).to_vec()
|
||||
}
|
||||
|
||||
fn set(&mut self, row: usize, col: usize, x: f64) {
|
||||
fn set(&mut self, row: usize, col: usize, x: T) {
|
||||
self[[row, col]] = x;
|
||||
}
|
||||
|
||||
@@ -49,11 +59,11 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
Array::ones((nrows, ncols))
|
||||
}
|
||||
|
||||
fn to_raw_vector(&self) -> Vec<f64> {
|
||||
fn to_raw_vector(&self) -> Vec<T> {
|
||||
self.to_owned().iter().map(|v| *v).collect()
|
||||
}
|
||||
|
||||
fn fill(nrows: usize, ncols: usize, value: f64) -> Self {
|
||||
fn fill(nrows: usize, ncols: usize, value: T) -> Self {
|
||||
Array::from_elem((nrows, ncols), value)
|
||||
}
|
||||
|
||||
@@ -73,7 +83,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self.dot(other)
|
||||
}
|
||||
|
||||
fn vector_dot(&self, other: &Self) -> f64 {
|
||||
fn vector_dot(&self, other: &Self) -> T {
|
||||
self.dot(&other.view().reversed_axes())[[0, 0]]
|
||||
}
|
||||
|
||||
@@ -81,7 +91,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self.slice(s![rows, cols]).to_owned()
|
||||
}
|
||||
|
||||
fn approximate_eq(&self, other: &Self, error: f64) -> bool {
|
||||
fn approximate_eq(&self, other: &Self, error: T) -> bool {
|
||||
(self - other).iter().all(|v| v.abs() <= error)
|
||||
}
|
||||
|
||||
@@ -105,22 +115,22 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) -> &Self{
|
||||
fn add_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
*self += scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) -> &Self{
|
||||
fn sub_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
*self -= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) -> &Self{
|
||||
fn mul_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
*self *= scalar;
|
||||
self
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) -> &Self{
|
||||
fn div_scalar_mut(&mut self, scalar: T) -> &Self{
|
||||
*self /= scalar;
|
||||
self
|
||||
}
|
||||
@@ -129,21 +139,20 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self.clone().reversed_axes()
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self{
|
||||
let mut rng = rand::thread_rng();
|
||||
let values: Vec<f64> = (0..nrows*ncols).map(|_| {
|
||||
rng.gen()
|
||||
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) -> f64{
|
||||
self.iter().map(|x| x * x).sum::<f64>().sqrt()
|
||||
fn norm2(&self) -> T{
|
||||
self.iter().map(|x| *x * *x).sum::<T>().sqrt()
|
||||
}
|
||||
|
||||
fn norm(&self, p:f64) -> f64 {
|
||||
fn norm(&self, p:T) -> T {
|
||||
if p.is_infinite() && p.is_sign_positive() {
|
||||
self.iter().fold(std::f64::NEG_INFINITY, |f, &val| {
|
||||
self.iter().fold(T::neg_infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
if f > v {
|
||||
f
|
||||
@@ -152,7 +161,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
}
|
||||
})
|
||||
} else if p.is_infinite() && p.is_sign_negative() {
|
||||
self.iter().fold(std::f64::INFINITY, |f, &val| {
|
||||
self.iter().fold(T::infinity(), |f, &val| {
|
||||
let v = val.abs();
|
||||
if f < v {
|
||||
f
|
||||
@@ -162,38 +171,38 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
})
|
||||
} else {
|
||||
|
||||
let mut norm = 0f64;
|
||||
let mut norm = T::zero();
|
||||
|
||||
for xi in self.iter() {
|
||||
norm += xi.abs().powf(p);
|
||||
norm = norm + xi.abs().powf(p);
|
||||
}
|
||||
|
||||
norm.powf(1.0/p)
|
||||
norm.powf(T::one()/p)
|
||||
}
|
||||
}
|
||||
|
||||
fn column_mean(&self) -> Vec<f64> {
|
||||
fn column_mean(&self) -> Vec<T> {
|
||||
self.mean_axis(Axis(0)).unwrap().to_vec()
|
||||
}
|
||||
|
||||
fn div_element_mut(&mut self, row: usize, col: usize, x: f64){
|
||||
self[[row, col]] /= x;
|
||||
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: f64){
|
||||
self[[row, col]] *= x;
|
||||
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: f64){
|
||||
self[[row, col]] += x;
|
||||
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: f64){
|
||||
self[[row, col]] -= x;
|
||||
fn sub_element_mut(&mut self, row: usize, col: usize, x: T){
|
||||
self[[row, col]] = self[[row, col]] - x;
|
||||
}
|
||||
|
||||
fn negative_mut(&mut self){
|
||||
*self *= -1.;
|
||||
*self *= -T::one();
|
||||
}
|
||||
|
||||
fn reshape(&self, nrows: usize, ncols: usize) -> Self{
|
||||
@@ -208,12 +217,12 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
self
|
||||
}
|
||||
|
||||
fn sum(&self) -> f64{
|
||||
fn sum(&self) -> T{
|
||||
self.sum()
|
||||
}
|
||||
|
||||
fn max_diff(&self, other: &Self) -> f64{
|
||||
let mut max_diff = 0f64;
|
||||
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());
|
||||
@@ -223,13 +232,13 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
}
|
||||
|
||||
fn softmax_mut(&mut self){
|
||||
let max = self.iter().map(|x| x.abs()).fold(std::f64::NEG_INFINITY, |a, b| a.max(b));
|
||||
let mut z = 0.;
|
||||
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() {
|
||||
let p = (self[(r, c)] - max).exp();
|
||||
self.set(r, c, p);
|
||||
z += p;
|
||||
z = z + p;
|
||||
}
|
||||
}
|
||||
for r in 0..self.nrows() {
|
||||
@@ -239,7 +248,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
}
|
||||
}
|
||||
|
||||
fn pow_mut(&mut self, p: f64) -> &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));
|
||||
@@ -252,7 +261,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
let mut res = vec![0usize; self.nrows()];
|
||||
|
||||
for r in 0..self.nrows() {
|
||||
let mut max = std::f64::NEG_INFINITY;
|
||||
let mut max = T::neg_infinity();
|
||||
let mut max_pos = 0usize;
|
||||
for c in 0..self.ncols() {
|
||||
let v = self[(r, c)];
|
||||
@@ -268,7 +277,7 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
|
||||
}
|
||||
|
||||
fn unique(&self) -> Vec<f64> {
|
||||
fn unique(&self) -> Vec<T> {
|
||||
let mut result = self.clone().into_raw_vec();
|
||||
result.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
result.dedup();
|
||||
@@ -277,13 +286,13 @@ impl BaseMatrix for ArrayBase<OwnedRepr<f64>, Ix2>
|
||||
|
||||
}
|
||||
|
||||
impl SVDDecomposableMatrix for ArrayBase<OwnedRepr<f64>, Ix2> {}
|
||||
impl<T: FloatExt + Debug + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> SVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
|
||||
impl EVDDecomposableMatrix for ArrayBase<OwnedRepr<f64>, Ix2> {}
|
||||
impl<T: FloatExt + Debug + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> EVDDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
|
||||
impl QRDecomposableMatrix for ArrayBase<OwnedRepr<f64>, Ix2> {}
|
||||
impl<T: FloatExt + Debug + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> QRDecomposableMatrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
|
||||
impl Matrix for ArrayBase<OwnedRepr<f64>, Ix2> {}
|
||||
impl<T: FloatExt + Debug + ScalarOperand + AddAssign + SubAssign + MulAssign + DivAssign + Sum> Matrix<T> for ArrayBase<OwnedRepr<T>, Ix2> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@@ -541,7 +550,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn softmax_mut(){
|
||||
let mut prob = arr2(&[[1., 2., 3.]]);
|
||||
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);
|
||||
|
||||
+24
-21
@@ -1,20 +1,23 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::math::num::FloatExt;
|
||||
use crate::linalg::BaseMatrix;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QR<M: BaseMatrix> {
|
||||
pub struct QR<T: FloatExt + Debug, M: BaseMatrix<T>> {
|
||||
QR: M,
|
||||
tau: Vec<f64>,
|
||||
tau: Vec<T>,
|
||||
singular: bool
|
||||
}
|
||||
|
||||
impl<M: BaseMatrix> QR<M> {
|
||||
pub fn new(QR: M, tau: Vec<f64>) -> QR<M> {
|
||||
impl<T: FloatExt + Debug, 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] == 0. {
|
||||
if tau[j] == T::zero() {
|
||||
singular = true;
|
||||
break;
|
||||
}
|
||||
@@ -44,12 +47,12 @@ impl<M: BaseMatrix> QR<M> {
|
||||
let mut Q = M::zeros(m, n);
|
||||
let mut k = n - 1;
|
||||
loop {
|
||||
Q.set(k, k, 1.0);
|
||||
Q.set(k, k, T::one());
|
||||
for j in k..n {
|
||||
if self.QR.get(k, k) != 0f64 {
|
||||
let mut s = 0f64;
|
||||
if self.QR.get(k, k) != T::zero() {
|
||||
let mut s = T::zero();
|
||||
for i in k..m {
|
||||
s += self.QR.get(i, k) * Q.get(i, j);
|
||||
s = s + self.QR.get(i, k) * Q.get(i, j);
|
||||
}
|
||||
s = -s / self.QR.get(k, k);
|
||||
for i in k..m {
|
||||
@@ -81,9 +84,9 @@ impl<M: BaseMatrix> QR<M> {
|
||||
|
||||
for k in 0..n {
|
||||
for j in 0..b_ncols {
|
||||
let mut s = 0f64;
|
||||
let mut s = T::zero();
|
||||
for i in k..m {
|
||||
s += self.QR.get(i, k) * b.get(i, j);
|
||||
s = s + self.QR.get(i, k) * b.get(i, j);
|
||||
}
|
||||
s = -s / self.QR.get(k, k);
|
||||
for i in k..m {
|
||||
@@ -109,38 +112,38 @@ impl<M: BaseMatrix> QR<M> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait QRDecomposableMatrix: BaseMatrix {
|
||||
pub trait QRDecomposableMatrix<T: FloatExt + Debug>: BaseMatrix<T> {
|
||||
|
||||
fn qr(&self) -> QR<Self> {
|
||||
fn qr(&self) -> QR<T, Self> {
|
||||
self.clone().qr_mut()
|
||||
}
|
||||
|
||||
fn qr_mut(mut self) -> QR<Self> {
|
||||
fn qr_mut(mut self) -> QR<T, Self> {
|
||||
|
||||
let (m, n) = self.shape();
|
||||
|
||||
let mut r_diagonal: Vec<f64> = vec![0f64; n];
|
||||
let mut r_diagonal: Vec<T> = vec![T::zero(); n];
|
||||
|
||||
for k in 0..n {
|
||||
let mut nrm = 0f64;
|
||||
let mut nrm = T::zero();
|
||||
for i in k..m {
|
||||
nrm = nrm.hypot(self.get(i, k));
|
||||
}
|
||||
|
||||
if nrm.abs() > std::f64::EPSILON {
|
||||
if nrm.abs() > T::epsilon() {
|
||||
|
||||
if self.get(k, k) < 0f64 {
|
||||
if self.get(k, k) < T::zero() {
|
||||
nrm = -nrm;
|
||||
}
|
||||
for i in k..m {
|
||||
self.div_element_mut(i, k, nrm);
|
||||
}
|
||||
self.add_element_mut(k, k, 1f64);
|
||||
self.add_element_mut(k, k, T::one());
|
||||
|
||||
for j in k+1..n {
|
||||
let mut s = 0f64;
|
||||
let mut s = T::zero();
|
||||
for i in k..m {
|
||||
s += self.get(i, k) * self.get(i, j);
|
||||
s = s + self.get(i, k) * self.get(i, j);
|
||||
}
|
||||
s = -s / self.get(k, k);
|
||||
for i in k..m {
|
||||
|
||||
+72
-70
@@ -1,19 +1,21 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::linalg::BaseMatrix;
|
||||
use crate::math::num::FloatExt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SVD<M: SVDDecomposableMatrix> {
|
||||
pub struct SVD<T: FloatExt + Debug, M: SVDDecomposableMatrix<T>> {
|
||||
pub U: M,
|
||||
pub V: M,
|
||||
pub s: Vec<f64>,
|
||||
pub s: Vec<T>,
|
||||
full: bool,
|
||||
m: usize,
|
||||
n: usize,
|
||||
tol: f64
|
||||
tol: T
|
||||
}
|
||||
|
||||
pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
pub trait SVDDecomposableMatrix<T: FloatExt + Debug>: BaseMatrix<T> {
|
||||
|
||||
fn svd_solve_mut(self, b: Self) -> Self {
|
||||
self.svd_mut().solve(b)
|
||||
@@ -23,50 +25,50 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
self.svd().solve(b)
|
||||
}
|
||||
|
||||
fn svd(&self) -> SVD<Self> {
|
||||
fn svd(&self) -> SVD<T, Self> {
|
||||
self.clone().svd_mut()
|
||||
}
|
||||
|
||||
fn svd_mut(self) -> SVD<Self> {
|
||||
fn svd_mut(self) -> SVD<T, Self> {
|
||||
|
||||
let mut U = self;
|
||||
|
||||
let (m, n) = U.shape();
|
||||
|
||||
let (mut l, mut nm) = (0usize, 0usize);
|
||||
let (mut anorm, mut g, mut scale) = (0f64, 0f64, 0f64);
|
||||
let (mut anorm, mut g, mut scale) = (T::zero(), T::zero(), T::zero());
|
||||
|
||||
let mut v = Self::zeros(n, n);
|
||||
let mut w = vec![0f64; n];
|
||||
let mut rv1 = vec![0f64; n];
|
||||
let mut w = vec![T::zero(); n];
|
||||
let mut rv1 = vec![T::zero(); n];
|
||||
|
||||
for i in 0..n {
|
||||
l = i + 2;
|
||||
rv1[i] = scale * g;
|
||||
g = 0f64;
|
||||
let mut s = 0f64;
|
||||
scale = 0f64;
|
||||
g = T::zero();
|
||||
let mut s = T::zero();
|
||||
scale = T::zero();
|
||||
|
||||
if i < m {
|
||||
for k in i..m {
|
||||
scale += U.get(k, i).abs();
|
||||
scale = scale + U.get(k, i).abs();
|
||||
}
|
||||
|
||||
if scale.abs() > std::f64::EPSILON {
|
||||
if scale.abs() > T::epsilon() {
|
||||
|
||||
for k in i..m {
|
||||
U.div_element_mut(k, i, scale);
|
||||
s += U.get(k, i) * U.get(k, i);
|
||||
s = s + U.get(k, i) * U.get(k, i);
|
||||
}
|
||||
|
||||
let mut f = U.get(i, i);
|
||||
g = -s.sqrt().copysign(f);
|
||||
g = -s.sqrt().copysign(f);
|
||||
let h = f * g - s;
|
||||
U.set(i, i, f - g);
|
||||
for j in l - 1..n {
|
||||
s = 0f64;
|
||||
s = T::zero();
|
||||
for k in i..m {
|
||||
s += U.get(k, i) * U.get(k, j);
|
||||
s = s + U.get(k, i) * U.get(k, j);
|
||||
}
|
||||
f = s / h;
|
||||
for k in i..m {
|
||||
@@ -80,19 +82,19 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
|
||||
w[i] = scale * g;
|
||||
g = 0f64;
|
||||
let mut s = 0f64;
|
||||
scale = 0f64;
|
||||
g = T::zero();
|
||||
let mut s = T::zero();
|
||||
scale = T::zero();
|
||||
|
||||
if i + 1 <= m && i + 1 != n {
|
||||
for k in l - 1..n {
|
||||
scale += U.get(i, k).abs();
|
||||
scale = scale + U.get(i, k).abs();
|
||||
}
|
||||
|
||||
if scale.abs() > std::f64::EPSILON {
|
||||
if scale.abs() > T::epsilon() {
|
||||
for k in l - 1..n {
|
||||
U.div_element_mut(i, k, scale);
|
||||
s += U.get(i, k) * U.get(i, k);
|
||||
s = s + U.get(i, k) * U.get(i, k);
|
||||
}
|
||||
|
||||
let f = U.get(i, l - 1);
|
||||
@@ -105,9 +107,9 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
|
||||
for j in l - 1..m {
|
||||
s = 0f64;
|
||||
s = T::zero();
|
||||
for k in l - 1..n {
|
||||
s += U.get(j, k) * U.get(i, k);
|
||||
s = s + U.get(j, k) * U.get(i, k);
|
||||
}
|
||||
|
||||
for k in l - 1..n {
|
||||
@@ -122,19 +124,19 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
|
||||
|
||||
anorm = f64::max(anorm, w[i].abs() + rv1[i].abs());
|
||||
anorm = T::max(anorm, w[i].abs() + rv1[i].abs());
|
||||
}
|
||||
|
||||
for i in (0..n).rev() {
|
||||
if i < n - 1 {
|
||||
if g != 0.0 {
|
||||
if g != T::zero() {
|
||||
for j in l..n {
|
||||
v.set(j, i, (U.get(i, j) / U.get(i, l)) / g);
|
||||
}
|
||||
for j in l..n {
|
||||
let mut s = 0f64;
|
||||
let mut s = T::zero();
|
||||
for k in l..n {
|
||||
s += U.get(i, k) * v.get(k, j);
|
||||
s = s + U.get(i, k) * v.get(k, j);
|
||||
}
|
||||
for k in l..n {
|
||||
v.add_element_mut(k, j, s * v.get(k, i));
|
||||
@@ -142,11 +144,11 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
}
|
||||
for j in l..n {
|
||||
v.set(i, j, 0f64);
|
||||
v.set(j, i, 0f64);
|
||||
v.set(i, j, T::zero());
|
||||
v.set(j, i, T::zero());
|
||||
}
|
||||
}
|
||||
v.set(i, i, 1.0);
|
||||
v.set(i, i, T::one());
|
||||
g = rv1[i];
|
||||
l = i;
|
||||
}
|
||||
@@ -155,15 +157,15 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
l = i + 1;
|
||||
g = w[i];
|
||||
for j in l..n {
|
||||
U.set(i, j, 0f64);
|
||||
U.set(i, j, T::zero());
|
||||
}
|
||||
|
||||
if g.abs() > std::f64::EPSILON {
|
||||
g = 1f64 / g;
|
||||
if g.abs() > T::epsilon() {
|
||||
g = T::one() / g;
|
||||
for j in l..n {
|
||||
let mut s = 0f64;
|
||||
let mut s = T::zero();
|
||||
for k in l..m {
|
||||
s += U.get(k, i) * U.get(k, j);
|
||||
s = s + U.get(k, i) * U.get(k, j);
|
||||
}
|
||||
let f = (s / U.get(i, i)) * g;
|
||||
for k in i..m {
|
||||
@@ -175,11 +177,11 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
} else {
|
||||
for j in i..m {
|
||||
U.set(j, i, 0f64);
|
||||
U.set(j, i, T::zero());
|
||||
}
|
||||
}
|
||||
|
||||
U.add_element_mut(i, i, 1f64);
|
||||
U.add_element_mut(i, i, T::one());
|
||||
}
|
||||
|
||||
for k in (0..n).rev() {
|
||||
@@ -187,30 +189,30 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
let mut flag = true;
|
||||
l = k;
|
||||
while l != 0 {
|
||||
if l == 0 || rv1[l].abs() <= std::f64::EPSILON * anorm {
|
||||
if l == 0 || rv1[l].abs() <= T::epsilon() * anorm {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
nm = l - 1;
|
||||
if w[nm].abs() <= std::f64::EPSILON * anorm {
|
||||
if w[nm].abs() <= T::epsilon() * anorm {
|
||||
break;
|
||||
}
|
||||
l -= 1;
|
||||
}
|
||||
|
||||
if flag {
|
||||
let mut c = 0.0;
|
||||
let mut s = 1.0;
|
||||
let mut c = T::zero();
|
||||
let mut s = T::one();
|
||||
for i in l..k+1 {
|
||||
let f = s * rv1[i];
|
||||
rv1[i] = c * rv1[i];
|
||||
if f.abs() <= std::f64::EPSILON * anorm {
|
||||
if f.abs() <= T::epsilon() * anorm {
|
||||
break;
|
||||
}
|
||||
g = w[i];
|
||||
let mut h = f.hypot(g);
|
||||
w[i] = h;
|
||||
h = 1.0 / h;
|
||||
h = T::one() / h;
|
||||
c = g * h;
|
||||
s = -f * h;
|
||||
for j in 0..m {
|
||||
@@ -224,7 +226,7 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
|
||||
let z = w[k];
|
||||
if l == k {
|
||||
if z < 0f64 {
|
||||
if z < T::zero() {
|
||||
w[k] = -z;
|
||||
for j in 0..n {
|
||||
v.set(j, k, -v.get(j, k));
|
||||
@@ -242,11 +244,11 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
let mut y = w[nm];
|
||||
g = rv1[nm];
|
||||
let mut h = rv1[k];
|
||||
let mut f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
|
||||
g = f.hypot(1.0);
|
||||
let mut f = ((y - z) * (y + z) + (g - h) * (g + h)) / (T::two() * h * y);
|
||||
g = f.hypot(T::one());
|
||||
f = ((x - z) * (x + z) + h * ((y / (f + g.copysign(f))) - h)) / x;
|
||||
let mut c = 1f64;
|
||||
let mut s = 1f64;
|
||||
let mut c = T::one();
|
||||
let mut s = T::one();
|
||||
|
||||
for j in l..=nm {
|
||||
let i = j + 1;
|
||||
@@ -261,7 +263,7 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
f = x * c + g * s;
|
||||
g = g * c - x * s;
|
||||
h = y * s;
|
||||
y *= c;
|
||||
y = y * c;
|
||||
|
||||
for jj in 0..n {
|
||||
x = v.get(jj, j);
|
||||
@@ -272,8 +274,8 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
|
||||
z = f.hypot(h);
|
||||
w[j] = z;
|
||||
if z.abs() > std::f64::EPSILON {
|
||||
z = 1.0 / z;
|
||||
if z.abs() > T::epsilon() {
|
||||
z = T::one() / z;
|
||||
c = f * z;
|
||||
s = h * z;
|
||||
}
|
||||
@@ -288,15 +290,15 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
rv1[l] = 0.0;
|
||||
rv1[l] = T::zero();
|
||||
rv1[k] = f;
|
||||
w[k] = x;
|
||||
}
|
||||
}
|
||||
|
||||
let mut inc = 1usize;
|
||||
let mut su = vec![0f64; m];
|
||||
let mut sv = vec![0f64; n];
|
||||
let mut su = vec![T::zero(); m];
|
||||
let mut sv = vec![T::zero(); n];
|
||||
|
||||
loop {
|
||||
inc *= 3;
|
||||
@@ -347,12 +349,12 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
for k in 0..n {
|
||||
let mut s = 0.;
|
||||
for i in 0..m {
|
||||
if U.get(i, k) < 0. {
|
||||
if U.get(i, k) < T::zero() {
|
||||
s += 1.;
|
||||
}
|
||||
}
|
||||
for j in 0..n {
|
||||
if v.get(j, k) < 0. {
|
||||
if v.get(j, k) < T::zero() {
|
||||
s += 1.;
|
||||
}
|
||||
}
|
||||
@@ -371,12 +373,12 @@ pub trait SVDDecomposableMatrix: BaseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: SVDDecomposableMatrix> SVD<M> {
|
||||
pub fn new(U: M, V: M, s: Vec<f64>) -> SVD<M> {
|
||||
impl<T: FloatExt + Debug, 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 tol = 0.5 * ((m + n) as f64 + 1.).sqrt() * s[0] * std::f64::EPSILON;
|
||||
let tol = T::half() * (T::from(m + n).unwrap() + T::one()).sqrt() * s[0] * T::epsilon();
|
||||
SVD {
|
||||
U: U,
|
||||
V: V,
|
||||
@@ -396,22 +398,22 @@ impl<M: SVDDecomposableMatrix> SVD<M> {
|
||||
}
|
||||
|
||||
for k in 0..p {
|
||||
let mut tmp = vec![0f64; self.n];
|
||||
let mut tmp = vec![T::zero(); self.n];
|
||||
for j in 0..self.n {
|
||||
let mut r = 0f64;
|
||||
let mut r = T::zero();
|
||||
if self.s[j] > self.tol {
|
||||
for i in 0..self.m {
|
||||
r += self.U.get(i, j) * b.get(i, k);
|
||||
r = r + self.U.get(i, j) * b.get(i, k);
|
||||
}
|
||||
r /= self.s[j];
|
||||
r = r / self.s[j];
|
||||
}
|
||||
tmp[j] = r;
|
||||
}
|
||||
|
||||
for j in 0..self.n {
|
||||
let mut r = 0.0;
|
||||
let mut r = T::zero();
|
||||
for jj in 0..self.n {
|
||||
r += self.V.get(j, jj) * tmp[jj];
|
||||
r = r + self.V.get(j, jj) * tmp[jj];
|
||||
}
|
||||
b.set(j, k, r);
|
||||
}
|
||||
@@ -434,7 +436,7 @@ mod tests {
|
||||
&[0.4000, 0.5000, 0.3000],
|
||||
&[0.7000, 0.3000, 0.8000]]);
|
||||
|
||||
let s = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
let s: Vec<f64> = vec![1.7498382, 0.3165784, 0.1335834];
|
||||
|
||||
let U = DenseMatrix::from_array(&[
|
||||
&[0.6881997, -0.07121225, 0.7220180],
|
||||
@@ -471,7 +473,7 @@ mod tests {
|
||||
&[0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535, -0.2158704, -0.27529472]
|
||||
]);
|
||||
|
||||
let s = 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],
|
||||
|
||||
Reference in New Issue
Block a user