{-# LANGUAGE TypeOperators #-} module DFT ( dft , idft , dftWithRoots) where import Data.Array.Repa as A import Data.Ratio import StrictComplex import Roots -- | Compute the (non-fast) Discrete Fourier Transform of a vector. dft :: Shape sh => Array (sh :. Int) Complex -> Array (sh :. Int) Complex dft v = let rofu = calcRofu (extent v) in force $ dftWithRoots rofu v -- | Compute the inverse (non-fast) Discrete Fourier Transform of a vector. idft :: Shape sh => Array (sh :. Int) Complex -> Array (sh :. Int) Complex idft v = let _ :. len = extent v scale = fromIntegral len :*: 0 rofu = calcInverseRofu (extent v) in force $ A.map (/ scale) $ dftWithRoots rofu v -- | Generic function for computation of forward or inverse Discrete Fourier Transforms. dftWithRoots :: Shape sh => Array (sh :. Int) Complex -- ^ Roots of unity for this vector length. -> Array (sh :. Int) Complex -- ^ Input vector. -> Array (sh :. Int) Complex dftWithRoots rofu arr = traverse arr id (\_ k -> dftK rofu arr k) -- | Compute one value of the DFT. dftK :: Shape sh => Array (sh :. Int) Complex -- ^ Roots of unity for this vector length. -> Array (sh :. Int) Complex -- ^ Input vector. -> (sh :. Int) -- ^ Index of the value we want. -> Complex dftK rofu arrX (_ :. k) = A.sumAll $ A.zipWith (*) arrX wroots where sh@(_ :. len) = extent arrX -- All the roots we need to multiply with. wroots = fromFunction sh elemFn elemFn (sh :. n) = rofu !: (sh :. (k * n) `mod` len)