use faer::{Mat, MatRef};
#[cfg(feature = "ndarray")]
use crate::utils::traits::EvocFloat;
#[cfg(feature = "ndarray")]
use ndarray::{Array2, ArrayView2};
pub enum MatInput<'a, T> {
Borrowed(MatRef<'a, T>),
Owned(Mat<T>),
}
impl<T> MatInput<'_, T> {
pub fn as_mat_ref(&self) -> MatRef<'_, T> {
match self {
MatInput::Borrowed(mat) => *mat,
MatInput::Owned(mat) => mat.as_ref(),
}
}
}
pub trait EvocMatrix<T> {
fn to_mat_input(&self) -> MatInput<'_, T>;
}
impl<T> EvocMatrix<T> for MatRef<'_, T> {
fn to_mat_input(&self) -> MatInput<'_, T> {
MatInput::Borrowed(*self)
}
}
impl<T> EvocMatrix<T> for &Mat<T> {
fn to_mat_input(&self) -> MatInput<'_, T> {
MatInput::Borrowed(self.as_ref())
}
}
impl<T> EvocMatrix<T> for Mat<T> {
fn to_mat_input(&self) -> MatInput<'_, T> {
MatInput::Borrowed(self.as_ref())
}
}
impl<T> EvocMatrix<T> for (&[T], usize, usize) {
fn to_mat_input(&self) -> MatInput<'_, T> {
let (data, n_samples, n_features) = *self;
assert_eq!(
data.len(),
n_samples * n_features,
"flat input length {} does not match shape {n_samples} x {n_features}",
data.len()
);
MatInput::Borrowed(MatRef::from_row_major_slice(data, n_samples, n_features))
}
}
impl<T> EvocMatrix<T> for (Vec<T>, usize, usize) {
fn to_mat_input(&self) -> MatInput<'_, T> {
let (data, n_samples, n_features) = (&self.0, self.1, self.2);
assert_eq!(
data.len(),
n_samples * n_features,
"flat input length {} does not match shape {n_samples} x {n_features}",
data.len()
);
MatInput::Borrowed(MatRef::from_row_major_slice(data, n_samples, n_features))
}
}
#[cfg(feature = "ndarray")]
impl<T> EvocMatrix<T> for ArrayView2<'_, T>
where
T: EvocFloat,
{
fn to_mat_input(&self) -> MatInput<'_, T> {
let (n_samples, n_features) = (self.nrows(), self.ncols());
match self.to_slice() {
Some(slice) => {
MatInput::Borrowed(MatRef::from_row_major_slice(slice, n_samples, n_features))
}
None => MatInput::Owned(Mat::from_fn(n_samples, n_features, |i, j| self[(i, j)])),
}
}
}
#[cfg(feature = "ndarray")]
impl<T> EvocMatrix<T> for Array2<T>
where
T: EvocFloat,
{
fn to_mat_input(&self) -> MatInput<'_, T> {
let (n_samples, n_features) = (self.nrows(), self.ncols());
match self.as_slice() {
Some(slice) => {
MatInput::Borrowed(MatRef::from_row_major_slice(slice, n_samples, n_features))
}
None => MatInput::Owned(Mat::from_fn(n_samples, n_features, |i, j| self[(i, j)])),
}
}
}
#[cfg(feature = "ndarray")]
impl<T> EvocMatrix<T> for &Array2<T>
where
T: EvocFloat,
{
fn to_mat_input(&self) -> MatInput<'_, T> {
(*self).to_mat_input()
}
}