use std::ops::Range;
use super::{MatrixErrorType, MatrixShape, Scalar};
#[derive(Clone, Copy, Debug)]
pub struct DenseBlock<'a, F> {
values: &'a [F],
nrows: usize,
ncols: usize,
}
impl<'a, F> DenseBlock<'a, F> {
pub fn new(values: &'a [F], nrows: usize, ncols: usize) -> Self {
let len = nrows.checked_mul(ncols).expect("block dimensions overflow");
assert_eq!(values.len(), len, "block dimensions must match values");
Self {
values,
nrows,
ncols,
}
}
pub fn values(&self) -> &'a [F] {
self.values
}
pub fn get(&self, row: usize, column: usize) -> F
where
F: Copy,
{
assert!(
row < self.nrows && column < self.ncols,
"block index out of bounds"
);
self.values[row * self.ncols + column]
}
}
impl<F> MatrixShape for DenseBlock<'_, F> {
fn nrows(&self) -> usize {
self.nrows
}
fn ncols(&self) -> usize {
self.ncols
}
}
pub trait ReadBlock<F: Scalar>: MatrixShape + MatrixErrorType {
fn read_block<'buf>(
&self,
rows: Range<usize>,
columns: Range<usize>,
buffer: &'buf mut [F],
) -> Result<DenseBlock<'buf, F>, Self::Error>;
}
impl<M: ReadBlock<F> + ?Sized, F: Scalar> ReadBlock<F> for &M {
fn read_block<'buf>(
&self,
rows: Range<usize>,
columns: Range<usize>,
buffer: &'buf mut [F],
) -> Result<DenseBlock<'buf, F>, Self::Error> {
(**self).read_block(rows, columns, buffer)
}
}
#[cfg(feature = "zarrs_all")]
pub(crate) fn validate_rectangle(
shape: &impl MatrixShape,
rows: &Range<usize>,
columns: &Range<usize>,
capacity: usize,
) -> usize {
assert!(
rows.start <= rows.end && rows.end <= shape.nrows(),
"block row range out of bounds"
);
assert!(
columns.start <= columns.end && columns.end <= shape.ncols(),
"block column range out of bounds"
);
let len = rows
.len()
.checked_mul(columns.len())
.expect("block dimensions overflow");
assert!(capacity >= len, "block buffer too short");
len
}
impl<M: ReadBlock<F> + ?Sized, F: Scalar> ReadBlock<F> for &mut M {
fn read_block<'buf>(
&self,
rows: Range<usize>,
columns: Range<usize>,
buffer: &'buf mut [F],
) -> Result<DenseBlock<'buf, F>, Self::Error> {
(**self).read_block(rows, columns, buffer)
}
}