diff --git a/src/lib.rs b/src/lib.rs index e153641..bfaaeac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![warn(clippy::all, clippy::pedantic)] - +// TODO: Update documentation /*! # Two Dimensional Grid Continuous growable 2D data structure. @@ -83,6 +83,7 @@ macro_rules! count { /// [4, 5] // This does not work! /// [7, 8, 9]]; /// ``` +// TODO: Add a way to change grid order #[macro_export] macro_rules! grid { () => { @@ -115,6 +116,26 @@ macro_rules! grid { }; } +/// Define the order of data inside the internal vector of the grid. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum Order { + /// The data is ordered row by row. + #[default] + RowMajor, + + /// The data is ordered column by column. + ColumnMajor, +} + +impl Order { + fn counterpart(self) -> Self { + match self { + Self::RowMajor => Self::ColumnMajor, + Self::ColumnMajor => Self::RowMajor, + } + } +} + /// Stores elements of a certain type in a 2D grid structure. /// /// Uses a rust `Vec` type to reference the grid data on the heap. @@ -127,6 +148,7 @@ pub struct Grid { data: Vec, cols: usize, rows: usize, + order: Order, } impl Grid { @@ -143,21 +165,41 @@ impl Grid { /// /// # Panics /// - /// Panics if `rows * cols > usize`. - pub fn new(rows: usize, cols: usize) -> Grid + /// Panics if `rows * cols > usize::MAX`. + #[must_use] + #[inline] + pub fn new(rows: usize, cols: usize) -> Self + where + T: Default, + { + Self::new_with_order(rows, cols, Order::default()) + } + + /// Same as [`new`](Self::new) but with a specific [`Order`]. + /// + /// # Panics + /// + /// Panics if `rows * cols > usize::MAX`. + pub fn new_with_order(rows: usize, cols: usize, order: Order) -> Self where T: Default, { if rows == 0 || cols == 0 { - return Grid { + return Self { data: Vec::new(), rows: 0, cols: 0, + order, }; } let mut data = Vec::new(); data.resize_with(rows.checked_mul(cols).unwrap(), T::default); - Grid { data, cols, rows } + Self { + data, + cols, + rows, + order, + } } /// Init a grid of size rows x columns with the given data element. @@ -166,22 +208,37 @@ impl Grid { /// /// # Panics /// - /// Panics if `rows * cols > usize`. - pub fn init(rows: usize, cols: usize, data: T) -> Grid + /// Panics if `rows * cols > usize::MAX`. + #[inline] + pub fn init(rows: usize, cols: usize, data: T) -> Self + where + T: Clone, + { + Self::init_with_order(rows, cols, Order::default(), data) + } + + /// Same as [`init`](Self::init) but with a specific [`Order`]. + /// + /// # Panics + /// + /// Panics if `rows * cols > usize::MAX`. + pub fn init_with_order(rows: usize, cols: usize, order: Order, data: T) -> Self where T: Clone, { if rows == 0 || cols == 0 { - return Grid { + return Self { data: Vec::new(), rows: 0, cols: 0, + order, }; } - Grid { + Self { data: vec![data; rows.checked_mul(cols).unwrap()], cols, rows, + order, } } @@ -211,7 +268,18 @@ impl Grid { /// /// This panics if the vector length isn't a multiple of the number of columns. #[must_use] - pub fn from_vec(vec: Vec, cols: usize) -> Grid { + #[inline] + pub fn from_vec(vec: Vec, cols: usize) -> Self { + Self::from_vec_with_order(vec, cols, Order::default()) + } + + /// Same as [`from_vec`](Self::from_vec) but with a specific [`Order`]. + /// + /// # Panics + /// + /// This panics if the vector length isn't a multiple of the number of columns. + #[must_use] + pub fn from_vec_with_order(vec: Vec, cols: usize, order: Order) -> Self { let rows = vec.len().checked_div(cols).unwrap_or(0); assert_eq!( rows * cols, @@ -225,16 +293,28 @@ impl Grid { data: vec, rows: 0, cols: 0, + order, } } else { Grid { data: vec, rows, cols, + order, } } } + /// Returns the index of the coordinates in the internal vector. + #[inline] + #[must_use] + fn get_index(&self, row: usize, col: usize) -> usize { + match self.order { + Order::RowMajor => row * self.cols + col, + Order::ColumnMajor => col * self.rows + row, + } + } + /// Returns a reference to an element, without performing bound checks. /// Generally not recommended, use with caution! /// @@ -244,7 +324,8 @@ impl Grid { #[inline] #[must_use] pub unsafe fn get_unchecked(&self, row: usize, col: usize) -> &T { - self.data.get_unchecked(row * self.cols + col) + let index = self.get_index(row, col); + self.data.get_unchecked(index) } /// Returns a mutable reference to an element, without performing bound checks. @@ -256,7 +337,8 @@ impl Grid { #[inline] #[must_use] pub unsafe fn get_unchecked_mut(&mut self, row: usize, col: usize) -> &mut T { - self.data.get_unchecked_mut(row * self.cols + col) + let index = self.get_index(row, col); + self.data.get_unchecked_mut(index) } /// Access a certain element in the grid. @@ -313,6 +395,8 @@ impl Grid { } /// Clears the grid. + /// + /// This doesn't change the grid order. pub fn clear(&mut self) { self.rows = 0; self.cols = 0; @@ -364,13 +448,19 @@ impl Grid { /// /// Panics if the col index is out of bounds. pub fn iter_col(&self, col: usize) -> StepBy> { - if col < self.cols { - return self.data[col..].iter().step_by(self.cols); + assert!( + col < self.cols, + "out of bounds. Column must be less than {:?}, but is {:?}", + self.cols, + col + ); + match self.order { + Order::RowMajor => self.data[col..].iter().step_by(self.cols), + Order::ColumnMajor => { + let start = col * self.rows; + self.data[start..(start + self.rows)].iter().step_by(1) + } } - panic!( - "out of bounds. Column must be less than {:?}, but is {:?}.", - self.cols, col - ) } /// Returns a mutable iterator over a column. @@ -391,14 +481,19 @@ impl Grid { /// /// Panics if the col index is out of bounds. pub fn iter_col_mut(&mut self, col: usize) -> StepBy> { - let cols = self.cols; - if col < cols { - return self.data[col..].iter_mut().step_by(cols); + assert!( + col < self.cols, + "out of bounds. Column must be less than {:?}, but is {:?}", + self.cols, + col + ); + match self.order { + Order::RowMajor => self.data[col..].iter_mut().step_by(self.cols), + Order::ColumnMajor => { + let start = col * self.rows; + self.data[start..(start + self.rows)].iter_mut().step_by(1) + } } - panic!( - "out of bounds. Column must be less than {:?}, but is {:?}.", - self.cols, col - ) } /// Returns an iterator over a row. @@ -418,15 +513,19 @@ impl Grid { /// # Panics /// /// Panics if the row index is out of bounds. - pub fn iter_row(&self, row: usize) -> Iter { - if row < self.rows { - let start = row * self.cols; - self.data[start..(start + self.cols)].iter() - } else { - panic!( - "out of bounds. Row must be less than {:?}, but is {:?}.", - self.rows, row - ) + pub fn iter_row(&self, row: usize) -> StepBy> { + assert!( + row < self.rows, + "out of bounds. Row must be less than {:?}, but is {:?}", + self.rows, + row + ); + match self.order { + Order::RowMajor => { + let start = row * self.cols; + self.data[start..(start + self.cols)].iter().step_by(1) + } + Order::ColumnMajor => self.data[row..].iter().step_by(self.rows), } } @@ -446,16 +545,19 @@ impl Grid { /// # Panics /// /// Panics if the row index is out of bounds. - pub fn iter_row_mut(&mut self, row: usize) -> IterMut { - if row < self.rows { - let cols = self.cols; - let start = row * cols; - self.data[start..(start + cols)].iter_mut() - } else { - panic!( - "out of bounds. Row must be less than {:?}, but is {:?}.", - self.rows, row - ) + pub fn iter_row_mut(&mut self, row: usize) -> StepBy> { + assert!( + row < self.rows, + "out of bounds. Row must be less than {:?}, but is {:?}", + self.rows, + row + ); + match self.order { + Order::RowMajor => { + let start = row * self.cols; + self.data[start..(start + self.cols)].iter_mut().step_by(1) + } + Order::ColumnMajor => self.data[row..].iter_mut().step_by(self.rows), } } @@ -480,10 +582,13 @@ impl Grid { /// } /// ``` pub fn indexed_iter(&self) -> impl Iterator { - self.data - .iter() - .enumerate() - .map(move |(idx, i)| ((idx / self.cols, idx % self.cols), i)) + self.data.iter().enumerate().map(move |(idx, i)| { + let position = match self.order { + Order::RowMajor => (idx / self.cols, idx % self.cols), + Order::ColumnMajor => (idx % self.rows, idx / self.rows), + }; + (position, i) + }) } /// Add a new row to the grid. @@ -525,6 +630,12 @@ impl Grid { row.len() ); self.data.extend(row); + if self.order == Order::ColumnMajor { + for i in (1..self.cols).rev() { + let col_idx = i * self.rows; + self.data[col_idx..col_idx + self.rows + i].rotate_right(i); + } + } self.rows += 1; if self.cols == 0 { self.cols = self.data.len(); @@ -573,9 +684,11 @@ impl Grid { col.len() ); self.data.extend(col); - for i in (1..self.rows).rev() { - let row_idx = i * self.cols; - self.data[row_idx..row_idx + self.cols + i].rotate_right(i); + if self.order == Order::RowMajor { + for i in (1..self.rows).rev() { + let row_idx = i * self.cols; + self.data[row_idx..row_idx + self.cols + i].rotate_right(i); + } } self.cols += 1; if self.rows == 0 { @@ -597,7 +710,13 @@ impl Grid { if self.rows == 0 { return None; } - let row = self.data.split_off((self.rows - 1) * self.cols); + if self.order == Order::ColumnMajor { + for i in 1..self.cols { + let col_idx = i * (self.rows - 1); + self.data[col_idx..col_idx + self.rows + i - 1].rotate_left(i); + } + } + let row = self.data.split_off(self.data.len() - self.cols); self.rows -= 1; if self.rows == 0 { self.cols = 0; @@ -620,15 +739,25 @@ impl Grid { if self.cols == 0 || self.rows == 0 || row_index >= self.rows { return None; } - let residue = self - .data - .drain((row_index * self.cols)..((row_index + 1) * self.cols)); - + let row = match self.order { + Order::RowMajor => self + .data + .drain((row_index * self.cols)..((row_index + 1) * self.cols)) + .collect(), + Order::ColumnMajor => { + for i in 0..self.cols { + let col_idx = row_index + i * (self.rows - 1); + let end = cmp::min(col_idx + self.rows + i, self.data.len()); + self.data[col_idx..end].rotate_left(i + 1); + } + self.data.split_off(self.data.len() - self.cols) + } + }; self.rows -= 1; if self.rows == 0 { self.cols = 0; } - Some(residue.collect()) + Some(row) } /// Removes the last column from a grid and returns it, or None if it is empty. @@ -649,9 +778,11 @@ impl Grid { if self.cols == 0 { return None; } - for i in 1..self.rows { - let row_idx = i * (self.cols - 1); - self.data[row_idx..row_idx + self.cols + i - 1].rotate_left(i); + if self.order == Order::RowMajor { + for i in 1..self.rows { + let row_idx = i * (self.cols - 1); + self.data[row_idx..row_idx + self.cols + i - 1].rotate_left(i); + } } let col = self.data.split_off(self.data.len() - self.rows); self.cols -= 1; @@ -677,12 +808,20 @@ impl Grid { if self.cols == 0 || self.rows == 0 || col_index >= self.cols { return None; } - for i in 0..self.rows { - let row_idx = col_index + i * (self.cols - 1); - let end = cmp::min(row_idx + self.cols + i, self.data.len()); - self.data[row_idx..end].rotate_left(i + 1); - } - let col = self.data.split_off(self.data.len() - self.rows); + let col = match self.order { + Order::RowMajor => { + for i in 0..self.rows { + let row_idx = col_index + i * (self.cols - 1); + let end = cmp::min(row_idx + self.cols + i, self.data.len()); + self.data[row_idx..end].rotate_left(i + 1); + } + self.data.split_off(self.data.len() - self.rows) + } + Order::ColumnMajor => self + .data + .drain((col_index * self.rows)..((col_index + 1) * self.rows)) + .collect(), + }; self.cols -= 1; if self.cols == 0 { self.rows = 0; @@ -722,8 +861,18 @@ impl Grid { index, self.rows ); - let data_idx = index * input_len; - self.data.splice(data_idx..data_idx, row.into_iter()); + match self.order { + Order::RowMajor => { + let data_idx = index * input_len; + self.data.splice(data_idx..data_idx, row); + } + Order::ColumnMajor => { + for (col_iter, row_val) in row.into_iter().enumerate() { + let data_idx = col_iter * self.rows + index + col_iter; + self.data.insert(data_idx, row_val); + } + } + } self.cols = input_len; self.rows += 1; } @@ -762,9 +911,17 @@ impl Grid { index, self.cols ); - for (row_iter, col_val) in col.into_iter().enumerate() { - let data_idx = row_iter * self.cols + index + row_iter; - self.data.insert(data_idx, col_val); + match self.order { + Order::RowMajor => { + for (row_iter, col_val) in col.into_iter().enumerate() { + let data_idx = row_iter * self.cols + index + row_iter; + self.data.insert(data_idx, col_val); + } + } + Order::ColumnMajor => { + let data_idx = index * input_len; + self.data.splice(data_idx..data_idx, col); + } } self.rows = input_len; self.cols += 1; @@ -772,8 +929,8 @@ impl Grid { /// Returns a reference to the internal data structure of the grid. /// - /// Grid uses a row major layout. - /// All rows are placed right after each other in the vector data structure. + /// The order of the elements depends on the grid order, which is + /// row-major by default. /// /// # Examples /// ``` @@ -788,55 +945,95 @@ impl Grid { } /// Converts self into a vector without clones or allocation. + /// + /// This vector represents the internal data structure of the grid, and + /// can be in row-major or column-major order, depending on the grid. #[must_use] pub fn into_vec(self) -> Vec { self.data } /// Transpose the grid so that columns become rows in new grid. - #[must_use] - pub fn transpose(&self) -> Grid - where - T: Clone, - { - let mut data = Vec::with_capacity(self.data.len()); - for c in 0..self.cols { - for r in 0..self.rows { - data.push(self[r][c].clone()); + /// + /// This changes the grid order. + pub fn transpose(&mut self) { + self.order = self.order.counterpart(); + core::mem::swap(&mut self.rows, &mut self.cols); + } + + /// Flip (or mirrors) the columns. + /// + /// # Examples + /// + /// ``` + /// use grid::*; + /// let mut grid = grid![[1,2,3][4,5,6]]; + /// grid.flip_cols(); + /// assert_eq!(grid, grid![[3,2,1][6,5,4]]) + /// ``` + pub fn flip_cols(&mut self) { + match self.order { + Order::RowMajor => { + for row in 0..self.rows { + let idx = row * self.cols; + self.data[idx..idx + self.cols].reverse(); + } + } + Order::ColumnMajor => { + for col in 0..self.cols / 2 { + for row in 0..self.rows { + let cell1 = self.get_index(row, col); + let cell2 = self.get_index(row, self.cols - col - 1); + self.data.swap(cell1, cell2); + } + } } - } - Grid { - data, - cols: self.rows, - rows: self.cols, } } - /// Rotate the grid 90° counter-clockwise. + /// Flip (or mirrors) the rows. /// /// # Examples /// /// ``` /// use grid::*; - /// let grid = grid![[1,2,3][4,5,6]]; - /// assert_eq!(grid.rotate_left(), grid![[3,6][2,5][1,4]]); + /// let mut grid = grid![[1,2,3][4,5,6]]; + /// grid.flip_rows(); + /// assert_eq!(grid, grid![[4,5,6][1,2,3]]) /// ``` - #[must_use] - pub fn rotate_left(&self) -> Grid - where - T: Clone, - { - let mut data = Vec::with_capacity(self.data.len()); - for c in (0..self.cols).rev() { - for r in 0..self.rows { - data.push(self[r][c].clone()); + pub fn flip_rows(&mut self) { + match self.order { + Order::RowMajor => { + for row in 0..self.rows / 2 { + for col in 0..self.cols { + let cell1 = self.get_index(row, col); + let cell2 = self.get_index(self.rows - row - 1, col); + self.data.swap(cell1, cell2); + } + } + } + Order::ColumnMajor => { + for col in 0..self.cols { + let idx = col * self.rows; + self.data[idx..idx + self.rows].reverse(); + } } } - Grid { - data, - cols: self.rows, - rows: self.cols, - } + } + + /// Rotate the grid 90° counter-clockwise. + /// + /// # Examples + /// + /// ``` + /// use grid::*; + /// let mut grid = grid![[1,2][3,4]]; + /// grid.rotate_left(); + /// assert_eq!(grid, grid![[2,4][1,3]]); + /// ``` + pub fn rotate_left(&mut self) { + self.transpose(); + self.flip_rows(); } /// Rotate the grid 90° clockwise. @@ -845,25 +1042,13 @@ impl Grid { /// /// ``` /// use grid::*; - /// let grid = grid![[1,2,3][4,5,6]]; - /// assert_eq!(grid.rotate_right(), grid![[4,1][5,2][6,3]]); + /// let mut grid = grid![[1,2][3,4]]; + /// grid.rotate_right(); + /// assert_eq!(grid, grid![[3,1][4,2]]); /// ``` - #[must_use] - pub fn rotate_right(&self) -> Grid - where - T: Clone, - { - let mut data = Vec::with_capacity(self.data.len()); - for c in 0..self.cols { - for r in (0..self.rows).rev() { - data.push(self[r][c].clone()); - } - } - Grid { - data, - cols: self.rows, - rows: self.cols, - } + pub fn rotate_right(&mut self) { + self.transpose(); + self.flip_cols(); } /// Rotate the grid 180°. @@ -872,20 +1057,12 @@ impl Grid { /// /// ``` /// use grid::*; - /// let grid = grid![[1,2,3][4,5,6]]; - /// assert_eq!(grid.rotate_half(), grid![[6,5,4][3,2,1]]); + /// let mut grid = grid![[1,2,3][4,5,6]]; + /// grid.rotate_half(); + /// assert_eq!(grid, grid![[6,5,4][3,2,1]]); /// ``` - #[must_use] - pub fn rotate_half(&self) -> Grid - where - T: Clone, - { - let data: Vec<_> = self.data.iter().rev().cloned().collect(); - Grid { - data, - cols: self.cols, - rows: self.rows, - } + pub fn rotate_half(&mut self) { + self.data.reverse(); } /// Fills the grid with elements by cloning `value`. @@ -982,11 +1159,13 @@ impl Clone for Grid { rows: self.rows, cols: self.cols, data: self.data.clone(), + order: self.order, } } } impl Index for Grid { + // TODO: Rework type Output = [T]; #[inline] @@ -997,6 +1176,7 @@ impl Index for Grid { } impl IndexMut for Grid { + // TODO: Rework #[inline] fn index_mut(&mut self, idx: usize) -> &mut [T] { let start_idx = idx * self.cols; @@ -1015,7 +1195,8 @@ impl Index<(usize, usize)> for Grid { self.rows, self.cols ); - &self.data[row * self.cols + col] + let index = self.get_index(row, col); + &self.data[index] } } @@ -1028,53 +1209,45 @@ impl IndexMut<(usize, usize)> for Grid { self.rows, self.cols ); - &mut self.data[row * self.cols + col] + let index = self.get_index(row, col); + &mut self.data[index] } } impl fmt::Debug for Grid { - #[allow(unused_must_use)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "["); + write!(f, "[")?; if self.cols > 0 { if f.alternate() { - writeln!(f); + writeln!(f)?; /* WARNING Compound types becoming enormous as the entire `fmt::Debug` width is applied to each item individually. For tuples and structs define padding and precision arguments manually to improve readability. */ - let width = f.width().unwrap_or( - /* - Conditionally calculate the longest item by default. - */ + let width = f.width().unwrap_or_else(|| { + // Conditionally calculate the longest item by default. self.data .iter() .map(|i| format!("{i:?}").len()) .max() - .unwrap(), - ); + .unwrap() + }); let precision = f.precision().unwrap_or(2); - for (i, _) in self.data.iter().enumerate().step_by(self.cols) { - let mut row = self.data[i..(i + self.cols)].iter().peekable(); - write!(f, " ["); + for mut row in self.iter_rows().map(Iterator::peekable) { + write!(f, " [")?; while let Some(item) = row.next() { - write!( - f, - " {item:width$.precision$?}", - // width = width, - // precision = precision - ); + write!(f, " {item:width$.precision$?}")?; if row.peek().is_some() { - write!(f, ","); + write!(f, ",")?; } } - writeln!(f, "]"); + writeln!(f, "]")?; } } else { - for (i, _) in self.data.iter().enumerate().step_by(self.cols) { - write!(f, "{:?}", &self.data[i..(i + self.cols)]); + for row in self.iter_rows() { + f.debug_list().entries(row).finish()?; } } } @@ -1084,7 +1257,18 @@ impl fmt::Debug for Grid { impl PartialEq for Grid { fn eq(&self, other: &Self) -> bool { - self.rows == other.rows && self.cols == other.cols && self.data == other.data + if self.rows != other.rows || self.cols != other.cols { + return false; + } + if self.order == other.order { + return self.data == other.data; + } + for (self_row, other_row) in core::iter::zip(self.iter_rows(), other.iter_rows()) { + if self_row.ne(other_row) { + return false; + } + } + true } } @@ -1100,7 +1284,7 @@ pub struct GridColIter<'a, T> { } impl<'a, T> Iterator for GridRowIter<'a, T> { - type Item = Iter<'a, T>; + type Item = StepBy>; fn next(&mut self) -> Option { let rows = self.grid.rows(); @@ -1139,148 +1323,342 @@ mod test { #[cfg(not(feature = "std"))] use alloc::string::String; + fn test_grid(grid: &Grid, rows: usize, cols: usize, order: Order, data: &[T]) + where + T: fmt::Debug + PartialEq, + { + assert_eq!(grid.rows, rows, "number of rows is unexpected"); + assert_eq!(grid.cols, cols, "number of cols is unexpected"); + assert_eq!(grid.order, order, "grid order is unexpected"); + assert_eq!(grid.data, data, "internal data is unexpected"); + } + #[test] fn from_vec_zero_with_cols() { let grid: Grid = Grid::from_vec(vec![], 1); - assert_eq!(grid.rows(), 0); - assert_eq!(grid.cols(), 0); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn from_vec_zero() { let grid: Grid = Grid::from_vec(vec![], 0); - let _ = grid.is_empty(); - assert_eq!(grid.rows(), 0); - assert_eq!(grid.cols(), 0); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + } + + #[test] + #[should_panic] + fn from_vec_panics_1() { + let _: Grid = Grid::from_vec(vec![1, 2, 3], 0); + } + + #[test] + #[should_panic] + fn from_vec_panics_2() { + let _: Grid = Grid::from_vec(vec![1, 2, 3], 2); + } + + #[test] + fn from_vec_uses_original_vec() { + let capacity = 10_000_000; + let vec = Vec::with_capacity(capacity); + let grid: Grid = Grid::from_vec(vec, 0); + assert!(grid.into_vec().capacity() >= capacity); + } + + #[test] + fn from_vec_with_order_zero_with_cols() { + let grid: Grid = Grid::from_vec_with_order(vec![], 1, Order::ColumnMajor); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn from_vec_with_order_zero() { + let grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + #[should_panic] + fn from_vec_with_order_panics_1() { + let _: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 0, Order::ColumnMajor); + } + + #[test] + #[should_panic] + fn from_vec_with_order_panics_2() { + let _: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 2, Order::ColumnMajor); + } + + #[test] + fn from_vec_with_order_uses_original_vec() { + let capacity = 10_000_000; + let vec = Vec::with_capacity(capacity); + let grid: Grid = Grid::from_vec_with_order(vec, 0, Order::ColumnMajor); + assert!(grid.into_vec().capacity() >= capacity); } #[test] fn insert_col_at_end() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); grid.insert_col(2, vec![5, 6]); - assert_eq!(grid[0], [1, 2, 5]); - assert_eq!(grid[1], [3, 4, 6]); + test_grid(&grid, 2, 3, Order::RowMajor, &[1, 2, 5, 3, 4, 6]); } #[test] #[should_panic] fn insert_col_out_of_idx() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); grid.insert_col(3, vec![4, 5]); } #[test] - fn insert_row_at_end() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); - grid.insert_row(2, vec![5, 6]); - assert_eq!(grid[0], [1, 2]); - assert_eq!(grid[1], [3, 4]); - assert_eq!(grid[2], [5, 6]); + fn insert_col_empty() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); + grid.insert_col(0, vec![1, 2, 3]); + test_grid(&grid, 3, 1, Order::RowMajor, &[1, 2, 3]); } #[test] - fn insert_row_empty() { - let mut grid: Grid = grid![]; - grid.insert_row(0, vec![1, 2, 3]); - assert_eq!(grid[0], [1, 2, 3]); - assert_eq!((1, 3), grid.size()); + fn insert_col_at_end_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.insert_col(2, vec![5, 6]); + test_grid(&grid, 2, 3, Order::ColumnMajor, &[1, 3, 2, 4, 5, 6]); } #[test] - fn insert_col_empty() { - let mut grid: Grid = grid![]; + #[should_panic] + fn insert_col_out_of_idx_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.insert_col(3, vec![4, 5]); + } + + #[test] + fn insert_col_empty_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); grid.insert_col(0, vec![1, 2, 3]); - assert_eq!(grid[0], [1]); - assert_eq!((3, 1), grid.size()); + test_grid(&grid, 3, 1, Order::ColumnMajor, &[1, 2, 3]); + } + + #[test] + fn insert_row_at_end() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); + grid.insert_row(2, vec![5, 6]); + test_grid(&grid, 3, 2, Order::RowMajor, &[1, 2, 3, 4, 5, 6]); + } + + #[test] + fn insert_row_empty() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); + grid.insert_row(0, vec![1, 2, 3]); + test_grid(&grid, 1, 3, Order::RowMajor, &[1, 2, 3]); } #[test] #[should_panic] fn insert_row_out_of_idx() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); grid.insert_row(3, vec![4, 5]); } #[test] #[should_panic] fn insert_row_wrong_size_of_idx() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); grid.insert_row(1, vec![4, 5, 4]); } #[test] fn insert_row_start() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); - let new_row = [5, 6]; - grid.insert_row(1, new_row.to_vec()); - assert_eq!(grid[1], new_row); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); + grid.insert_row(1, vec![5, 6]); + test_grid(&grid, 3, 2, Order::RowMajor, &[1, 2, 5, 6, 3, 4]); + } + + #[test] + fn insert_row_at_end_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.insert_row(2, vec![5, 6]); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[1, 3, 5, 2, 4, 6]); + } + + #[test] + fn insert_row_empty_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + grid.insert_row(0, vec![1, 2, 3]); + test_grid(&grid, 1, 3, Order::ColumnMajor, &[1, 2, 3]); + } + + #[test] + #[should_panic] + fn insert_row_out_of_idx_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::ColumnMajor); + grid.insert_row(3, vec![4, 5]); + } + + #[test] + #[should_panic] + fn insert_row_wrong_size_of_idx_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::ColumnMajor); + grid.insert_row(1, vec![4, 5, 4]); + } + + #[test] + fn insert_row_start_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.insert_row(1, vec![5, 6]); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[1, 5, 3, 2, 6, 4]); } #[test] fn pop_col_1x3() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3], 3); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 3, Order::RowMajor); assert_eq!(grid.pop_col(), Some(vec![3])); - assert_eq!(grid.size(), (1, 2)); + test_grid(&grid, 1, 2, Order::RowMajor, &[1, 2]); assert_eq!(grid.pop_col(), Some(vec![2])); - assert_eq!(grid.size(), (1, 1)); + test_grid(&grid, 1, 1, Order::RowMajor, &[1]); assert_eq!(grid.pop_col(), Some(vec![1])); - assert!(grid.is_empty()); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn pop_col_3x1() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3], 1); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 1, Order::RowMajor); assert_eq!(grid.pop_col(), Some(vec![1, 2, 3])); - assert!(grid.is_empty()); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn pop_col_2x2() { - let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); assert_eq!(grid.pop_col(), Some(vec![2, 4])); assert_eq!(grid.size(), (2, 1)); + test_grid(&grid, 2, 1, Order::RowMajor, &[1, 3]); assert_eq!(grid.pop_col(), Some(vec![1, 3])); - assert_eq!(grid.size(), (0, 0)); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn pop_col_3x4() { - let mut grid: Grid = - Grid::from_vec(vec![1, 2, 3, 4, 11, 22, 33, 44, 111, 222, 333, 444], 4); + let internal = vec![1, 2, 3, 4, 11, 22, 33, 44, 111, 222, 333, 444]; + let mut grid: Grid = Grid::from_vec_with_order(internal, 4, Order::RowMajor); assert_eq!(grid.pop_col(), Some(vec![4, 44, 444])); - assert_eq!(grid.size(), (3, 3)); + let expected = [1, 2, 3, 11, 22, 33, 111, 222, 333]; + test_grid(&grid, 3, 3, Order::RowMajor, &expected); assert_eq!(grid.pop_col(), Some(vec![3, 33, 333])); - assert_eq!(grid.size(), (3, 2)); + test_grid(&grid, 3, 2, Order::RowMajor, &[1, 2, 11, 22, 111, 222]); assert_eq!(grid.pop_col(), Some(vec![2, 22, 222])); - assert_eq!(grid.size(), (3, 1)); + test_grid(&grid, 3, 1, Order::RowMajor, &[1, 11, 111]); assert_eq!(grid.pop_col(), Some(vec![1, 11, 111])); - assert_eq!(grid.size(), (0, 0)); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn pop_col_empty() { - let mut grid: Grid = Grid::from_vec(vec![], 0); - assert_eq!(grid.pop_row(), None); + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + } + + #[test] + fn pop_col_1x3_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 3, Order::ColumnMajor); + assert_eq!(grid.pop_col(), Some(vec![3])); + test_grid(&grid, 1, 2, Order::ColumnMajor, &[1, 2]); + assert_eq!(grid.pop_col(), Some(vec![2])); + test_grid(&grid, 1, 1, Order::ColumnMajor, &[1]); + assert_eq!(grid.pop_col(), Some(vec![1])); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn pop_col_3x1_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 2, 3], 1, Order::ColumnMajor); + assert_eq!(grid.pop_col(), Some(vec![1, 2, 3])); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn pop_col_2x2_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + assert_eq!(grid.pop_col(), Some(vec![2, 4])); + assert_eq!(grid.size(), (2, 1)); + test_grid(&grid, 2, 1, Order::ColumnMajor, &[1, 3]); + assert_eq!(grid.pop_col(), Some(vec![1, 3])); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn pop_col_3x4_column_major() { + let internal = vec![1, 11, 111, 2, 22, 222, 3, 33, 333, 4, 44, 444]; + let mut grid: Grid = Grid::from_vec_with_order(internal, 4, Order::ColumnMajor); + assert_eq!(grid.pop_col(), Some(vec![4, 44, 444])); + let expected = [1, 11, 111, 2, 22, 222, 3, 33, 333]; + test_grid(&grid, 3, 3, Order::ColumnMajor, &expected); + assert_eq!(grid.pop_col(), Some(vec![3, 33, 333])); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[1, 11, 111, 2, 22, 222]); + assert_eq!(grid.pop_col(), Some(vec![2, 22, 222])); + test_grid(&grid, 3, 1, Order::ColumnMajor, &[1, 11, 111]); + assert_eq!(grid.pop_col(), Some(vec![1, 11, 111])); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn pop_col_empty_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + assert_eq!(grid.pop_col(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); } #[test] fn pop_row_2x2() { let mut grid: Grid = Grid::from_vec(vec![1, 2, 3, 4], 2); assert_eq!(grid.pop_row(), Some(vec![3, 4])); - assert_ne!(grid.size(), (1, 4)); + test_grid(&grid, 1, 2, Order::RowMajor, &[1, 2]); assert_eq!(grid.pop_row(), Some(vec![1, 2])); - assert_eq!(grid.size(), (0, 0)); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq!(grid.pop_row(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn pop_row_empty() { let mut grid: Grid = Grid::from_vec(vec![], 0); assert_eq!(grid.pop_row(), None); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + } + + #[test] + fn pop_row_2x2_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + assert_eq!(grid.pop_row(), Some(vec![3, 4])); + test_grid(&grid, 1, 2, Order::ColumnMajor, &[1, 2]); + assert_eq!(grid.pop_row(), Some(vec![1, 2])); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq!(grid.pop_row(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn pop_row_empty_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + assert_eq!(grid.pop_row(), None); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); } #[test] @@ -1333,57 +1711,38 @@ mod test { #[test] fn push_col_2x3() { - let mut grid: Grid = grid![ + let mut grid: Grid = grid![ [0, 1, 2] [10, 11, 12]]; grid.push_col(vec![3, 13]); - assert_eq!(grid.size(), (2, 4)); - assert_eq!( - grid.iter_row(0).copied().collect::>(), - vec![0, 1, 2, 3] - ); - assert_eq!( - grid.iter_row(1).copied().collect::>(), - vec![10, 11, 12, 13] - ); + test_grid(&grid, 2, 4, Order::RowMajor, &[0, 1, 2, 3, 10, 11, 12, 13]); } #[test] fn push_col_3x4() { - let mut grid: Grid = grid![ + let mut grid: Grid = grid![ ['a', 'b', 'c', 'd'] ['a', 'b', 'c', 'd'] ['a', 'b', 'c', 'd']]; grid.push_col(vec!['x', 'y', 'z']); - assert_eq!(grid.size(), (3, 5)); - assert_eq!( - grid.iter_row(0).copied().collect::>(), - vec!['a', 'b', 'c', 'd', 'x'] - ); - assert_eq!( - grid.iter_row(1).copied().collect::>(), - vec!['a', 'b', 'c', 'd', 'y'] - ); - assert_eq!( - grid.iter_row(2).copied().collect::>(), - vec!['a', 'b', 'c', 'd', 'z'] - ); + let expected = [ + 'a', 'b', 'c', 'd', 'x', 'a', 'b', 'c', 'd', 'y', 'a', 'b', 'c', 'd', 'z', + ]; + test_grid(&grid, 3, 5, Order::RowMajor, &expected); } #[test] fn push_col_1x3() { let mut grid: Grid = grid![['a', 'b', 'c']]; grid.push_col(vec!['d']); - assert_eq!(grid.size(), (1, 4)); - assert_eq!(grid[0][3], 'd'); + test_grid(&grid, 1, 4, Order::RowMajor, &['a', 'b', 'c', 'd']); } #[test] fn push_col_empty() { let mut grid: Grid = grid![]; grid.push_col(vec!['b', 'b', 'b', 'b']); - assert_eq!(grid.size(), (4, 1)); - assert_eq!(grid[0][0], 'b'); + test_grid(&grid, 4, 1, Order::RowMajor, &['b', 'b', 'b', 'b']); } #[test] @@ -1401,12 +1760,68 @@ mod test { grid.push_col(vec![]); } + #[test] + fn push_col_2x3_column_major() { + let internal = vec![0, 10, 1, 11, 2, 12]; + let mut grid: Grid = Grid::from_vec_with_order(internal, 3, Order::ColumnMajor); + grid.push_col(vec![3, 13]); + let expected = [0, 10, 1, 11, 2, 12, 3, 13]; + test_grid(&grid, 2, 4, Order::ColumnMajor, &expected); + } + + #[test] + fn push_col_3x4_column_major() { + let internal = vec!['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd']; + let mut grid: Grid = Grid::from_vec_with_order(internal, 4, Order::ColumnMajor); + grid.push_col(vec!['x', 'y', 'z']); + let expected = [ + 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'x', 'y', 'z', + ]; + test_grid(&grid, 3, 5, Order::ColumnMajor, &expected); + } + + #[test] + fn push_col_1x3_column_major() { + let mut grid: Grid = + Grid::from_vec_with_order(vec!['a', 'b', 'c'], 3, Order::ColumnMajor); + grid.push_col(vec!['d']); + test_grid(&grid, 1, 4, Order::ColumnMajor, &['a', 'b', 'c', 'd']); + } + + #[test] + fn push_col_empty_column_major() { + let mut grid: Grid = Grid::new_with_order(0, 0, Order::ColumnMajor); + grid.push_col(vec!['b', 'b', 'b', 'b']); + test_grid(&grid, 4, 1, Order::ColumnMajor, &['b', 'b', 'b', 'b']); + } + + #[test] + #[should_panic] + fn push_col_wrong_size_column_major() { + let mut grid: Grid = Grid::init_with_order(2, 3, Order::ColumnMajor, 'a'); + grid.push_col(vec!['b']); + grid.push_col(vec!['b', 'b']); + } + + #[test] + #[should_panic] + fn push_col_zero_len_column_major() { + let mut grid: Grid = Grid::new_with_order(0, 0, Order::ColumnMajor); + grid.push_col(vec![]); + } + + #[test] + fn push_row() { + let mut grid: Grid = grid![[1, 2][3, 4]]; + grid.push_row(vec![5, 6]); + test_grid(&grid, 3, 2, Order::RowMajor, &[1, 2, 3, 4, 5, 6]) + } + #[test] fn push_row_empty() { let mut grid: Grid = grid![]; grid.push_row(vec!['b', 'b', 'b', 'b']); - assert_eq!(grid.size(), (1, 4)); - assert_eq!(grid[0][0], 'b'); + test_grid(&grid, 1, 4, Order::RowMajor, &['b', 'b', 'b', 'b']) } #[test] @@ -1424,44 +1839,204 @@ mod test { grid.push_row(vec!['b', 'b', 'b', 'b']); } + #[test] + fn push_row_column_major() { + let mut grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.push_row(vec![5, 6]); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[1, 3, 5, 2, 4, 6]) + } + + #[test] + fn push_row_empty_column_major() { + let mut grid: Grid = Grid::new_with_order(0, 0, Order::ColumnMajor); + grid.push_row(vec!['b', 'b', 'b', 'b']); + test_grid(&grid, 1, 4, Order::ColumnMajor, &['b', 'b', 'b', 'b']) + } + + #[test] + #[should_panic] + fn push_empty_row_column_major() { + let mut grid = Grid::init_with_order(0, 1, Order::ColumnMajor, 0); + grid.push_row(vec![]); + } + + #[test] + #[should_panic] + fn push_row_wrong_size_column_major() { + let mut grid: Grid = + Grid::from_vec_with_order(vec!['a', 'a', 'a', 'a', 'a', 'a'], 3, Order::ColumnMajor); + grid.push_row(vec!['b']); + grid.push_row(vec!['b', 'b', 'b', 'b']); + } + #[test] fn iter_row() { - let grid: Grid = grid![[1,2,3][1,2,3]]; - let mut iter = grid.iter_row(0); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.next(), None); + let grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let row: Vec<_> = grid.iter_row(1).collect(); + assert_eq!(row, [&4, &5, &6]); } #[test] #[should_panic] - fn iter_row_empty() { - let grid: Grid = grid![]; + fn iter_row_out_of_bound() { + let grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let _ = grid.iter_row(3); + } + + #[test] + #[should_panic] + fn iter_row_zero() { + let grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); let _ = grid.iter_row(0); } + #[test] + fn iter_row_rowumn_major() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let row: Vec<_> = grid.iter_row(1).collect(); + assert_eq!(row, [&4, &5, &6]); + } + #[test] #[should_panic] - fn iter_row_out_of_bound() { - let grid: Grid = grid![[1,2,3][1,2,3]]; - let _ = grid.iter_row(2); + fn iter_row_rowumn_major_out_of_bound() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let _ = grid.iter_row(3); + } + + #[test] + #[should_panic] + fn iter_row_rowumn_major_zero() { + let grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + let _ = grid.iter_row(0); + } + + #[test] + fn iter_row_mut() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let row: Vec<_> = grid.iter_row_mut(1).collect(); + assert_eq!(row, [&mut 4, &mut 5, &mut 6]); + } + + #[test] + #[should_panic] + fn iter_row_mut_out_of_bound() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let _ = grid.iter_row_mut(3); + } + + #[test] + #[should_panic] + fn iter_row_mut_zero() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); + let _ = grid.iter_row_mut(0); + } + + #[test] + fn iter_row_mut_rowumn_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let row: Vec<_> = grid.iter_row_mut(1).collect(); + assert_eq!(row, [&mut 4, &mut 5, &mut 6]); + } + + #[test] + #[should_panic] + fn iter_row_mut_rowumn_major_out_of_bound() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let _ = grid.iter_row_mut(3); + } + + #[test] + #[should_panic] + fn iter_row_mut_rowumn_major_zero() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + let _ = grid.iter_row_mut(0); + } + + #[test] + fn iter_col() { + let grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let col: Vec<_> = grid.iter_col(1).collect(); + assert_eq!(col, [&2, &5]); } #[test] #[should_panic] fn iter_col_out_of_bound() { - let grid: Grid = grid![[1,2,3][1,2,3]]; + let grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); let _ = grid.iter_col(3); } #[test] #[should_panic] fn iter_col_zero() { - let grid: Grid = grid![]; + let grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); let _ = grid.iter_col(0); } + #[test] + fn iter_col_column_major() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let col: Vec<_> = grid.iter_col(1).collect(); + assert_eq!(col, [&2, &5]); + } + + #[test] + #[should_panic] + fn iter_col_column_major_out_of_bound() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let _ = grid.iter_col(3); + } + + #[test] + #[should_panic] + fn iter_col_column_major_zero() { + let grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + let _ = grid.iter_col(0); + } + + #[test] + fn iter_col_mut() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let col: Vec<_> = grid.iter_col_mut(1).collect(); + assert_eq!(col, [&mut 2, &mut 5]); + } + + #[test] + #[should_panic] + fn iter_col_mut_out_of_bound() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + let _ = grid.iter_col_mut(3); + } + + #[test] + #[should_panic] + fn iter_col_mut_zero() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::RowMajor); + let _ = grid.iter_col_mut(0); + } + + #[test] + fn iter_col_mut_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let col: Vec<_> = grid.iter_col_mut(1).collect(); + assert_eq!(col, [&mut 2, &mut 5]); + } + + #[test] + #[should_panic] + fn iter_col_mut_column_major_out_of_bound() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let _ = grid.iter_col_mut(3); + } + + #[test] + #[should_panic] + fn iter_col_mut_column_major_zero() { + let mut grid: Grid = Grid::from_vec_with_order(vec![], 0, Order::ColumnMajor); + let _ = grid.iter_col_mut(0); + } + #[test] fn iter() { let grid: Grid = grid![[1,2][3,4]]; @@ -1491,6 +2066,24 @@ mod test { assert_eq!(iter.next(), None); } + #[test] + fn indexed_iter_column_major() { + let grid: Grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + let mut iter = grid.indexed_iter(); + assert_eq!(iter.next(), Some(((0, 0), &1))); + assert_eq!(iter.next(), Some(((1, 0), &3))); + assert_eq!(iter.next(), Some(((0, 1), &2))); + assert_eq!(iter.next(), Some(((1, 1), &4))); + assert_eq!(iter.next(), None); + } + + #[test] + fn indexed_iter_empty_column_major() { + let grid: Grid = Grid::new_with_order(0, 0, Order::ColumnMajor); + let mut iter = grid.indexed_iter(); + assert_eq!(iter.next(), None); + } + #[test] fn clear() { let mut grid: Grid = grid![[1, 2, 3]]; @@ -1541,6 +2134,12 @@ mod test { assert_eq!(format!("{:?}", grid), "[[1, 2, 3][4, 5, 6][7, 8, 9]]"); } + #[test] + fn fmt_column_major() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + assert_eq!(format!("{:?}", grid), "[[1, 2, 3][4, 5, 6]]"); + } + #[test] fn fmt_pretty_empty() { let grid: Grid = grid![]; @@ -1649,6 +2248,16 @@ mod test { assert_eq!(format!("{:#5.5?}", grid), expected_output); } + #[test] + fn fmt_pretty_column_major() { + let grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + let expected_output = r#"[ + [ 1, 2, 3] + [ 4, 5, 6] +]"#; + assert_eq!(format!("{:#?}", grid), expected_output); + } + #[test] fn clone() { let grid = grid![[1, 2, 3][4, 5, 6]]; @@ -1696,44 +2305,63 @@ mod test { } #[test] - #[should_panic] - fn from_vec_panics_1() { - let _: Grid = Grid::from_vec(vec![1, 2, 3], 0); + fn init() { + let grid = Grid::init(1, 2, 3); + test_grid(&grid, 1, 2, Order::RowMajor, &[3, 3]); + + let grid = Grid::init(1, 2, 1.2); + test_grid(&grid, 1, 2, Order::RowMajor, &[1.2, 1.2]); + + let grid = Grid::init(1, 2, 'a'); + test_grid(&grid, 1, 2, Order::RowMajor, &['a', 'a']); } #[test] #[should_panic] - fn from_vec_panics_2() { - let _: Grid = Grid::from_vec(vec![1, 2, 3], 2); + fn init_panics() { + Grid::init(usize::MAX, 2, 3); } #[test] - fn from_vec_uses_original_vec() { - let capacity = 10_000_000; - let vec = Vec::with_capacity(capacity); - let grid: Grid = Grid::from_vec(vec, 0); - assert!(grid.into_vec().capacity() >= capacity); + fn init_empty() { + let grid = Grid::init(0, 1, 0); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + + let grid = Grid::init(1, 0, -1); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] - fn init() { - Grid::init(1, 2, 3); - Grid::init(1, 2, 1.2); - Grid::init(1, 2, 'a'); + fn init_with_order() { + let grid = Grid::init_with_order(1, 2, Order::RowMajor, 3); + test_grid(&grid, 1, 2, Order::RowMajor, &[3, 3]); + + let grid = Grid::init_with_order(1, 2, Order::ColumnMajor, 1.2); + test_grid(&grid, 1, 2, Order::ColumnMajor, &[1.2, 1.2]); + + let grid = Grid::init_with_order(1, 2, Order::ColumnMajor, 'a'); + test_grid(&grid, 1, 2, Order::ColumnMajor, &['a', 'a']); } #[test] - fn init_empty() { - let grid = Grid::init(0, 1, 0); - assert!(grid.is_empty()); - assert_eq!(grid.cols(), 0); - assert_eq!(grid.rows(), 0); + #[should_panic] + fn init_with_order_panics() { + Grid::init_with_order(usize::MAX, 2, Order::ColumnMajor, 3); + } + + #[test] + fn init_with_order_empty() { + let grid = Grid::init_with_order(0, 1, Order::ColumnMajor, 0); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + + let grid = Grid::init_with_order(1, 0, Order::RowMajor, -1); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } #[test] fn new() { let grid: Grid = Grid::new(1, 2); - assert_eq!(grid[0][0], 0); + test_grid(&grid, 1, 2, Order::RowMajor, &[0, 0]); } #[test] @@ -1745,41 +2373,79 @@ mod test { #[test] fn new_empty() { let grid: Grid = Grid::new(0, 1); - assert!(grid.is_empty()); - assert_eq!(grid.cols(), 0); - assert_eq!(grid.rows(), 0); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + + let grid: Grid = Grid::new(1, 0); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + } + + #[test] + fn new_with_order() { + let grid: Grid = Grid::new_with_order(2, 2, Order::ColumnMajor); + test_grid(&grid, 2, 2, Order::ColumnMajor, &[0, 0, 0, 0]); } #[test] #[should_panic] - fn init_panics() { - Grid::init(usize::MAX, 2, 3); + fn new_with_order_panics() { + let _: Grid = Grid::new_with_order(usize::MAX, 2, Order::ColumnMajor); + } + + #[test] + fn new_with_order_empty() { + let grid: Grid = Grid::new_with_order(0, 3, Order::RowMajor); + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + + let grid: Grid = Grid::new_with_order(3, 0, Order::ColumnMajor); + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); } #[test] fn get() { - let grid = Grid::init(1, 2, 3); - assert_eq!(grid.get(0, 0), Some(&3)); + let grid = Grid::from_vec_with_order(vec![1, 2], 2, Order::RowMajor); + assert_eq!(grid.get(0, 1), Some(&2)); } + + #[test] + fn get_column_major() { + let grid = Grid::from_vec_with_order(vec![1, 2], 1, Order::ColumnMajor); + assert_eq!(grid.get(1, 0), Some(&2)); + } + #[test] fn get_none() { - let grid = Grid::init(1, 2, 3); + let grid = Grid::from_vec_with_order(vec![1, 2], 2, Order::RowMajor); assert_eq!(grid.get(1, 0), None); } + #[test] + fn get_none_column_major() { + let grid = Grid::from_vec_with_order(vec![1, 2], 1, Order::ColumnMajor); + assert_eq!(grid.get(0, 1), None); + } + #[test] fn get_mut() { - let mut grid = Grid::init(1, 2, 3); - let mut_ref = grid.get_mut(0, 0).unwrap(); - *mut_ref = 5; - assert_eq!(grid[0][0], 5); + let mut grid = Grid::from_vec_with_order(vec![1, 2], 2, Order::RowMajor); + assert_eq!(grid.get_mut(0, 1), Some(&mut 2)); + } + + #[test] + fn get_mut_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 2], 1, Order::ColumnMajor); + assert_eq!(grid.get_mut(1, 0), Some(&mut 2)); } #[test] fn get_mut_none() { - let mut grid = Grid::init(1, 2, 3); - let mut_ref = grid.get_mut(1, 4); - assert_eq!(mut_ref, None); + let mut grid = Grid::from_vec_with_order(vec![1, 2], 2, Order::RowMajor); + assert_eq!(grid.get_mut(1, 0), None); + } + + #[test] + fn get_mut_none_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 2], 1, Order::ColumnMajor); + assert_eq!(grid.get_mut(0, 1), None); } #[test] @@ -1850,8 +2516,9 @@ mod test { #[test] fn transpose() { - let grid: Grid = grid![[1,2,3][4,5,6]]; - assert_eq!(format!("{:?}", grid.transpose()), "[[1, 4][2, 5][3, 6]]"); + let mut grid: Grid = grid![[1,2,3][4,5,6]]; + grid.transpose(); + assert_eq!(grid, grid![[1,4][2,5][3,6]]); } #[test] @@ -1898,33 +2565,160 @@ mod test { let sum_by_col: Vec = grid.iter_cols().map(|col| col.sum()).collect(); assert_eq!(sum_by_col, vec![1 + 4, 2 + 5, 3 + 6]); } - #[test] - fn remove_col() { - let mut grid = grid![[1,2,3,4][5,6,7,8][9,10,11,12][13,14,15,16]]; - assert_eq![grid.remove_col(3), Some(vec![4, 8, 12, 16])]; - assert_eq![grid.remove_col(0), Some(vec![1, 5, 9, 13])]; - assert_eq![grid.remove_col(1), Some(vec![3, 7, 11, 15])]; - assert_eq![grid.remove_col(0), Some(vec![2, 6, 10, 14])]; - assert_eq![grid.remove_col(0), None]; - } + #[test] fn remove_row() { let mut grid = grid![[1,2][3,4][5,6]]; assert_eq![grid.remove_row(1), Some(vec![3, 4])]; + test_grid(&grid, 2, 2, Order::RowMajor, &[1, 2, 5, 6]); assert_eq![grid.remove_row(0), Some(vec![1, 2])]; + test_grid(&grid, 1, 2, Order::RowMajor, &[5, 6]); assert_eq![grid.remove_row(0), Some(vec![5, 6])]; + test_grid(&grid, 0, 0, Order::RowMajor, &[]); assert_eq![grid.remove_row(0), None]; + test_grid(&grid, 0, 0, Order::RowMajor, &[]); } + #[test] fn remove_row_out_of_bound() { let mut grid = grid![[1, 2][3, 4]]; assert_eq![grid.remove_row(5), None]; + test_grid(&grid, 2, 2, Order::RowMajor, &[1, 2, 3, 4]); assert_eq![grid.remove_row(1), Some(vec![3, 4])]; + test_grid(&grid, 1, 2, Order::RowMajor, &[1, 2]); } + + #[test] + fn remove_row_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 3, 5, 2, 4, 6], 2, Order::ColumnMajor); + assert_eq![grid.remove_row(1), Some(vec![3, 4])]; + test_grid(&grid, 2, 2, Order::ColumnMajor, &[1, 5, 2, 6]); + assert_eq![grid.remove_row(0), Some(vec![1, 2])]; + test_grid(&grid, 1, 2, Order::ColumnMajor, &[5, 6]); + assert_eq![grid.remove_row(0), Some(vec![5, 6])]; + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq![grid.remove_row(0), None]; + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn remove_row_out_of_bound_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + assert_eq![grid.remove_row(5), None]; + test_grid(&grid, 2, 2, Order::ColumnMajor, &[1, 3, 2, 4]); + assert_eq![grid.remove_row(1), Some(vec![3, 4])]; + test_grid(&grid, 1, 2, Order::ColumnMajor, &[1, 2]); + } + + #[test] + fn remove_col() { + let mut grid = grid![[1,2,3,4][5,6,7,8][9,10,11,12][13,14,15,16]]; + assert_eq![grid.remove_col(3), Some(vec![4, 8, 12, 16])]; + let expected = [1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15]; + test_grid(&grid, 4, 3, Order::RowMajor, &expected); + assert_eq![grid.remove_col(0), Some(vec![1, 5, 9, 13])]; + test_grid(&grid, 4, 2, Order::RowMajor, &[2, 3, 6, 7, 10, 11, 14, 15]); + assert_eq![grid.remove_col(1), Some(vec![3, 7, 11, 15])]; + test_grid(&grid, 4, 1, Order::RowMajor, &[2, 6, 10, 14]); + assert_eq![grid.remove_col(0), Some(vec![2, 6, 10, 14])]; + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + assert_eq![grid.remove_col(0), None]; + test_grid(&grid, 0, 0, Order::RowMajor, &[]); + } + #[test] fn remove_col_out_of_bound() { let mut grid = grid![[1, 2][3, 4]]; assert_eq!(grid.remove_col(5), None); + test_grid(&grid, 2, 2, Order::RowMajor, &[1, 2, 3, 4]); assert_eq!(grid.remove_col(1), Some(vec![2, 4])); + test_grid(&grid, 2, 1, Order::RowMajor, &[1, 3]); + } + + #[test] + fn remove_col_column_major() { + let internal = vec![1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]; + let mut grid = Grid::from_vec_with_order(internal, 4, Order::ColumnMajor); + assert_eq![grid.remove_col(3), Some(vec![4, 8, 12, 16])]; + let expected = [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]; + test_grid(&grid, 4, 3, Order::ColumnMajor, &expected); + assert_eq![grid.remove_col(0), Some(vec![1, 5, 9, 13])]; + let expected = [2, 6, 10, 14, 3, 7, 11, 15]; + test_grid(&grid, 4, 2, Order::ColumnMajor, &expected); + assert_eq![grid.remove_col(1), Some(vec![3, 7, 11, 15])]; + test_grid(&grid, 4, 1, Order::ColumnMajor, &[2, 6, 10, 14]); + assert_eq![grid.remove_col(0), Some(vec![2, 6, 10, 14])]; + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + assert_eq![grid.remove_col(0), None]; + test_grid(&grid, 0, 0, Order::ColumnMajor, &[]); + } + + #[test] + fn remove_col_out_of_bound_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + assert_eq!(grid.remove_col(5), None); + test_grid(&grid, 2, 2, Order::ColumnMajor, &[1, 3, 2, 4]); + assert_eq!(grid.remove_col(1), Some(vec![2, 4])); + test_grid(&grid, 2, 1, Order::ColumnMajor, &[1, 3]); + } + + #[test] + fn flip_cols() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); + grid.flip_cols(); + test_grid(&grid, 2, 2, Order::RowMajor, &[2, 1, 4, 3]); + } + + #[test] + fn flip_cols_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.flip_cols(); + test_grid(&grid, 2, 2, Order::ColumnMajor, &[2, 4, 1, 3]); + } + + #[test] + fn flip_rows() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4], 2, Order::RowMajor); + grid.flip_rows(); + test_grid(&grid, 2, 2, Order::RowMajor, &[3, 4, 1, 2]); + } + + #[test] + fn flip_rows_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 3, 2, 4], 2, Order::ColumnMajor); + grid.flip_rows(); + test_grid(&grid, 2, 2, Order::ColumnMajor, &[3, 1, 4, 2]); + } + + #[test] + fn rotate_left() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + grid.rotate_left(); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[3, 2, 1, 6, 5, 4]); + assert_eq!(grid, grid![[3,6][2,5][1,4]]); + } + + #[test] + fn rotate_left_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + grid.rotate_left(); + test_grid(&grid, 3, 2, Order::RowMajor, &[3, 6, 2, 5, 1, 4]); + assert_eq!(grid, grid![[3,6][2,5][1,4]]); + } + + #[test] + fn rotate_right() { + let mut grid = Grid::from_vec_with_order(vec![1, 2, 3, 4, 5, 6], 3, Order::RowMajor); + grid.rotate_right(); + test_grid(&grid, 3, 2, Order::ColumnMajor, &[4, 5, 6, 1, 2, 3]); + assert_eq!(grid, grid![[4,1][5,2][6,3]]); + } + + #[test] + fn rotate_right_column_major() { + let mut grid = Grid::from_vec_with_order(vec![1, 4, 2, 5, 3, 6], 3, Order::ColumnMajor); + grid.rotate_right(); + test_grid(&grid, 3, 2, Order::RowMajor, &[4, 1, 5, 2, 6, 3]); + assert_eq!(grid, grid![[4,1][5,2][6,3]]); } }