use crate::shape::Shape;
#[derive(Clone, PartialEq, Eq)]
pub struct Mask {
padded_rows: usize,
padded_cols: usize,
rows: usize,
cols: usize,
words: Vec<u64>,
}
impl Mask {
pub fn from_shape(shape: &Shape) -> Self {
let total = shape.padded_len();
let word_count = total.div_ceil(64);
let mut words = vec![0u64; word_count];
for row in 0..shape.rows {
for col in 0..shape.cols {
let idx = row * shape.padded_cols + col;
words[idx / 64] |= 1u64 << (idx % 64);
}
}
Mask {
padded_rows: shape.padded_rows,
padded_cols: shape.padded_cols,
rows: shape.rows,
cols: shape.cols,
words,
}
}
#[inline]
fn bit_index(&self, row: usize, col: usize) -> usize {
row * self.padded_cols + col
}
#[inline]
pub fn is_valid(&self, row: usize, col: usize) -> bool {
if row >= self.padded_rows || col >= self.padded_cols {
return false;
}
let idx = self.bit_index(row, col);
(self.words[idx / 64] >> (idx % 64)) & 1 == 1
}
#[inline]
pub fn count_valid(&self) -> usize {
self.rows * self.cols
}
#[inline]
pub fn count_padding(&self) -> usize {
self.padded_rows * self.padded_cols - self.rows * self.cols
}
#[inline]
pub fn is_full(&self) -> bool {
self.count_padding() == 0
}
pub fn count_valid_in_tile(
&self,
base_row: usize,
base_col: usize,
sublanes: usize,
lanes: usize,
) -> usize {
let mut count = 0;
for r in base_row..(base_row + sublanes) {
for c in base_col..(base_col + lanes) {
if self.is_valid(r, c) {
count += 1;
}
}
}
count
}
}
impl core::fmt::Debug for Mask {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"Mask {{ {} valid, {} padding }}",
self.count_valid(),
self.count_padding()
)
}
}