diff --git a/Cargo.lock b/Cargo.lock index a13fbee..b126c47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "fractions" version = "0.1.0" -source = "git+https://laentropia-homelab.tail7368da.ts.net/laentropia/Rusty-Fractions.git?branch=main#e79d93aa9d20a90358789f872994bc8cefa2779e" +source = "git+https://laentropia-homelab.tail7368da.ts.net/laentropia/Rusty-Fractions.git?branch=main#885bbfeebed047a62ef86eae5bcc44137e2ae127" [[package]] name = "matrix" diff --git a/f b/f deleted file mode 100644 index 23b7279..0000000 --- a/f +++ /dev/null @@ -1,23 +0,0 @@ -commit 918815f5b1a997018bc83b9ec7d65dd3a7ca7bce (HEAD -> main) -Author: LaEntropiaa -Date: Tue Aug 26 11:38:47 2025 -0600 - - Added sum and substract function - -commit a0523d9ccb77f77184429638f33cc4adc1376a48 -Author: LaEntropiaa -Date: Thu Aug 21 11:45:42 2025 -0600 - - added display trait for matrix struct - -commit 6b426fa1b0f9ebdbbf5e8c3b2eb2e435a053eca4 -Author: LaEntropiaa -Date: Wed Aug 20 10:32:43 2025 -0600 - - added get function - -commit ef914ed0169305a120c16ad1e0c4927049af4c94 -Author: LaEntropiaa -Date: Sat Aug 9 16:19:53 2025 -0600 - - Initial comit, bases for matrix struct and creation diff --git a/src/lib.rs b/src/lib.rs index 2fe4d0b..760b8a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,41 +1,32 @@ use core::panic; use fractions::Fraction; -use num_traits::{Float, Num, NumAssign, Signed}; -use std::fmt::{self, Debug}; +use std::fmt::{Debug, Display}; use std::ops::Add; use std::ops::Mul; use std::ops::Sub; -#[derive(PartialEq, Eq, Debug)] -pub struct Matrix< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, -> { - rows: usize, - columns: usize, - data: Vec, +#[derive(Debug, Eq, PartialEq)] +pub enum MatrixError { + IndexOutOfRange, + RowOutOfRange, + ColumnOutOfRange, + NotSquared, + InvalidDataSize, + InvalidSizeForAdd, + InvalidSizeForSub, + InvalidSizeForMul, + ZeroSize, } -impl< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, - > Matrix -{ - pub fn new(rows: usize, columns: usize, default: T) -> Self { +#[derive(PartialEq, Eq, Debug)] +pub struct Matrix { + rows: usize, + columns: usize, + data: Vec, +} + +impl Matrix { + pub fn new(rows: usize, columns: usize, default: Fraction) -> Self { Self { rows, columns, @@ -43,7 +34,7 @@ impl< } } - pub fn get(&self, row: usize, column: usize) -> &T { + pub fn get(&self, row: usize, column: usize) -> &Fraction { if row >= self.rows || column >= self.columns { panic!("Index given is out of range.") } @@ -53,7 +44,7 @@ impl< return &self.data[index]; } - pub fn get_row(&self, row: usize) -> Vec { + pub fn get_row(&self, row: usize) -> Vec { if row >= self.rows { panic!("Row index is out of bounds."); } @@ -69,7 +60,7 @@ impl< return data; } - pub fn get_column(&self, column: usize) -> Vec { + pub fn get_column(&self, column: usize) -> Vec { if column >= self.columns { panic!("Column index is out of bounds."); } @@ -84,14 +75,14 @@ impl< return data; } - pub fn get_diagonal(&self) -> Vec { + pub fn get_diagonal(&self) -> Vec { if self.columns != self.rows { panic!("The matrix needs to be squared for getting diagonal.") } let mut data = Vec::new(); - let mut index = 0; + let mut index; for i in 0..self.columns { index = i + (i * self.columns); data.push(self.data[index]); @@ -99,7 +90,7 @@ impl< return data; } - pub fn set(&mut self, row: usize, column: usize, data: T) -> () { + pub fn set(&mut self, row: usize, column: usize, data: Fraction) -> () { if row >= self.rows || column >= self.columns { panic!("Index given is out of range.") } @@ -110,7 +101,7 @@ impl< return; } - pub fn set_row(&mut self, row: usize, data: Vec) -> () { + pub fn set_row(&mut self, row: usize, data: Vec) -> () { if row >= self.rows { panic!("Row index given is out of bounds.") } @@ -123,7 +114,7 @@ impl< } } - pub fn set_column(&mut self, column: usize, data: Vec) -> () { + pub fn set_column(&mut self, column: usize, data: Vec) -> () { if column >= self.columns { panic!("Column index given is out of bouds.") } @@ -167,7 +158,7 @@ impl< } } - pub fn get_determinant(&self) -> T { + pub fn get_determinant(&self) -> Fraction { if self.rows != self.columns { panic!("Only nxn matrixes can have a determinant."); } @@ -177,65 +168,66 @@ impl< rows: self.rows, data: self.data.clone(), }; - let mut sign = T::one(); + let mut sign = Fraction::new(1, 1).unwrap(); for i in 0..self.columns { - let mut pivot = *trig_matrix.get(i, i); + let mut max_row = i; + let mut max_value = trig_matrix.get(i, i).abs(); - // Assign x to next row - let mut x = i + 1; - while pivot.is_zero() && x < self.rows { - if !trig_matrix.get(x, i).is_zero() { - trig_matrix.exchange_rows(x, i); - sign = -sign; - pivot = *trig_matrix.get(i, i); - break; + // 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(); + if val > max_value { + max_value = val; + max_row = r; } - x += 1; - } - // If even exchanging in all ways posible pivot is still 0 - // then determinant is 0 - if pivot.is_zero() { - return T::zero(); } - //So, we got the pivot, now we evaluate to 0 to create the - //triangular matrix - x = i + 1; - while x < trig_matrix.rows { - let m = *trig_matrix.get(x, i) / pivot; + // 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(); + } + + if max_row != i { + trig_matrix.exchange_rows(i, max_row); + sign = -sign; + } + + let pivot = *trig_matrix.get(i, i); + + // 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 new_row = trig_matrix .get_row(x) .iter() .zip(trig_matrix.get_row(i).iter()) .map(|(a, b)| *a - m * *b) - .collect::>(); + .collect::>(); + trig_matrix.set_row(x, new_row); - x += 1; } } // YES, now we got ourselves a triangular matrix, now we just // take the product of the diagonal and multiply by sign, that's // the determinant :) - let determinant = sign * trig_matrix.get_diagonal().iter().copied().product::(); + let determinant = sign + * trig_matrix + .get_diagonal() + .iter() + .copied() + .fold(Fraction::from(1i64), |acc, x| acc * x); return determinant; } } -impl< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, - > Add for Matrix -{ +impl Add for Matrix { type Output = Self; fn add(self, other: Self) -> Self::Output { @@ -256,18 +248,7 @@ impl< } } -impl< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, - > Sub for Matrix -{ +impl Sub for Matrix { type Output = Self; fn sub(self, other: Self) -> Self::Output { @@ -288,18 +269,7 @@ impl< } } -impl< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, - > Mul for Matrix -{ +impl Mul for Matrix { type Output = Self; fn mul(self, other: Self) -> Self::Output { @@ -307,15 +277,15 @@ impl< panic!("Matrix dimentions are inadecuate."); } - let mut new_data: Vec = Vec::new(); + let mut new_data: Vec = Vec::new(); for i in 0..self.rows { let current_row = self.get_row(i); for k in 0..other.columns { let current_column = other.get_column(k); - let mut new_value = T::zero(); + let mut new_value = Fraction::new(0, 1).unwrap(); for (a, b) in current_row.iter().zip(current_column.iter()) { - new_value += *a * *b; + new_value = new_value + (*a * *b); } new_data.push(new_value); } @@ -329,18 +299,7 @@ impl< } } -impl< - T: Num - + NumAssign - + Signed - + Float - + fmt::Display - + Copy - + PartialEq - + Debug - + std::iter::Product, - > fmt::Display for Matrix -{ +impl Display for Matrix { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut display = String::new(); let mut index = 0; @@ -359,411 +318,4 @@ impl< #[cfg(test)] mod tests { use super::*; - - #[test] - fn sum_two_matrix_1() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let matrix2 = Matrix::new(4, 4, 3.0); - let result_matrix = Matrix::new(4, 4, 5.0); - - matrix1 = matrix1 + matrix2; - - assert_eq!(matrix1, result_matrix); - } - - #[test] - fn sum_two_matrix_2() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let mut matrix2 = Matrix::new(4, 4, 0.0); - let mut result_matrix = Matrix::new(4, 4, 2.0); - - result_matrix.set(0, 0, 9.0); - matrix2.set(0, 0, 7.0); - matrix1 = matrix1 + matrix2; - - assert_eq!(matrix1, result_matrix); - } - - #[test] - #[should_panic] - fn sum_two_matrix_3() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let matrix2 = Matrix::new(4, 5, 0.0); - - matrix1 = matrix1 + matrix2; - } - - #[test] - fn substract_two_matrix_1() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let matrix2 = Matrix::new(4, 4, 3.0); - let result_matrix = Matrix::new(4, 4, -1.0); - - matrix1 = matrix1 - matrix2; - - assert_eq!(matrix1, result_matrix); - } - - #[test] - fn substract_two_matrix_2() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let mut matrix2 = Matrix::new(4, 4, 0.0); - let mut result_matrix = Matrix::new(4, 4, 2.0); - - result_matrix.set(0, 0, -5.0); - matrix2.set(0, 0, 7.0); - matrix1 = matrix1 - matrix2; - - assert_eq!(matrix1, result_matrix); - } - - #[test] - #[should_panic] - fn substract_two_matrix_3() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let matrix2 = Matrix::new(4, 5, 0.0); - - matrix1 = matrix1 - matrix2; - } - - #[test] - fn get_row_1() { - let mut matrix1 = Matrix::new(3, 4, 0.0); - matrix1.set(0, 0, 8.0); - matrix1.set(0, 1, 7.0); - matrix1.set(0, 2, 9.0); - matrix1.set(0, 3, 6.0); - - let data = vec![8.0, 7.0, 9.0, 6.0]; - - assert_eq!(matrix1.get_row(0), data); - } - - #[test] - fn get_row_2() { - let mut matrix1 = Matrix::new(3, 4, 0.0); - - matrix1.set(2, 0, 8.0); - matrix1.set(2, 1, 7.0); - matrix1.set(2, 2, 9.0); - matrix1.set(2, 3, 6.0); - - let data = vec![8.0, 7.0, 9.0, 6.0]; - - assert_eq!(matrix1.get_row(2), data); - } - - #[test] - #[should_panic] - fn get_row_3() { - let matrix1 = Matrix::new(3, 4, 0.0); - - let _data = matrix1.get_row(4); - } - - #[test] - fn get_column_1() { - let mut matrix1 = Matrix::new(4, 3, 0.0); - matrix1.set(0, 0, 8.0); - matrix1.set(1, 0, 7.0); - matrix1.set(2, 0, 9.0); - matrix1.set(3, 0, 6.0); - - let data = vec![8.0, 7.0, 9.0, 6.0]; - - assert_eq!(matrix1.get_column(0), data); - } - - #[test] - fn get_column_2() { - let mut matrix1 = Matrix::new(4, 3, 0.0); - - matrix1.set(0, 2, 8.0); - matrix1.set(1, 2, 7.0); - matrix1.set(2, 2, 9.0); - matrix1.set(3, 2, 6.0); - - let data = vec![8.0, 7.0, 9.0, 6.0]; - - assert_eq!(matrix1.get_column(2), data); - } - - #[test] - #[should_panic] - fn get_column_3() { - let matrix1 = Matrix::new(4, 4, 0.0); - - let _data = matrix1.get_column(4); - } - - #[test] - fn mult_matrix_1() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let matrix2 = Matrix::new(4, 4, 2.0); - let result_matrix = Matrix::new(4, 4, 16.0); - - matrix1 = matrix1 * matrix2; - - assert_eq!(matrix1, result_matrix); - } - - #[test] - fn mult_matrix_2() { - let mut matrix1 = Matrix::new(4, 4, 2.0); - let mut matrix2 = Matrix::new(4, 3, 4.0); - let mut result_matrix = Matrix::new(4, 3, 0.0); - - matrix1.set(0, 0, 6.0); - matrix1.set(0, 1, 8.0); - matrix1.set(0, 2, 9.0); - matrix1.set(0, 3, 5.0); - matrix1.set(1, 0, 3.0); - matrix1.set(1, 1, 8.0); - matrix1.set(1, 2, 4.0); - matrix1.set(1, 3, 7.0); - matrix1.set(2, 0, 4.0); - matrix1.set(2, 1, 5.0); - matrix1.set(2, 2, 6.0); - matrix1.set(2, 3, 4.0); - matrix1.set(3, 0, 6.0); - matrix1.set(3, 1, 2.0); - matrix1.set(3, 2, 2.0); - matrix1.set(3, 3, 9.0); - - matrix2.set(0, 0, 7.0); - matrix2.set(0, 1, 6.0); - matrix2.set(0, 2, 1.0); - matrix2.set(1, 0, 6.0); - matrix2.set(1, 1, 4.0); - matrix2.set(1, 2, 8.0); - matrix2.set(2, 0, 3.0); - matrix2.set(2, 1, 0.0); - matrix2.set(2, 2, 6.0); - matrix2.set(3, 0, 1.0); - matrix2.set(3, 1, 1.0); - matrix2.set(3, 2, 1.0); - - result_matrix.set(0, 0, 122.0); - result_matrix.set(0, 1, 73.0); - result_matrix.set(0, 2, 129.0); - result_matrix.set(1, 0, 88.0); - result_matrix.set(1, 1, 57.0); - result_matrix.set(1, 2, 98.0); - result_matrix.set(2, 0, 80.0); - result_matrix.set(2, 1, 48.0); - result_matrix.set(2, 2, 84.0); - result_matrix.set(3, 0, 69.0); - result_matrix.set(3, 1, 53.0); - result_matrix.set(3, 2, 43.0); - - matrix1 = matrix1 * matrix2; - - assert_eq!(result_matrix, matrix1); - } - - #[test] - fn exchange_rows_1() { - let mut matrix = Matrix::new(3, 4, 5.0); - matrix.set(0, 0, 1.0); - matrix.set(0, 1, 2.0); - matrix.set(0, 2, 3.0); - matrix.set(0, 3, 4.0); - matrix.set(1, 0, 5.0); - matrix.set(1, 1, 6.0); - matrix.set(1, 2, 7.0); - matrix.set(1, 3, 8.0); - - matrix.exchange_rows(0, 1); - - let row1 = vec![1.0, 2.0, 3.0, 4.0]; - let row2 = vec![5.0, 6.0, 7.0, 8.0]; - - assert_eq!(row1, matrix.get_row(1)); - assert_eq!(row2, matrix.get_row(0)); - } - - #[test] - fn exchange_rows_2() { - let mut matrix = Matrix::new(3, 4, 5.0); - matrix.set(0, 0, 1.0); - matrix.set(0, 1, 2.0); - matrix.set(0, 2, 3.0); - matrix.set(0, 3, 4.0); - matrix.set(2, 0, 5.0); - matrix.set(2, 1, 6.0); - matrix.set(2, 2, 7.0); - matrix.set(2, 3, 8.0); - - matrix.exchange_rows(0, 2); - - let row1 = vec![1.0, 2.0, 3.0, 4.0]; - let row2 = vec![5.0, 6.0, 7.0, 8.0]; - - assert_eq!(row1, matrix.get_row(2)); - assert_eq!(row2, matrix.get_row(0)); - } - - #[test] - fn exchange_columns_1() { - let mut matrix = Matrix::new(3, 4, 5.0); - matrix.set(0, 0, 1.0); - matrix.set(1, 0, 2.0); - matrix.set(2, 0, 3.0); - matrix.set(0, 1, 4.0); - matrix.set(1, 1, 5.0); - matrix.set(2, 1, 6.0); - - matrix.exchange_columns(0, 1); - - let column1 = vec![1.0, 2.0, 3.0]; - let column2 = vec![4.0, 5.0, 6.0]; - - assert_eq!(column1, matrix.get_column(1)); - assert_eq!(column2, matrix.get_column(0)); - } - - #[test] - fn exchange_columns_2() { - let mut matrix = Matrix::new(3, 4, 5.0); - matrix.set(0, 0, 1.0); - matrix.set(1, 0, 2.0); - matrix.set(2, 0, 3.0); - matrix.set(0, 3, 4.0); - matrix.set(1, 3, 5.0); - matrix.set(2, 3, 6.0); - - matrix.exchange_columns(0, 3); - - let column1 = vec![1.0, 2.0, 3.0]; - let column2 = vec![4.0, 5.0, 6.0]; - - assert_eq!(column1, matrix.get_column(3)); - assert_eq!(column2, matrix.get_column(0)); - } - - #[test] - fn set_row_1() { - let mut matrix = Matrix::new(3, 4, 5.0); - let vec1 = vec![1.0, 2.0, 3.0, 4.0]; - matrix.set_row(0, vec1); - - let vec2 = vec![1.0, 2.0, 3.0, 4.0]; - let row = matrix.get_row(0); - assert_eq!(row, vec2); - } - - #[test] - fn set_row_2() { - let mut matrix = Matrix::new(3, 4, 5.0); - let vec1 = vec![1.0, 2.0, 3.0, 4.0]; - matrix.set_row(2, vec1); - - let vec2 = vec![1.0, 2.0, 3.0, 4.0]; - let row = matrix.get_row(2); - assert_eq!(row, vec2); - } - - #[test] - fn set_column_1() { - let mut matrix = Matrix::new(3, 4, 5.0); - let vec1 = vec![1.0, 2.0, 3.0]; - matrix.set_column(0, vec1); - - let vec2 = vec![1.0, 2.0, 3.0]; - let column = matrix.get_column(0); - assert_eq!(column, vec2); - } - - #[test] - fn set_column_2() { - let mut matrix = Matrix::new(3, 4, 5.0); - let vec1 = vec![1.0, 2.0, 3.0]; - matrix.set_column(3, vec1); - - let vec2 = vec![1.0, 2.0, 3.0]; - let column = matrix.get_column(3); - assert_eq!(column, vec2); - } - - #[test] - fn get_diagonal_1() { - let mut matrix = Matrix::new(3, 3, 8.0); - matrix.set(0, 0, 1.0); - matrix.set(1, 1, 2.0); - matrix.set(2, 2, 3.0); - - let vec1 = vec![1.0, 2.0, 3.0]; - assert_eq!(matrix.get_diagonal(), vec1); - } - - #[test] - fn get_diagonal_2() { - let mut matrix = Matrix::new(4, 4, 8.0); - matrix.set(0, 0, 1.0); - matrix.set(1, 1, 2.0); - matrix.set(2, 2, 3.0); - matrix.set(3, 3, 4.0); - - let vec1 = vec![1.0, 2.0, 3.0, 4.0]; - assert_eq!(matrix.get_diagonal(), vec1); - } - - #[test] - fn get_determinant_1() { - let mut matrix = Matrix::new(2, 2, 0.0); - matrix.set(0, 0, 2.0); - matrix.set(1, 0, 4.0); - matrix.set(0, 1, 3.0); - matrix.set(1, 1, 5.0); - - assert_eq!(matrix.get_determinant(), -2.0); - } - - #[test] - fn get_determinant_2() { - let mut matrix = Matrix::new(3, 3, 0.0); - matrix.set(0, 0, 3.0); - matrix.set(1, 0, 4.0); - matrix.set(2, 0, 7.0); - matrix.set(0, 1, 2.0); - matrix.set(1, 1, 5.0); - matrix.set(2, 1, 8.0); - matrix.set(0, 2, 1.0); - matrix.set(1, 2, 6.0); - matrix.set(2, 2, 9.0); - - assert_eq!(matrix.get_determinant(), 0.0); - } - - #[test] - fn get_determinant_3() { - let mut matrix = Matrix::new(3, 3, 0.0); - matrix.set(0, 0, 0.0); - matrix.set(1, 0, 1.0); - matrix.set(2, 0, 2.0); - matrix.set(0, 1, 2.0); - matrix.set(1, 1, 3.0); - matrix.set(2, 1, 1.0); - matrix.set(0, 2, 1.0); - matrix.set(1, 2, 4.0); - matrix.set(2, 2, 3.0); - - assert_eq!(matrix.get_determinant(), 5.0); - } - - #[test] - fn get_determinant_4() { - let mut matrix = Matrix::new(3, 3, 0.0); - matrix.set(0, 0, 2.0); - matrix.set(1, 0, 0.0); - matrix.set(2, 0, 1.0); - matrix.set(0, 1, 3.0); - matrix.set(1, 1, 4.0); - matrix.set(2, 1, 0.0); - matrix.set(0, 2, 5.0); - matrix.set(1, 2, 1.0); - matrix.set(2, 2, 6.0); - - assert_eq!(matrix.get_determinant(), 31.0); - } } diff --git a/src/main.rs b/src/main.rs index 2c03b9a..b9c226b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,3 @@ -use matrix::Matrix; - fn main() { println!("Hola mundo que rollo wey"); - let mut matriz1 = Matrix::new(10, 15, 0.0); - matriz1.set(5, 5, 40.0); - println!("{}", matriz1); }