#![allow(
clippy::cast_sign_loss,
clippy::cast_lossless,
clippy::doc_markdown,
clippy::field_reassign_with_default
)]
use crate::decompress::{ChunkUpload, CHUNK_Z, OCC_WORDS_PER_COLUMN};
pub struct GridUpload {
pub vsid: u32,
pub origin_chunk: [i32; 3],
pub chunks_dims: [u32; 3],
pub pool_dims: [u32; 3],
pub chunks: Vec<([i32; 3], ChunkUpload)>,
}
impl GridUpload {
#[must_use]
pub fn total_chunks(&self) -> u32 {
self.chunks_dims[0] * self.chunks_dims[1] * self.chunks_dims[2]
}
#[must_use]
pub fn default_pool_dims(chunks_dims: [u32; 3]) -> [u32; 3] {
[
ceil_pow2(chunks_dims[0]),
ceil_pow2(chunks_dims[1]),
ceil_pow2(chunks_dims[2]),
]
}
#[must_use]
pub fn meta_idx_of(&self, chunk_idx: [i32; 3]) -> Option<u32> {
let dx = chunk_idx[0] - self.origin_chunk[0];
let dy = chunk_idx[1] - self.origin_chunk[1];
let dz = chunk_idx[2] - self.origin_chunk[2];
if dx < 0
|| dy < 0
|| dz < 0
|| (dx as u32) >= self.chunks_dims[0]
|| (dy as u32) >= self.chunks_dims[1]
|| (dz as u32) >= self.chunks_dims[2]
{
return None;
}
Some(
(dx as u32)
+ (dy as u32) * self.chunks_dims[0]
+ (dz as u32) * self.chunks_dims[0] * self.chunks_dims[1],
)
}
}
#[must_use]
pub fn ceil_pow2(n: u32) -> u32 {
if n <= 1 {
return 1;
}
1u32 << (32 - (n - 1).leading_zeros())
}
#[must_use]
pub fn bounding_box_of(chunks: impl IntoIterator<Item = [i32; 3]>) -> Option<([i32; 3], [u32; 3])> {
let mut min = [i32::MAX; 3];
let mut max = [i32::MIN; 3];
let mut any = false;
for idx in chunks {
for i in 0..3 {
if idx[i] < min[i] {
min[i] = idx[i];
}
if idx[i] > max[i] {
max[i] = idx[i];
}
}
any = true;
}
if !any {
return None;
}
#[allow(clippy::cast_sign_loss)]
let dims = [
(max[0] - min[0] + 1) as u32,
(max[1] - min[1] + 1) as u32,
(max[2] - min[2] + 1) as u32,
];
Some((min, dims))
}
#[must_use]
pub fn occ_words_per_chunk(vsid: u32) -> u32 {
vsid * vsid * OCC_WORDS_PER_COLUMN
}
pub const GRID_CHUNK_Z: u32 = CHUNK_Z;