use std;
use std::any::Any;
use std::marker::PhantomData;
use libnum::Float;
use error::{Error, ErrorKind};
use vector::Vector;
pub mod decomposition;
mod base;
mod deref;
mod impl_mat;
mod impl_ops;
mod iter;
mod mat_mul;
mod slice;
mod permutation_matrix;
mod impl_permutation_mul;
pub use self::base::{BaseMatrix, BaseMatrixMut};
pub use self::permutation_matrix::{PermutationMatrix, Parity};
#[derive(Debug, Clone, Copy)]
pub enum Axes {
Row,
Col,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Matrix<T> {
rows: usize,
cols: usize,
data: Vec<T>,
}
#[derive(Debug, Clone, Copy)]
pub struct MatrixSlice<'a, T: 'a> {
ptr: *const T,
rows: usize,
cols: usize,
row_stride: usize,
marker: PhantomData<&'a T>,
}
#[derive(Debug)]
pub struct MatrixSliceMut<'a, T: 'a> {
ptr: *mut T,
rows: usize,
cols: usize,
row_stride: usize,
marker: PhantomData<&'a mut T>,
}
#[derive(Debug, Clone, Copy)]
pub struct Row<'a, T: 'a> {
row: MatrixSlice<'a, T>,
}
#[derive(Debug)]
pub struct RowMut<'a, T: 'a> {
row: MatrixSliceMut<'a, T>,
}
#[derive(Debug)]
pub struct Rows<'a, T: 'a> {
slice_start: *const T,
row_pos: usize,
slice_rows: usize,
slice_cols: usize,
row_stride: isize,
_marker: PhantomData<&'a T>,
}
#[derive(Debug)]
pub struct RowsMut<'a, T: 'a> {
slice_start: *mut T,
row_pos: usize,
slice_rows: usize,
slice_cols: usize,
row_stride: isize,
_marker: PhantomData<&'a mut T>,
}
impl<'a, T: 'a> Row<'a, T> {
pub fn raw_slice(&self) -> &'a [T] {
unsafe { std::slice::from_raw_parts(self.row.as_ptr(), self.row.cols()) }
}
}
impl<'a, T: 'a> RowMut<'a, T> {
pub fn raw_slice(&self) -> &'a [T] {
unsafe { std::slice::from_raw_parts(self.row.as_ptr(), self.row.cols()) }
}
pub fn raw_slice_mut(&mut self) -> &'a mut [T] {
unsafe { std::slice::from_raw_parts_mut(self.row.as_mut_ptr(), self.row.cols()) }
}
}
#[derive(Debug, Clone, Copy)]
pub struct Column<'a, T: 'a> {
col: MatrixSlice<'a, T>,
}
#[derive(Debug)]
pub struct ColumnMut<'a, T: 'a> {
col: MatrixSliceMut<'a, T>,
}
#[derive(Debug)]
pub struct Cols<'a, T: 'a> {
_marker: PhantomData<&'a T>,
col_pos: usize,
row_stride: isize,
slice_cols: usize,
slice_rows: usize,
slice_start: *const T,
}
#[derive(Debug)]
pub struct ColsMut<'a, T: 'a> {
_marker: PhantomData<&'a mut T>,
col_pos: usize,
row_stride: isize,
slice_cols: usize,
slice_rows: usize,
slice_start: *mut T,
}
#[derive(Debug, PartialEq)]
pub enum DiagOffset {
Main,
Above(usize),
Below(usize),
}
#[derive(Debug)]
pub struct Diagonal<'a, T: 'a, M: 'a + BaseMatrix<T>> {
matrix: &'a M,
diag_pos: usize,
diag_end: usize,
_marker: PhantomData<&'a T>,
}
#[derive(Debug)]
pub struct DiagonalMut<'a, T: 'a, M: 'a + BaseMatrixMut<T>> {
matrix: &'a mut M,
diag_pos: usize,
diag_end: usize,
_marker: PhantomData<&'a mut T>,
}
#[derive(Debug)]
pub struct SliceIter<'a, T: 'a> {
slice_start: *const T,
row_pos: usize,
col_pos: usize,
slice_rows: usize,
slice_cols: usize,
row_stride: usize,
_marker: PhantomData<&'a T>,
}
#[derive(Debug)]
pub struct SliceIterMut<'a, T: 'a> {
slice_start: *mut T,
row_pos: usize,
col_pos: usize,
slice_rows: usize,
slice_cols: usize,
row_stride: usize,
_marker: PhantomData<&'a mut T>,
}
fn back_substitution<T, M>(m: &M, y: Vector<T>) -> Result<Vector<T>, Error>
where T: Any + Float,
M: BaseMatrix<T>
{
if m.is_empty() {
return Err(Error::new(ErrorKind::InvalidArg, "Matrix is empty."));
}
let mut x = vec![T::zero(); y.size()];
unsafe {
for i in (0..y.size()).rev() {
let mut holding_u_sum = T::zero();
for j in (i + 1..y.size()).rev() {
holding_u_sum = holding_u_sum + *m.get_unchecked([i, j]) * x[j];
}
let diag = *m.get_unchecked([i, i]);
if diag.abs() < T::min_positive_value() + T::min_positive_value() {
return Err(Error::new(ErrorKind::AlgebraFailure,
"Linear system cannot be solved (matrix is singular)."));
}
x[i] = (y[i] - holding_u_sum) / diag;
}
}
Ok(Vector::new(x))
}
fn forward_substitution<T, M>(m: &M, y: Vector<T>) -> Result<Vector<T>, Error>
where T: Any + Float,
M: BaseMatrix<T>
{
if m.is_empty() {
return Err(Error::new(ErrorKind::InvalidArg, "Matrix is empty."));
}
let mut x = Vec::with_capacity(y.size());
unsafe {
for (i, y_item) in y.data().iter().enumerate().take(y.size()) {
let mut holding_l_sum = T::zero();
for (j, x_item) in x.iter().enumerate().take(i) {
holding_l_sum = holding_l_sum + *m.get_unchecked([i, j]) * *x_item;
}
let diag = *m.get_unchecked([i, i]);
if diag.abs() < T::min_positive_value() + T::min_positive_value() {
return Err(Error::new(ErrorKind::AlgebraFailure,
"Linear system cannot be solved (matrix is singular)."));
}
x.push((*y_item - holding_l_sum) / diag);
}
}
Ok(Vector::new(x))
}