module Numeric.Transform.Fourier.Rader (fft_rader1, fft_rader2) where
import Data.Array
import Data.Complex
fft_rader1 :: (Ix a, Integral a, RealFloat b) => Array a (Complex b)
-> a
-> Array a (Complex b)
fft_rader1 f n = f'
where h = listArray (0,n2) [ f!(a ^* (n(1+n'))) | n' <- [0..(n2)] ]
g = listArray (0,n2) [ w!(a ^* n') | n' <- [0..(n2)] ]
hg = listArray (0,n2) [ sum [ h!j * g!((ij)`mod`(n1)) | j <- [0..(n2)] ] | i <- [0..(n2)] ]
f' = array (0,n1) ((0, sum [ f!i | i <- [0..(n1)] ]) : [ (a ^* i, f!0 + hg!i) | i <- [0..(n2)] ])
wn = cis (2 * pi / fromIntegral n)
w = listArray (0,n1) $ iterate (* wn) 1
_ ^* 0 = 1
i ^* j = (i * (i ^* (j1))) `mod` n
a = generator n
fft_rader2 :: (Ix a, Integral a, RealFloat b) => Array a (Complex b)
-> a
-> (Array a (Complex b) -> Array a (Complex b))
-> Array a (Complex b)
fft_rader2 f n fft = f'
where h = listArray (0,n2) [ f!(a ^* (n(1+n'))) | n' <- [0..(n2)] ]
g = listArray (0,n2) [ w!(a ^* n') | n' <- [0..(n2)] ]
h' = fft h
g' = fft g
hg' = listArray (0,n2) [ h'!i * g'!i | i <- [0..(n2)] ]
hg = ifft hg'
f' = array (0,n1) ((0, sum [ f!i | i <- [0..(n1)] ]) : [ (a ^* i, f!0 + hg!i) | i <- [0..(n2)] ])
wn = cis (2 * pi / fromIntegral n)
w = listArray (0,n1) $ iterate (* wn) 1
_ ^* 0 = 1
i ^* j = (i * (i ^* (j1))) `mod` n
a = generator n
ifft b = fmap (/ fromIntegral (n1)) $ fmap swap $ fft $ fmap swap b
swap (x:+y) = (y:+x)
generator :: (Integral a) => a -> a
generator p = findgen 1
where findgen 0 = error "rader: generator: no primitive root?"
findgen x | (period x x) == (p 1) = x
| otherwise = findgen ((x + 1) `mod` p)
period _ 1 = 1
period x prod = 1 + (period x (prod * x `mod` p))