1use ndarray::{Array, Array1, Array2, Dimension, Ix1, Ix2};
2use num::complex::Complex;
3use num::traits::Float;
4
5pub trait Angles {
11 fn to_radians(&self) -> Self;
12 fn to_degrees(&self) -> Self;
13}
14
15impl<T: Float + ndarray::ScalarOperand> Angles for Array1<T> {
17 fn to_radians(&self) -> Self {
18 self.mapv(|angle| angle.to_radians())
19 }
20
21 fn to_degrees(&self) -> Self {
22 self.mapv(|angle| angle.to_degrees())
23 }
24}
25
26impl<T: Float + ndarray::ScalarOperand> Angles for Array2<T> {
28 fn to_radians(&self) -> Self {
29 self.mapv(|angle| angle.to_radians())
30 }
31
32 fn to_degrees(&self) -> Self {
33 self.mapv(|angle| angle.to_degrees())
34 }
35}
36
37pub trait ComplexExt<T, D: Dimension> {
41 fn abs(&self) -> Array<T, D>;
42 fn imag(&self) -> Array<T, D>;
43 fn real(&self) -> Array<T, D>;
44 fn phase(&self) -> Array<T, D>;
45 fn from_real_imag(real: Array<T, D>, imag: Array<T, D>) -> Array<Complex<T>, D>;
46}
47
48impl<T: Float> ComplexExt<T, Ix1> for Array1<Complex<T>> {
50 fn abs(&self) -> Array<T, Ix1> {
51 self.map(|c| c.norm())
52 }
53
54 fn imag(&self) -> Array<T, Ix1> {
55 self.map(|c| c.im)
56 }
57
58 fn real(&self) -> Array<T, Ix1> {
59 self.map(|c| c.re)
60 }
61
62 fn phase(&self) -> Array<T, Ix1> {
63 self.map(|c| c.arg())
64 }
65
66 fn from_real_imag(real: Array<T, Ix1>, imag: Array<T, Ix1>) -> Array<Complex<T>, Ix1> {
67 let vec: Vec<_> = real
68 .iter()
69 .zip(imag.iter())
70 .map(|(&r, &i)| Complex::new(r, i))
71 .collect();
72 Array::from_shape_vec(real.raw_dim(), vec).unwrap()
73 }
74}
75
76impl<T: Float> ComplexExt<T, Ix2> for Array2<Complex<T>> {
78 fn abs(&self) -> Array2<T> {
79 self.map(|c| c.norm())
80 }
81
82 fn imag(&self) -> Array2<T> {
83 self.map(|c| c.im)
84 }
85
86 fn real(&self) -> Array2<T> {
87 self.map(|c| c.re)
88 }
89
90 fn phase(&self) -> Array2<T> {
91 self.map(|c| c.arg())
92 }
93
94 fn from_real_imag(real: Array<T, Ix2>, imag: Array<T, Ix2>) -> Array2<Complex<T>> {
95 let vec: Vec<_> = real
96 .iter()
97 .zip(imag.iter())
98 .map(|(&r, &i)| Complex::new(r, i))
99 .collect();
100 Array::from_shape_vec(real.raw_dim(), vec).unwrap()
101 }
102}
103
104pub trait FromVecVec<T: Clone> {
116 fn from_vec_vec(vec_vec: Vec<Vec<T>>) -> Array2<T> {
117 let rows = vec_vec.len();
118 let cols = vec_vec[0].len();
119
120 Array2::from_shape_vec((rows, cols), vec_vec.into_iter().flatten().collect())
121 .expect("Failed to create Array2, incorrect shape")
122 }
123}
124
125impl FromVecVec<f32> for Array2<f32> {}
127
128impl FromVecVec<f64> for Array2<f64> {}
130
131impl FromVecVec<Complex<f32>> for Array2<Complex<f32>> {}
133
134impl FromVecVec<Complex<f64>> for Array2<Complex<f64>> {}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use ndarray::{arr1, arr2};
141 use num_complex::Complex64;
142
143 #[test]
144 fn test_from_real_imag_1x3() {
145 let real = arr1(&[1.0, 2.0, 3.0]);
146 let imag = arr1(&[4.0, 5.0, 6.0]);
147 let expected = arr1(&[
148 Complex64::new(1.0, 4.0),
149 Complex64::new(2.0, 5.0),
150 Complex64::new(3.0, 6.0),
151 ]);
152 assert_eq!(Array1::from_real_imag(real, imag), expected);
153 }
154
155 #[test]
156 fn test_from_real_imag_2x2() {
157 let real = arr2(&[[1.0, 2.0], [3.0, 4.0]]);
158 let imag = arr2(&[[5.0, 6.0], [7.0, 8.0]]);
159 let expected = arr2(&[
160 [Complex64::new(1.0, 5.0), Complex64::new(2.0, 6.0)],
161 [Complex64::new(3.0, 7.0), Complex64::new(4.0, 8.0)],
162 ]);
163 assert_eq!(Array2::from_real_imag(real, imag), expected);
164 }
165
166 #[test]
167 fn test_from_real_imag_2x3() {
168 let real = arr2(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]);
169 let imag = arr2(&[[7.0, 8.0, 9.0], [10.0, 11.0, 12.0]]);
170 let expected = arr2(&[
171 [
172 Complex64::new(1.0, 7.0),
173 Complex64::new(2.0, 8.0),
174 Complex64::new(3.0, 9.0),
175 ],
176 [
177 Complex64::new(4.0, 10.0),
178 Complex64::new(5.0, 11.0),
179 Complex64::new(6.0, 12.0),
180 ],
181 ]);
182 assert_eq!(Array2::from_real_imag(real, imag), expected);
183 }
184}