1#![doc(html_root_url = "https://docs.rs/matfile-ndarray/0.2.0")]
2
3use matfile as mf;
51use ndarray as nd;
52use ndarray::IntoDimension;
53use ndarray::ShapeBuilder;
54use num_complex::Complex;
55
56#[derive(Debug)]
57pub enum Error {
58 ShapeError,
61 TypeError,
63}
64
65impl std::fmt::Display for Error {
66 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
67 match self {
68 Error::ShapeError => write!(f, "Array shapes do not match"),
69 Error::TypeError => write!(f, "Array types are not compatible"),
70 }
71 }
72}
73
74impl std::error::Error for Error {
75 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
76 None
77 }
78}
79
80pub trait TryInto<T> {
84 type Error;
85 fn try_into(self) -> Result<T, Self::Error>;
86}
87
88macro_rules! dynamic_conversions {
89 ( $num:ty, $variant:ident ) => {
90 impl<'me> TryInto<nd::ArrayViewD<'me, $num>> for &'me mf::Array {
91 type Error = Error;
92 fn try_into(self) -> Result<nd::ArrayViewD<'me, $num>, Self::Error> {
93 match self.data() {
94 mf::NumericData::$variant { ref real, imag: None } => {
95 let dimension: nd::IxDyn = self.size().clone().into_dimension();
96 nd::ArrayView::from_shape(dimension.set_f(true), real)
97 .map_err(|_err| Error::ShapeError)
98 }
99 _ => Err(Error::TypeError),
100 }
101 }
102 }
103
104 impl TryInto<nd::ArrayD<$num>> for &mf::Array {
105 type Error = Error;
106 fn try_into(self) -> Result<nd::ArrayD<$num>, Self::Error> {
107 match self.data() {
108 mf::NumericData::$variant { ref real, imag: None } => {
109 let dimension: nd::IxDyn = self.size().clone().into_dimension();
110 nd::Array::from_shape_vec(dimension.set_f(true), real.clone())
111 .map_err(|_err| Error::ShapeError)
112 }
113 _ => Err(Error::TypeError),
114 }
115 }
116 }
117
118 impl TryInto<nd::ArrayD<Complex<$num>>> for &mf::Array {
119 type Error = Error;
120 fn try_into(self) -> Result<nd::ArrayD<Complex<$num>>, Self::Error> {
121 match self.data() {
122 mf::NumericData::$variant { ref real, imag: Some(ref imag) } => {
123 let dimension: nd::IxDyn = self.size().clone().into_dimension();
124 let values = real.iter().zip(imag.iter()).map(|(&re, &im)| Complex::new(re, im)).collect();
125 nd::Array::from_shape_vec(dimension.set_f(true), values)
126 .map_err(|_err| Error::ShapeError)
127 }
128 _ => Err(Error::TypeError),
129 }
130 }
131 }
132 };
133}
134
135macro_rules! static_conversions_n {
136 ( $num:ty, $variant:ident, $ndims:literal ) => {
137 impl<'me> TryInto<nd::ArrayView<'me, $num, nd::Dim<[nd::Ix; $ndims]>>> for &'me mf::Array {
138 type Error = Error;
139 fn try_into(self) -> Result<nd::ArrayView<'me, $num, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
140 let size = self.size();
141 if size.len() != $ndims {
142 return Err(Error::ShapeError);
143 }
144 let mut shape = [0; $ndims];
145 shape.copy_from_slice(size);
146 match self.data() {
147 mf::NumericData::$variant { ref real, imag: None } => {
148 let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
149 nd::ArrayView::from_shape(dimension.set_f(true), real)
150 .map_err(|_err| Error::ShapeError)
151 }
152 _ => Err(Error::TypeError),
153 }
154 }
155 }
156
157 impl TryInto<nd::Array<$num, nd::Dim<[nd::Ix; $ndims]>>> for &mf::Array {
158 type Error = Error;
159 fn try_into(self) -> Result<nd::Array<$num, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
160 let size = self.size();
161 if size.len() != $ndims {
162 return Err(Error::ShapeError);
163 }
164 let mut shape = [0; $ndims];
165 shape.copy_from_slice(size);
166 match self.data() {
167 mf::NumericData::$variant { ref real, imag: None } => {
168 let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
169 nd::Array::from_shape_vec(dimension.set_f(true), real.clone())
170 .map_err(|_err| Error::ShapeError)
171 }
172 _ => Err(Error::TypeError),
173 }
174 }
175 }
176
177 impl TryInto<nd::Array<Complex<$num>, nd::Dim<[nd::Ix; $ndims]>>> for &mf::Array {
178 type Error = Error;
179 fn try_into(self) -> Result<nd::Array<Complex<$num>, nd::Dim<[nd::Ix; $ndims]>>, Self::Error> {
180 let size = self.size();
181 if size.len() != $ndims {
182 return Err(Error::ShapeError);
183 }
184 let mut shape = [0; $ndims];
185 shape.copy_from_slice(size);
186 match self.data() {
187 mf::NumericData::$variant { ref real, imag: Some(ref imag) } => {
188 let dimension: nd::Dim<[nd::Ix; $ndims]> = shape.into_dimension();
189 let values = real.iter().zip(imag.iter()).map(|(&re, &im)| Complex::new(re, im)).collect();
190 nd::Array::from_shape_vec(dimension.set_f(true), values)
191 .map_err(|_err| Error::ShapeError)
192 }
193 _ => Err(Error::TypeError),
194 }
195 }
196 }
197 };
198}
199
200macro_rules! static_conversions {
201 ( $num:ty, $variant:ident ) => {
202 static_conversions_n!($num, $variant, 2);
203 static_conversions_n!($num, $variant, 3);
204 static_conversions_n!($num, $variant, 4);
205 static_conversions_n!($num, $variant, 5);
206 static_conversions_n!($num, $variant, 6);
207 };
208}
209
210macro_rules! all_conversions {
211 ( $num:ty, $variant:ident ) => {
212 dynamic_conversions!($num, $variant);
213 static_conversions!($num, $variant);
214 };
215}
216
217all_conversions!(f64, Double);
218all_conversions!(f32, Single);
219all_conversions!(i64, Int64);
220all_conversions!(u64, UInt64);
221all_conversions!(i32, Int32);
222all_conversions!(u32, UInt32);
223all_conversions!(i16, Int16);
224all_conversions!(u16, UInt16);
225all_conversions!(i8, Int8);
226all_conversions!(u8, UInt8);