-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathberlekamp_massey.cpp
129 lines (101 loc) · 3.68 KB
/
berlekamp_massey.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
122
123
124
125
126
127
128
129
#include "test_utils.hpp"
#include "numeric/modnum.hpp"
#include "linear/berlekamp_massey.hpp"
#include "lib/lr.hpp"
constexpr int M = 998244353;
using num = modnum<M>;
using namespace polymath;
void stress_test_berlekamp_massey() {
int shorter = 0;
LOOP_FOR_DURATION_OR_RUNS_TRACKED (30s, now, 50'000, runs) {
print_time(now, 30s, "stress BM ({} runs) ({} shorter)", runs, shorter);
int n = rand_unif<int>(1, 100);
int m = rand_unif<int>(2 * n, 7 * n);
auto rec = rand_recurrence<num>(n);
auto x = rand_poly<num>(n);
extend_recurrence_inplace<num>(m, x, rec);
assert(size(x) == m && size(rec) == n);
auto ans = berlekamp_massey(x);
if (ans != rec) {
assert(size(ans) <= size(rec));
assert(verify_recurrence(x, rec));
shorter++;
}
}
}
void stress_test_kitamasa() {
LOOP_FOR_DURATION_OR_RUNS_TRACKED (30s, now, 50'000, runs) {
print_time(now, 30s, "stress kitamasa ({} runs)", runs);
int n = rand_unif<int>(1, 40);
int m = rand_unif<int>(2 * n, 100 * n);
int k = rand_unif<int>(n, 2 * n);
auto rec = rand_recurrence<num>(n);
auto x = rand_poly<num>(n);
extend_recurrence_inplace<num>(m, x, rec);
auto y = shrunk(x, k);
assert(size(x) == m && size(y) == k && size(rec) == n);
for (int i = 0; i < m; i++) {
assert(kitamasa(y, rec, i) == x[i]);
}
}
}
void speed_test_berlekamp_massey() {
vector<int> Ns = {100, 300, 600, 1000, 1800, 3000, 5000, 8000, 12000, 20000};
vector<int> Ms = {2000, 3000, 5000, 10000, 20000, 30000, 40000};
vector<pair<int, int>> inputs;
for (int N : Ns) {
for (int M : Ms) {
if (2 * N <= M) {
inputs.push_back({N, M});
}
}
}
auto runtime = 120'000ms / inputs.size();
map<pair<int, int>, stringable> table;
for (auto [N, M] : inputs) {
START_ACC(bm);
LOOP_FOR_DURATION_OR_RUNS_TRACKED (runtime, now, 10'000, runs) {
print_time(now, runtime, "speed BM N={} M={} ({} runs)", N, M, runs);
auto rec = rand_recurrence<num>(N);
auto x = rand_poly<num>(N);
extend_recurrence_inplace<num>(M, x, rec);
ADD_TIME_BLOCK(bm) { berlekamp_massey(x); }
}
table[{M, N}] = FORMAT_EACH(bm, runs);
}
print_time_table(table, "Berlekamp-Massey");
}
void speed_test_kitamasa() {
vector<int> Ns = {6000, 15000, 30000, 50000, 100000, 200000, 300000, 500000};
vector<double> Ks = {1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15};
vector<pair<int, uint64_t>> inputs;
for (int N : Ns) {
for (auto K : Ks) {
inputs.push_back({N, uint64_t(K)});
}
}
const auto runtime = 300'000ms / inputs.size();
map<pair<stringable, int>, stringable> table;
for (auto [N, K] : inputs) {
START_ACC(kita);
string Kstr = format("{:.0e}", 1.0 * K);
auto rec = rand_recurrence<num>(N);
auto x = rand_poly<num>(N);
LOOP_FOR_DURATION_OR_RUNS_TRACKED (runtime, now, 10'000, runs) {
print_time(now, runtime, "speed KM N={} K={} ({} runs)", N, Kstr, runs);
ADD_TIME_BLOCK(kita) {
int64_t k = rand_unif<int64_t>(K, 1.1 * K);
kitamasa(x, rec, k);
}
}
table[{Kstr, N}] = FORMAT_EACH(kita, runs);
}
print_time_table(table, "Kitamasa Kth Term");
}
int main() {
RUN_BLOCK(stress_test_kitamasa());
RUN_BLOCK(speed_test_kitamasa());
RUN_BLOCK(stress_test_berlekamp_massey());
RUN_BLOCK(speed_test_berlekamp_massey());
return 0;
}