1use crate::multicore_support::{Chunk, Complexity, MultiCoreSettings};
2use crate::numbers::*;
3use crate::simd_extensions::*;
4use crate::{array_to_complex, array_to_complex_mut};
5use std;
6use std::cmp;
7use std::fmt;
8use std::mem;
9use std::ops::*;
10use std::result;
11
12mod requirements;
13pub use self::requirements::*;
14mod to_from_vec_conversions;
15pub use self::to_from_vec_conversions::*;
16mod support_core;
17pub use self::support_core::*;
18#[cfg(any(feature = "std", test))]
19mod support_std;
20#[cfg(any(feature = "std", test))]
21pub use self::support_std::*;
22#[cfg(feature = "std")]
23mod support_std_par;
24#[cfg(feature = "std")]
25pub use self::support_std_par::*;
26mod vec_impl_and_indexers;
27pub use self::vec_impl_and_indexers::*;
28mod complex;
29pub use self::complex::*;
30mod real;
31pub use self::real::*;
32mod time_freq;
33pub use self::time_freq::*;
34mod rededicate_and_relations;
35pub use self::rededicate_and_relations::*;
36mod checks_and_results;
37pub use self::checks_and_results::*;
38mod general;
39pub use self::general::*;
40mod buffer;
41pub use self::buffer::*;
42use super::meta;
43
44pub type TransRes<T> = result::Result<T, (ErrorReason, T)>;
49
50pub type VoidResult = result::Result<(), ErrorReason>;
52
53pub type ScalarResult<T> = result::Result<T, ErrorReason>;
55
56#[derive(Copy, Clone, PartialEq, Debug)]
58pub enum DataDomain {
59 Time,
61 Frequency,
63}
64
65pub trait NumberSpace: fmt::Debug + cmp::PartialEq + Clone {
67 fn is_complex(&self) -> bool;
68
69 fn to_complex(&mut self);
74
75 fn to_real(&mut self);
77}
78
79pub trait Domain: fmt::Debug + cmp::PartialEq + Clone {
81 fn domain(&self) -> DataDomain;
82
83 fn to_freq(&mut self);
85
86 fn to_time(&mut self);
88}
89
90pub trait RealNumberSpace: NumberSpace {}
92
93pub trait ComplexNumberSpace: NumberSpace {}
95
96pub trait TimeDomain: Domain {}
98
99pub trait FrequencyDomain: Domain {}
101
102pub trait PosEq<O> {}
104
105pub struct DspVec<S, T, N, D>
126where
127 S: ToSlice<T>,
128 T: RealNumber,
129 N: NumberSpace,
130 D: Domain,
131{
132 pub data: S,
135 delta: T,
136 domain: D,
137 number_space: N,
138 valid_len: usize,
139 multicore_settings: MultiCoreSettings,
140}
141
142#[derive(Clone, Copy)]
144pub struct TypeMetaData<T, N, D> {
145 delta: T,
146 domain: D,
147 number_space: N,
148 multicore_settings: MultiCoreSettings,
149}
150
151impl<S, T, N, D> fmt::Debug for DspVec<S, T, N, D>
152where
153 S: ToSlice<T>,
154 T: RealNumber,
155 D: Domain,
156 N: NumberSpace,
157{
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 write!(
160 f,
161 "DspVec {{ points: {}, domain: {:?}, number_space: {:?} }}",
162 self.valid_len, self.domain, self.number_space
163 )
164 }
165}
166
167fn swap_array_halves<T>(data: &mut [T], forward: bool)
172where
173 T: Copy,
174{
175 let len = data.len();
176 if len % 2 == 0 {
177 let (lo, up) = data.split_at_mut(len / 2);
178 for (lo, up) in lo.iter_mut().zip(up.iter_mut()) {
179 mem::swap(lo, up);
180 }
181 } else {
182 let step = if forward { len / 2 } else { len / 2 + 1 };
183 let mut temp = data[0];
184 let mut pos = step;
185 for _ in 0..len {
186 let pos_new = (pos + step) % len;
187 mem::swap(&mut temp, &mut data[pos]);
188 pos = pos_new;
189 }
190 }
191}
192
193fn complex_to_array<T>(complex: &[Complex<T>]) -> &[T]
195where
196 T: RealNumber,
197{
198 super::transmute_slice(complex)
199}
200
201fn complex_to_array_mut<T>(complex: &mut [Complex<T>]) -> &mut [T]
203where
204 T: RealNumber,
205{
206 super::transmute_slice_mut(complex)
207}
208
209impl<S: ToSliceMut<T>, T: RealNumber> DspVec<S, T, meta::RealOrComplex, meta::TimeOrFreq> {
210 pub fn is_erroneous(&self) -> bool {
214 self.valid_len == 0 && self.delta.is_nan()
215 }
216}
217
218impl<S, T, N, D> DspVec<S, T, N, D>
219where
220 S: ToSliceMut<T>,
221 T: RealNumber,
222 N: NumberSpace,
223 D: Domain,
224{
225 fn mark_vector_as_invalid(&mut self) {
227 self.valid_len = 0;
228 self.delta = T::nan();
229 }
230
231 #[inline]
233 fn pure_real_operation<A, F>(&mut self, op: F, argument: A, complexity: Complexity)
234 where
235 A: Sync + Copy + Send,
236 F: Fn(T, A) -> T + 'static + Sync,
237 {
238 {
239 let len = self.valid_len;
240 let array = self.data.to_slice_mut();
241 Chunk::execute_partial(
242 complexity,
243 &self.multicore_settings,
244 &mut array[0..len],
245 1,
246 argument,
247 move |array, argument| {
248 for num in array {
249 *num = op(*num, argument);
250 }
251 },
252 );
253 }
254 }
255
256 #[inline]
258 fn pure_complex_operation<A, F>(&mut self, op: F, argument: A, complexity: Complexity)
259 where
260 A: Sync + Copy + Send,
261 F: Fn(Complex<T>, A) -> Complex<T> + 'static + Sync,
262 {
263 {
264 let len = self.valid_len;
265 let array = self.data.to_slice_mut();
266 Chunk::execute_partial(
267 complexity,
268 &self.multicore_settings,
269 &mut array[0..len],
270 2,
271 argument,
272 move |array, argument| {
273 let array = array_to_complex_mut(array);
274 for num in array {
275 *num = op(*num, argument);
276 }
277 },
278 );
279 }
280 }
281
282 #[inline]
283 fn simd_real_operationf<Reg: SimdGeneric<T>, F, G>(
284 &mut self,
285 reg: RegType<Reg>,
286 simd_op: F,
287 scalar_op: G,
288 argument: T,
289 complexity: Complexity,
290 ) where
291 F: Fn(Reg, Reg) -> Reg + 'static + Sync,
292 G: Fn(T, Reg) -> T + 'static + Sync,
293 {
294 self.simd_real_operation(reg, simd_op, scalar_op, Reg::splat(argument), complexity);
295 }
296
297 #[inline]
299 fn simd_real_operation<Reg: SimdGeneric<T>, A, F, G>(
300 &mut self,
301 _: RegType<Reg>,
302 simd_op: F,
303 scalar_op: G,
304 argument: A,
305 complexity: Complexity,
306 ) where
307 A: Sync + Copy + Send,
308 F: Fn(Reg, A) -> Reg + 'static + Sync,
309 G: Fn(T, A) -> T + 'static + Sync,
310 {
311 {
312 let data_length = self.valid_len;
313 let array = self.data.to_slice_mut();
314 let partition = Reg::calc_data_alignment_reqs(&array[0..data_length]);
315 Chunk::execute_partial(
316 complexity,
317 &self.multicore_settings,
318 partition.center_mut(array),
319 Reg::LEN,
320 argument,
321 move |array, argument| {
322 let array = Reg::array_to_regs_mut(array);
323 for reg in array {
324 *reg = simd_op(*reg, argument);
325 }
326 },
327 );
328
329 for num in partition.edge_iter_mut(&mut array[0..data_length]) {
330 *num = scalar_op(*num, argument);
331 }
332 }
333 }
334
335 #[inline]
336 fn simd_complex_operationf<Reg: SimdGeneric<T>, F, G>(
337 &mut self,
338 reg: RegType<Reg>,
339 simd_op: F,
340 scalar_op: G,
341 argument: Complex<T>,
342 complexity: Complexity,
343 ) where
344 F: Fn(Reg, Reg) -> Reg + 'static + Sync,
345 G: Fn(Complex<T>, Reg) -> Complex<T> + 'static + Sync,
346 {
347 self.simd_complex_operation(
348 reg,
349 simd_op,
350 scalar_op,
351 Reg::from_complex(argument),
352 complexity,
353 )
354 }
355
356 #[inline]
358 fn simd_complex_operation<Reg: SimdGeneric<T>, A, F, G>(
359 &mut self,
360 _: RegType<Reg>,
361 simd_op: F,
362 scalar_op: G,
363 argument: A,
364 complexity: Complexity,
365 ) where
366 A: Sync + Copy + Send,
367 F: Fn(Reg, A) -> Reg + 'static + Sync,
368 G: Fn(Complex<T>, A) -> Complex<T> + 'static + Sync,
369 {
370 {
371 let data_length = self.valid_len;
372 let array = self.data.to_slice_mut();
373 let partition = Reg::calc_data_alignment_reqs(&array[0..data_length]);
374 Chunk::execute_partial(
375 complexity,
376 &self.multicore_settings,
377 partition.center_mut(array),
378 Reg::LEN,
379 argument,
380 move |array, argument| {
381 let array = Reg::array_to_regs_mut(array);
382 for reg in array {
383 *reg = simd_op(*reg, argument);
384 }
385 },
386 );
387
388 for num in partition.cedge_iter_mut(array_to_complex_mut(&mut array[0..data_length])) {
389 *num = scalar_op(*num, argument);
390 }
391 }
392 }
393
394 #[inline]
396 fn pure_complex_to_real_operation<A, F, B>(
397 &mut self,
398 buffer: &mut B,
399 op: F,
400 argument: A,
401 complexity: Complexity,
402 ) where
403 A: Sync + Copy + Send,
404 F: Fn(Complex<T>, A) -> T + 'static + Sync,
405 B: for<'a> Buffer<'a, S, T>,
406 {
407 {
408 let data_length = self.len();
409 let mut result = buffer.borrow(data_length / 2);
410 {
411 let array = self.data.to_slice_mut();
412 let temp = result.to_slice_mut();
413 Chunk::from_src_to_dest(
414 complexity,
415 &self.multicore_settings,
416 &array[0..data_length],
417 2,
418 &mut temp[0..data_length / 2],
419 1,
420 argument,
421 move |array, range, target, argument| {
422 let array = array_to_complex(&array[range.start..range.end]);
423 for pair in array.iter().zip(target) {
424 let (src, dest) = pair;
425 *dest = op(*src, argument);
426 }
427 },
428 );
429 self.valid_len = data_length / 2;
430 }
431 result.trade(&mut self.data);
432 }
433 }
434
435 #[inline]
437 fn pure_complex_to_real_operation_inplace<A, F>(&mut self, op: F, argument: A)
438 where
439 A: Sync + Copy + Send,
440 F: Fn(Complex<T>, A) -> T + 'static + Sync,
441 {
442 {
443 let data_length = self.len();
444 let array = self.data.to_slice_mut();
445 for i in 0..data_length / 2 {
446 let input = Complex::new(array[2 * i], array[2 * i + 1]);
447 array[i] = op(input, argument);
448 }
449
450 self.valid_len /= 2;
451 }
452 }
453
454 #[inline]
456 fn simd_complex_to_real_operation<Reg: SimdGeneric<T>, A, F, G, B>(
457 &mut self,
458 _: RegType<Reg>,
459 buffer: &mut B,
460 simd_op: F,
461 scalar_op: G,
462 argument: A,
463 complexity: Complexity,
464 ) where
465 A: Sync + Copy + Send,
466 F: Fn(Reg, A) -> Reg + 'static + Sync,
467 G: Fn(Complex<T>, A) -> T + 'static + Sync,
468 B: for<'a> Buffer<'a, S, T>,
469 {
470 let data_length = self.len();
471 let mut result = buffer.borrow(data_length / 2);
472 {
473 let array = self.data.to_slice_mut();
474 let temp = result.to_slice_mut();
475 let partition = Reg::calc_data_alignment_reqs(&array[0..data_length]);
476 Chunk::from_src_to_dest(
477 complexity,
478 &self.multicore_settings,
479 partition.center(&array),
480 Reg::LEN,
481 partition.rcenter_mut(temp),
482 Reg::LEN / 2,
483 argument,
484 move |array, range, target, argument| {
485 let array = Reg::array_to_regs(&array[range.start..range.end]);
486 let mut j = 0;
487 for reg in array {
488 let result = simd_op(*reg, argument);
489 result.store_real(target, j);
490 j += Reg::LEN / 2;
491 }
492 },
493 );
494
495 let array = array_to_complex(&array[0..data_length]);
496 for (src, dest) in partition
497 .cedge_iter(array)
498 .zip(partition.redge_iter_mut(temp))
499 {
500 *dest = scalar_op(*src, argument);
501 }
502
503 self.valid_len /= 2;
504 }
505 result.trade(&mut self.data);
506 }
507
508 #[inline]
510 fn swap_halves_priv(&mut self, forward: bool) {
511 let len = self.len();
512 if len == 0 {
513 return;
514 }
515
516 if self.is_complex() {
517 let data = self.data.to_slice_mut();
518 let data = array_to_complex_mut(&mut data[0..len]);
519 swap_array_halves(data, forward);
520 } else {
521 let data = self.data.to_slice_mut();
522 swap_array_halves(&mut data[0..len], forward);
523 }
524 }
525
526 #[inline]
528 fn multiply_window_priv<TT, CMut, FA, F>(
529 &mut self,
530 is_symmetric: bool,
531 convert_mut: CMut,
532 function_arg: FA,
533 fun: F,
534 ) where
535 CMut: Fn(&mut [T]) -> &mut [TT],
536 FA: Copy + Sync + Send,
537 F: Fn(FA, usize, usize) -> TT + 'static + Sync,
538 TT: Zero + Mul<Output = TT> + Copy + Send + Sync + From<T>,
539 {
540 if !is_symmetric {
541 {
542 let len = self.len();
543 let points = self.points();
544 let data = self.data.to_slice_mut();
545 let converted = convert_mut(&mut data[0..len]);
546 Chunk::execute_with_range(
547 Complexity::Medium,
548 &self.multicore_settings,
549 converted,
550 1,
551 function_arg,
552 move |array, range, arg| {
553 let mut j = range.start;
554 for num in array {
555 *num = (*num) * fun(arg, j, points);
556 j += 1;
557 }
558 },
559 );
560 }
561 } else {
562 {
563 let len = self.len();
564 let points = self.points();
565 let data = self.data.to_slice_mut();
566 let converted = convert_mut(&mut data[0..len]);
567 Chunk::execute_sym_pairs_with_range(
568 Complexity::Medium,
569 &self.multicore_settings,
570 converted,
571 1,
572 function_arg,
573 move |array1, range, array2, _, arg| {
574 assert!(array1.len() >= array2.len());
575 let mut j = range.start;
576 let len1 = array1.len();
577 let len_diff = len1 - array2.len();
578 {
579 let iter1 = array1.iter_mut();
580 let iter2 = array2.iter_mut().rev();
581 for (num1, num2) in iter1.zip(iter2) {
582 let arg = fun(arg, j, points);
583 *num1 = (*num1) * arg;
584 *num2 = (*num2) * arg;
585 j += 1;
586 }
587 }
588 for num1 in &mut array1[len1 - len_diff..len1] {
589 let arg = fun(arg, j, points);
590 *num1 = (*num1) * arg;
591 j += 1;
592 }
593 },
594 );
595 }
596 }
597 }
598}
599
600pub struct NoTradeBufferBurrow<'a, T: RealNumber + 'a> {
602 data: &'a mut [T],
603}
604
605impl<'a, T: RealNumber + 'a> ToSlice<T> for NoTradeBufferBurrow<'a, T> {
606 fn to_slice(&self) -> &[T] {
607 self.data.to_slice()
608 }
609
610 fn len(&self) -> usize {
611 self.data.len()
612 }
613
614 fn is_empty(&self) -> bool {
615 self.data.is_empty()
616 }
617
618 fn alloc_len(&self) -> usize {
619 self.data.alloc_len()
620 }
621
622 fn try_resize(&mut self, len: usize) -> VoidResult {
623 self.data.try_resize(len)
624 }
625}
626
627impl<'a, T: RealNumber + 'a> ToSliceMut<T> for NoTradeBufferBurrow<'a, T> {
628 fn to_slice_mut(&mut self) -> &mut [T] {
629 self.data.to_slice_mut()
630 }
631}
632
633impl<'a, S: ToSliceMut<T>, T: RealNumber> BufferBorrow<S, T> for NoTradeBufferBurrow<'a, T> {
634 fn trade(self, _: &mut S) {
635 }
637}
638
639struct NoTradeBuffer<B, S, T>
642where
643 B: BufferBorrow<S, T>,
644 S: ToSliceMut<T>,
645 T: RealNumber,
646{
647 data: B,
648 storage_type: std::marker::PhantomData<S>,
649 data_type: std::marker::PhantomData<T>,
650}
651
652impl<B, S, T> NoTradeBuffer<B, S, T>
653where
654 B: BufferBorrow<S, T>,
655 S: ToSliceMut<T>,
656 T: RealNumber,
657{
658 pub fn new(storage: B) -> NoTradeBuffer<B, S, T> {
661 NoTradeBuffer {
662 data: storage,
663 storage_type: std::marker::PhantomData,
664 data_type: std::marker::PhantomData,
665 }
666 }
667}
668
669impl<'a, B, S, T> Buffer<'a, &mut [T], T> for NoTradeBuffer<B, S, T>
670where
671 B: BufferBorrow<S, T>,
672 S: ToSliceMut<T>,
673 T: RealNumber + 'a,
674{
675 type Borrow = NoTradeBufferBurrow<'a, T>;
676
677 fn borrow(&'a mut self, len: usize) -> Self::Borrow {
678 self.data
679 .try_resize(len)
680 .expect("NoTradeBuffer: Out of memory");
681 NoTradeBufferBurrow {
682 data: &mut self.data.to_slice_mut()[0..len],
683 }
684 }
685
686 fn alloc_len(&self) -> usize {
687 self.data.alloc_len()
688 }
689}
690
691#[cfg(test)]
692mod tests {
693 use super::swap_array_halves;
694
695 #[test]
696 fn swap_halves_even_test() {
697 let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
698 swap_array_halves(&mut v, false);
699 assert_eq!(&v[..], &[5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0]);
700 }
701
702 #[test]
703 fn swap_halves_odd_foward_test() {
704 let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
705 swap_array_halves(&mut v, true);
706 assert_eq!(&v[..], &[6.0, 7.0, 8.0, 9.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
707 }
708
709 #[test]
710 fn swap_halves_odd_inverse_test() {
711 let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
712 swap_array_halves(&mut v, false);
713 assert_eq!(&v[..], &[5.0, 6.0, 7.0, 8.0, 9.0, 1.0, 2.0, 3.0, 4.0]);
714 }
715}