Add macro

This commit is contained in:
Armin Becher 2020-04-02 23:08:02 +02:00
parent a1a19520a4
commit 21f84fc468
4 changed files with 127 additions and 29 deletions

View file

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["Armin Becher <armin.becher@gmai.com>"] authors = ["Armin Becher <armin.becher@gmai.com>"]
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dev-dependencies] [dev-dependencies]
criterion = "0.3.1" criterion = "0.3.1"

View file

@ -10,7 +10,7 @@ fn init_vec_flat(size: usize) -> Vec<u32> {
} }
fn init_grid(size: usize) -> Grid<u32> { fn init_grid(size: usize) -> Grid<u32> {
Grid::new(size, size, 0) Grid::init(size, size, 0)
} }
fn get_vec_vec(x: usize, y: usize) -> u32 { 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) { fn criterion_benchmark(c: &mut Criterion) {
// Init // New
c.bench_function("Init vec vec 10x10", |b| { c.bench_function("Init vec vec 10x10", |b| {
b.iter(|| init_vec_vec(black_box(10))) b.iter(|| init_vec_vec(black_box(10)))
}); });

View file

@ -3,28 +3,94 @@ use std::ops::IndexMut;
pub struct Grid<T> { pub struct Grid<T> {
data: Vec<T>, data: Vec<T>,
columns: usize, cols: usize,
rows: 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<T: Clone> Grid<T> { impl<T: Clone> Grid<T> {
pub fn new(rows: usize, columns: usize, data: T) -> Grid<T> { /// Init a grid of size rows x columns with default values of the given type.
if rows < 1 || columns < 1 { /// For example this will generate a 2x3 grid of zeros:
/// ```
/// use grid::Grid;
/// let grid : Grid<u8> = Grid::new(2,2);
/// assert_eq!(grid[0][0], 0);
/// ```
pub fn new(rows: usize, cols: usize) -> Grid<T>
where
T: Default,
{
if rows < 1 || cols < 1 {
panic!("Grid size of rows and columns must be greater than zero."); panic!("Grid size of rows and columns must be greater than zero.");
} }
Grid { Grid {
data: vec![data; rows * columns], data: vec![T::default(); rows * cols],
columns: columns, cols: cols,
rows: rows, rows: rows,
} }
} }
pub fn get(&self, row: usize, column: usize) -> Option<&T> { /// Init a grid of size rows x columns with the given data element.
self.data.get(row * self.columns + column % self.columns) pub fn init(rows: usize, cols: usize, data: T) -> Grid<T> {
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) { pub fn size(&self) -> (usize, usize) {
(self.rows, self.columns) (self.rows, self.cols)
} }
} }
@ -38,7 +104,7 @@ impl<T: Clone> Index<usize> for Grid<T> {
self.rows, idx self.rows, idx
); );
} }
&self.data[(idx * &self.columns)..] &self.data[(idx * &self.cols)..]
} }
} }
@ -50,7 +116,7 @@ impl<T: Clone> IndexMut<usize> for Grid<T> {
self.rows, idx self.rows, idx
); );
} }
&mut self.data[(idx * &self.columns)..] &mut self.data[(idx * &self.cols)..]
} }
} }
@ -59,64 +125,98 @@ mod test {
use super::*; use super::*;
#[test] #[test]
fn ctr() { fn macro_init() {
Grid::new(1, 2, 3); //TODO let grid = grid![[1, 2, 3][4, 5, 6]];
Grid::new(1, 2, 1.2); let grid = grid![[1,2,3]4,5,6];
Grid::new(1, 2, 'a'); 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<usize> = 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<usize> = 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<u8> = Grid::new(1, 2);
assert_eq!(grid[0][0], 0);
}
#[test] #[test]
#[should_panic] #[should_panic]
fn ctr_panics() { fn init_panics() {
Grid::new(0, 2, 3); Grid::init(0, 2, 3);
} }
#[test] #[test]
#[should_panic] #[should_panic]
fn ctr_panics_2() { fn ctr_panics_2() {
Grid::new(1, 0, 3); Grid::init(1, 0, 3);
} }
#[test] #[test]
fn get() { fn get() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
assert_eq!(grid.get(0, 0), Some(&3)); assert_eq!(grid.get(0, 0), Some(&3));
} }
#[test] #[test]
fn get_none() { fn get_none() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
assert_eq!(grid.get(1, 0), None); assert_eq!(grid.get(1, 0), None);
} }
#[test] #[test]
fn idx() { fn idx() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
assert_eq!(grid[0][0], 3); assert_eq!(grid[0][0], 3);
} }
#[test] #[test]
#[should_panic] #[should_panic]
fn idx_panic_1() { fn idx_panic_1() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
grid[20][0]; grid[20][0];
} }
#[test] #[test]
#[should_panic] #[should_panic]
fn idx_panic_2() { fn idx_panic_2() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
grid[0][20]; grid[0][20];
} }
#[test] #[test]
fn idx_set() { fn idx_set() {
let mut grid = Grid::new(1, 2, 3); let mut grid = Grid::init(1, 2, 3);
grid[0][0] = 4; grid[0][0] = 4;
assert_eq!(grid[0][0], 4); assert_eq!(grid[0][0], 4);
} }
#[test] #[test]
fn size() { fn size() {
let grid = Grid::new(1, 2, 3); let grid = Grid::init(1, 2, 3);
assert_eq!(grid.size(), (1, 2)); assert_eq!(grid.size(), (1, 2));
} }
} }