1use super::super::{
2 ComplexNumberSpace, Domain, DspVec, ErrorReason, MetaData, RealNumberSpace, ScalarResult,
3 ToSlice, ToSliceMut,
4};
5use crate::inline_vector::InlineVector;
6use crate::multicore_support::*;
7use crate::numbers::*;
8use crate::{array_to_complex, array_to_complex_mut};
9
10pub trait MapInplaceOps<T>: Sized
13where
14 T: Sized,
15{
16 fn map_inplace<'a, A, F>(&mut self, argument: A, map: &F)
18 where
19 A: Sync + Copy + Send,
20 F: Fn(T, usize, A) -> T + 'a + Sync;
21}
22
23pub trait MapAggregateOps<T, R>: Sized
25where
26 T: Sized,
27 R: Send,
28{
29 type Output;
30 fn map_aggregate<'a, A, FMap, FAggr>(
35 &self,
36 argument: A,
37 map: &FMap,
38 aggregate: &FAggr,
39 ) -> Self::Output
40 where
41 A: Sync + Copy + Send,
42 FMap: Fn(T, usize, A) -> R + 'a + Sync,
43 FAggr: Fn(R, R) -> R + 'a + Sync + Send;
44}
45
46impl<S, T, N, D> MapInplaceOps<T> for DspVec<S, T, N, D>
47where
48 S: ToSliceMut<T>,
49 T: RealNumber,
50 N: RealNumberSpace,
51 D: Domain,
52{
53 fn map_inplace<'a, A, F>(&mut self, argument: A, map: &F)
54 where
55 A: Sync + Copy + Send,
56 F: Fn(T, usize, A) -> T + 'a + Sync,
57 {
58 if self.is_complex() {
59 self.mark_vector_as_invalid();
60 return;
61 }
62
63 let array = self.data.to_slice_mut();
64 let length = array.len();
65 Chunk::execute_with_range(
66 Complexity::Small,
67 &self.multicore_settings,
68 &mut array[0..length],
69 1,
70 argument,
71 move |array, range, argument| {
72 let mut i = range.start;
73 for num in array {
74 *num = map(*num, i, argument);
75 i += 1;
76 }
77 },
78 );
79 }
80}
81
82impl<S, T, N, D, R> MapAggregateOps<T, R> for DspVec<S, T, N, D>
83where
84 S: ToSlice<T>,
85 T: RealNumber,
86 N: RealNumberSpace,
87 D: Domain,
88 R: Send,
89{
90 type Output = ScalarResult<R>;
91
92 fn map_aggregate<'a, A, FMap, FAggr>(
93 &self,
94 argument: A,
95 map: &FMap,
96 aggregate: &FAggr,
97 ) -> ScalarResult<R>
98 where
99 A: Sync + Copy + Send,
100 FMap: Fn(T, usize, A) -> R + 'a + Sync,
101 FAggr: Fn(R, R) -> R + 'a + Sync + Send,
102 {
103 let mut result = {
104 if self.is_complex() {
105 return Err(ErrorReason::InputMustBeReal);
106 }
107
108 let array = self.data.to_slice();
109 let length = array.len();
110 if length == 0 {
111 return Err(ErrorReason::InputMustNotBeEmpty);
112 }
113 Chunk::map_on_array_chunks(
114 Complexity::Small,
115 &self.multicore_settings,
116 &array[0..length],
117 1,
118 argument,
119 move |array, range, argument| {
120 let mut i = range.start;
121 let mut sum: Option<R> = None;
122 for num in array {
123 let res = map(*num, i, argument);
124 sum = match sum {
125 None => Some(res),
126 Some(s) => Some(aggregate(s, res)),
127 };
128 i += 1;
129 }
130 sum
131 },
132 )
133 };
134 let mut only_valid_options = InlineVector::with_capacity(result.len());
137 for _ in 0..result.len() {
138 let elem = result.pop().unwrap();
139 match elem {
140 None => (),
141 Some(e) => only_valid_options.push(e),
142 };
143 }
144
145 if only_valid_options.is_empty() {
146 return Err(ErrorReason::InputMustNotBeEmpty);
147 }
148 let mut aggregated = only_valid_options.pop().unwrap();
149 for _ in 0..only_valid_options.len() {
150 aggregated = aggregate(aggregated, only_valid_options.pop().unwrap());
151 }
152 Ok(aggregated)
153 }
154}
155
156impl<S, T, N, D> MapInplaceOps<Complex<T>> for DspVec<S, T, N, D>
157where
158 S: ToSliceMut<T>,
159 T: RealNumber,
160 N: ComplexNumberSpace,
161 D: Domain,
162{
163 fn map_inplace<'a, A, F>(&mut self, argument: A, map: &F)
164 where
165 A: Sync + Copy + Send,
166 F: Fn(Complex<T>, usize, A) -> Complex<T> + 'a + Sync,
167 {
168 if !self.is_complex() {
169 self.mark_vector_as_invalid();
170 return;
171 }
172
173 let array = self.data.to_slice_mut();
174 let length = array.len();
175 Chunk::execute_with_range(
176 Complexity::Small,
177 &self.multicore_settings,
178 &mut array[0..length],
179 2,
180 argument,
181 move |array, range, argument| {
182 let mut i = range.start / 2;
183 let array = array_to_complex_mut(array);
184 for num in array {
185 *num = map(*num, i, argument);
186 i += 1;
187 }
188 },
189 );
190 }
191}
192
193impl<S, T, N, D, R> MapAggregateOps<Complex<T>, R> for DspVec<S, T, N, D>
194where
195 S: ToSlice<T>,
196 T: RealNumber,
197 N: ComplexNumberSpace,
198 D: Domain,
199 R: Send,
200{
201 type Output = ScalarResult<R>;
202
203 fn map_aggregate<'a, A, FMap, FAggr>(
204 &self,
205 argument: A,
206 map: &FMap,
207 aggregate: &FAggr,
208 ) -> ScalarResult<R>
209 where
210 A: Sync + Copy + Send,
211 FMap: Fn(Complex<T>, usize, A) -> R + 'a + Sync,
212 FAggr: Fn(R, R) -> R + 'a + Sync + Send,
213 {
214 let mut result = {
215 if !self.is_complex() {
216 return Err(ErrorReason::InputMustBeComplex);
217 }
218
219 let array = self.data.to_slice();
220 let length = array.len();
221 if length == 0 {
222 return Err(ErrorReason::InputMustNotBeEmpty);
223 }
224 Chunk::map_on_array_chunks(
225 Complexity::Small,
226 &self.multicore_settings,
227 &array[0..length],
228 2,
229 argument,
230 move |array, range, argument| {
231 let array = array_to_complex(array);
232 let mut i = range.start / 2;
233 let mut sum: Option<R> = None;
234 for num in array {
235 let res = map(*num, i, argument);
236 sum = match sum {
237 None => Some(res),
238 Some(s) => Some(aggregate(s, res)),
239 };
240 i += 1;
241 }
242 sum
243 },
244 )
245 };
246 let mut only_valid_options = InlineVector::with_capacity(result.len());
249 for _ in 0..result.len() {
250 let elem = result.pop().unwrap();
251 match elem {
252 None => (),
253 Some(e) => only_valid_options.push(e),
254 };
255 }
256
257 if only_valid_options.is_empty() {
258 return Err(ErrorReason::InputMustNotBeEmpty);
259 }
260 let mut aggregated = only_valid_options.pop().unwrap();
261 for _ in 0..only_valid_options.len() {
262 aggregated = aggregate(aggregated, only_valid_options.pop().unwrap());
263 }
264 Ok(aggregated)
265 }
266}