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?
Answers:
The problem is that, in ifft
, you’re dividing the root of unity by n
. You need to divide the final result instead.
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?
The problem is that, in ifft
, you’re dividing the root of unity by n
. You need to divide the final result instead.