LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
berlekamp_basis.cpp
浏览该文件的文档.
2#include <algorithm>
3#include <limits>
4
6
7/**
8 * @brief 在 F_p 上计算 a(x) * b(x) mod f(x)。
9 *
10 * @param[in] a 第一个多项式系数向量(升幂排列)
11 * @param[in] b 第二个多项式系数向量(升幂排列)
12 * @param[in] f 模多项式系数向量(首一,升幂排列)
13 * @param[in] p 素数模数
14 * @return a * b mod f 的系数向量
15 * @internal
16 */
17static std::vector<int64_t> bk_poly_mul_mod(
18 const std::vector<int64_t>& a,
19 const std::vector<int64_t>& b,
20 const std::vector<int64_t>& f,
21 int64_t p) {
22
23 if (a.empty() || b.empty()) {
24 return {};
25 }
26 size_t prod_size = a.size() + b.size() - 1;
27 std::vector<int64_t> product(prod_size, 0);
28
29 for (size_t i = 0; i < a.size(); ++i) {
30 if (a[i] == 0) continue;
31 for (size_t j = 0; j < b.size(); ++j) {
32 product[i + j] = (product[i + j] + a[i] * b[j]) % p;
33 if (product[i + j] < 0) product[i + j] += p;
34 }
35 }
36
37 std::vector<int64_t> q, r;
38 bk_div_mod(product, f, p, q, r);
39
40 return r;
41}
42
43/**
44 * @brief 在 F_p 上用平方乘法计算 base^exp mod f(x)。
45 *
46 * @param[in] base 底多项式系数向量(升幂排列)
47 * @param[in] exp 指数(非负整数)
48 * @param[in] f 模多项式系数向量(首一,升幂排列)
49 * @param[in] p 素数模数
50 * @return base^exp mod f 的系数向量
51 *
52 * @see Berlekamp, E.R. "Factoring polynomials over finite fields."
53 * @internal
54 */
55static std::vector<int64_t> bk_poly_pow_mod(
56 const std::vector<int64_t>& base,
57 int64_t exp,
58 const std::vector<int64_t>& f,
59 int64_t p) {
60
61 if (exp == 0) {
62 return {1};
63 }
64
65 if (exp == 1) {
66 std::vector<int64_t> q, r;
67 bk_div_mod(base, f, p, q, r);
68 return r;
69 }
70 std::vector<int64_t> result = {1};
71 std::vector<int64_t> cur = base;
72 {
73 std::vector<int64_t> q, r;
74 bk_div_mod(cur, f, p, q, r);
75 cur = std::move(r);
76 }
77
78 int64_t e = exp;
79 while (e > 0) {
80 if (e & 1) {
81 result = bk_poly_mul_mod(result, cur, f, p);
82 }
83 e >>= 1;
84 if (e > 0) {
85 cur = bk_poly_mul_mod(cur, cur, f, p);
86 }
87 }
88
89 return result;
90}
91
92/**
93 * @brief 构造 F_p 上的 Berlekamp 矩阵 Q。
94 *
95 * 对次数为 n 的首一多项式 f,Q 的第 i 行为 x^(i*p) mod f(x) 的系数向量。
96 * 先用平方乘法求 h = x^p mod f,再由第 0 行 [1, 0, ..., 0] 逐行乘 h 并取余。
97 *
98 * @param[in] f 首一多项式系数向量(升幂排列,deg(f) = n)
99 * @param[in] p 素数模数
100 * @return nxn Berlekamp 矩阵(行优先存储)
101 *
102 * @see Berlekamp, E.R. "Factoring polynomials over finite fields."
103 * Bell System Technical Journal, 46(8), 1967.
104 * @internal
105 */
106std::vector<std::vector<int64_t>> bk_build_q_matrix(
107 const std::vector<int64_t>& f,
108 int64_t p) {
109
110 int n = static_cast<int>(f.size()) - 1; /**< f 的次数。 */
111
112 std::vector<std::vector<int64_t>> Q(n, std::vector<int64_t>(n, 0));
113
114 if (n <= 0) {
115 return Q;
116 }
117 Q[0][0] = 1;
118
119 if (n == 1) {
120 return Q;
121 }
122 std::vector<int64_t> x_poly = {0, 1};
123 std::vector<int64_t> h = bk_poly_pow_mod(x_poly, p, f, p);
124 for (size_t j = 0; j < h.size() && j < static_cast<size_t>(n); ++j) {
125 Q[1][j] = h[j];
126 }
127 std::vector<int64_t> current = h;
128 for (int i = 2; i < n; ++i) {
129 current = bk_poly_mul_mod(current, h, f, p);
130 for (size_t j = 0; j < current.size() && j < static_cast<size_t>(n); ++j) {
131 Q[i][j] = current[j];
132 }
133 }
134
135 return Q;
136}
137
138static void bk_eliminate_column(std::vector<std::vector<int64_t>>& matrix,
139 int current_row, int col, int64_t p) {
140 const int n = static_cast<int>(matrix.size());
141 int64_t inverse = bk_mod_inverse(matrix[current_row][col], p);
142 for (int j = 0; j < n; ++j) {
143 matrix[current_row][j] = (matrix[current_row][j] * inverse) % p;
144 }
145 for (int row = 0; row < n; ++row) {
146 if (row == current_row) continue;
147 int64_t factor = matrix[row][col];
148 if (factor == 0) continue;
149 for (int j = 0; j < n; ++j) {
150 matrix[row][j] =
151 (matrix[row][j] - factor * matrix[current_row][j] % p + p) % p;
152 }
153 }
154}
155
156static void bk_reduce_matrix(std::vector<std::vector<int64_t>>& M, int64_t p,
157 std::vector<int>& pivot_col, std::vector<int>& pivot_row) {
158 const int n = static_cast<int>(M.size());
159 int current_row = 0;
160 for (int col = 0; col < n && current_row < n; ++col) {
161 int pivot = -1;
162 for (int row = current_row; row < n; ++row) {
163 if (M[row][col] != 0) {
164 pivot = row;
165 break;
166 }
167 }
168
169 if (pivot == -1) {
170 continue;
171 }
172
173 if (pivot != current_row) {
174 std::swap(M[pivot], M[current_row]);
175 }
176
177 pivot_col[current_row] = col;
178 pivot_row[col] = current_row;
179 bk_eliminate_column(M, current_row, col, p);
180 ++current_row;
181 }
182}
183
184std::vector<std::vector<int64_t>> bk_null_space(
185 const std::vector<std::vector<int64_t>>& Q,
186 int64_t p) {
187
188 int n = static_cast<int>(Q.size());
189 if (n == 0) {
190 return {};
191 }
192 std::vector<std::vector<int64_t>> M(n, std::vector<int64_t>(n, 0));
193 for (int i = 0; i < n; ++i) {
194 for (int j = 0; j < n; ++j) {
195 int64_t val = Q[j][i];
196 if (i == j) {
197 val = (val - 1 + p) % p;
198 }
199 M[i][j] = val;
200 }
201 }
202 std::vector<int> pivot_col(n, -1);
203 std::vector<int> pivot_row(n, -1);
204
205 bk_reduce_matrix(M, p, pivot_col, pivot_row);
206 std::vector<std::vector<int64_t>> basis;
207
208 for (int col = 0; col < n; ++col) {
209 if (pivot_row[col] != -1) {
210 continue;
211 }
212
213 std::vector<int64_t> vec(n, 0);
214 vec[col] = 1; /**< 当前自由变量取 1,其余自由变量取 0。 */
215
216 for (int row = 0; row < n; ++row) {
217 int pc = pivot_col[row];
218 if (pc == -1) continue;
219 /**
220 * @brief 由行简化阶梯形回代约束分量。
221 * M[row][pc] = 1,故 x[pc] + sum_{自由列 j} M[row][j] * x[j] = 0,
222 * 当前基向量满足 x[pc] = -M[row][col] mod p。
223 */
224 vec[pc] = (p - M[row][col]) % p;
225 }
226
227 basis.push_back(std::move(vec));
228 }
229
230 return basis;
231}
232
233}
int64_t bk_mod_inverse(int64_t a, int64_t p)
模 p 下求乘法逆元.
std::vector< std::vector< int64_t > > bk_build_q_matrix(const std::vector< int64_t > &f, int64_t p)
构造 F_p 上的 Berlekamp 矩阵 Q。
static void bk_eliminate_column(std::vector< std::vector< int64_t > > &matrix, int current_row, int col, int64_t p)
void bk_div_mod(const std::vector< int64_t > &a, const std::vector< int64_t > &b, int64_t p, std::vector< int64_t > &q, std::vector< int64_t > &r)
模 p 多项式带余除法.
static std::vector< int64_t > bk_poly_mul_mod(const std::vector< int64_t > &a, const std::vector< int64_t > &b, const std::vector< int64_t > &f, int64_t p)
在 F_p 上计算 a(x) * b(x) mod f(x)。
std::vector< std::vector< int64_t > > bk_null_space(const std::vector< std::vector< int64_t > > &Q, int64_t p)
static void bk_reduce_matrix(std::vector< std::vector< int64_t > > &M, int64_t p, std::vector< int > &pivot_col, std::vector< int > &pivot_row)
static std::vector< int64_t > bk_poly_pow_mod(const std::vector< int64_t > &base, int64_t exp, const std::vector< int64_t > &f, int64_t p)
在 F_p 上用平方乘法计算 base^exp mod f(x)。
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
ExprResult e()
__attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std std::shared_ptr< SymbolicExpr > r
const MultiPoly & b
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const std::vector< FGLMPoly > & basis