Re: FFT algorithm

new topic     » goto parent     » topic index » view thread      » older message » newer message

Michael J. Sabal writes:
> Does anybody have a pre-built FFT (Fast Fourier Transform) algorithm
> already built in Euphoria?

I wrote the following code many years ago,
back in the pre-1.0 days of Euphoria.
It was one of the first Euphoria programs I wrote.
I used to be heavily involved in writing a compiler for
a machine that was designed to do FFTs and litte else,
but I've forgotten all that stuff now. I hope the code below 
does approximately what you want.

    ----------------------------------
    --    FAST FOURIER TRANSFORM    --
    ----------------------------------

constant SCREEN = 1,
      pi = 3.141592653589793,
    REAL = 1, IMAG = 2

type complex(sequence x)
    return length(x) = 2 and atom(x[1]) and atom(x[2])
end type

global function p2round(integer x)
-- rounds x up to a power of two
    integer p

    p = 1
    while p < x do
         p = p + p
    end while
    return p
end function


global function log2(atom x)
-- return log2 of x, or -1 if x is not a power of 2

    integer p

    if x < 1 then
         return -1 
    end if
    p = -1
    while floor(x) = x do
         x = x / 2
         p = p + 1
    end while
    if x = 0.5 then
         return p
    else
         return -1
    end if 
end function

function input()
-- input all the complex numbers

    sequence a
    integer n

    -- read in all the numbers, for now...
    a = {{1.0, 1.1},
          {1.0, 1.9},
          {1.0, 1.0},
          {4.1, 1.0},
          {1.0, 1.0},
          {1.0, 6.5},
          {1.5, 1.0},
          {1.0, 8.0}}
    
    n = length(a)
    if log2(n) = -1 then
         puts(SCREEN, "input vector length is not a power of two\n") 
         puts(SCREEN, "--> padded with 0's\n\n")
         n = p2round(n)
         -- pad with 0's 
         for j = length(a)+1 to n do
             a[j] = {0, 0}
         end for
    end if
    return a
end function

function bitrev(sequence a)
-- bitrev an array of complex numbers

    atom nv2
    integer nm1, j, k, n
    complex temp

    n = length(a)
    nv2 = n / 2
    nm1 = n - 1
    j = 1
    for i = 1 to nm1 do
         if i < j then
             temp = a[i]
             a[i] = a[j]
             a[j] = temp
         end if
         k = nv2
         while k < j do
             j = j - k
             k = k / 2
         end while
         j = j + k
    end for
    return a
end function


function cmult(complex arg1, complex arg2)
-- complex multiply 
    return { arg1[REAL] * arg2[REAL] - arg1[IMAG] * arg2[IMAG],
      arg1[REAL] * arg2[IMAG] + arg1[IMAG] * arg2[REAL] }
end function


function fft(sequence a)
-- perform an in-place fft on an array of complex numbers
-- that has already been bit reversed

    integer m, ip, le
    integer n
    integer le1
    complex u, w, t

    n = length(a)
    m = log2(n)
    for l = 1 to m do
         le = power(2, l)
         le1 = le / 2
         u = {1, 0}
         w = {cos(pi/le1), sin(pi/le1)}
         for j = 1 to le1 do
             for i = j to n by le do
                   ip = i + le1
                   t = cmult(a[ip], u)
                  a[ip] = a[i] - t
                  a[i]  = a[i] + t
             end for
             u = cmult(u, w)
         end for
    end for
    return a
end function


function frequency_reverse(sequence a)
-- reverse output from fft to switch +ve and -ve frequencies

    integer n
    sequence temp

    n = length(a)
    for i = 2 to n / 2 do
         temp = a[i]
         a[i] = a[n + 2 - i]
         a[n + 2 - i] = temp
    end for
    return a
end function


procedure output(sequence a)
-- output an array of complex numbers

    for i = 1 to length(a) do
         print(SCREEN, a[i])
    end for
end procedure


function make_inverse(sequence a)
-- modifies results to get inverse fft

    for i = 1 to length(a) do
         a[i] = a[i] / length(a) 
    end for
    return a
end function


global procedure main(integer argv)
-- FFT / IFFT 
    sequence a

    a = fft(bitrev(input()))

    if argv = 1 then
         a = make_inverse(a)
         printf(SCREEN, "Results of %d-point inverse fft:\n\n", length(a))
    else 
         a = frequency_reverse(a)
         printf(SCREEN, "Results of %d-point fft:\n\n", length(a))
    end if
    output(a)
end procedure

main(0)

---------------------------------------------------
Regards,
   Rob Craig
   Rapid Deployment Software
   http://www.RapidEuphoria.com

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu