diff --git a/dsp/src/lib.rs b/dsp/src/lib.rs index f3af4d4..581f585 100644 --- a/dsp/src/lib.rs +++ b/dsp/src/lib.rs @@ -1,102 +1,7 @@ #![cfg_attr(not(test), no_std)] -#![cfg_attr(feature = "nightly", feature(asm, core_intrinsics))] - -use core::ops::{Add, Mul, Neg}; - -fn abs(x: T) -> T -where - T: PartialOrd + Default + Neg, -{ - if x >= T::default() { - x - } else { - -x - } -} - -// These are implemented here because core::f32 doesn't have them (yet). -// They are naive and don't handle inf/nan. -// `compiler-intrinsics`/llvm should have better (robust, universal, and -// faster) implementations. - -fn copysign(x: T, y: T) -> T -where - T: PartialOrd + Default + Neg, -{ - if (x >= T::default() && y >= T::default()) - || (x <= T::default() && y <= T::default()) - { - x - } else { - -x - } -} - -#[cfg(not(feature = "nightly"))] -fn max(x: T, y: T) -> T -where - T: PartialOrd, -{ - if x > y { - x - } else { - y - } -} - -#[cfg(not(feature = "nightly"))] -fn min(x: T, y: T) -> T -where - T: PartialOrd, -{ - if x < y { - x - } else { - y - } -} - -#[cfg(feature = "nightly")] -fn max(x: f32, y: f32) -> f32 { - core::intrinsics::maxnumf32(x, y) -} - -#[cfg(feature = "nightly")] -fn min(x: f32, y: f32) -> f32 { - core::intrinsics::minnumf32(x, y) -} - -// Multiply-accumulate vectors `x` and `a`. -// -// A.k.a. dot product. -// Rust/LLVM optimize this nicely. -fn macc(y0: T, x: &[T], a: &[T]) -> T -where - T: Add + Mul + Copy, -{ - x.iter() - .zip(a) - .map(|(x, a)| *x * *a) - .fold(y0, |y, xa| y + xa) -} - -/// Combine high and low i32 into a single downscaled i32, saturating the type. -pub fn saturating_scale(lo: i32, hi: i32, shift: u32) -> i32 { - debug_assert!(shift & 31 == shift); - - let shift_hi = 31 - shift; - debug_assert!(shift_hi & 31 == shift_hi); - - let over = hi >> shift; - if over < -1 { - i32::MIN - } else if over > 0 { - i32::MAX - } else { - (lo >> shift) + (hi << shift_hi) - } -} +mod tools; +pub use tools::*; mod atan2; pub use atan2::*; mod accu; diff --git a/dsp/src/tools.rs b/dsp/src/tools.rs new file mode 100644 index 0000000..45dd66f --- /dev/null +++ b/dsp/src/tools.rs @@ -0,0 +1,97 @@ +#![cfg_attr(feature = "nightly", feature(asm, core_intrinsics))] + +use core::ops::{Add, Mul, Neg}; + +pub fn abs(x: T) -> T +where + T: PartialOrd + Default + Neg, +{ + if x >= T::default() { + x + } else { + -x + } +} + +// These are implemented here because core::f32 doesn't have them (yet). +// They are naive and don't handle inf/nan. +// `compiler-intrinsics`/llvm should have better (robust, universal, and +// faster) implementations. + +pub fn copysign(x: T, y: T) -> T +where + T: PartialOrd + Default + Neg, +{ + if (x >= T::default() && y >= T::default()) + || (x <= T::default() && y <= T::default()) + { + x + } else { + -x + } +} + +#[cfg(not(feature = "nightly"))] +pub fn max(x: T, y: T) -> T +where + T: PartialOrd, +{ + if x > y { + x + } else { + y + } +} + +#[cfg(not(feature = "nightly"))] +pub fn min(x: T, y: T) -> T +where + T: PartialOrd, +{ + if x < y { + x + } else { + y + } +} + +#[cfg(feature = "nightly")] +pub fn max(x: f32, y: f32) -> f32 { + core::intrinsics::maxnumf32(x, y) +} + +#[cfg(feature = "nightly")] +pub fn min(x: f32, y: f32) -> f32 { + core::intrinsics::minnumf32(x, y) +} + +// Multiply-accumulate vectors `x` and `a`. +// +// A.k.a. dot product. +// Rust/LLVM optimize this nicely. +pub fn macc(y0: T, x: &[T], a: &[T]) -> T +where + T: Add + Mul + Copy, +{ + x.iter() + .zip(a) + .map(|(x, a)| *x * *a) + .fold(y0, |y, xa| y + xa) +} + +/// Combine high and low i32 into a single downscaled i32, saturating the type. +pub fn saturating_scale(lo: i32, hi: i32, shift: u32) -> i32 { + debug_assert!(shift & 31 == shift); + + let shift_hi = 31 - shift; + debug_assert!(shift_hi & 31 == shift_hi); + + let over = hi >> shift; + if over < -1 { + i32::MIN + } else if over > 0 { + i32::MAX + } else { + (lo >> shift) + (hi << shift_hi) + } +}