use std::mem;
use core::ops::{Index, IndexMut};
pub use crate::vector::{Vector, Vec64};
pub use crate::matrix::{Matrix, Mat64};
pub use crate::traits::{Number, Signed, Zero, One};
impl<T> Index<(usize, usize)> for Matrix<T> {
type Output = T;
#[inline]
fn index<'a>(&'a self, index: (usize, usize) ) -> &'a T {
&self.mat[ index.0 * self.cols + index.1 ]
}
}
impl<T> IndexMut<(usize, usize)> for Matrix<T> {
#[inline]
fn index_mut(&mut self, index: (usize, usize) ) -> &mut T {
&mut self.mat[ index.0 * self.cols + index.1 ]
}
}
impl<T> Matrix<T> {
#[inline]
pub fn clear(&mut self) {
self.mat.clear();
self.rows = 0;
self.cols = 0;
}
}
impl<T: Clone + Copy + Number> Matrix<T> {
#[inline]
pub fn get_row(&self, row: usize ) -> Vector<T> {
if self.rows <= row { panic!( "Matrix range error in get_row" ); }
let mut result = Vector::<T>::new( self.cols, T::zero() );
for j in 0..self.cols {
result[ j ] = self.mat[ row * self.cols + j ];
}
result
}
#[inline]
pub fn get_col(&self, col: usize ) -> Vector<T> {
if self.cols <= col { panic!( "Matrix range error in get_col" ); }
let mut result = Vector::<T>::new( self.rows, T::zero() );
for i in 0..self.rows {
result[ i ] = self.mat[ i * self.cols + col ];
}
result
}
#[inline]
pub fn set_row(&mut self, row: usize, vec: Vector<T> ) {
if vec.size() != self.cols { panic!( "Matrix size error in set_row" ); }
if self.rows <= row { panic!( "Matrix range error in set_row" ); }
for j in 0..self.cols {
self.mat[ row * self.cols + j ] = vec[ j ];
}
}
#[inline]
pub fn set_col(&mut self, col: usize, vec: Vector<T> ) {
if vec.size() != self.rows { panic!( "Matrix size error in set_col" ); }
if self.rows <= col { panic!( "Matrix range error in set_col" ); }
for i in 0..self.rows {
self[(i, col)] = vec[ i ];
}
}
#[inline]
pub fn delete_row(&mut self, row: usize ) {
if self.rows <= row { panic!( "Matrix range error in delete_row" ); }
self.mat.drain( row * self.cols..(row+1) * self.cols );
self.rows -= 1;
}
#[inline]
pub fn multiply(&self, vec: &Vector<T> ) -> Vector<T> {
if vec.size() != self.cols { panic!( "Matrix dimensions do not agree in multiply." ); }
let mut result = Vector::<T>::empty();
for row in 0..self.rows {
result.push( self.get_row( row ).dot( vec ) );
}
result
}
#[inline]
pub fn eye( size: usize ) -> Self {
let mut identity = Matrix::<T>::new( size, size, T::zero() );
for i in 0..size {
identity[(i, i)] = T::one();
}
identity
}
#[inline]
pub fn resize(&mut self, n_rows: usize, n_cols: usize ) {
let temp = self.clone();
*self = Matrix::<T>::new( n_rows, n_cols, T::zero() );
for i in 0..n_rows {
for j in 0..n_cols {
if i < temp.rows() && j < temp.cols() {
self[(i, j)] = temp[(i, j)].clone();
}
}
}
}
#[inline]
pub fn transpose_in_place(&mut self) {
if self.rows == self.cols {
for i in 0..self.rows {
for j in i+1..self.cols {
let mut temp = self[(i,j)];
mem::swap( &mut self[(j,i)], &mut temp );
self[(i,j)] = temp;
}
}
} else {
let mut temp = Vec::with_capacity( self.rows * self.cols );
for j in 0..self.cols {
for i in 0..self.rows {
temp.push( self[(i,j)] );
}
}
self.mat = temp;
mem::swap( &mut self.rows, &mut self.cols );
}
}
#[inline]
pub fn transpose(&self) -> Matrix<T> {
let mut temp: Matrix<T> = self.clone();
temp.transpose_in_place();
temp
}
#[inline]
pub fn swap_rows(&mut self, row_1: usize, row_2: usize ) {
if self.rows <= row_1 || self.rows <= row_2 { panic!( "Matrix swap row range error." ); }
for j in 0..self.cols {
self.swap_elem( row_1, j, row_2, j );
}
}
#[inline]
pub fn swap_elem(&mut self, row_1: usize, col_1: usize, row_2: usize, col_2: usize ) {
let mut temp = self[(row_1,col_1)].clone();
mem::swap( &mut self[(row_2,col_2)], &mut temp );
self[(row_1, col_1)] = temp;
}
#[inline]
pub fn fill(&mut self, elem: T ) {
for i in 0..self.rows {
for j in 0..self.cols {
self[(i, j)] = elem.clone();
}
}
}
#[inline]
pub fn fill_diag(&mut self, elem: T ) {
let n: usize = if self.cols < self.rows { self.cols } else { self.rows };
for i in 0..n {
self[(i, i)] = elem.clone();
}
}
#[inline]
pub fn fill_band(&mut self, offset: isize, elem: T ) {
for row in 0..self.rows {
let i = (row as isize) + offset;
if (i as usize) < self.cols && i >= 0 {
self[(row, i as usize)] = elem.clone();
}
}
}
#[inline]
pub fn fill_tridiag(&mut self, lower: T, diag: T, upper: T ) {
self.fill_band( -1, lower );
self.fill_diag( diag );
self.fill_band( 1, upper );
}
#[inline]
pub fn fill_row(&mut self, row: usize, elem: T ) {
if self.rows <= row { panic!( "Matrix range error in fill_row" ); }
for j in 0..self.cols {
self[(row, j)] = elem.clone();
}
}
#[inline]
pub fn fill_col(&mut self, col: usize, elem: T ) {
if self.cols <= col { panic!( "Matrix range error in fill_col" ); }
for i in 0..self.rows {
self[(i, col)] = elem.clone();
}
}
}