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];