Fast Fourier Transform (FFT)
FFT is an efficient algorithm for computing the Discrete Fourier Transform (DFT) and its inverse, which has applications in polynomial multiplication, signal processing, and more.
Fast Fourier Transform (FFT)
Polynomial Representation
- Coefficient Representation: A polynomial of degree can be represented by its coefficients as , where is the coefficient of .
- Point-Value Representation: represented by its values at specific points, a set of pairs .
FFT by Divide and Conquer
- Input: A polynomial of degree with coefficients, where is a power of 2.
- Output: values at the -th roots of unity. for .
Discrete Fourier Transform (DFT): .
Inverse DFT: .
where with the terms .
Replace with and use the property to get:
Inverse FFT
To compute the inverse FFT, we can use the same algorithm with a slight modification. Instead of using , we use , and after computing the FFT, we divide each result by to get the original coefficients.
Proof
Let matrix be the DFT matrix
Since , so ,
Code
递归版本
using cd = complex<double>;
const double PI = acos(-1.0);
void FFT(vector<cd> &a, int invert) { //系数表达转点值表达
int n = a.size(), m = n >> 1;
if (n == 1) return; //递归边界
vector<cd> a0(m), a1(m);
for (int i = 0; i < m; ++i) //奇数与偶数分开
a0[i] = a[i << 1], a1[i] = a[i << 1 | 1];
FFT(a0, invert), FFT(a1, invert); //分治处理
cd w(1.0, 0.0), wn(cos(PI / m), invert * sin(PI / m)); //不能写成 wn = (a, b),那是逗号表达式
for (int i = 0; i < m; ++i, w *= wn) { //权值汇总
a[i] = a0[i] + w * a1[i]; //左半部分
a[i + m] = a0[i] - w * a1[i]; //右半部分
// if (invert) a[i] /= 2, a[i + m] /= 2; //逆变换时除以n
}
}
迭代版本
int rev[Z];
void get_rader() {
bit = log2(n + m) + 1; k = 1 << bit;//强制达到2的幂级
for (int i = 0; i < k; ++i) rev[i] = rev[i >> 1] >> 1 | (i & 1) << bit - 1;
}
void FFT(complex <double> a[], int n, int opt) { //系数表达转点值表达
for (int i = 1; i < n; ++i) if (rev[i] > i) swap(a[i], a[rev[i]]);
for (int m = 1; m < n; m <<= 1) {
complex <double> W(cos(PI / m), opt * sin(PI / m));
for (int i = 0; i < n; i += m << 1) {
complex <double> w(1.0, 0.0);
for (int j = 0; j < m; ++j, w *= W) {
complex <double> x = a[i + j], y = w * a[i + j + m];
a[i + j] = x + y, a[i + j + m] = x - y;
}
}
}
}
逆变换
void IFFT(vector<cd> &a) { //point-value to coefficient
int n = a.size();
FFT(a, -1);
for (int i = 0; i < n; ++i) a[i] = a[i].real() / n;
}
Polynomial Multiplication
Input: Two polynomials and represented by their coefficients.
Output: The coefficients of the product polynomial . (Convolution of coefficients)
- , where is the coefficient of .
- , where is the coefficient of .
- , where .
Naive approach: time by directly computing each coefficient of
We need to extend the coefficients of and to length that is at least and is a power of 2.
FFT Algorithm workflow:
- Compute the FFT of both polynomials to get their point-value representations.
- Perform point-wise multiplication of the two FFT results.
- Compute the inverse FFT of the product to get the coefficients of the resulting polynomial.
void multiply(vector<int> &a, vector<int> &b, vector<int> &c) {
int n = 1;
while (n < a.size() + b.size()) n <<= 1; // Find the next power of 2
vector<cd> A(a.begin(), a.end()), B(b.begin(), b.end()), C(n);
A.resize(n), B.resize(n);
FFT(A, 1); // Forward FFT on A
FFT(B, 1); // Forward FFT on B
for (int i = 0; i < n; ++i) C[i] = A[i] * B[i]; // Point-wise multiplication
IFFT(C); // Inverse FFT to get the coefficients of the product polynomial
c.resize(a.size() + b.size() - 1);
for (int i = 0; i < c.size(); ++i) c[i] = round(C[i].real());
}
Applications of FFT
- Polynomial Multiplication: As described above, FFT can be used to multiply two polynomials efficiently.
- Signal Processing: FFT is widely used in signal processing for analyzing the frequency components of signals.
- Image Processing: FFT can be used for image filtering and compression.
- Convolution: FFT can be used to compute the convolution of two sequences efficiently, which is useful in various applications such as digital signal processing and machine learning.
- Fast Multiplication of Large Integers: By representing large integers as polynomials, FFT can be used to multiply them efficiently.
Linear Filter:
Mean Filter
Replace with the average of its neighbors:
Let (a filter of length ), then the mean filter can be expressed as a convolution:
Gaussian Filter
Replace with a weighted average of its neighbors, wheint the weights are determined by a Gaussian function:
Let for , then the Gaussian filter can also be expressed as a convolution: