From 21f84fc4680fc1bcdd16fa725e2e8e8f57700c3a Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Thu, 2 Apr 2020 23:08:02 +0200 Subject: [PATCH 1/6] Add macro --- Cargo.toml | 2 - README.md | 2 +- benches/benches.rs | 4 +- src/lib.rs | 148 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 127 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5eb16dd..c7667ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,6 @@ version = "0.1.0" authors = ["Armin Becher "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dev-dependencies] criterion = "0.3.1" diff --git a/README.md b/README.md index a617cd9..43e7b4a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Grid -Data structure grid for rust. Provide a two dimensional data storage that is easy to use and fast. +Data structure grid for rust. Provide a two dimensional data storage that is easy to use and fast. diff --git a/benches/benches.rs b/benches/benches.rs index 1d12f2a..4858b55 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -10,7 +10,7 @@ fn init_vec_flat(size: usize) -> Vec { } fn init_grid(size: usize) -> Grid { - Grid::new(size, size, 0) + Grid::init(size, size, 0) } fn get_vec_vec(x: usize, y: usize) -> u32 { @@ -48,7 +48,7 @@ fn set_grid(x: usize, y: usize) { } fn criterion_benchmark(c: &mut Criterion) { - // Init + // New c.bench_function("Init vec vec 10x10", |b| { b.iter(|| init_vec_vec(black_box(10))) }); diff --git a/src/lib.rs b/src/lib.rs index 7cf2f4d..979b0e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,28 +3,94 @@ use std::ops::IndexMut; pub struct Grid { data: Vec, - columns: usize, + cols: usize, rows: usize, } +#[allow(unused_macros)] +macro_rules! count { + () => (0usize); + ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); +} + +#[macro_export] +macro_rules! grid { + () => { + Grid { + rows: 0, + cols: 0, + data: vec![], + } + }; + ( [$( $x:expr ),* ]) => { { + let vec = vec![$($x),*]; + Grid { rows : 1, cols: vec.len(), data: vec } + } }; + ( [$( $x0:expr ),*] $($( $x:expr ),*);* ) => { + { + let mut _assert_width0 = [(); count!($($x0)*)]; + let mut vec = Vec::new(); + let rows = 1usize; + let cols = count!($($x0)*); + + $( vec.push($x0); )* + + $( + let rows = rows + 1usize; + let _assert_width = [(); count!($($x)*)]; + _assert_width0 = _assert_width; + $( vec.push($x); )* + )* + + Grid { rows : rows, cols: cols, data: vec } + } + }; +} + impl Grid { - pub fn new(rows: usize, columns: usize, data: T) -> Grid { - if rows < 1 || columns < 1 { + /// Init a grid of size rows x columns with default values of the given type. + /// For example this will generate a 2x3 grid of zeros: + /// ``` + /// use grid::Grid; + /// let grid : Grid = Grid::new(2,2); + /// assert_eq!(grid[0][0], 0); + /// ``` + pub fn new(rows: usize, cols: usize) -> Grid + where + T: Default, + { + if rows < 1 || cols < 1 { panic!("Grid size of rows and columns must be greater than zero."); } Grid { - data: vec![data; rows * columns], - columns: columns, + data: vec![T::default(); rows * cols], + cols: cols, rows: rows, } } - pub fn get(&self, row: usize, column: usize) -> Option<&T> { - self.data.get(row * self.columns + column % self.columns) + /// Init a grid of size rows x columns with the given data element. + pub fn init(rows: usize, cols: usize, data: T) -> Grid { + if rows < 1 || cols < 1 { + panic!("Grid size of rows and columns must be greater than zero."); + } + Grid { + data: vec![data; rows * cols], + cols: cols, + rows: rows, + } } + /// Access a certain element in the grid. + /// Returns None if an element beyond the grid bounds is tried to be accessed. + pub fn get(&self, row: usize, column: usize) -> Option<&T> { + self.data.get(row * self.cols + column % self.cols) + } + + /// Returns the size of the gird as a two element tuple. + /// First element are the number of rows and the second the columns. pub fn size(&self) -> (usize, usize) { - (self.rows, self.columns) + (self.rows, self.cols) } } @@ -38,7 +104,7 @@ impl Index for Grid { self.rows, idx ); } - &self.data[(idx * &self.columns)..] + &self.data[(idx * &self.cols)..] } } @@ -50,7 +116,7 @@ impl IndexMut for Grid { self.rows, idx ); } - &mut self.data[(idx * &self.columns)..] + &mut self.data[(idx * &self.cols)..] } } @@ -59,64 +125,98 @@ mod test { use super::*; #[test] - fn ctr() { - Grid::new(1, 2, 3); - Grid::new(1, 2, 1.2); - Grid::new(1, 2, 'a'); + fn macro_init() { + //TODO let grid = grid![[1, 2, 3][4, 5, 6]]; + let grid = grid![[1,2,3]4,5,6]; + assert_eq!(grid[0][0], 1); + assert_eq!(grid[0][1], 2); + assert_eq!(grid[0][2], 3); + assert_eq!(grid[1][0], 4); + assert_eq!(grid[1][1], 5); + assert_eq!(grid[1][2], 6); } + + #[test] + fn macro_one_row() { + let grid: Grid = grid![[1, 2, 3, 4]]; + assert_eq!(grid.size(), (1, 0)); + assert_eq!(grid[0][0], 1); + assert_eq!(grid[0][1], 2); + assert_eq!(grid[0][2], 3); + } + + #[test] + fn macro_init_empty() { + let grid: Grid = grid![]; + assert_eq!(grid.size(), (0, 0)); + } + + #[test] + fn init() { + Grid::init(1, 2, 3); + Grid::init(1, 2, 1.2); + Grid::init(1, 2, 'a'); + } + + #[test] + fn new() { + let grid: Grid = Grid::new(1, 2); + assert_eq!(grid[0][0], 0); + } + #[test] #[should_panic] - fn ctr_panics() { - Grid::new(0, 2, 3); + fn init_panics() { + Grid::init(0, 2, 3); } #[test] #[should_panic] fn ctr_panics_2() { - Grid::new(1, 0, 3); + Grid::init(1, 0, 3); } #[test] fn get() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); assert_eq!(grid.get(0, 0), Some(&3)); } #[test] fn get_none() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); assert_eq!(grid.get(1, 0), None); } #[test] fn idx() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); assert_eq!(grid[0][0], 3); } #[test] #[should_panic] fn idx_panic_1() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); grid[20][0]; } #[test] #[should_panic] fn idx_panic_2() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); grid[0][20]; } #[test] fn idx_set() { - let mut grid = Grid::new(1, 2, 3); + let mut grid = Grid::init(1, 2, 3); grid[0][0] = 4; assert_eq!(grid[0][0], 4); } #[test] fn size() { - let grid = Grid::new(1, 2, 3); + let grid = Grid::init(1, 2, 3); assert_eq!(grid.size(), (1, 2)); } } From fc2120719b3671343c42b2849faf46d835b596c0 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Thu, 2 Apr 2020 23:23:23 +0200 Subject: [PATCH 2/6] Fix grid init --- src/lib.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 979b0e7..5571464 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ macro_rules! grid { let vec = vec![$($x),*]; Grid { rows : 1, cols: vec.len(), data: vec } } }; - ( [$( $x0:expr ),*] $($( $x:expr ),*);* ) => { + ( [$( $x0:expr ),*] $([$( $x:expr ),*])* ) => { { let mut _assert_width0 = [(); count!($($x0)*)]; let mut vec = Vec::new(); @@ -126,8 +126,7 @@ mod test { #[test] fn macro_init() { - //TODO let grid = grid![[1, 2, 3][4, 5, 6]]; - let grid = grid![[1,2,3]4,5,6]; + let grid = grid![[1, 2, 3][4, 5, 6]]; assert_eq!(grid[0][0], 1); assert_eq!(grid[0][1], 2); assert_eq!(grid[0][2], 3); @@ -136,10 +135,18 @@ mod test { assert_eq!(grid[1][2], 6); } + #[test] + fn macro_init_2() { + let grid = grid![[1, 2, 3] + [4, 5, 6] + [7,8,9]]; + assert_eq!(grid.size(), (3, 3)) + } + #[test] fn macro_one_row() { let grid: Grid = grid![[1, 2, 3, 4]]; - assert_eq!(grid.size(), (1, 0)); + assert_eq!(grid.size(), (1, 4)); assert_eq!(grid[0][0], 1); assert_eq!(grid[0][1], 2); assert_eq!(grid[0][2], 3); From 4636e982abebc887bc1eb98ceb5aa95469c91515 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Fri, 3 Apr 2020 15:48:01 +0200 Subject: [PATCH 3/6] Add working grid macro --- benches/benches.rs | 65 ++++++---------------- src/lib.rs | 132 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 128 insertions(+), 69 deletions(-) diff --git a/benches/benches.rs b/benches/benches.rs index 4858b55..93170ba 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -13,40 +13,6 @@ fn init_grid(size: usize) -> Grid { Grid::init(size, size, 0) } -fn get_vec_vec(x: usize, y: usize) -> u32 { - let mat = init_vec_vec(10); - mat[x][y] -} - -fn get_vec_flat(x: usize, y: usize) -> u32 { - let mat = init_vec_flat(10); - mat[x * 10 + y % 10] -} - -fn get_grid(x: usize, y: usize) -> u32 { - let mat = init_grid(10); - mat[x][y] -} - -fn get_grid_fn(x: usize, y: usize) { - let mat = init_grid(10); - mat.get(x, y); -} - -fn set_vec_vec(x: usize, y: usize) { - let mut mat = init_vec_vec(10); - mat[x][y] = 10; -} -fn set_vec_flat(x: usize, y: usize) { - let mut mat = init_vec_flat(10); - mat[x * 10 + y % 10] = 10; -} - -fn set_grid(x: usize, y: usize) { - let mut mat = init_grid(10); - mat[x][y] = 10; -} - fn criterion_benchmark(c: &mut Criterion) { // New c.bench_function("Init vec vec 10x10", |b| { @@ -58,28 +24,31 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("Init grid 10x10", |b| b.iter(|| init_grid(black_box(10)))); // Get - c.bench_function("Get vec vec 10x10", |b| { - b.iter(|| get_vec_vec(black_box(2), black_box(3))) + c.bench_function("Idx vec vec 10x10", |b| { + let vec_vec = init_vec_vec(10); + b.iter(|| vec_vec[black_box(2)][black_box(3)]) }); - c.bench_function("Get vec flat 10x10", |b| { - b.iter(|| get_vec_flat(black_box(2), black_box(3))) + c.bench_function("Idx grid 10x10", |b| { + let grid = init_grid(10); + b.iter(|| grid[black_box(2)][black_box(3)]) }); - c.bench_function("Get grid 10x10", |b| { - b.iter(|| get_grid(black_box(2), black_box(3))) + c.bench_function("Get_fn vec vec 10x10", |b| { + let vec_vec = init_vec_vec(10); + b.iter(|| vec_vec.get(black_box(2)).unwrap().get(black_box(3))) }); - c.bench_function("Get grid fn 10x10", |b| { - b.iter(|| get_grid_fn(black_box(2), black_box(3))) + c.bench_function("Get_fn grid 10x10", |b| { + let grid = init_grid(10); + b.iter(|| grid.get(black_box(2), black_box(3))) }); //Set c.bench_function("Set vec vec 10x10", |b| { - b.iter(|| set_vec_vec(black_box(2), black_box(3))) + let mut vec_vec = init_vec_vec(10); + b.iter(|| vec_vec[black_box(2)][black_box(3)] = 2) }); - c.bench_function("Set vec flat 10x10", |b| { - b.iter(|| set_vec_flat(black_box(2), black_box(3))) - }); - c.bench_function("Set grid 10x10", |b| { - b.iter(|| set_grid(black_box(2), black_box(3))) + c.bench_function("Set gird 10x10", |b| { + let mut gird = init_grid(10); + b.iter(|| gird[black_box(2)][black_box(3)] = 2) }); } diff --git a/src/lib.rs b/src/lib.rs index 5571464..76a8b06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,28 @@ use std::ops::Index; use std::ops::IndexMut; +/// Stores elements of a certain type in a 2D grid structure. pub struct Grid { data: Vec, cols: usize, rows: usize, } -#[allow(unused_macros)] +#[doc(hidden)] +#[macro_export] macro_rules! count { () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); + ( $x:tt $($xs:tt)* ) => (1usize + $crate::count!($($xs)*)); } +/// Init a grid with values. +/// ``` +/// use grid::grid; +/// let grid = grid![[1, 2, 3] +/// [4, 5, 6] +/// [7, 8, 9]]; +/// assert_eq!(grid.size(), (3, 3)) +/// ``` #[macro_export] macro_rules! grid { () => { @@ -24,25 +34,23 @@ macro_rules! grid { }; ( [$( $x:expr ),* ]) => { { let vec = vec![$($x),*]; - Grid { rows : 1, cols: vec.len(), data: vec } + $crate::Grid::from_vec(&vec, vec.len()) } }; ( [$( $x0:expr ),*] $([$( $x:expr ),*])* ) => { { - let mut _assert_width0 = [(); count!($($x0)*)]; + let mut _assert_width0 = [(); $crate::count!($($x0)*)]; let mut vec = Vec::new(); - let rows = 1usize; - let cols = count!($($x0)*); + let cols = $crate::count!($($x0)*); $( vec.push($x0); )* $( - let rows = rows + 1usize; - let _assert_width = [(); count!($($x)*)]; + let _assert_width = [(); $crate::count!($($x)*)]; _assert_width0 = _assert_width; $( vec.push($x); )* )* - Grid { rows : rows, cols: cols, data: vec } + $crate::Grid::from_vec(&vec, cols) } }; } @@ -81,10 +89,54 @@ impl Grid { } } + /// Returns a grid from a vector with a given column length. + /// The length of `vec` must be a multiple of `cols`. + /// + /// For example: + /// + /// ``` + /// use grid::Grid; + /// let grid = Grid::from_vec(&vec![1,2,3,4,5,6], 3); + /// assert_eq!(grid.size(), (2, 3)); + /// ``` + /// + /// will create a grid with the following layout: + /// [1,2,3] + /// [4,5,6] + /// + /// This example will fail, because `vec.len()` is not a multiple of `cols`: + /// + /// ``` should_panic + /// use grid::Grid; + /// Grid::from_vec(&vec![1,2,3,4,5], 3); + /// ``` + pub fn from_vec(vec: &Vec, cols: usize) -> Grid { + if vec.len() == 0 { + if cols == 0 { + return grid![]; + } else { + panic!("Vector length is zero, but cols is {:?}", cols); + } + } + if vec.len() % cols != 0 { + panic!("Vector length must be a multiple of cols."); + } + Grid { + data: vec.to_vec(), + rows: vec.len() / cols, + cols: cols, + } + } + /// Access a certain element in the grid. /// Returns None if an element beyond the grid bounds is tried to be accessed. - pub fn get(&self, row: usize, column: usize) -> Option<&T> { - self.data.get(row * self.cols + column % self.cols) + pub fn get(&self, row: usize, col: usize) -> Option<&T> { + if row < self.rows && col < self.cols() { + //unsafe { Some(&self.index(row).get_unchecked(col)) } + Some(&self.data[row * self.cols() + col]) + } else { + None + } } /// Returns the size of the gird as a two element tuple. @@ -92,30 +144,35 @@ impl Grid { pub fn size(&self) -> (usize, usize) { (self.rows, self.cols) } + + /// Returns the number of rows of the grid. + pub fn rows(&self) -> usize { + self.rows + } + + /// Returns the number of columns of the grid. + pub fn cols(&self) -> usize { + self.cols + } } impl Index for Grid { type Output = [T]; fn index(&self, idx: usize) -> &Self::Output { - if idx >= self.rows { + if idx < self.rows { + &self.data[(idx * &self.cols)..] + } else { panic!( - "index out of bounds: grid has {:?} but the index is {:?}", + "index {:?} out of bounds. Grid has {:?} rows.", self.rows, idx ); } - &self.data[(idx * &self.cols)..] } } impl IndexMut for Grid { fn index_mut(&mut self, idx: usize) -> &mut Self::Output { - if idx >= self.rows { - panic!( - "index out of bounds: grid has {:?} but the index is {:?}", - self.rows, idx - ); - } &mut self.data[(idx * &self.cols)..] } } @@ -139,10 +196,19 @@ mod test { fn macro_init_2() { let grid = grid![[1, 2, 3] [4, 5, 6] - [7,8,9]]; + [7, 8, 9]]; assert_eq!(grid.size(), (3, 3)) } + #[test] + fn macro_init_char() { + let grid = grid![['a', 'b', 'c'] + ['a', 'b', 'c'] + ['a', 'b', 'c']]; + assert_eq!(grid.size(), (3, 3)); + assert_eq!(grid[1][1], 'b'); + } + #[test] fn macro_one_row() { let grid: Grid = grid![[1, 2, 3, 4]]; @@ -158,6 +224,30 @@ mod test { assert_eq!(grid.size(), (0, 0)); } + #[test] + fn from_vec_zero() { + let grid: Grid = Grid::from_vec(&vec![], 0); + assert_eq!(grid.size(), (0, 0)); + } + + #[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] + #[should_panic] + fn from_vec_panics_3() { + let _: Grid = Grid::from_vec(&vec![], 1); + } + #[test] fn init() { Grid::init(1, 2, 3); From 182d349c23a93d50345a20e1bc2d244e108b2598 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 4 Apr 2020 13:28:18 +0200 Subject: [PATCH 4/6] Update benchmark --- Cargo.toml | 1 + benches/benches.rs | 112 ++++++++++++++++++++++++++++++++------------- src/lib.rs | 4 +- 3 files changed, 83 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c7667ab..7ddc0d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dev-dependencies] criterion = "0.3.1" +rand="0.7.3" [[bench]] name = "benches" diff --git a/benches/benches.rs b/benches/benches.rs index 93170ba..3167106 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -1,54 +1,102 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; +use grid::grid; use grid::Grid; +use rand::Rng; -fn init_vec_vec(size: usize) -> Vec> { - vec![vec![0; size]; size] +const SIZE: usize = 1000; + +fn init_vec_vec() -> Vec> { + vec![vec![0; SIZE]; SIZE] } -fn init_vec_flat(size: usize) -> Vec { - vec![0; size * size] +fn init_vec_flat() -> Vec { + vec![0; SIZE * SIZE] } -fn init_grid(size: usize) -> Grid { - Grid::init(size, size, 0) +fn init_grid() -> Grid { + Grid::init(SIZE, SIZE, 0) } fn criterion_benchmark(c: &mut Criterion) { + let mut rng = rand::thread_rng(); + let mut rand = || rng.gen_range(0, SIZE); + + let mut rng_u32 = rand::thread_rng(); + let mut rand_u32 = || rng_u32.gen::(); + + // Init macro + c.bench_function("Macro init vec vec", |b| { + b.iter(|| { + vec![ + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + ] + }) + }); + c.bench_function("Macro init vec flat", |b| { + b.iter(|| { + vec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + ] + }) + }); + c.bench_function("Macro init grid", |b| { + b.iter(|| { + grid![[0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9] + [0,1,2,3,4,5,6,7,8,9]] + }) + }); + // New - c.bench_function("Init vec vec 10x10", |b| { - b.iter(|| init_vec_vec(black_box(10))) - }); - c.bench_function("Init vec flat 10x10", |b| { - b.iter(|| init_vec_flat(black_box(10))) - }); - c.bench_function("Init grid 10x10", |b| b.iter(|| init_grid(black_box(10)))); + c.bench_function("Init vec vec", |b| b.iter(|| init_vec_vec())); + c.bench_function("Init vec flat", |b| b.iter(|| init_vec_flat())); + c.bench_function("Init grid", |b| b.iter(|| init_grid())); // Get - c.bench_function("Idx vec vec 10x10", |b| { - let vec_vec = init_vec_vec(10); - b.iter(|| vec_vec[black_box(2)][black_box(3)]) + c.bench_function("Idx vec vec", |b| { + let vec_vec = init_vec_vec(); + b.iter(|| vec_vec[rand()][rand()]) }); - c.bench_function("Idx grid 10x10", |b| { - let grid = init_grid(10); - b.iter(|| grid[black_box(2)][black_box(3)]) + c.bench_function("Idx grid", |b| { + let grid = init_grid(); + b.iter(|| grid[rand()][rand()]) }); - c.bench_function("Get_fn vec vec 10x10", |b| { - let vec_vec = init_vec_vec(10); - b.iter(|| vec_vec.get(black_box(2)).unwrap().get(black_box(3))) + c.bench_function("Get_fn vec vec", |b| { + let vec_vec = init_vec_vec(); + b.iter(|| vec_vec.get(rand()).unwrap().get(rand())) }); - c.bench_function("Get_fn grid 10x10", |b| { - let grid = init_grid(10); - b.iter(|| grid.get(black_box(2), black_box(3))) + c.bench_function("Get_fn grid", |b| { + let grid = init_grid(); + b.iter(|| grid.get(rand(), rand())) }); //Set - c.bench_function("Set vec vec 10x10", |b| { - let mut vec_vec = init_vec_vec(10); - b.iter(|| vec_vec[black_box(2)][black_box(3)] = 2) + c.bench_function("Set vec vec", |b| { + let mut vec_vec = init_vec_vec(); + b.iter(|| vec_vec[rand()][rand()] = rand_u32()) }); - c.bench_function("Set gird 10x10", |b| { - let mut gird = init_grid(10); - b.iter(|| gird[black_box(2)][black_box(3)] = 2) + c.bench_function("Set gird", |b| { + let mut gird = init_grid(); + b.iter(|| gird[rand()][rand()] = rand_u32()) }); } diff --git a/src/lib.rs b/src/lib.rs index 76a8b06..01193ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,8 +132,8 @@ impl Grid { /// Returns None if an element beyond the grid bounds is tried to be accessed. pub fn get(&self, row: usize, col: usize) -> Option<&T> { if row < self.rows && col < self.cols() { - //unsafe { Some(&self.index(row).get_unchecked(col)) } - Some(&self.data[row * self.cols() + col]) + unsafe { Some(&self.data.get_unchecked(row * self.cols() + col)) } + //Some(&self.data.get_unchecked(row * self.cols() + col)) } else { None } From b7dff2e5732751b3131e5f606bb363dd51ffb846 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 4 Apr 2020 18:18:37 +0200 Subject: [PATCH 5/6] Speedup init grid --- src/lib.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 01193ca..5875e8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,8 @@ macro_rules! grid { }; ( [$( $x:expr ),* ]) => { { let vec = vec![$($x),*]; - $crate::Grid::from_vec(&vec, vec.len()) + let len = vec.len(); + $crate::Grid::from_vec(vec, len) } }; ( [$( $x0:expr ),*] $([$( $x:expr ),*])* ) => { { @@ -50,7 +51,7 @@ macro_rules! grid { $( vec.push($x); )* )* - $crate::Grid::from_vec(&vec, cols) + $crate::Grid::from_vec(vec, cols) } }; } @@ -110,7 +111,7 @@ impl Grid { /// use grid::Grid; /// Grid::from_vec(&vec![1,2,3,4,5], 3); /// ``` - pub fn from_vec(vec: &Vec, cols: usize) -> Grid { + pub fn from_vec(vec: Vec, cols: usize) -> Grid { if vec.len() == 0 { if cols == 0 { return grid![]; @@ -121,9 +122,10 @@ impl Grid { if vec.len() % cols != 0 { panic!("Vector length must be a multiple of cols."); } + let rows = vec.len(); Grid { - data: vec.to_vec(), - rows: vec.len() / cols, + data: vec, + rows: rows / cols, cols: cols, } } @@ -226,26 +228,26 @@ mod test { #[test] fn from_vec_zero() { - let grid: Grid = Grid::from_vec(&vec![], 0); + let grid: Grid = Grid::from_vec(vec![], 0); assert_eq!(grid.size(), (0, 0)); } #[test] #[should_panic] fn from_vec_panics_1() { - let _: Grid = Grid::from_vec(&vec![1, 2, 3], 0); + 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); + let _: Grid = Grid::from_vec(vec![1, 2, 3], 2); } #[test] #[should_panic] fn from_vec_panics_3() { - let _: Grid = Grid::from_vec(&vec![], 1); + let _: Grid = Grid::from_vec(vec![], 1); } #[test] From 00a5677ff66ee6c929d0d7636bf2a87652718aaf Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 4 Apr 2020 18:43:28 +0200 Subject: [PATCH 6/6] Speedup init vec macro --- benches/benches.rs | 11 +++++++++++ src/lib.rs | 12 ++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/benches/benches.rs b/benches/benches.rs index 3167106..f3ac035 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -51,6 +51,17 @@ fn criterion_benchmark(c: &mut Criterion) { ] }) }); + c.bench_function("Macro init grid from_vec", |b| { + b.iter(|| { + let vec = vec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + ]; + Grid::from_vec(vec, 10) + }) + }); c.bench_function("Macro init grid", |b| { b.iter(|| { grid![[0,1,2,3,4,5,6,7,8,9] diff --git a/src/lib.rs b/src/lib.rs index 5875e8e..d7d8d92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,17 +40,21 @@ macro_rules! grid { ( [$( $x0:expr ),*] $([$( $x:expr ),*])* ) => { { let mut _assert_width0 = [(); $crate::count!($($x0)*)]; - let mut vec = Vec::new(); + let cols = $crate::count!($($x0)*); - - $( vec.push($x0); )* + let rows = 1usize; $( let _assert_width = [(); $crate::count!($($x)*)]; _assert_width0 = _assert_width; - $( vec.push($x); )* + let rows = rows + 1usize; )* + let mut vec = Vec::with_capacity(rows * cols); + + $( vec.push($x0); )* + $( $( vec.push($x); )* )* + $crate::Grid::from_vec(vec, cols) } };