module Numeric.Transform.Fourier.Goertzel where
import Data.Array
import Data.Complex
cgoertzel :: (RealFloat a, Ix b, Integral b) => Array b (Complex a)
-> b
-> Complex a
cgoertzel x0 k = g (elems x0) 0 0
where w = 2 * pi * fromIntegral k / fromIntegral n
a = 2 * cos w
g [] x1 x2 = x1 * cis w - x2
g (x:xs) x1@(x1r:+x1i) x2 = g xs (x + (a*x1r:+a*x1i) - x2) x1
n = (snd $ bounds x0) - 1
cgoertzel_power :: (RealFloat a, Ix b, Integral b) => Array b (Complex a)
-> b
-> a
cgoertzel_power x k = (magnitude $ cgoertzel x k)^(2::Int)
rgoertzel :: (RealFloat a, Ix b, Integral b) => Array b a
-> b
-> Complex a
rgoertzel x0 k = g (elems x0) 0 0
where w = 2 * pi * fromIntegral k / fromIntegral n
a = 2 * cos w
g [] x1 x2 = ((x1 - cos w * x2) :+ x2 * sin w)
g (x:xs) x1 x2 = g xs (x + a * x1 - x2) x1
n = (snd $ bounds x0) - 1
rgoertzel_power :: (RealFloat a, Ix b, Integral b) => Array b a
-> b
-> a
rgoertzel_power x0 k = g (elems x0) 0 0
where w = 2 * pi * fromIntegral k / fromIntegral n
a = 2 * cos w
g [] x1 x2 = x1^(2::Int) + x2^(2::Int) - a * x1 * x2
g (x:xs) x1 x2 = g xs (x + a * x1 - x2) x1
n = (snd $ bounds x0) - 1