block_grid/block_width.rs
1/// A type that represents compile time block dimensions.
2pub trait BlockDim: Clone {
3 /// Number of left shifts of 1 for value.
4 const SHIFT: usize;
5
6 /// Width and height of 2D block.
7 const WIDTH: usize = 1 << Self::SHIFT;
8 /// Number of elements in 2D block.
9 const AREA: usize = Self::WIDTH * Self::WIDTH;
10 /// Bitmask for value.
11 const MASK: usize = Self::WIDTH - 1;
12
13 /// Rounds up dimensions to next valid size. Returns `(rows, cols)`.
14 ///
15 /// # Example
16 ///
17 /// ```
18 /// use block_grid::{BlockDim, U4};
19 ///
20 /// // (3, 10) are not valid dimensions for a block size of 4
21 /// let new_valid = U4::round_up_to_valid(3, 10);
22 /// // (4, 12) are the returned valid dimensions
23 /// assert_eq!(new_valid, (4, 12));
24 /// ```
25 fn round_up_to_valid(rows: usize, cols: usize) -> (usize, usize) {
26 let round_up = |i: usize| {
27 let mut i = i.max(1);
28 let rem = i % Self::WIDTH;
29 if rem != 0 {
30 i += Self::WIDTH - rem;
31 }
32 i
33 };
34 (round_up(rows), round_up(cols))
35 }
36}
37
38macro_rules! make_block_width [
39 ($($name: ident, $shift: literal);*) => {
40 $(
41 #[allow(missing_docs)]
42 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
43 pub struct $name;
44
45 impl BlockDim for $name {
46 const SHIFT: usize = $shift;
47 }
48 )*
49 }
50];
51
52make_block_width![
53 U1, 0;
54 U2, 1;
55 U4, 2;
56 U8, 3;
57 U16, 4;
58 U32, 5;
59 U64, 6;
60 U128, 7;
61 U256, 8;
62 U512, 9
63];