Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit 05fc7ea

Browse files
committed
RecursiveFFT.cpp
1 parent 37d76ef commit 05fc7ea

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@
192192
| 29 | Simplex.cpp | Pivot | 869 |
193193
| 29 | Simplex.cpp | Simplex | 871 |
194194
| 29 | Simplex.cpp | Initialize Simplex | 887 |
195+
| 30 | RecursiveFFT.cpp | Recursive FFT | 911 |
196+
| 30 | RecursiveFFT.cpp | Inverse FFT | 913 |
197+
| 30 | RecursiveFFT.cpp | Polynomial Multiply | 914 |
195198

196199
# Supplementary Files
197200
* `utils.h`: Utils

RecursiveFFT.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//
2+
// algorithm - some algorithms in "Introduction to Algorithms", third edition
3+
// Copyright (C) 2018 lxylxy123456
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
#ifndef MAIN
20+
#define MAIN
21+
#define MAIN_RecursiveFFT
22+
#endif
23+
24+
#ifndef FUNC_RecursiveFFT
25+
#define FUNC_RecursiveFFT
26+
27+
#include <cmath>
28+
#include "utils.h"
29+
30+
#include "SquareMatrixMultiply.cpp"
31+
32+
template <typename T>
33+
class Complex {
34+
public:
35+
Complex(): real(0), imag(0) {}
36+
Complex(T x): real(x), imag(0) {}
37+
Complex(T x, T y): real(x), imag(y) {}
38+
Complex<T> operator+(const Complex<T>& rhs) const {
39+
return Complex<T>(real + rhs.real, imag + rhs.imag);
40+
}
41+
Complex<T> operator-(const Complex<T>& rhs) const {
42+
return Complex<T>(real - rhs.real, imag - rhs.imag);
43+
}
44+
Complex<T> operator*(const Complex<T>& rhs) const {
45+
return Complex<T>(real * rhs.real - imag * rhs.imag,
46+
real * rhs.imag + imag * rhs.real);
47+
}
48+
Complex<T>& operator*=(const Complex<T>& rhs) {
49+
T r = real * rhs.real - imag * rhs.imag;
50+
T i = real * rhs.imag + imag * rhs.real;
51+
real = r;
52+
imag = i;
53+
return *this;
54+
}
55+
Complex<T>& operator/=(const T& rhs) {
56+
real /= rhs;
57+
imag /= rhs;
58+
return *this;
59+
}
60+
friend std::ostream& operator<<(std::ostream& os, const Complex<T>& r) {
61+
if (abs(r.imag) > 0.0000000001)
62+
return os << r.real << " + " << r.imag << " i";
63+
else
64+
return os << r.real;
65+
}
66+
T real, imag;
67+
};
68+
69+
template <typename T>
70+
Complex<T> expi(T x) {
71+
return Complex<T>(cos(x), sin(x));
72+
}
73+
74+
template <typename T>
75+
Matrix<T> RecursiveFFT(Matrix<T>& a, bool neg = false) {
76+
const size_t n = a.rows;
77+
if (n == 1)
78+
return a;
79+
assert(n % 2 == 0);
80+
T wn = expi((neg ? -1 : 1) * 2 * M_PI / n);
81+
T w = 1;
82+
Matrix<T> a0(n / 2, 1), a1(n / 2, 1);
83+
for (size_t i = 0; i < n; i += 2) {
84+
a0.data.push_back(a[i]);
85+
a1.data.push_back(a[i + 1]);
86+
}
87+
Matrix<T> y0 = RecursiveFFT(a0, neg);
88+
Matrix<T> y1 = RecursiveFFT(a1, neg);
89+
Matrix<T> y(n, 1, 0);
90+
for (size_t k = 0; k < n / 2; k++) {
91+
y[k][0] = y0[k][0] + w * y1[k][0];
92+
y[k + n/2][0] = y0[k][0] - w * y1[k][0];
93+
w *= wn;
94+
}
95+
return y;
96+
}
97+
98+
template <typename T>
99+
Matrix<T> InverseFFT(Matrix<T>& a) {
100+
const size_t n = a.rows;
101+
Matrix<T> ans = RecursiveFFT(a, true);
102+
for (size_t i = 0; i < n; i++)
103+
ans[i][0] /= n;
104+
return ans;
105+
}
106+
107+
template <typename T>
108+
Matrix<T> PolynomialMultiply(Matrix<T>& a, Matrix<T>& b) {
109+
const size_t n = a.rows;
110+
assert(n == b.rows);
111+
Matrix<T> n0(n, 1, 0);
112+
Matrix<T> aa = a.concat_v(n0);
113+
Matrix<T> bb = b.concat_v(n0);
114+
Matrix<T> fa = RecursiveFFT(aa);
115+
Matrix<T> fb = RecursiveFFT(bb);
116+
Matrix<T> fc(2 * n, 1, 0);
117+
for (size_t i = 0; i < 2 * n; i++)
118+
fc[i][0] = fa[i][0] * fb[i][0];
119+
return InverseFFT(fc);
120+
}
121+
#endif
122+
123+
#ifdef MAIN_RecursiveFFT
124+
int main(int argc, char *argv[]) {
125+
const size_t n = get_argv(argc, argv, 1, 16);
126+
std::vector<int> int_a, int_b;
127+
random_integers(int_a, -n, n, n);
128+
random_integers(int_b, -n, n, n);
129+
using T = Complex<double>;
130+
std::vector<T> buf_a(n), buf_b(n);
131+
for (size_t i = 0; i < int_a.size(); i++)
132+
buf_a[i] = int_a[i];
133+
for (size_t i = 0; i < int_a.size(); i++)
134+
buf_b[i] = int_b[i];
135+
Matrix<T> a(n, 1, buf_a);
136+
std::cout << a << std::endl;
137+
Matrix<T> b(n, 1, buf_b);
138+
std::cout << b << std::endl;
139+
Matrix<T> c = PolynomialMultiply(a, b);
140+
std::cout << c << std::endl;
141+
return 0;
142+
}
143+
#endif
144+

0 commit comments

Comments
 (0)