From 38c5c284544282c804803934f14d543d9b096aa9 Mon Sep 17 00:00:00 2001 From: Palash Tyagi <23239946+Magnus167@users.noreply.github.com> Date: Thu, 1 May 2025 23:10:51 +0100 Subject: [PATCH] Enhance matrix assertions for row and column operations to allow 0-row matrices with empty columns and improve error messages for index out of bounds. --- src/matrix/mat.rs | 62 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/matrix/mat.rs b/src/matrix/mat.rs index 02a042b..07a3d3d 100644 --- a/src/matrix/mat.rs +++ b/src/matrix/mat.rs @@ -14,7 +14,11 @@ impl Matrix { let cols = cols_data.len(); assert!(cols > 0, "need at least one column"); let rows = cols_data[0].len(); - assert!(rows > 0, "need at least one row"); + // Allow 0-row matrices if columns are empty, but not 0-col matrices if rows > 0 + assert!( + rows > 0 || cols == 0, + "need at least one row if columns exist" + ); for (i, col) in cols_data.iter().enumerate().skip(1) { assert!( col.len() == rows, @@ -32,8 +36,14 @@ impl Matrix { } pub fn from_vec(data: Vec, rows: usize, cols: usize) -> Self { - assert!(rows > 0, "need at least one row"); - assert!(cols > 0, "need at least one column"); + assert!( + rows > 0 || cols == 0, + "need at least one row if columns exist" + ); + assert!( + cols > 0 || rows == 0, + "need at least one column if rows exist" + ); assert_eq!(data.len(), rows * cols, "data length mismatch"); Matrix { rows, cols, data } } @@ -67,11 +77,23 @@ impl Matrix { #[inline] pub fn column(&self, c: usize) -> &[T] { + assert!( + c < self.cols, + "column index {} out of bounds for {} columns", + c, + self.cols + ); let start = c * self.rows; &self.data[start..start + self.rows] } #[inline] pub fn column_mut(&mut self, c: usize) -> &mut [T] { + assert!( + c < self.cols, + "column index {} out of bounds for {} columns", + c, + self.cols + ); let start = c * self.rows; &mut self.data[start..start + self.rows] } @@ -90,8 +112,16 @@ impl Matrix { /// Swaps two columns in the matrix. pub fn swap_columns(&mut self, c1: usize, c2: usize) { assert!( - c1 < self.cols && c2 < self.cols, - "column index out of bounds" + c1 < self.cols, + "column index c1={} out of bounds for {} columns", + c1, + self.cols + ); + assert!( + c2 < self.cols, + "column index c2={} out of bounds for {} columns", + c2, + self.cols ); if c1 == c2 { // Indices are equal; no operation required @@ -132,7 +162,7 @@ impl Matrix { impl Matrix { /// Adds a column to the matrix at the specified index. pub fn add_column(&mut self, index: usize, column: Vec) { - assert!(index <= self.cols, "column index out of bounds"); + assert!(index <= self.cols, "add_column index {} out of bounds for {} columns", index, self.cols); assert_eq!(column.len(), self.rows, "column length mismatch"); for (r, value) in column.into_iter().enumerate() { @@ -143,7 +173,7 @@ impl Matrix { /// Adds a row to the matrix at the specified index. pub fn add_row(&mut self, index: usize, row: Vec) { - assert!(index <= self.rows, "row index out of bounds"); + assert!(index <= self.rows, "add_row index {} out of bounds for {} rows", index, self.rows); assert_eq!(row.len(), self.cols, "row length mismatch"); for (c, value) in row.into_iter().enumerate() { @@ -159,7 +189,14 @@ impl Index<(usize, usize)> for Matrix { #[inline] fn index(&self, (r, c): (usize, usize)) -> &T { // Validate that the requested indices are within bounds - assert!(r < self.rows && c < self.cols, "index out of bounds"); + assert!( + r < self.rows && c < self.cols, + "index out of bounds: ({}, {}) vs {}x{}", + r, + c, + self.rows, + self.cols + ); // Compute column-major offset and return reference &self.data[c * self.rows + r] } @@ -169,7 +206,14 @@ impl IndexMut<(usize, usize)> for Matrix { #[inline] fn index_mut(&mut self, (r, c): (usize, usize)) -> &mut T { // Validate that the requested indices are within bounds - assert!(r < self.rows && c < self.cols, "index out of bounds"); + assert!( + r < self.rows && c < self.cols, + "index out of bounds: ({}, {}) vs {}x{}", + r, + c, + self.rows, + self.cols + ); // Compute column-major offset and return mutable reference &mut self.data[c * self.rows + r] }