feat(from): impl From i32 vector

This commit is contained in:
Zhongheng Liu 2025-01-23 19:11:36 +02:00
commit 4c2ebb1afd
Signed by: steven
GPG key ID: 805A28B071DAD84B

View file

@ -25,6 +25,102 @@ pub struct Matrix {
/// Data stored in the matrix, you should not access this directly /// Data stored in the matrix, you should not access this directly
data: Vec<Vec<i32>>, 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 { impl FromStr for Matrix {
type Err = ParseMatrixError; type Err = ParseMatrixError;
@ -120,100 +216,13 @@ impl<'a, 'b> Mul<&'b Matrix> for &'a Matrix {
} }
} }
impl Matrix { impl From<Vec<i32>> for Matrix {
/// Matrix initialiser function. fn from(value: Vec<i32>) -> Self {
///
/// 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 { Matrix {
nrows: data.len(), nrows: value.len(),
ncols: data[0].len(), ncols: 1,
data, data: vec![value],
}
}
/// 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,
} }
} }
} }