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