use crate::Complex;
#[cfg(not(feature = "std"))]
#[allow(unused_imports)]
use num_traits::float::Float as _;
use num_traits::{AsPrimitive, Float, FloatConst};
use crate::iir::Biquad;
fn polyval<T: Float>(p: &[T], z: Complex<T>) -> Complex<T> {
p.iter()
.rev()
.fold(Complex::new(T::zero(), T::zero()), |a, &p| {
a * z + Complex::new(p, T::zero())
})
}
pub fn freqz<T: Float + FloatConst>(b: &[T], a: &[T], frequency: T) -> Complex<T> {
assert!(!a.is_empty(), "freqz requires a non-empty denominator");
let (i, r) = (-T::TAU() * frequency).sin_cos();
let z = Complex::new(r, i);
let q = polyval(a, z);
polyval(b, z) * q.conj() / (q.re() * q.re() + q.im() * q.im())
}
impl<C> Biquad<C> {
pub fn freqz<T: 'static + Float + FloatConst>(&self, frequency: T) -> Complex<T>
where
C: Copy + AsPrimitive<T>,
{
let [b0, b1, b2, a1, a2] = self.ba.map(AsPrimitive::as_);
freqz(&[b0, b1, b2], &[T::one(), -a1, -a2], frequency)
}
}