# `block-grid`
#### A quick, cache-conscious, blocked 2D array
[![Crate][crate_badge]][crate]
[![Docs][docs_badge]][docs]
[![License][license_badge]][license]
[![CI][ci_badge]][ci]
`block-grid` gives you a fixed size, two-dimensional array, with a blocked memory representation. This has the sweet benefit of being much more cache-friendly if you're often accessing nearby coordinates.
## Features
- Can store any type
- Generic compile-time block sizes
- Indexing with `(row, col): (usize, usize)`
- Block level access with `Block` and `BlockMut`
- Constructors from row-major and column-major order arrays
- Iterators for in-memory and row-major order, and by block
- `no_std` and [`serde`][serde] support
- Also supports no blocks (i.e. classic row-major)
## Example
```rust
use block_grid::{BlockGrid, CoordsIterator, U2};
fn main() {
let data: Vec<_> = (0..(4 * 6)).collect();
// Construct from row-major ordered data
let grid = BlockGrid::::from_row_major(4, 6, &data).unwrap();
// The 2D grid looks like:
// +-----------------------+
// | 0 1 | 2 3 | 4 5 |
// | 6 7 | 8 9 | 10 11 |
// |-------+-------+-------|
// | 12 13 | 14 15 | 16 17 |
// | 18 19 | 20 21 | 22 23 |
// +-----------------------+
// Indexing
assert_eq!(grid[(1, 3)], 9);
// Access raw array
let first_five = &grid.raw()[..5];
assert_eq!(first_five, &[0, 1, 6, 7, 2]);
// Iterate over blocks, and access the last
let block = grid.block_iter().last().unwrap();
assert_eq!(block[(0, 1)], 17);
// Iterate in row-major order
for (i, &x) in grid.row_major_iter().enumerate() {
assert_eq!(x, i);
}
// Iterate in memory order, with coordinates
for ((row, col), &x) in grid.each_iter().coords() {
assert_eq!(row * 6 + col, x);
}
}
```
## Why
TODO: Stuff about caches
## Trade-offs
- Non-resizable, and grid dimensions have to be a multiple of the block size.
- Currently, only square blocks, and power-of-two block sizes are supported.
- Computing the modified index takes just a bit more time.
- There are still cache misses when you cross tile boundaries.
- No support for strides or general subsets.
## Changelog
See [`CHANGELOG.md`](CHANGELOG.md).
## License
`block-grid` is licensed under the [MIT license](LICENSE).
## Alternatives
If your access patterns suit a typical row-major memory representation, you can still use `block-grid`! If you truly desire alternatives, however, check out [`array2d`][array2d], [`imgref`][imgref], [`grid`][grid], or [`toodee`][toodee]. The last two support dynamic resizing. For matrices and linear algebra, there's also [`nalgebra`][nalgebra].
[serde]: https://crates.io/crates/serde "serde"
[array2d]: https://crates.io/crates/array2d "array2d"
[imgref]: https://crates.io/crates/imgref "imgref"
[grid]: https://crates.io/crates/grid "grid"
[toodee]: https://crates.io/crates/toodee "toodee"
[nalgebra]: https://nalgebra.org "nalgebra"
[crate]: https://crates.io/crates/block-grid "Crate"
[crate_badge]: https://img.shields.io/crates/v/block-grid?logo=rust "Crate"
[docs]: https://docs.rs/block-grid "Docs"
[docs_badge]: https://docs.rs/block-grid/badge.svg "Docs"
[ci]: https://github.com/gunvirranu/block-grid/actions "Github Actions"
[ci_badge]: https://github.com/gunvirranu/block-grid/workflows/CI/badge.svg?branch=master "Github Actions"
[license]: #license "License"
[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg "License"