use std::ops::{Index, Add, Sub, Mul, Neg};
use common::Number;
use vector;
use vector::{Vector};
pub struct Matrix<T: Number> {
rows: usize,
cols: usize,
data: Vector<T>
}
impl<T: Number> Index<usize> for Matrix<T> {
type Output = [T];
#[inline]
fn index<'a>(&'a self, index: usize) -> &'a [T] {
&self.data.data[self.rows * index..self.rows * index + self.cols]
}
}
impl<T: Number> Clone for Matrix<T> {
fn clone(&self) -> Matrix<T> {
Matrix::<T> {
rows: self.num_rows(),
cols: self.num_cols(),
data: self.data.clone()
}
}
fn clone_from(&mut self, source: &Matrix<T>) {
self.rows = source.num_rows();
self.cols = source.num_cols();
self.data = source.data.clone();
}
}
impl<T: Number> Add<Matrix<T>> for Matrix<T> {
type Output = Matrix<T>;
fn add(self, rhs: Matrix<T>) -> Matrix<T> {
if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
Matrix::<T> {
rows: self.num_rows(),
cols: self.num_cols(),
data: self.data + rhs.data
}
} else {
panic!("Matrices are not conformable for addition.");
}
}
}
impl<T: Number> Sub<Matrix<T>> for Matrix<T> {
type Output = Matrix<T>;
fn sub(self, rhs: Matrix<T>) -> Matrix<T> {
if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
Matrix::<T> {
rows: self.num_rows(),
cols: self.num_cols(),
data: self.data - rhs.data
}
} else {
panic!("Matrices are not conformable for subtraction.");
}
}
}
impl<T: Number> Mul<Matrix<T>> for Matrix<T> {
type Output = Matrix<T>;
fn mul(self, rhs: Matrix<T>) -> Matrix<T> {
if self.num_cols() == rhs.num_rows() {
let mut new_mat = Matrix::<T>::new(self.num_rows(), rhs.num_cols(), T::zero());
for i in 0..self.num_rows() {
for j in 0..rhs.num_cols() {
let mut sum: T = T::zero();
for k in 0..self.num_cols() {
sum = sum + self.get(i, k) * rhs.get(k, j);
}
new_mat.set(i, j, sum);
}
}
new_mat
} else {
panic!("Matrices are not conformable for multiplication.")
}
}
}
impl<T: Number + Neg<Output = T>> Neg for Matrix<T> {
type Output = Matrix<T>;
fn neg(self) -> Matrix<T> {
Matrix::<T> {
rows: self.num_rows(),
cols: self.num_cols(),
data: -self.data
}
}
}
impl<T: Number> Mul<T> for Matrix<T> {
type Output = Matrix<T>;
fn mul(self, rhs: T) -> Matrix<T> {
Matrix::<T> {
rows: self.num_rows(),
cols: self.num_cols(),
data: self.data * rhs
}
}
}
impl<T: Number> PartialEq for Matrix<T> {
fn eq(&self, other: &Matrix<T>) -> bool {
if self.num_rows() != other.num_rows() || self.num_cols() != other.num_cols() {
return false;
}
self.data == other.data
}
}
impl<T: Number> Eq for Matrix<T> {}
impl<T: Number> Matrix<T> {
#[inline]
pub fn num_rows(&self) -> usize{
self.rows
}
#[inline]
pub fn num_cols(&self) -> usize {
self.cols
}
#[inline]
pub fn get(&self, i: usize, j: usize) -> T {
if i < self.num_rows() && j < self.num_cols() {
self.data[i * self.num_cols() + j]
} else {
panic!(format!("Matrix index ({}, {}) out of bounds.", i, j))
}
}
#[inline]
pub fn set(&mut self, i: usize, j: usize, num: T) {
let (rows, cols) = (self.num_rows(), self.num_cols());
if i < rows && j < cols {
self.data[i * cols + j] = num
} else {
panic!(format!("Matrix index ({}, {}) out of bounds.", i, j))
}
}
pub fn new(rows: usize, cols: usize, default: T) -> Matrix<T> {
Matrix::<T> {
rows: rows,
cols: cols,
data: Vector::new(rows * cols, default)
}
}
pub fn reshape(&mut self, newrows: usize, newcols: usize) {
if self.rows * self.cols == newrows * newcols {
self.rows = newrows;
self.cols = newcols;
} else {
panic!("Total number of elements in matrix should be same.")
}
}
pub fn get_vec(&self) -> Vec<T> {
self.data.data.clone()
}
pub fn transpose(&mut self) {
let mut v = self.data.clone();
for i in 0..self.num_rows() {
for j in 0..self.num_cols() {
v[j * self.num_cols() + i] = self.get(i, j);
}
}
self.data = v;
}
pub fn trace(&self) -> T {
if self.num_rows() == self.num_cols() {
let mut sum: T = T::zero();
for i in 0..self.num_rows() {
sum = sum + self.get(i, i);
}
return sum;
}
panic!("The matrix should be a square matrix.")
}
}
pub fn from_elems<T: Number>(rows: usize, cols: usize, elems: &[T]) -> Matrix<T> {
Matrix::<T> {
rows: rows,
cols: cols,
data: vector::from_elems(elems)
}
}
pub fn identity<T: Number>(n: usize) -> Matrix<T> {
let mut m = Matrix::<T>::new(n, n, T::zero());
for i in 0..n {
m.set(i, i, T::one());
}
m
}