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
//! Basic digital signal processing (DSP) operations //! //! Digital signal processing based on real or complex vectors in time or frequency domain. //! Vectors are expected to typically have a size which is at least in the order //! of magnitude of a couple of thousand elements. This crate tries to balance between a clear //! API and performance in terms of processing speed. //! This project started as small pet project to learn more about DSP, CPU architecture and Rust. //! Since learning //! involves making mistakes, don't expect things to be flawless or even close to flawless. //! //! This library isn't suited - from my point of view - for game programming. If you are looking //! for vector types to do //! 2D or 3D graphics calculations then you unfortunately have to continue with your search. //! However there seem to be //! a lot of suitable crates on `crates.io` for you. //! //! The vector types don't distinguish between 1xN or Nx1. This is a difference to other //! conventions such as in MATLAB or GNU Octave. //! The reason for this decision is that it seems to be more practical to ignore the //! shape of the vector. //! //! Right now the library uses pretty aggressive parallelization. So this means that it will //! keep all CPU cores busy //! even if the performance gain is minimal e.g. because the multi core overhead is nearly as //! large as the performance boost //! of multiple cores. In future there will be likely an option which tells the library how it //! should balance between processing time //! and CPU utilization. The library also avoids to allocate and free memory so it allocates //! all of the required temporary memory when a new vector //! is constructed. Therefore the library is likely not suitable for devices which are tight //! on memory. On normal desktop computers there is usually plenty of //! memory available so that the optimization focus is on decreasing the processing time //! for every (common) operation and to spent little time with memory allocations. #[cfg(any(feature = "doc", feature="use_sse", feature="use_avx"))] extern crate simd; extern crate num_cpus; extern crate crossbeam; extern crate num; extern crate rustfft; mod vector_types; mod multicore_support; mod simd_extensions; pub mod window_functions; pub mod conv_types; pub use vector_types::*; pub use multicore_support::MultiCoreSettings; use num::traits::Float; use std::fmt::Debug; use std::ops::*; use simd_extensions::*; /// Associates a number type with a SIMD register type. pub trait ToSimd: Sized + Sync + Send { type Reg: Simd<Self> + SimdGeneric<Self> + Copy + Sync + Send + Add<Output = Self::Reg> + Sub<Output = Self::Reg> + Mul<Output = Self::Reg> + Div<Output = Self::Reg> + Zero; } impl ToSimd for f32 { type Reg = Reg32; } impl ToSimd for f64 { type Reg = Reg64; } /// A real floating pointer number intended to abstract over `f32` and `f64`. pub trait RealNumber : Float + Copy + Clone + Send + Sync + ToSimd + Debug + num::Signed + num::FromPrimitive { } impl<T> RealNumber for T where T: Float + Copy + Clone + Send + Sync + ToSimd + Debug + num::Signed + num::FromPrimitive { } /// This trait is necessary so that we can define zero for types outside this crate. /// It calls the `num::Zero` trait where possible. pub trait Zero { fn zero() -> Self; } impl<T> Zero for T where T: RealNumber { fn zero() -> Self { <Self as num::Zero>::zero() } } impl<T> Zero for num::Complex<T> where T: RealNumber { fn zero() -> Self { <Self as num::Zero>::zero() } } #[cfg(test)] mod tests { use super::*; use simd_extensions::Simd; #[test] fn to_simd_test() { // This is more a check for syntax. So if it compiles // then the test already passes. The assert is then only // a sanity check. let reg = <f32 as ToSimd>::Reg::splat(1.0); let sum = reg.sum_real(); assert!(sum > 0.0); } }