iir: more generic math helpers, use core::intrinsics

This commit is contained in:
Robert Jördens 2020-11-27 10:36:30 +01:00
parent ea3e343c39
commit 74349e5d68
2 changed files with 28 additions and 28 deletions

View File

@ -1,4 +1,4 @@
use core::ops::{Add, Mul}; use core::ops::{Add, Mul, Neg};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use core::f32; use core::f32;
@ -8,16 +8,24 @@ use core::f32;
// `compiler-intrinsics`/llvm should have better (robust, universal, and // `compiler-intrinsics`/llvm should have better (robust, universal, and
// faster) implementations. // faster) implementations.
fn abs(x: f32) -> f32 { fn abs<T>(x: T) -> T
if x >= 0. { where
T: PartialOrd + Default + Neg<Output = T>,
{
if x >= T::default() {
x x
} else { } else {
-x -x
} }
} }
fn copysign(x: f32, y: f32) -> f32 { fn copysign<T>(x: T, y: T) -> T
if (x >= 0. && y >= 0.) || (x <= 0. && y <= 0.) { where
T: PartialOrd + Default + Neg<Output = T>,
{
if (x >= T::default() && y >= T::default())
|| (x <= T::default() && y <= T::default())
{
x x
} else { } else {
-x -x
@ -25,7 +33,10 @@ fn copysign(x: f32, y: f32) -> f32 {
} }
#[cfg(not(feature = "nightly"))] #[cfg(not(feature = "nightly"))]
fn max(x: f32, y: f32) -> f32 { fn max<T>(x: T, y: T) -> T
where
T: PartialOrd,
{
if x > y { if x > y {
x x
} else { } else {
@ -34,7 +45,10 @@ fn max(x: f32, y: f32) -> f32 {
} }
#[cfg(not(feature = "nightly"))] #[cfg(not(feature = "nightly"))]
fn min(x: f32, y: f32) -> f32 { fn min<T>(x: T, y: T) -> T
where
T: PartialOrd,
{
if x < y { if x < y {
x x
} else { } else {
@ -44,26 +58,12 @@ fn min(x: f32, y: f32) -> f32 {
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
fn max(x: f32, y: f32) -> f32 { fn max(x: f32, y: f32) -> f32 {
let o: f32; core::intrinsics::maxnumf32(x, y)
unsafe {
asm!("vmaxnm.f32 {}, {}, {}",
lateout(sreg) o, in(sreg) x, in(sreg) y,
options(pure, nomem, nostack, preserves_flags)
);
}
o
} }
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
fn min(x: f32, y: f32) -> f32 { fn min(x: f32, y: f32) -> f32 {
let o: f32; core::intrinsics::minnumf32(x, y)
unsafe {
asm!("vminnm.f32 {}, {}, {}",
lateout(sreg) o, in(sreg) x, in(sreg) y,
options(pure, nomem, nostack, preserves_flags)
);
}
o
} }
// Multiply-accumulate vectors `x` and `a`. // Multiply-accumulate vectors `x` and `a`.
@ -76,7 +76,7 @@ where
{ {
x.iter() x.iter()
.zip(a) .zip(a)
.map(|(&x, &a)| x * a) .map(|(x, a)| *x * *a)
.fold(y0, |y, xa| y + xa) .fold(y0, |y, xa| y + xa)
} }
@ -84,10 +84,10 @@ where
/// ///
/// To represent the IIR state (input and output memory) during the filter update /// To represent the IIR state (input and output memory) during the filter update
/// this contains the three inputs (x0, x1, x2) and the two outputs (y1, y2) /// this contains the three inputs (x0, x1, x2) and the two outputs (y1, y2)
/// concatenated. /// concatenated. Lower indices correspond to more recent samples.
/// To represent the IIR coefficients, this contains the feed-forward /// To represent the IIR coefficients, this contains the feed-forward
/// coefficients (b0, b1, b2) followd by the feed-back coefficients (a1, a2), /// coefficients (b0, b1, b2) followd by the negated feed-back coefficients
/// all normalized such that a0 = 1. /// (-a1, -a2), all five normalized such that a0 = 1.
pub type IIRState = [f32; 5]; pub type IIRState = [f32; 5];
/// IIR configuration. /// IIR configuration.

View File

@ -1,4 +1,4 @@
#![no_std] #![no_std]
#![cfg_attr(feature = "nightly", feature(asm))] #![cfg_attr(feature = "nightly", feature(asm, core_intrinsics))]
pub mod iir; pub mod iir;