This repository was archived by the owner on Nov 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathIterativeFFT.cpp
122 lines (111 loc) · 3.19 KB
/
IterativeFFT.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// algorithm - some algorithms in "Introduction to Algorithms", third edition
// Copyright (C) 2018 lxylxy123456
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef MAIN
#define MAIN
#define MAIN_IterativeFFT
#endif
#ifndef FUNC_IterativeFFT
#define FUNC_IterativeFFT
#include "utils.h"
#include "RecursiveFFT.cpp"
size_t rev(size_t k, size_t n) {
size_t ans = 0;
for (size_t i = 1; i != n; i <<= 1) {
ans <<= 1;
if (k & i)
ans |= 1;
}
return ans;
}
template <typename T>
Matrix<T> BitReverseCopy(Matrix<T>& a) {
const size_t n = a.rows;
Matrix<T> A(n, 1, 0);
for (size_t k = 0; k < n; k++)
A[rev(k, n)] = a[k];
return A;
}
template <typename T>
Matrix<T> IterativeFFT(Matrix<T>& a, bool neg = false) {
const size_t n = a.rows;
Matrix<T> A = BitReverseCopy(a);
for (size_t s = 1; size_t (1 << s) <= n; s++) {
size_t m = 1 << s;
T wm = expi((neg ? -1 : 1) * 2 * M_PI / m);
for (size_t k = 0; k < n; k += m) {
T w = 1;
for (size_t j = 0; j < m / 2; j++) {
T t = w * A[k + j + m / 2][0];
T u = A[k + j][0];
A[k + j][0] = u + t;
A[k + j + m / 2][0] = u - t;
w *= wm;
}
}
}
return A;
}
template <typename T>
Matrix<T> IterativeInverseFFT(Matrix<T>& a) {
const size_t n = a.rows;
Matrix<T> ans = IterativeFFT(a, true);
for (size_t i = 0; i < n; i++)
ans[i][0] /= n;
return ans;
}
template <typename T>
Matrix<T> IterativePolynomialMultiply(Matrix<T>& a, Matrix<T>& b) {
const size_t n = a.rows;
assert(n == b.rows);
Matrix<T> n0(n, 1, 0);
Matrix<T> aa = a.concat_v(n0);
Matrix<T> bb = b.concat_v(n0);
Matrix<T> fa = IterativeFFT(aa);
Matrix<T> fb = IterativeFFT(bb);
Matrix<T> fc(2 * n, 1, 0);
for (size_t i = 0; i < 2 * n; i++)
fc[i][0] = fa[i][0] * fb[i][0];
return IterativeInverseFFT(fc);
}
#endif
#ifdef MAIN_IterativeFFT
int main(int argc, char *argv[]) {
for (size_t i = 0; i < 8; i++) {
std::cout << rev(i, 8) << std::endl;
}
const size_t n = get_argv(argc, argv, 1, 16);
std::vector<int> int_a, int_b;
random_integers(int_a, -n, n, n);
random_integers(int_b, -n, n, n);
using T = Complex<double>;
std::vector<T> buf_a(n), buf_b(n);
for (size_t i = 0; i < int_a.size(); i++)
buf_a[i] = int_a[i];
for (size_t i = 0; i < int_a.size(); i++)
buf_b[i] = int_b[i];
Matrix<T> a(n, 1, buf_a);
std::cout << a << std::endl;
Matrix<T> b(n, 1, buf_b);
std::cout << b << std::endl;
Matrix<T> ans(2 * n, 0);
ans = ans.concat_h(PolynomialMultiply(a, b));
ans = ans.concat_h(IterativePolynomialMultiply(a, b));
std::cout << ans << std::endl;
return 0;
}
#endif