1- use core:: ops:: { Add , Mul } ;
1+ use core:: ops:: { Add , Mul , Neg } ;
22use serde:: { Deserialize , Serialize } ;
33
44use core:: f32;
@@ -8,38 +8,64 @@ use core::f32;
88// `compiler-intrinsics`/llvm should have better (robust, universal, and
99// faster) implementations.
1010
11- fn abs ( x : f32 ) -> f32 {
12- if x >= 0. {
11+ fn abs < T > ( x : T ) -> T
12+ where
13+ T : PartialOrd + Default + Neg < Output = T > ,
14+ {
15+ if x >= T :: default ( ) {
1316 x
1417 } else {
1518 -x
1619 }
1720}
1821
19- fn copysign ( x : f32 , y : f32 ) -> f32 {
20- if ( x >= 0. && y >= 0. ) || ( x <= 0. && y <= 0. ) {
22+ fn copysign < T > ( x : T , y : T ) -> T
23+ where
24+ T : PartialOrd + Default + Neg < Output = T > ,
25+ {
26+ if ( x >= T :: default ( ) && y >= T :: default ( ) )
27+ || ( x <= T :: default ( ) && y <= T :: default ( ) )
28+ {
2129 x
2230 } else {
2331 -x
2432 }
2533}
2634
27- fn max ( x : f32 , y : f32 ) -> f32 {
35+ #[ cfg( not( feature = "nightly" ) ) ]
36+ fn max < T > ( x : T , y : T ) -> T
37+ where
38+ T : PartialOrd ,
39+ {
2840 if x > y {
2941 x
3042 } else {
3143 y
3244 }
3345}
3446
35- fn min ( x : f32 , y : f32 ) -> f32 {
47+ #[ cfg( not( feature = "nightly" ) ) ]
48+ fn min < T > ( x : T , y : T ) -> T
49+ where
50+ T : PartialOrd ,
51+ {
3652 if x < y {
3753 x
3854 } else {
3955 y
4056 }
4157}
4258
59+ #[ cfg( feature = "nightly" ) ]
60+ fn max ( x : f32 , y : f32 ) -> f32 {
61+ core:: intrinsics:: maxnumf32 ( x, y)
62+ }
63+
64+ #[ cfg( feature = "nightly" ) ]
65+ fn min ( x : f32 , y : f32 ) -> f32 {
66+ core:: intrinsics:: minnumf32 ( x, y)
67+ }
68+
4369// Multiply-accumulate vectors `x` and `a`.
4470//
4571// A.k.a. dot product.
@@ -50,18 +76,18 @@ where
5076{
5177 x. iter ( )
5278 . zip ( a)
53- . map ( |( & x, & a) | x * a)
79+ . map ( |( x, a) | * x * * a)
5480 . fold ( y0, |y, xa| y + xa)
5581}
5682
5783/// IIR state and coefficients type.
5884///
5985/// To represent the IIR state (input and output memory) during the filter update
6086/// this contains the three inputs (x0, x1, x2) and the two outputs (y1, y2)
61- /// concatenated.
87+ /// concatenated. Lower indices correspond to more recent samples.
6288/// To represent the IIR coefficients, this contains the feed-forward
63- /// coefficients (b0, b1, b2) followd by the feed-back coefficients (a1, a2),
64- /// all normalized such that a0 = 1.
89+ /// coefficients (b0, b1, b2) followd by the negated feed-back coefficients
90+ /// (-a1, -a2), all five normalized such that a0 = 1.
6591pub type IIRState = [ f32 ; 5 ] ;
6692
6793/// IIR configuration.
@@ -159,18 +185,21 @@ impl IIR {
159185 /// * `xy` - Current filter state.
160186 /// * `x0` - New input.
161187 pub fn update ( & self , xy : & mut IIRState , x0 : f32 ) -> f32 {
188+ let n = self . ba . len ( ) ;
189+ debug_assert ! ( xy. len( ) == n) ;
162190 // `xy` contains x0 x1 y0 y1 y2
163191 // Increment time x1 x2 y1 y2 y3
164- // Rotate y3 x1 x2 y1 y2
165- xy. rotate_right ( 1 ) ;
192+ // Shift x1 x1 x2 y1 y2
193+ // This unrolls better than xy.rotate_right(1)
194+ xy. copy_within ( 0 ..n - 1 , 1 ) ;
166195 // Store x0 x0 x1 x2 y1 y2
167196 xy[ 0 ] = x0;
168197 // Compute y0 by multiply-accumulate
169198 let y0 = macc ( self . y_offset , xy, & self . ba ) ;
170199 // Limit y0
171200 let y0 = max ( self . y_min , min ( self . y_max , y0) ) ;
172201 // Store y0 x0 x1 y0 y1 y2
173- xy[ xy . len ( ) / 2 ] = y0;
202+ xy[ n / 2 ] = y0;
174203 y0
175204 }
176205}
0 commit comments