diff options
Diffstat (limited to 'src/matrix.rs')
-rw-r--r-- | src/matrix.rs | 195 |
1 files changed, 102 insertions, 93 deletions
diff --git a/src/matrix.rs b/src/matrix.rs index ec347c9..9227917 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -25,6 +25,102 @@ pub struct Matrix { /// Data stored in the matrix, you should not access this directly data: Vec<Vec<i32>>, } +impl Matrix { + /// Matrix initialiser function. + /// + /// Accepts a new array of data as a list of rows. + /// + /// TODOs + /// - Add row length check + pub fn new(data: Vec<Vec<i32>>) -> Matrix { + Matrix { + nrows: data.len(), + ncols: data[0].len(), + data, + } + } + /// Query one element at selected position. + /// + /// Returns `None` if index is out of bounds. + pub fn get(&self, row_index: usize, column_index: usize) -> Option<i32> { + let r = self.data.get(row_index)?; + let n = r.get(column_index)?; + Some(*n) + } + + /// Update one element at selected position. + /// + /// Returns `Err()` if index is out of bounds. + pub fn set( + &mut self, + row_index: usize, + column_index: usize, + new_data: i32, + ) -> Result<(), MatrixSetValueError> { + self.data[row_index][column_index] = new_data; + Ok(()) + } + + /// Checks if this is a square matrix. + pub fn is_square(&self) -> bool { + self.nrows == self.ncols + } + fn splice(&self, at_index: usize) -> Matrix { + let mut data: Vec<Vec<i32>> = Vec::new(); + for i in 0..self.data.len() { + if i == 0 { + continue; + } + let mut r: Vec<i32> = Vec::new(); + for j in 0..self.data[i].len() { + if j == at_index { + continue; + } + r.push(self.data[i][j]); + } + data.push(r); + } + Matrix::new(data) + } + + /// Evaluates any N-by-N matrix. + /// + /// This function panics if the matrix is not square! + pub fn determinant(&self) -> i32 { + if !self.is_square() { + panic!() + }; + if self.nrows == 2 && self.ncols == 2 { + return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]; + } + let mut tmp = 0; + for (i, n) in self.data[0].iter().enumerate() { + let mult = if i % 2 == 0 { -*n } else { *n }; + let eval = self.splice(i).determinant(); + tmp += mult * eval; + } + tmp + } + + /// Evaluates the tranpose of the matrix. + /// + /// Each row becomes a column, each column becomes a row. + pub fn transpose(&self) -> Matrix { + let mut new_data = Vec::<Vec<i32>>::new(); + for i in 0..self.nrows { + let mut new_row = Vec::<i32>::new(); + for j in 0..self.ncols { + new_row.push(self.data[j][i]); + } + new_data.push(new_row); + } + Matrix { + nrows: self.ncols, + ncols: self.nrows, + data: new_data, + } + } +} impl FromStr for Matrix { type Err = ParseMatrixError; @@ -120,100 +216,13 @@ impl<'a, 'b> Mul<&'b Matrix> for &'a Matrix { } } -impl Matrix { - /// Matrix initialiser function. - /// - /// Accepts a new array of data as a list of rows. - /// - /// TODOs - /// - Add row length check - pub fn new(data: Vec<Vec<i32>>) -> Matrix { +impl From<Vec<i32>> for Matrix { + fn from(value: Vec<i32>) -> Self { Matrix { - nrows: data.len(), - ncols: data[0].len(), - data, - } - } - - /// Query one element at selected position. - /// - /// Returns `None` if index is out of bounds. - pub fn get(&self, row_index: usize, column_index: usize) -> Option<i32> { - let r = self.data.get(row_index)?; - let n = r.get(column_index)?; - Some(*n) - } - - /// Update one element at selected position. - /// - /// Returns `Err()` if index is out of bounds. - pub fn set( - &mut self, - row_index: usize, - column_index: usize, - new_data: i32, - ) -> Result<(), MatrixSetValueError> { - self.data[row_index][column_index] = new_data; - Ok(()) - } - - /// Checks if this is a square matrix. - pub fn is_square(&self) -> bool { - self.nrows == self.ncols - } - fn splice(&self, at_index: usize) -> Matrix { - let mut data: Vec<Vec<i32>> = Vec::new(); - for i in 0..self.data.len() { - if i == 0 { - continue; - } - let mut r: Vec<i32> = Vec::new(); - for j in 0..self.data[i].len() { - if j == at_index { - continue; - } - r.push(self.data[i][j]); - } - data.push(r); - } - Matrix::new(data) - } - - /// Evaluates any N-by-N matrix. - /// - /// This function panics if the matrix is not square! - pub fn determinant(&self) -> i32 { - if !self.is_square() { - panic!() - }; - if self.nrows == 2 && self.ncols == 2 { - return self.data[0][0] * self.data[1][1] - self.data[0][1] * self.data[1][0]; - } - let mut tmp = 0; - for (i, n) in self.data[0].iter().enumerate() { - let mult = if i % 2 == 0 { -*n } else { *n }; - let eval = self.splice(i).determinant(); - tmp += mult * eval; - } - tmp - } - - /// Evaluates the tranpose of the matrix. - /// - /// Each row becomes a column, each column becomes a row. - pub fn transpose(&self) -> Matrix { - let mut new_data = Vec::<Vec<i32>>::new(); - for i in 0..self.nrows { - let mut new_row = Vec::<i32>::new(); - for j in 0..self.ncols { - new_row.push(self.data[j][i]); - } - new_data.push(new_row); - } - Matrix { - nrows: self.ncols, - ncols: self.nrows, - data: new_data, + nrows: value.len(), + ncols: 1, + data: vec![value], } } } + |