pythonpython-2.7scipyfftifft

Recursive Inverse FFT


I have implemented two functions FFT and InverseFFT in recursive mode.

These are the functions:

def rfft(a):
    n = a.size
    if n == 1:
        return a
    i = 1j
    w_n = e ** (-2 * i * pi / float(n))
    w = 1
    a_0 = np.zeros(int(math.ceil(n / 2.0)), dtype=np.complex_)
    a_1 = np.zeros(n / 2, dtype=np.complex_)
    for index in range(0, n):
        if index % 2 == 0:
            a_0[index / 2] = a[index]
        else:
            a_1[index / 2] = a[index]
    y_0 = rfft(a_0)
    y_1 = rfft(a_1)
    y = np.zeros(n, dtype=np.complex_)
    for k in range(0, n / 2):
        y[k] = y_0[k] + w * y_1[k]
        y[k + n / 2] = y_0[k] - w * y_1[k]
        w = w * w_n
    return y

def rifft(y):
    n = y.size
    if n == 1:
        return y
    i = 1j
    w_n = e ** (2 * i * pi / float(n))
    w = 1
    y_0 = np.zeros(int(math.ceil(n / 2.0)), dtype=np.complex_)
    y_1 = np.zeros(n / 2, dtype=np.complex_)
    for index in range(0, n):
        if index % 2 == 0:
            y_0[index / 2] = y[index]
        else:
            y_1[index / 2] = y[index]
    a_0 = rifft(y_0)
    a_1 = rifft(y_1)
    a = np.zeros(n, dtype=np.complex_)
    for k in range(0, n / 2):
        a[k] = (a_0[k] + w * a_1[k]) / n
        a[k + n / 2] = (a_0[k] - w * a_1[k]) / n
        w = w * w_n
    return a

Based on the definition of IFFT, converting FFT function to IFFT function can be done by changing 2*i*pi to -2*i*pi and dividing the result by N. The rfft() function works fine but the rifft() function, after these modifications, does not work.

I compare the output of my functions with scipy.fftpack.fft and scipy.fftpack.ifft functions.

I feed the following NumPy array:

a = np.array([1, 0, -1, 3, 0, 0, 0, 0])

The following box shows the results of rfft() function and scipy.fftpack.fft function.

//rfft(a)
[ 3.00000000+0.j -1.12132034-1.12132034j 2.00000000+3.j 3.12132034-3.12132034j -3.00000000+0.j 3.12132034+3.12132034j 2.00000000-3.j -1.12132034+1.12132034j]
//scipy.fftpack.fft(a)
[ 3.00000000+0.j -1.12132034-1.12132034j 2.00000000+3.j 3.12132034-3.12132034j -3.00000000+0.j 3.12132034+3.12132034j 2.00000000-3.j -1.12132034+1.12132034j]

And this box shows the results of rifft() function and scipy.fftpack.ifft function.

//rifft(a)
[ 0.04687500+0.j -0.01752063+0.01752063j 0.03125000-0.046875j 0.04877063+0.04877063j -0.04687500+0.j 0.04877063-0.04877063j 0.03125000+0.046875j -0.01752063-0.01752063j]
//scipy.fftpack.ifft(a)
[ 0.37500000+0.j -0.14016504+0.14016504j 0.25000000-0.375j 0.39016504+0.39016504j -0.37500000+0.j 0.39016504-0.39016504j  0.25000000+0.375j -0.14016504-0.14016504j]

Solution

  • The division by the size N is a global scaling factor and should be performed on the result of the recursion rather than dividing at each stage of the recursion as you have done (by a decreasing factor as you go deeper in the recursion; overall scaling down the result too much). You could address this by removing the / n factor in the final loop of your original implementation, which gets called by another function performing the scaling:

    def unscaledrifft(y):
      ...
      for k in range(0, n / 2):
        a[k] = (a_0[k] + w * a_1[k])
        a[k + n / 2] = (a_0[k] - w * a_1[k])
        w = w * w_n
      return a
    
    def rifft(y):
      return unscaledrifft(y)/y.size
    

    Alternatively, since you are performing a radix-2 FFT, the global factor N would be a power of 2 such that N=2**n, where n is the number of steps in the recursion. You could thus divide by 2 at each stage of the recursion to achieve the same result:

    def rifft(y):
      ...
      for k in range(0, n / 2):
        a[k] = (a_0[k] + w * a_1[k]) / 2
        a[k + n / 2] = (a_0[k] - w * a_1[k]) / 2
        w = w * w_n
      return a