pub mod cholesky;
pub mod evd;
pub mod high_order;
pub mod lu;
pub mod naive;
#[cfg(feature = "nalgebra-bindings")]
pub mod nalgebra_bindings;
#[cfg(feature = "ndarray-bindings")]
pub mod ndarray_bindings;
pub mod qr;
pub mod stats;
pub mod svd;
use std::fmt::{Debug, Display};
use std::marker::PhantomData;
use std::ops::Range;
use crate::math::num::RealNumber;
use cholesky::CholeskyDecomposableMatrix;
use evd::EVDDecomposableMatrix;
use high_order::HighOrderOperations;
use lu::LUDecomposableMatrix;
use qr::QRDecomposableMatrix;
use stats::{MatrixPreprocessing, MatrixStats};
use svd::SVDDecomposableMatrix;
pub trait BaseVector<T: RealNumber>: Clone + Debug {
fn get(&self, i: usize) -> T;
fn set(&mut self, i: usize, x: T);
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn from_array(f: &[T]) -> Self {
let mut v = Self::zeros(f.len());
for (i, elem) in f.iter().enumerate() {
v.set(i, *elem);
}
v
}
fn to_vec(&self) -> Vec<T>;
fn zeros(len: usize) -> Self;
fn ones(len: usize) -> Self;
fn fill(len: usize, value: T) -> Self;
fn dot(&self, other: &Self) -> T;
fn approximate_eq(&self, other: &Self, error: T) -> bool;
fn norm2(&self) -> T;
fn norm(&self, p: T) -> T;
fn div_element_mut(&mut self, pos: usize, x: T);
fn mul_element_mut(&mut self, pos: usize, x: T);
fn add_element_mut(&mut self, pos: usize, x: T);
fn sub_element_mut(&mut self, pos: usize, x: T);
fn sub_scalar_mut(&mut self, x: T) -> &Self {
for i in 0..self.len() {
self.set(i, self.get(i) - x);
}
self
}
fn add_scalar_mut(&mut self, x: T) -> &Self {
for i in 0..self.len() {
self.set(i, self.get(i) + x);
}
self
}
fn mul_scalar_mut(&mut self, x: T) -> &Self {
for i in 0..self.len() {
self.set(i, self.get(i) * x);
}
self
}
fn div_scalar_mut(&mut self, x: T) -> &Self {
for i in 0..self.len() {
self.set(i, self.get(i) / x);
}
self
}
fn add_scalar(&self, x: T) -> Self {
let mut r = self.clone();
r.add_scalar_mut(x);
r
}
fn sub_scalar(&self, x: T) -> Self {
let mut r = self.clone();
r.sub_scalar_mut(x);
r
}
fn mul_scalar(&self, x: T) -> Self {
let mut r = self.clone();
r.mul_scalar_mut(x);
r
}
fn div_scalar(&self, x: T) -> Self {
let mut r = self.clone();
r.div_scalar_mut(x);
r
}
fn add_mut(&mut self, other: &Self) -> &Self;
fn sub_mut(&mut self, other: &Self) -> &Self;
fn mul_mut(&mut self, other: &Self) -> &Self;
fn div_mut(&mut self, other: &Self) -> &Self;
fn add(&self, other: &Self) -> Self {
let mut r = self.clone();
r.add_mut(other);
r
}
fn sub(&self, other: &Self) -> Self {
let mut r = self.clone();
r.sub_mut(other);
r
}
fn mul(&self, other: &Self) -> Self {
let mut r = self.clone();
r.mul_mut(other);
r
}
fn div(&self, other: &Self) -> Self {
let mut r = self.clone();
r.div_mut(other);
r
}
fn sum(&self) -> T;
fn unique(&self) -> Vec<T>;
fn mean(&self) -> T {
self.sum() / T::from_usize(self.len()).unwrap()
}
fn var(&self) -> T {
let n = self.len();
let mut mu = T::zero();
let mut sum = T::zero();
let div = T::from_usize(n).unwrap();
for i in 0..n {
let xi = self.get(i);
mu += xi;
sum += xi * xi;
}
mu /= div;
sum / div - mu * mu
}
fn std(&self) -> T {
self.var().sqrt()
}
fn copy_from(&mut self, other: &Self);
fn take(&self, index: &[usize]) -> Self {
let n = index.len();
let mut result = Self::zeros(n);
for (i, idx) in index.iter().enumerate() {
result.set(i, self.get(*idx));
}
result
}
}
pub trait BaseMatrix<T: RealNumber>: 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_row_as_vec(&self, row: usize) -> Vec<T>;
fn get_row(&self, row: usize) -> Self::RowVector;
fn copy_row_as_vec(&self, row: usize, result: &mut Vec<T>);
fn get_col_as_vec(&self, col: usize) -> Vec<T>;
fn copy_col_as_vec(&self, col: usize, result: &mut Vec<T>);
fn set(&mut self, row: usize, col: usize, x: T);
fn eye(size: usize) -> Self;
fn zeros(nrows: usize, ncols: usize) -> Self;
fn ones(nrows: usize, ncols: usize) -> Self;
fn fill(nrows: usize, ncols: usize, value: T) -> Self;
fn shape(&self) -> (usize, usize);
fn h_stack(&self, other: &Self) -> Self;
fn v_stack(&self, other: &Self) -> Self;
fn matmul(&self, other: &Self) -> Self;
fn dot(&self, other: &Self) -> T;
fn slice(&self, rows: Range<usize>, cols: Range<usize>) -> Self;
fn approximate_eq(&self, other: &Self, error: T) -> bool;
fn add_mut(&mut self, other: &Self) -> &Self;
fn sub_mut(&mut self, other: &Self) -> &Self;
fn mul_mut(&mut self, other: &Self) -> &Self;
fn div_mut(&mut self, other: &Self) -> &Self;
fn div_element_mut(&mut self, row: usize, col: usize, x: T);
fn mul_element_mut(&mut self, row: usize, col: usize, x: T);
fn add_element_mut(&mut self, row: usize, col: usize, x: T);
fn sub_element_mut(&mut self, row: usize, col: usize, x: T);
fn add(&self, other: &Self) -> Self {
let mut r = self.clone();
r.add_mut(other);
r
}
fn sub(&self, other: &Self) -> Self {
let mut r = self.clone();
r.sub_mut(other);
r
}
fn mul(&self, other: &Self) -> Self {
let mut r = self.clone();
r.mul_mut(other);
r
}
fn div(&self, other: &Self) -> Self {
let mut r = self.clone();
r.div_mut(other);
r
}
fn add_scalar_mut(&mut self, scalar: T) -> &Self;
fn sub_scalar_mut(&mut self, scalar: T) -> &Self;
fn mul_scalar_mut(&mut self, scalar: T) -> &Self;
fn div_scalar_mut(&mut 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 {
let mut r = self.clone();
r.sub_scalar_mut(scalar);
r
}
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 {
let mut r = self.clone();
r.div_scalar_mut(scalar);
r
}
fn transpose(&self) -> Self;
fn rand(nrows: usize, ncols: usize) -> Self;
fn norm2(&self) -> T;
fn norm(&self, p: T) -> T;
fn column_mean(&self) -> Vec<T>;
fn negative_mut(&mut self);
fn negative(&self) -> Self {
let mut result = self.clone();
result.negative_mut();
result
}
fn reshape(&self, nrows: usize, ncols: usize) -> Self;
fn copy_from(&mut self, other: &Self);
fn abs_mut(&mut self) -> &Self;
fn abs(&self) -> Self {
let mut result = self.clone();
result.abs_mut();
result
}
fn sum(&self) -> T;
fn max(&self) -> T;
fn min(&self) -> T;
fn max_diff(&self, other: &Self) -> T {
self.sub(other).abs().max()
}
fn softmax_mut(&mut self);
fn pow_mut(&mut self, p: T) -> &Self;
fn pow(&mut self, p: T) -> Self {
let mut result = self.clone();
result.pow_mut(p);
result
}
fn argmax(&self) -> Vec<usize>;
fn unique(&self) -> Vec<T>;
fn cov(&self) -> Self;
fn take(&self, index: &[usize], axis: u8) -> Self {
let (n, p) = self.shape();
let k = match axis {
0 => p,
_ => n,
};
let mut result = match axis {
0 => Self::zeros(index.len(), p),
_ => Self::zeros(n, index.len()),
};
for (i, idx) in index.iter().enumerate() {
for j in 0..k {
match axis {
0 => result.set(i, j, self.get(*idx, j)),
_ => result.set(j, i, self.get(j, *idx)),
};
}
}
result
}
}
pub trait Matrix<T: RealNumber>:
BaseMatrix<T>
+ SVDDecomposableMatrix<T>
+ EVDDecomposableMatrix<T>
+ QRDecomposableMatrix<T>
+ LUDecomposableMatrix<T>
+ CholeskyDecomposableMatrix<T>
+ MatrixStats<T>
+ MatrixPreprocessing<T>
+ HighOrderOperations<T>
+ PartialEq
+ Display
{
}
pub(crate) fn row_iter<F: RealNumber, M: BaseMatrix<F>>(m: &M) -> RowIter<'_, F, M> {
RowIter {
m,
pos: 0,
max_pos: m.shape().0,
phantom: PhantomData,
}
}
pub(crate) struct RowIter<'a, T: RealNumber, M: BaseMatrix<T>> {
m: &'a M,
pos: usize,
max_pos: usize,
phantom: PhantomData<&'a T>,
}
impl<'a, T: RealNumber, M: BaseMatrix<T>> Iterator for RowIter<'a, T, M> {
type Item = Vec<T>;
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))
} else {
res = None
}
self.pos += 1;
res
}
}
#[cfg(test)]
mod tests {
use crate::linalg::naive::dense_matrix::DenseMatrix;
use crate::linalg::BaseMatrix;
use crate::linalg::BaseVector;
#[test]
fn mean() {
let m = vec![1., 2., 3.];
assert_eq!(m.mean(), 2.0);
}
#[test]
fn std() {
let m = vec![1., 2., 3.];
assert!((m.std() - 0.81f64).abs() < 1e-2);
}
#[test]
fn var() {
let m = vec![1., 2., 3., 4.];
assert!((m.var() - 1.25f64).abs() < std::f64::EPSILON);
}
#[test]
fn vec_take() {
let m = vec![1., 2., 3., 4., 5.];
assert_eq!(m.take(&vec!(0, 0, 4, 4)), vec![1., 1., 5., 5.]);
}
#[test]
fn take() {
let m = DenseMatrix::from_2d_array(&[
&[1.0, 2.0],
&[3.0, 4.0],
&[5.0, 6.0],
&[7.0, 8.0],
&[9.0, 10.0],
]);
let expected_0 = DenseMatrix::from_2d_array(&[&[3.0, 4.0], &[3.0, 4.0], &[7.0, 8.0]]);
let expected_1 = DenseMatrix::from_2d_array(&[
&[2.0, 1.0],
&[4.0, 3.0],
&[6.0, 5.0],
&[8.0, 7.0],
&[10.0, 9.0],
]);
assert_eq!(m.take(&vec!(1, 1, 3), 0), expected_0);
assert_eq!(m.take(&vec!(1, 0), 1), expected_1);
}
}