use crate::{MatrwError, interface::variable::MatVariable};
pub trait ArrayType {
fn dim(&self) -> &Vec<usize>;
fn get_ref_colmaj(&self, index: usize) -> Option<&MatVariable>;
fn get_clone_colmaj(&self, index: usize) -> Option<MatVariable>;
fn get_ref_multidim(&self, idx: &[usize]) -> Option<&MatVariable> {
self.get_ref_colmaj(self.column_index(idx)?)
}
fn get_clone_multidim(&self, idx: &[usize]) -> Option<MatVariable> {
self.get_clone_colmaj(self.column_index(idx)?)
}
fn column_index(&self, idx: &[usize]) -> Option<usize> {
if self.dim().len() != idx.len() {
return None;
}
for (i, v) in idx.iter().enumerate() {
if self.dim()[i] <= *v {
return None;
}
}
let mut v_idx = 0;
let mut stride = 1;
for (i, dim) in idx.iter().zip(self.dim().iter()) {
v_idx += i * stride;
stride *= dim;
}
Some(v_idx)
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_Array_for {
($type:ty) => {
impl ArrayType for $type {
fn dim(&self) -> &Vec<usize> {
&self.dim
}
fn get_ref_colmaj(&self, index: usize) -> Option<&MatVariable> {
self.value.get(index)
}
fn get_clone_colmaj(&self, _index: usize) -> Option<MatVariable> {
unimplemented!()
}
}
};
}
pub fn ensure_matching_dimension(elem_from_dim: usize, elem_provided: usize) -> Result<(), MatrwError> {
if elem_from_dim != elem_provided {
Err(MatrwError::TypeConstruction(format!(
"Specified size from dimension {} does not match number of elements {}.",
elem_from_dim, elem_provided
)))
} else {
Ok(())
}
}
pub fn ensure_matching_complex_size(value_len: usize, value_comp_len: usize) -> Result<(), MatrwError> {
if value_len != value_comp_len {
Err(MatrwError::TypeConstruction(format!(
"Size of real ({}) and complex ({}) data of different size.",
value_len, value_comp_len
)))
} else {
Ok(())
}
}
pub fn normalize_dimension(dim: Vec<usize>, value_len: usize) -> Vec<usize> {
if dim.is_empty() || (dim.len() == 1 && dim[0] > 0) {
vec![1, value_len]
} else if dim.len() == 1 && dim[0] == 0 {
vec![0, 0]
} else {
dim
}
}