#![allow(
// Serde
clippy::integer_arithmetic
)]
mod dense_error;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use cl_aux::{ArrayWrapper, SingleTypeStorage};
pub use dense_error::*;
pub type DenseArray<DATA, const D: usize, const DN: usize> = Dense<[DATA; DN], D>;
pub type DenseMut<'data, DATA, const D: usize> = Dense<&'data mut [DATA], D>;
pub type DenseRef<'data, DATA, const D: usize> = Dense<&'data [DATA], D>;
#[cfg(feature = "alloc")]
pub type DenseVec<DATA, const D: usize> = Dense<Vec<DATA>, D>;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct Dense<DS, const D: usize> {
pub(crate) data: DS,
pub(crate) dims: ArrayWrapper<usize, D>,
}
impl<DS, const D: usize> Dense<DS, D> {
#[inline]
pub fn dims(&self) -> &[usize; D] {
&self.dims
}
}
impl<DATA, DS, const D: usize> Dense<DS, D>
where
DS: AsRef<[<DS as SingleTypeStorage>::Item]> + SingleTypeStorage<Item = DATA>,
{
#[cfg_attr(feature = "alloc", doc = "```rust")]
#[cfg_attr(not(feature = "alloc"), doc = "```ignore")]
#[inline]
pub fn new(dims: [usize; D], data: DS) -> crate::Result<Self> {
if dims.iter().copied().any(|elem| elem >= D) {
return Err(DenseError::InvalidIndcs.into());
}
Ok(Self { data, dims: dims.into() })
}
#[inline]
pub fn data(&self) -> &[DATA] {
self.data.as_ref()
}
#[inline]
pub fn value(&self, indcs: [usize; D]) -> Option<&DATA> {
self.data().get(self.idx(indcs))
}
#[inline]
fn dim_stride(&self, dim_idx: usize, target_dim_idx: usize) -> usize {
self.dims.iter().copied().skip(1).rev().skip(dim_idx).chain([target_dim_idx]).product()
}
#[inline]
fn idx(&self, indcs: [usize; D]) -> usize {
let mut rslt: usize = 0;
for (dim_idx, target_dim_idx) in (0..self.dims.len()).zip(indcs) {
rslt = rslt.wrapping_add(self.dim_stride(dim_idx, target_dim_idx));
}
rslt
}
}