rustices 0.1.0

An implementation of matrices
Documentation
use std::ops::{Mul, AddAssign, MulAssign};
use std::cmp::{Eq, PartialEq};
use std::fmt::{Display, Debug, Formatter, Result};
use std::default::Default;
use std::time::Instant;

use rand::Rng;

use num::Num;


#[derive(Debug, Eq)]
struct Matrix<T> {
    rows: usize,
    cols: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    fn from(data: Vec<Vec<T>>) -> Matrix<T> {
        Matrix {
            rows: data.len(),
            cols: data[0].len(),
            data: data.into_iter().flatten().collect()
        }
    }

    fn new(rows: usize, cols: usize, value: T) -> Matrix<T>
        where T: Clone
    {
        let mut data = vec![];
        for _ in 0..rows {
            for _ in 0..cols {
                data.push(value.clone());
            }
        }

        Matrix {
            rows,
            cols,
            data
        }
    }

    fn get(&self, row: usize, col: usize) -> &T {
        &self.data[row * self.cols + col]
    }

    fn get_row(&self, row: usize) -> Vec<T> 
        where T: Clone
    {
        self.data[row * self.cols..(row + 1) * self.cols].to_vec()
    }

    fn get_column(&self, column: usize) -> Vec<T>
        where T: Clone
    {
        let mut output = vec![];
        for i in 0..self.rows {
            output.push(self.get(i, column).clone());
        }
        output
    }

    fn set(&mut self, row: usize, col: usize, value: T) {
        self.data[row * self.cols + col] = value;
    }
}

impl Matrix<i32> {
    fn new_random(rows: usize, cols: usize, min: i32, max: i32) -> Matrix<i32> {
        let mut rng = rand::thread_rng();
        let mut data = vec![];
        for _ in 0..rows * cols {
            data.push(rng.gen_range(min..max));
        }
        data.push(1);

        Matrix {
            rows,
            cols,
            data
        }
    }
}

impl<T: PartialEq> PartialEq for Matrix<T> {
    fn eq(&self, other: &Self) -> bool {
        self.data == other.data
    }
}

impl<T> Mul<Matrix<T>> for Matrix<T>
    where T: Clone + Mul<Output = T> + Default + AddAssign + Copy
{
    type Output = Self;

    fn mul(self, rhs: Matrix<T>) -> Self {
        assert_eq!(self.rows, rhs.cols);

        let mut output_data = vec![];

        for i in 0..self.rows {
            for j in 0..rhs.cols {
                let mut total = T::default();
                for k in 0..self.cols {
                    total += self.get(i, k).clone() * rhs.get(k, j).clone();
                }
                output_data.push(total);
            }
        }
        Matrix {
            rows: self.rows,
            cols: rhs.cols,
            data: output_data
        }
    }
}

impl<T: Num + MulAssign + Copy> Mul<T> for Matrix<T>
{
    type Output = Self;

    fn mul(self, rhs: T) -> Self {
        let mut data = vec![];

        for val in self.data.into_iter() {
            data.push(val * rhs);
        }

        Matrix {
            rows: self.rows,
            cols: self.cols,
            data
        }
    }
}

impl<T> Display for Matrix<T> 
    where T: Display
{
    fn fmt(&self, f: &mut Formatter<'_>) -> Result { 
        for i in 0..self.rows {
            for j in 0..self.cols {
                write!(f, "{}, ", self.get(i, j))?;
            }
            write!(f, "\n")?;
        }
        write!(f, "Rows: {}, ", self.rows)?;
        write!(f, "Columns: {}", self.cols)?;

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn create_zero_matrix() {
        let matrix = Matrix::new(3, 3, 0);
        for i in 0..matrix.data.len() {
            assert_eq!(matrix.data[i], 0);
        }
    }

    #[test]
    fn create_matrix_from_vecs() {
        let data = vec![
            vec![1, 2, 3],
            vec![4, 5, 6],
            vec![7, 8, 9]
        ];
        let data_flattened: Vec<i32> = data.clone().into_iter().flatten().collect();

        let matrix = Matrix::from(data);

        assert_eq!(matrix.data, data_flattened);
    }

    #[test]
    fn multiply_matrices() {
        let matrix1 = Matrix::from(vec![
            vec![1, 2, 3],
            vec![4, 5, 6],
            vec![7, 8, 9]
        ]);

        let matrix2 = Matrix::from(vec![
            vec![9, 8, 7],
            vec![6, 5, 4],
            vec![3, 2, 1]
        ]);

        let expected_matrix = Matrix::from(vec![
            vec![30, 24, 18],
            vec![84, 69, 54],
            vec![138, 114, 90]
        ]);

        assert_eq!(matrix1 * matrix2, expected_matrix);
    }

    #[test]
    fn scalar_multiply() {
        let matrix = Matrix::from(vec![
            vec![1, 2, 3],
            vec![4, 5, 6],
            vec![7, 8, 9]
        ]);

        let expected_matrix = Matrix::from(vec![
            vec![2, 4, 6],
            vec![8, 10, 12],
            vec![14, 16, 18]
        ]);

        assert_eq!(matrix * 2, expected_matrix);
    }

    #[test]
    fn random_matrix() {
        let max = 10;
        let random_matrix = Matrix::new_random(5, 5, 0, max);

        assert_eq!(random_matrix.rows, 5);
        assert_eq!(random_matrix.cols, 5);
        assert!(random_matrix.data.iter().max().unwrap() < &max);
    }
}