1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
use super::*;
use crate::TransformContent;
use std::marker;

macro_rules! add_mat_impl {
    ($($matrix:ident);*) => {
        $(
			impl <V: Vector<T> + ToRealResult, S: ToSlice<T>, T: RealNumber>
				ToRealResult for $matrix<V, S, T>
				where <V as ToRealResult>::RealResult: Vector<T> {
					type RealResult = $matrix<V::RealResult, S, T>;
			}

			impl<V: Vector<T>, S: ToSlice<T>, T: RealNumber>
					ComplexToRealTransformsOps<T> for $matrix<V, S, T>
					where <V as ToRealResult>::RealResult: Vector<T>,
                          V: ComplexToRealTransformsOps<T> {
				fn magnitude(self) -> Self::RealResult {
					let rows = self.rows.transform(|v|v.magnitude());
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn magnitude_squared(self) -> Self::RealResult {
                    let rows = self.rows.transform(|v|v.magnitude_squared());
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn to_real(self) -> Self::RealResult {
                    let rows = self.rows.transform(|v|v.to_real());
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn to_imag(self) -> Self::RealResult {
                    let rows = self.rows.transform(|v|v.to_imag());
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn phase(self) -> Self::RealResult {
                    let rows = self.rows.transform(|v|v.phase());
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}
			}

			impl<V: Vector<T>, S: ToSliceMut<T>, T: RealNumber>
					ComplexToRealTransformsOpsBuffered<S, T> for $matrix<V, S, T>
					where <V as ToRealResult>::RealResult: Vector<T>,
                          V: ComplexToRealTransformsOpsBuffered<S, T> {
				fn magnitude_b<B>(self, buffer: &mut B) -> Self::RealResult
                    where B: for<'b> Buffer<'b, S, T> {
					let rows = self.rows.transform(|v|v.magnitude_b(buffer));
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn magnitude_squared_b<B>(self, buffer: &mut B) -> Self::RealResult
                    where B: for<'b> Buffer<'b, S, T> {
                    let rows = self.rows.transform(|v|v.magnitude_squared_b(buffer));
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn to_real_b<B>(self, buffer: &mut B) -> Self::RealResult
                    where B: for<'b> Buffer<'b, S, T> {
                    let rows = self.rows.transform(|v|v.to_real_b(buffer));
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn to_imag_b<B>(self, buffer: &mut B) -> Self::RealResult
                    where B: for<'b> Buffer<'b, S, T> {
                    let rows = self.rows.transform(|v|v.to_imag_b(buffer));
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}

				fn phase_b<B>(self, buffer: &mut B) -> Self::RealResult
                    where B: for<'b> Buffer<'b, S, T> {
                    let rows = self.rows.transform(|v|v.phase_b(buffer));
                    $matrix {
                        rows: rows,
                        storage_type: marker::PhantomData,
                	  	number_type: marker::PhantomData
                    }
				}
			}

			impl<V: Vector<T>, S: ToSlice<T>, T: RealNumber, N: NumberSpace, D: Domain, O>
					ComplexToRealGetterOps<O, T, N, D> for $matrix<V, S, T>
					where O: Matrix<V, T> + GetMetaData<T, N, D>,
                          V: ComplexToRealGetterOps<V, T, N, D> + GetMetaData<T, N, D> {
				fn get_real(&self, destination: &mut O) {
                    for (o, v) in destination.rows_mut().iter_mut().zip(self.rows()) {
						v.get_real(o);
					}
				}

				fn get_imag(&self, destination: &mut O) {
                    for (o, v) in destination.rows_mut().iter_mut().zip(self.rows()) {
						v.get_imag(o);
					}
				}

				fn get_magnitude(&self, destination: &mut O) {
                    for (o, v) in destination.rows_mut().iter_mut().zip(self.rows()) {
						v.get_imag(o);
					}
				}

				fn get_magnitude_squared(&self, destination: &mut O) {
                    for (o, v) in destination.rows_mut().iter_mut().zip(self.rows()) {
						v.get_imag(o);
					}
				}

				fn get_phase(&self, destination: &mut O) {
                    for (o, v) in destination.rows_mut().iter_mut().zip(self.rows()) {
						v.get_imag(o);
					}
				}

				fn get_real_imag(&self,
                                 real: &mut O,
                                 imag: &mut O) {
                    for ((r, i), v) in real.rows_mut().iter_mut()
                                    .zip(imag.rows_mut())
                                    .zip(self.rows()) {
 						v.get_real_imag(r, i);
 					}
				}

				fn get_mag_phase(&self,
                                 mag: &mut O,
                                 phase: &mut O) {
                    for ((r, i), v) in mag.rows_mut().iter_mut()
                                     .zip(phase.rows_mut())
                                     .zip(self.rows()) {
  						v.get_mag_phase(r, i);
  					}
				}
			}

            impl<V: Vector<T>, S: ToSlice<T>, T: RealNumber, N: NumberSpace, D: Domain, O>
					ComplexToRealSetterOps<O, T, N, D> for $matrix<V, S, T>
					where O: Matrix<V, T> + GetMetaData<T, N, D>,
                          V: ComplexToRealSetterOps<V, T, N, D> + GetMetaData<T, N, D> {
				fn set_real_imag(&mut self,
                                 real: &O,
                                 imag: &O) -> VoidResult {
                    for ((v, r), i) in self.rows_mut().iter_mut()
                                    .zip(real.rows())
                                    .zip(imag.rows()) {
 						v.set_real_imag(r, i)?;
 					}

                    Ok(())
				}

				fn set_mag_phase(&mut self,
                                 mag: &O,
                                 phase: &O) -> VoidResult {
                    for ((v, r), i) in self.rows_mut().iter_mut()
                                     .zip(mag.rows())
                                     .zip(phase.rows()) {
  						v.set_mag_phase(r, i)?;
  					}

                    Ok(())
				}
			}

			impl<V: Vector<T>, S: ToSlice<T>, T: RealNumber> ComplexOps<T>
                    for $matrix<V, S, T>
                    where V: ComplexOps<T> {
				fn multiply_complex_exponential(&mut self, a: T, b: T) {
                    for v in self.rows_mut() {
                        v.multiply_complex_exponential(a, b);
                    }
				}

				fn conj(&mut self) {
                    for v in self.rows_mut() {
                        v.conj();
                    }
				}
			}
		)*
	}
}

add_mat_impl!(MatrixMxN; Matrix2xN; Matrix3xN; Matrix4xN);