#![doc(html_root_url = "https://docs.rs/matfile-ndarray/0.2.0")]
use matfile as mf;
use ndarray as nd;
use ndarray::IntoDimension;
use ndarray::ShapeBuilder;
use num_complex::Complex;
#[derive(Debug)]
pub enum Error {
ShapeError,
TypeError,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::ShapeError => write!(f, "Array shapes do not match"),
Error::TypeError => write!(f, "Array types are not compatible"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
pub trait TryInto<T> {
type Error;
fn try_into(self) -> Result<T, Self::Error>;
}
macro_rules! dynamic_conversions {
( $num:ty, $variant:ident ) => {
impl<'me> TryInto<nd::ArrayViewD<'me, $num>> for &'me mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::ArrayViewD<'me, $num>, Self::Error> {
match self.data() {
mf::NumericData::$variant { ref real, imag: None } => {
let dimension: nd::IxDyn = self.size().clone().into_dimension();
nd::ArrayView::from_shape(dimension.set_f(true), real)
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
impl TryInto<nd::ArrayD<$num>> for &mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::ArrayD<$num>, Self::Error> {
match self.data() {
mf::NumericData::$variant { ref real, imag: None } => {
let dimension: nd::IxDyn = self.size().clone().into_dimension();
nd::Array::from_shape_vec(dimension.set_f(true), real.clone())
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
impl TryInto<nd::ArrayD<Complex<$num>>> for &mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::ArrayD<Complex<$num>>, Self::Error> {
match self.data() {
mf::NumericData::$variant { ref real, imag: Some(ref imag) } => {
let dimension: nd::IxDyn = self.size().clone().into_dimension();
let values = real.iter().zip(imag.iter()).map(|(&re, &im)| Complex::new(re, im)).collect();
nd::Array::from_shape_vec(dimension.set_f(true), values)
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
};
}
macro_rules! static_conversions_n {
( $num:ty, $variant:ident, $ndims:literal ) => {
impl<'me> TryInto<nd::ArrayView<'me, $num, nd::Dim<[nd::Ix; $ndims]>>> for &'me mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::ArrayView<'me, $num, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
let size = self.size();
if size.len() != $ndims {
return Err(Error::ShapeError);
}
let mut shape = [0; $ndims];
shape.copy_from_slice(size);
match self.data() {
mf::NumericData::$variant { ref real, imag: None } => {
let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
nd::ArrayView::from_shape(dimension.set_f(true), real)
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
impl TryInto<nd::Array<$num, nd::Dim<[nd::Ix; $ndims]>>> for &mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::Array<$num, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
let size = self.size();
if size.len() != $ndims {
return Err(Error::ShapeError);
}
let mut shape = [0; $ndims];
shape.copy_from_slice(size);
match self.data() {
mf::NumericData::$variant { ref real, imag: None } => {
let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
nd::Array::from_shape_vec(dimension.set_f(true), real.clone())
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
impl TryInto<nd::Array<Complex<$num>, nd::Dim<[nd::Ix; $ndims]>>> for &mf::Array {
type Error = Error;
fn try_into(self) -> Result<nd::Array<Complex<$num>, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
let size = self.size();
if size.len() != $ndims {
return Err(Error::ShapeError);
}
let mut shape = [0; $ndims];
shape.copy_from_slice(size);
match self.data() {
mf::NumericData::$variant { ref real, imag: Some(ref imag) } => {
let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
let values = real.iter().zip(imag.iter()).map(|(&re, &im)| Complex::new(re, im)).collect();
nd::Array::from_shape_vec(dimension.set_f(true), values)
.map_err(|_err| Error::ShapeError)
}
_ => Err(Error::TypeError),
}
}
}
};
}
macro_rules! static_conversions {
( $num:ty, $variant:ident ) => {
static_conversions_n!($num, $variant, 2);
static_conversions_n!($num, $variant, 3);
static_conversions_n!($num, $variant, 4);
static_conversions_n!($num, $variant, 5);
static_conversions_n!($num, $variant, 6);
};
}
macro_rules! all_conversions {
( $num:ty, $variant:ident ) => {
dynamic_conversions!($num, $variant);
static_conversions!($num, $variant);
};
}
all_conversions!(f64, Double);
all_conversions!(f32, Single);
all_conversions!(i64, Int64);
all_conversions!(u64, UInt64);
all_conversions!(i32, Int32);
all_conversions!(u32, UInt32);
all_conversions!(i16, Int16);
all_conversions!(u16, UInt16);
all_conversions!(i8, Int8);
all_conversions!(u8, UInt8);