1use core::ops::{Add, Mul, Neg};
4use dsp_process::{SplitInplace, SplitProcess};
5
6use num_traits::AsPrimitive;
7
8#[cfg(not(feature = "std"))]
9#[allow(unused_imports)]
10use num_traits::float::Float as _;
11
12use crate::Complex;
13
14use super::DirectForm1;
15
16#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
27pub struct Normal<C> {
28 pub b: [C; 3],
30 pub p: Complex<C>,
34}
35
36impl<
38 C: Copy + Mul<T, Output = A> + Neg<Output = C>,
39 A: Add<Output = A> + AsPrimitive<T>,
40 T: 'static + Copy,
41> SplitProcess<T, T, DirectForm1<T>> for Normal<C>
42{
43 fn process(&self, state: &mut DirectForm1<T>, x0: T) -> T {
44 let y1 = (self.b[0] * x0
45 + self.b[1] * state.x[0]
46 + self.b[2] * state.x[1]
47 + self.p.re() * state.y[0][1]
48 + -self.p.im() * state.y[0][0])
49 .as_();
50 let y0: T = (self.p.im() * state.y[0][1] + self.p.re() * state.y[0][0]).as_();
51 state.x = [x0, state.x[0]];
52 state.y[0] = [y0, y1];
53 y0
54 }
55}
56
57impl<C, T: Copy> SplitInplace<T, DirectForm1<T>> for Normal<C> where
58 Self: SplitProcess<T, T, DirectForm1<T>>
59{
60}
61
62impl<C: Neg<Output = C> + From<f64>> From<&[[f64; 3]; 2]> for Normal<C> {
63 fn from(ba: &[[f64; 3]; 2]) -> Self {
64 let a0 = 1.0 / ba[1][0];
65 let b = [ba[0][0] * a0, ba[0][1] * a0, ba[0][2] * a0];
66 let p2 = -0.5 * ba[1][1];
68 let pq = ba[1][0] * ba[1][2] - p2.powi(2);
69 assert!(pq >= 0.0);
70 let p = [p2 * a0, pq.sqrt() * a0];
71 Self {
72 b: b.map(Into::into),
73 p: Complex(p.map(Into::into)),
74 }
75 }
76}