pub struct Matrix {
    pub mat: Vec<Vec<f32>>,
    rows: usize,
    cols: usize,
}

pub struct Mat2x2 {
    mat: [[f32; 2]; 2],
}

pub struct Mat3x3 {
    mat: [[f32; 3]; 3],
}

impl Matrix {
    pub fn shape(&self) -> (usize, usize) {
        (self.rows, self.cols)
    }

    pub fn checkShape(&self) -> bool {
        if self.mat.len() != self.rows {
            return false;
        }

        for i in 0..self.rows {
            if self.mat.get(i).unwrap().len() != self.cols {
                return false;
            }
        }
        return true;
    }

    pub fn zeros(row: usize, col: usize) -> Self {
        let mut r = vec![0 as f32; col];
        let mut rs = vec![r; row];
        Matrix {
            mat: rs,
            rows: row,
            cols: col,
        }
    }

    pub fn new(row: usize, col: usize) -> Self {
        return Matrix::zeros(row, col);
    }

    pub fn getTranspose(&self) -> Self {
        let mut t = Matrix::new(self.rows, self.cols);
        for i in 0..self.rows {
            for j in 0..self.cols {
                t.mat[i][j] = self.mat[j][i];
            }
        }
        t
    }

    pub fn isSquare(&self) -> bool {
        self.rows == self.cols
    }

    pub fn trace(&self) -> f32 {
        if self.isSquare() {
            return (0..self.rows).map(|a| self.mat[a][a]).sum();
        }
        0.
    }
}
