> module Fourier
> (fft, fftinv, dft, dftinv, sft, sct)
> where
> import Complex--1.3
> import List(transpose)--1.3
> import Complex_Vectors
> fft:: [ComplexF] -> [ComplexF] -- Warning: works only for n=2^km
> -- time=O(n log(n)) algorithm
> fft xs = map((1/(fromInt n))*) (ffth xs us) where
> us = map conjugate (rootsOfUnity n)
> n = length xs
> fromInt = fromInteger . toInteger -- partain addition
> fftinv:: [ComplexF] -> [ComplexF] -- Warning: works only for n=2^km
> -- time=O(n log(n)) algorithm
> fftinv xs = ffth xs us where
> us = rootsOfUnity n
> n = length xs
> ffth:: [ComplexF] -> [ComplexF] -> [ComplexF]
> ffth xs us
> | n>1 = (replikate fftEvn) `plus`
> (us `times` (replikate fftOdd))
> | n==1 = xs
> where
> fftEvn = ffth (evns xs) uEvns
> fftOdd = ffth (odds xs) uEvns
> uEvns = evns us
> evns = everyNth 2
> odds = everyNth 2 . tail
> n = length xs
Discrete Fourier Transform (fft generalized to non-binary orders)
> dft:: [ComplexF] -> [ComplexF]
> -- time=O(n*sum(map (^2) (factors n))) algorithm
> -- =O(n*log(n)) when n is a product of small primes
> dft xs
> = map((1/(fromInt n))*) (dfth fs xs us)
> where
> us = replikate(map conjugate (rootsOfUnity n))
> fs = factors n
> n = length xs
> fromInt = fromInteger . toInteger -- partain addition
> dftinv:: [ComplexF] -> [ComplexF]
> -- time=O(n*sum(map (^2) (factors n))) algorithm
> -- =O(n*log(n)) when n is a product of small primes
> dftinv xs
> = dfth fs xs us
> where
> us = replikate(rootsOfUnity n)
> fs = factors n
> n = length xs
> dfth:: [Int] -> [ComplexF] -> [ComplexF] -> [ComplexF]
> dfth (f:fs) xs us
> | fs==[] = sfth f xs us
> | otherwise = map sum (transpose pfts)
> where
> pfts = [(dftOfSection k) `times` (us `toThe` k)| k<-[0..f-1]]
> dftOfSection k = repl f
> (dfth fs (fsectionOfxs k) (us `toThe` f))
> fsectionOfxs k = everyNth f (drop k xs)
Slow Fourier Transform
> sft:: [ComplexF] -> [ComplexF] -- time=O(n^2) algorithm
> sft xs
> = map((1/(fromInt n))*) (sfth n xs us)
> where
> us = replikate(map conjugate (rootsOfUnity n))
> n = length xs
> fromInt = fromInteger . toInteger -- partain addition
> sftinv:: [ComplexF] -> [ComplexF] -- time=O(n^2) algorithm
> sftinv xs
> = sfth n xs us
> where
> us = replikate(rootsOfUnity n)
> n = length xs
> sfth:: Int -> [ComplexF] -> [ComplexF] -> [ComplexF]
> sfth n xs us
> = [sum(xs `times` upowers)| upowers<-[us `toThe` k| k<-[0..n-1]]]
Slow Cosine Transform
> sct:: [Double] -> [Double] -- time=O(n^2) algorithm
> sct xs -- computes n^2 cosines
> = [xs_dot (map (cos.((fromInt k)*)) (thetas n))| k<-[0 .. n-1]]
> where
> n = length xs
> xs_dot = sum.(zipWith (*) xs)
> fromInt = fromInteger . toInteger -- partain addition
Utilities
> plus = zipWith (+)
> times = zipWith (*)
> replikate = cycle
> repl n = concat . take n . repeat
> everyNth n = (map head).(takeWhile (/=[])).(iterate (drop n))
> toThe:: [ComplexF] -> Int -> [ComplexF]
> rootsOfUnity `toThe` k = everyNth k rootsOfUnity
> factors:: Int -> [Int]
> factors n = factorsh n primes
> factorsh:: Int -> [Int] -> [Int]
> factorsh n (p:ps)
> | n==1 = []
> | n `mod` p == 0 = p: factorsh (n `div` p) (p:ps)
> | otherwise = factorsh n ps
> primes:: [Int]
> primes = map head (iterate sieve [2..])
> sieve(p:xs) = [x| x<-xs, x `mod` p /= 0]
|