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