refactor: added result and Matrix Error

This commit is contained in:
2026-04-27 21:39:26 -06:00
parent 5125e5c3c0
commit 2f03d65267

View File

@@ -26,27 +26,31 @@ pub struct Matrix {
} }
impl Matrix { impl Matrix {
pub fn new(rows: usize, columns: usize, default: Fraction) -> Self { pub fn new(rows: usize, columns: usize, default: Fraction) -> Result<Self, MatrixError> {
Self { if columns < 1 || rows < 1 {
return Err(MatrixError::ZeroSize);
}
Ok(Self {
rows, rows,
columns, columns,
data: vec![default; rows * columns], data: vec![default; rows * columns],
} })
} }
pub fn get(&self, row: usize, column: usize) -> &Fraction { pub fn get(&self, row: usize, column: usize) -> Result<&Fraction, MatrixError> {
if row >= self.rows || column >= self.columns { if row >= self.rows || column >= self.columns {
panic!("Index given is out of range.") return Err(MatrixError::IndexOutOfRange);
} }
let mut index = 0; let mut index = 0;
index += row * self.columns; index += row * self.columns;
index += column; index += column;
return &self.data[index]; return Ok(&self.data[index]);
} }
pub fn get_row(&self, row: usize) -> Vec<Fraction> { pub fn get_row(&self, row: usize) -> Result<Vec<Fraction>, MatrixError> {
if row >= self.rows { if row >= self.rows {
panic!("Row index is out of bounds."); return Err(MatrixError::RowOutOfRange);
} }
let mut index = 0; let mut index = 0;
@@ -57,12 +61,12 @@ impl Matrix {
data.push(self.data[index + i]); data.push(self.data[index + i]);
} }
return data; return Ok(data);
} }
pub fn get_column(&self, column: usize) -> Vec<Fraction> { pub fn get_column(&self, column: usize) -> Result<Vec<Fraction>, MatrixError> {
if column >= self.columns { if column >= self.columns {
panic!("Column index is out of bounds."); return Err(MatrixError::ColumnOutOfRange);
} }
let index = column; let index = column;
@@ -72,12 +76,12 @@ impl Matrix {
data.push(self.data[(i * self.columns) + index]) data.push(self.data[(i * self.columns) + index])
} }
return data; return Ok(data);
} }
pub fn get_diagonal(&self) -> Vec<Fraction> { pub fn get_diagonal(&self) -> Result<Vec<Fraction>, MatrixError> {
if self.columns != self.rows { if self.columns != self.rows {
panic!("The matrix needs to be squared for getting diagonal.") return Err(MatrixError::NotSquared);
} }
let mut data = Vec::new(); let mut data = Vec::new();
@@ -87,53 +91,57 @@ impl Matrix {
index = i + (i * self.columns); index = i + (i * self.columns);
data.push(self.data[index]); data.push(self.data[index]);
} }
return data; return Ok(data);
} }
pub fn set(&mut self, row: usize, column: usize, data: Fraction) -> () { pub fn set(&mut self, row: usize, column: usize, data: Fraction) -> Option<MatrixError> {
if row >= self.rows || column >= self.columns { if row >= self.rows || column >= self.columns {
panic!("Index given is out of range.") return Some(MatrixError::IndexOutOfRange);
} }
let mut index = 0; let mut index = 0;
index += row * self.columns; index += row * self.columns;
index += column; index += column;
self.data[index] = data; self.data[index] = data;
return; return None;
} }
pub fn set_row(&mut self, row: usize, data: Vec<Fraction>) -> () { pub fn set_row(&mut self, row: usize, data: Vec<Fraction>) -> Option<MatrixError> {
if row >= self.rows { if row >= self.rows {
panic!("Row index given is out of bounds.") return Some(MatrixError::IndexOutOfRange);
} }
if data.len() != self.columns { if data.len() != self.columns {
panic!("Data is not the required size") return Some(MatrixError::InvalidDataSize);
} }
for i in 0..data.len() { for i in 0..data.len() {
self.set(row, i, data[i]); self.set(row, i, data[i]);
} }
None
} }
pub fn set_column(&mut self, column: usize, data: Vec<Fraction>) -> () { pub fn set_column(&mut self, column: usize, data: Vec<Fraction>) -> Option<MatrixError> {
if column >= self.columns { if column >= self.columns {
panic!("Column index given is out of bouds.") return Some(MatrixError::ColumnOutOfRange);
} }
if data.len() != self.rows { if data.len() != self.rows {
panic!("Data is not the required size") return Some(MatrixError::InvalidDataSize);
} }
for i in 0..data.len() { for i in 0..data.len() {
self.set(i, column, data[i]); self.set(i, column, data[i]);
} }
None
} }
pub fn exchange_rows(&mut self, row1: usize, row2: usize) -> () { pub fn exchange_rows(&mut self, row1: usize, row2: usize) -> Option<MatrixError> {
if row1 >= self.rows || row2 >= self.rows { if row1 >= self.rows || row2 >= self.rows {
panic!("Row index is out of bounds."); return Some(MatrixError::RowOutOfRange);
} }
//Get copy of row2 //Get copy of row2
let temp = self.get_row(row2); let temp = self.get_row(row2).unwrap();
let mut index1 = 0; let mut index1 = 0;
let mut index2 = 0; let mut index2 = 0;
//Move from row1 to row2 //Move from row1 to row2
@@ -143,24 +151,28 @@ impl Matrix {
self.data[index2 + i] = self.data[index1 + i]; self.data[index2 + i] = self.data[index1 + i];
self.data[index1 + i] = temp[i]; self.data[index1 + i] = temp[i];
} }
None
} }
pub fn exchange_columns(&mut self, column1: usize, column2: usize) -> () { pub fn exchange_columns(&mut self, column1: usize, column2: usize) -> Option<MatrixError> {
if column1 >= self.columns || column2 >= self.columns { if column1 >= self.columns || column2 >= self.columns {
panic!("Column index is out of bounds.") return Some(MatrixError::ColumnOutOfRange);
} }
//Get copy of column2 //Get copy of column2
let temp = self.get_column(column2); let temp = self.get_column(column2).unwrap();
for i in 0..self.rows { for i in 0..self.rows {
self.data[column2 + (i * self.columns)] = self.data[column1 + (i * self.columns)]; self.data[column2 + (i * self.columns)] = self.data[column1 + (i * self.columns)];
self.data[column1 + (i * self.columns)] = temp[i]; self.data[column1 + (i * self.columns)] = temp[i];
} }
None
} }
pub fn get_determinant(&self) -> Fraction { pub fn get_determinant(&self) -> Result<Fraction, MatrixError> {
if self.rows != self.columns { if self.rows != self.columns {
panic!("Only nxn matrixes can have a determinant."); return Err(MatrixError::NotSquared);
} }
let mut trig_matrix = Matrix { let mut trig_matrix = Matrix {
@@ -172,12 +184,12 @@ impl Matrix {
for i in 0..self.columns { for i in 0..self.columns {
let mut max_row = i; let mut max_row = i;
let mut max_value = trig_matrix.get(i, i).abs(); let mut max_value = trig_matrix.get(i, i).unwrap().abs();
// We do parcial pivoting to avoid getting insane // We do parcial pivoting to avoid getting insane
// numbers that may result in overflow with fractions // numbers that may result in overflow with fractions
for r in (i + 1)..self.rows { for r in (i + 1)..self.rows {
let val = trig_matrix.get(r, i).abs(); let val = trig_matrix.get(r, i).unwrap().abs();
if val > max_value { if val > max_value {
max_value = val; max_value = val;
max_row = r; max_row = r;
@@ -187,7 +199,7 @@ impl Matrix {
// If there ain't no other thing but 0 then we're // If there ain't no other thing but 0 then we're
// fucked, determinant is zero // fucked, determinant is zero
if max_value.is_zero() { if max_value.is_zero() {
return Fraction::new(0, 1).unwrap(); return Ok(Fraction::new(0, 1).unwrap());
} }
if max_row != i { if max_row != i {
@@ -195,17 +207,19 @@ impl Matrix {
sign = -sign; sign = -sign;
} }
let pivot = *trig_matrix.get(i, i); let pivot = *trig_matrix.get(i, i).unwrap();
// The main gaussian elimination, not even I remember how // The main gaussian elimination, not even I remember how
// i did it in such a asimple way // i did it in such a asimple way
for x in (i + 1)..trig_matrix.rows { for x in (i + 1)..trig_matrix.rows {
let m = (*trig_matrix.get(x, i) / pivot).unwrap(); let m = (*trig_matrix.get(x, i).unwrap() / pivot).unwrap();
let new_row = trig_matrix let row_x = trig_matrix.get_row(x)?;
.get_row(x) let row_i = trig_matrix.get_row(i)?;
let new_row = row_x
.iter() .iter()
.zip(trig_matrix.get_row(i).iter()) .zip(row_i.iter())
.map(|(a, b)| *a - m * *b) .map(|(a, b)| *a - m * *b)
.collect::<Vec<Fraction>>(); .collect::<Vec<Fraction>>();
@@ -218,21 +232,21 @@ impl Matrix {
// the determinant :) // the determinant :)
let determinant = sign let determinant = sign
* trig_matrix * trig_matrix
.get_diagonal() .get_diagonal()?
.iter() .iter()
.copied() .copied()
.fold(Fraction::from(1i64), |acc, x| acc * x); .fold(Fraction::from(1i64), |acc, x| acc * x);
return determinant; return Ok(determinant);
} }
} }
impl Add for Matrix { impl Add for Matrix {
type Output = Self; type Output = Result<Self, MatrixError>;
fn add(self, other: Self) -> Self::Output { fn add(self, other: Self) -> Self::Output {
if self.data.len() != other.data.len() { if self.data.len() != other.data.len() {
panic!("Matrix size is inadecuate."); return Err(MatrixError::InvalidSizeForAdd);
} }
let mut new_data = Vec::new(); let mut new_data = Vec::new();
@@ -240,20 +254,20 @@ impl Add for Matrix {
new_data.push(self.data[i] + other.data[i]); new_data.push(self.data[i] + other.data[i]);
} }
Matrix { Ok(Matrix {
columns: self.columns, columns: self.columns,
rows: self.rows, rows: self.rows,
data: new_data, data: new_data,
} })
} }
} }
impl Sub for Matrix { impl Sub for Matrix {
type Output = Self; type Output = Result<Self, MatrixError>;
fn sub(self, other: Self) -> Self::Output { fn sub(self, other: Self) -> Self::Output {
if self.data.len() != other.data.len() { if self.data.len() != other.data.len() {
panic!("Matrix size is inadecuate."); return Err(MatrixError::InvalidSizeForSub);
} }
let mut new_data = Vec::new(); let mut new_data = Vec::new();
@@ -261,16 +275,16 @@ impl Sub for Matrix {
new_data.push(self.data[i] - other.data[i]); new_data.push(self.data[i] - other.data[i]);
} }
Matrix { Ok(Matrix {
columns: self.columns, columns: self.columns,
rows: self.rows, rows: self.rows,
data: new_data, data: new_data,
} })
} }
} }
impl Mul for Matrix { impl Mul for Matrix {
type Output = Self; type Output = Result<Self, MatrixError>;
fn mul(self, other: Self) -> Self::Output { fn mul(self, other: Self) -> Self::Output {
if self.columns != other.rows { if self.columns != other.rows {
@@ -279,10 +293,10 @@ impl Mul for Matrix {
let mut new_data: Vec<Fraction> = Vec::new(); let mut new_data: Vec<Fraction> = Vec::new();
for i in 0..self.rows { for i in 0..self.rows {
let current_row = self.get_row(i); let current_row = self.get_row(i)?;
for k in 0..other.columns { for k in 0..other.columns {
let current_column = other.get_column(k); let current_column = other.get_column(k)?;
let mut new_value = Fraction::new(0, 1).unwrap(); let mut new_value = Fraction::new(0, 1).unwrap();
for (a, b) in current_row.iter().zip(current_column.iter()) { for (a, b) in current_row.iter().zip(current_column.iter()) {
new_value = new_value + (*a * *b); new_value = new_value + (*a * *b);
@@ -291,11 +305,11 @@ impl Mul for Matrix {
} }
} }
Matrix { Ok(Matrix {
rows: self.rows, rows: self.rows,
columns: other.columns, columns: other.columns,
data: new_data, data: new_data,
} })
} }
} }