Issue with implementing inverse FFT for polynoms

Question:

I am studying the FFT algorithm for fast polynomial multiplication. We went over the algorithm and I decided to try and implement it in Python.

from typing import List
import numpy as np


def fft(p: List[int]) -> List[int]:
    n = len(p)
    if n == 1:
        return p
    
    unity_root = np.exp(2j * np.pi / n)
    
    p_even = p[::2]
    p_odd = p[1::2]
    
    y_even = fft(p_even)
    y_odd = fft(p_odd)
    
    y = [0] * n
    for j in range(n // 2):
        omega = np.power(unity_root, j)
        y[j] = y_even[j] + omega * y_odd[j]
        y[n // 2 + j] = y_even[j] - omega * y_odd[j]
    
    return y


def ifft(p: List[int]) -> List[int]:
    n = len(p)
    if n == 1:
        return p
    
    unity_root = (1 / n) * np.exp(-2j * np.pi / n)
    
    p_even = p[::2]
    p_odd = p[1::2]
    
    y_even = ifft(p_even)
    y_odd = ifft(p_odd)
    
    y = [0] * n
    for j in range(n // 2):
        omega = np.power(unity_root, j)
        y[j] = y_even[j] + omega * y_odd[j]
        y[n // 2 + j] = y_even[j] - omega * y_odd[j]
    
    return y

I tried running the following code to make sure it works

print(ifft(fft([1, 2, 3, 4])))

I expected the output to be the original list I started with as that list represents the coefficients, yet I am getting (ignoring precision issues with floating point arithmetic):

[(4+0j), (11-0j), (12+0j), (13+0j)]

My question is:

Shouldn’t I be getting the original list? If I should be getting the original list, where is the mistake in the code? as I went over the code several times and I am having issues finding it. If I shouldn’t be getting the original list back and my code is correct, what am I actually getting?

Asked By: Rami Hashan

||

Answers:

The problem is that, in ifft, you’re dividing the root of unity by n. You need to divide the final result instead.

Answered By: David Eisenstat
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.