array_object/convert/
into_complex.rs

1use crate::adaptor::*;
2use crate::error::ArrayObjectError;
3use crate::storage::*;
4use num_complex::Complex;
5
6macro_rules! into_complex {
7    ($($ty:tt),*) => {
8        $(
9            impl TryFrom<ArrayObject> for Pair<$ty> {
10                type Error = ArrayObjectError;
11                fn try_from(mut val: ArrayObject) -> Result<Self, Self::Error> {
12                    if !val.shape.is_empty() || val.datatype != DataType::Complex {
13                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
14                    }
15                    match val.data.len() / 2 {
16                        4 => {
17                            let data_im = val.data.split_off(4);
18                            let re = f32::from_le_bytes(val.data.try_into().unwrap()) as $ty;
19                            let im = f32::from_le_bytes(data_im.try_into().unwrap()) as $ty;
20                            Ok(Pair(re, im))
21                        }
22                        8 => {
23                            #[cfg(not(feature = "allow_float_down_convert"))]
24                            if size_of::<$ty>() < 8 {
25                                return Err(ArrayObjectError::LossyConversion);
26                            }
27                            let data_im = val.data.split_off(8);
28                            let re = f64::from_le_bytes(val.data.try_into().unwrap()) as $ty;
29                            let im = f64::from_le_bytes(data_im.try_into().unwrap()) as $ty;
30                            Ok(Pair(re, im))
31                        }
32                        _ => {panic!();}
33                    }
34                }
35            }
36            impl TryFrom<ArrayObject> for Complex<$ty> {
37                type Error = ArrayObjectError;
38                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
39                    let Pair(re, im) = val.try_into()?;
40                    Ok(Complex::new(re, im))
41                }
42            }
43            impl TryFrom<ArrayObject> for VecShape<Pair<$ty>> {
44                type Error = ArrayObjectError;
45                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
46                    if val.shape.is_empty() || val.datatype != DataType::Complex {
47                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
48                    }
49                    let len = val.len();
50                    if len == 0 {
51                        return Ok(VecShape(vec![], val.shape));
52                    }
53                    match val.data.len() / (2 * len) {
54                        4 => {
55                            let data = val.data.chunks(8).map(|b| {
56                                let mut iter = b.chunks(4);
57                                let re = f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
58                                let im = f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
59                                Pair(re, im)
60                            }).collect();
61                            Ok(VecShape(data, val.shape))
62                        }
63                        8 => {
64                            #[cfg(not(feature = "allow_float_down_convert"))]
65                            if size_of::<$ty>() < 8 {
66                                return Err(ArrayObjectError::LossyConversion);
67                            }
68                            let data = val.data.chunks(16).map(|b| {
69                                let mut iter = b.chunks(8);
70                                let re = f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
71                                let im = f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
72                                Pair(re, im)
73                            }).collect();
74                            Ok(VecShape(data, val.shape))
75                        }
76                        _ => {panic!();}
77                    }
78                }
79            }
80            impl TryFrom<ArrayObject> for VecShape<Complex<$ty>> {
81                type Error = ArrayObjectError;
82                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
83                    if val.shape.is_empty() || val.datatype != DataType::Complex {
84                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
85                    }
86                    let len = val.len();
87                    if len == 0 {
88                        return Ok(VecShape(vec![], val.shape));
89                    }
90                    match val.data.len() / (2 * len) {
91                        4 => {
92                            let data = val.data.chunks(8).map(|b| {
93                                let mut iter = b.chunks(4);
94                                let re = f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
95                                let im = f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
96                                Complex::<$ty>::new(re, im)
97                            }).collect();
98                            Ok(VecShape(data, val.shape))
99                        }
100                        8 => {
101                            #[cfg(not(feature = "allow_float_down_convert"))]
102                            if size_of::<$ty>() < 8 {
103                                return Err(ArrayObjectError::LossyConversion);
104                            }
105                            let data = val.data.chunks(16).map(|b| {
106                                let mut iter = b.chunks(8);
107                                let re = f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
108                                let im = f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty;
109                                Complex::<$ty>::new(re, im)
110                            }).collect();
111                            Ok(VecShape(data, val.shape))
112                        }
113                        _ => {panic!();}
114                    }
115                }
116            }
117            impl TryFrom<ArrayObject> for VecVecShape<$ty> {
118                type Error = ArrayObjectError;
119                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
120                    if val.shape.is_empty() || val.datatype != DataType::Complex {
121                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
122                    }
123                    let len = val.len();
124                    if len == 0 {
125                        return Ok(VecVecShape(vec![], vec![], val.shape));
126                    }
127                    let mut re = Vec::<$ty>::with_capacity(len * 2);
128                    let mut im = Vec::<$ty>::with_capacity(len * 2);
129                    match val.data.len() / (2 * len) {
130                        4 => {
131                            for b in val.data.chunks(8) {
132                                let mut iter = b.chunks(4);
133                                re.push(f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty);
134                                im.push(f32::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty);
135                            }
136                        }
137                        8 => {
138                            #[cfg(not(feature = "allow_float_down_convert"))]
139                            if size_of::<$ty>() < 8 {
140                                return Err(ArrayObjectError::LossyConversion);
141                            }
142                            for b in val.data.chunks(16) {
143                                let mut iter = b.chunks(8);
144                                re.push(f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty);
145                                im.push(f64::from_le_bytes(iter.next().unwrap().to_vec().try_into().unwrap()) as $ty);
146                            }
147                        }
148                        _ => {panic!();}
149                    }
150                    Ok(VecVecShape(re, im, val.shape))
151                }
152            }
153            impl TryFrom<ArrayObject> for Vec<Complex<$ty>> {
154                type Error = ArrayObjectError;
155                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
156                    if val.shape.len() != 1 {
157                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
158                    }
159                    let VecShape::<Complex<$ty>>(data, _) = val.try_into()?;
160                    Ok(data)
161                }
162            }
163            impl<const N: usize> TryFrom<ArrayObject> for [Complex<$ty>; N] {
164                type Error = ArrayObjectError;
165                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
166                    if val.len() != N {
167                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
168                    }
169                    let data: Vec<Complex<$ty>> = val.try_into()?;
170                    Ok(data.try_into().unwrap())
171                }
172            }
173        )*
174    };
175}
176
177into_complex!(f32, f64);