LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
multivariate_factor.cpp
浏览该文件的文档.
1/**
2 * @file multivariate_factor.cpp
3 * @brief 多元多项式因式分解器实现.
4 */
7#include <algorithm>
8#include <climits>
9#include <cstdint>
10#include <cmath>
11#include <functional>
12#include <iterator>
13#include <map>
14#include <set>
15#include <stdexcept>
16#include <new>
18namespace LMCAS {
19static std::map<int, MultiPoly>
20extract_coefficients(const MultiPoly& poly, const std::string& main_var)
21{
22 const auto& vars = poly.variables();
23 int var_idx = -1;
24 for (size_t i = 0; i < vars.size(); ++i) {
25 if (vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
26 }
27 std::vector<std::string> remaining_vars;
28 for (size_t i = 0; i < vars.size(); ++i) {
29 if (static_cast<int>(i) != var_idx) { remaining_vars.push_back(vars[i]); }
30 }
31 std::map<int, MultiPoly> coeffs;
32 if (var_idx < 0) { coeffs[0] = poly; return coeffs; }
33 for (const auto& term : poly.terms()) {
34 const Monomial& mono = term.first;
35 int exp = (static_cast<size_t>(var_idx) < mono.size()) ? mono[var_idx] : 0;
36 Monomial reduced_mono;
37 reduced_mono.reserve(vars.size() - 1);
38 for (size_t i = 0; i < mono.size(); ++i) {
39 if (static_cast<int>(i) != var_idx) { reduced_mono.push_back(mono[i]); }
40 }
41 std::vector<MultiPoly::Term> t_vec = {{reduced_mono, term.second}};
42 MultiPoly term_poly(std::move(t_vec), remaining_vars);
43 if (coeffs.find(exp) == coeffs.end()) {
44 coeffs[exp] = term_poly;
45 } else {
46 coeffs[exp] = coeffs[exp] + term_poly;
47 }
48 }
49 return coeffs;
50}
51static bool divides_poly(const MultiPoly& dividend, const MultiPoly& divisor)
52{
53 if (divisor.is_zero()) { return false; }
54 if (dividend.is_zero()) { return true; }
55 try { dividend.exact_div(divisor); return true; }
56 catch (const std::runtime_error&) { return false; }
57}
58static std::string choose_main_variable(const MultiPoly& a, const MultiPoly& b)
59{
60 const auto& vars = a.variables();
61 if (vars.empty()) { return ""; }
62 std::string best_var = vars[0];
63 int best_deg = a.degree(vars[0]) + b.degree(vars[0]);
64 for (size_t i = 1; i < vars.size(); ++i) {
65 int deg = a.degree(vars[i]) + b.degree(vars[i]);
66 if (deg > best_deg) { best_deg = deg; best_var = vars[i]; }
67 }
68 return best_var;
69}
70static Rational rational_gcd(const Rational& a, const Rational& b)
71{
72 if (a.is_zero()) { return b.abs(); }
73 if (b.is_zero()) { return a.abs(); }
74 BigInt num_gcd = BigInt::gcd(a.get_numerator().abs(), b.get_numerator().abs());
75 BigInt den_gcd = BigInt::gcd(a.get_denominator(), b.get_denominator());
76 BigInt den_lcm = a.get_denominator() * b.get_denominator() / den_gcd;
77 return Rational(num_gcd, den_lcm);
78}
80 size_t variable_count, int variable_index, int exponent) {
81 Monomial full(variable_count, 0);
82 size_t reduced_index = 0;
83 for (size_t i = 0; i < variable_count; ++i) {
84 if (static_cast<int>(i) == variable_index) {
85 full[i] = exponent;
86 } else {
87 if (reduced_index < reduced.size()) { full[i] = reduced[reduced_index]; }
88 ++reduced_index;
89 }
90 }
91 return full;
92}
93
94static std::vector<Rational> lagrange_basis_coefficients(
95 const std::vector<Rational>& points, size_t i, const Rational& denom) {
96 const size_t n = points.size();
97 std::vector<Rational> basis_coeffs = {Rational(1)};
98 for (size_t j = 0; j < n; ++j) {
99 if (j == i) { continue; }
100 std::vector<Rational> nc(basis_coeffs.size() + 1, Rational(0));
101 for (size_t k = 0; k < basis_coeffs.size(); ++k) {
102 nc[k + 1] = nc[k + 1] + basis_coeffs[k];
103 nc[k] = nc[k] - points[j] * basis_coeffs[k];
104 }
105 basis_coeffs = std::move(nc);
106 }
107 for (auto& c : basis_coeffs) c = c / denom;
108 return basis_coeffs;
109}
110
111static void add_lagrange_value(MultiPoly& result, const MultiPoly& value,
112 const std::vector<Rational>& basis_coeffs,
113 const std::vector<std::string>& all_vars, int var_idx) {
114 for (size_t k = 0; k < basis_coeffs.size(); ++k) {
115 if (basis_coeffs[k].is_zero()) { continue; }
116 MultiPoly scaled = value * basis_coeffs[k];
117 if (scaled.is_zero()) { continue; }
118 for (const auto& term : scaled.terms()) {
120 term.first, all_vars.size(), var_idx, static_cast<int>(k));
121 std::vector<MultiPoly::Term> t = {{full_mono, term.second}};
122 result = result + MultiPoly(std::move(t), all_vars);
123 }
124 }
125}
126static MultiPoly lagrange_interpolate(const std::vector<Rational>& points,
127 const std::vector<MultiPoly>& values, const std::string& main_var,
128 const std::vector<std::string>& all_vars)
129{
130 size_t n = points.size();
131 if (n == 0) { return MultiPoly(Rational(0), all_vars); }
132 int var_idx = -1;
133 for (size_t i = 0; i < all_vars.size(); ++i) {
134 if (all_vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
135 }
136 MultiPoly result(Rational(0), all_vars);
137 for (size_t i = 0; i < n; ++i) {
138 if (values[i].is_zero()) { continue; }
139 Rational denom(1);
140 for (size_t j = 0; j < n; ++j) {
141 if (j == i) { continue; }
142 denom = denom * (points[i] - points[j]);
143 }
144 if (denom.is_zero()) { continue; }
145 auto basis_coeffs = lagrange_basis_coefficients(points, i, denom);
146 add_lagrange_value(result, values[i], basis_coeffs, all_vars, var_idx);
147 }
148 return result;
149}
150
151MultiPoly multivariate_content(const MultiPoly& poly, const std::string& main_var)
152{
153 if (poly.is_zero()) { return MultiPoly(); }
154 /// 若 main_var 不在变量列表中,或多项式在 main_var 上次数为 0,容度就是多项式本身
155 const auto& vars = poly.variables();
156 int var_idx = -1;
157 for (size_t i = 0; i < vars.size(); ++i) {
158 if (vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
159 }
160 if (var_idx < 0) { return poly; }
161 if (poly.degree(main_var) <= 0) { return poly; }
162 auto coeffs = extract_coefficients(poly, main_var);
163 if (coeffs.empty()) { return MultiPoly(); }
164 auto it = coeffs.begin();
165 MultiPoly content_gcd = it->second;
166 ++it;
167 for (; it != coeffs.end(); ++it) {
168 if (it->second.is_zero()) { continue; }
169 content_gcd = multivariate_gcd(content_gcd, it->second);
170 if (content_gcd.is_constant()) {
171 Rational nc = content_gcd.numeric_content();
172 if (nc == Rational(1)) { return content_gcd; }
173 }
174 }
175 if (!content_gcd.is_zero() && !content_gcd.terms().empty()) {
176 if (content_gcd.terms()[0].second < Rational(0)) { content_gcd = content_gcd * Rational(-1); }
177 }
178 return content_gcd;
179}
180MultiPoly multivariate_primitive_part(const MultiPoly& poly, const std::string& main_var)
181{
182 if (poly.is_zero()) { return poly; }
183 MultiPoly content = multivariate_content(poly, main_var);
184 if (content.is_zero()) { return MultiPoly(); }
185 if (content.is_constant() && content.numeric_content() == Rational(1)) { return poly; }
186
187 /// content 的变量集是去掉 main_var 后的辅助变量集,
188 /// 需要将其嵌入到 poly 的完整变量集中才能正确执行 exact_div.
189 const auto& full_vars = poly.variables();
190 int var_idx = -1;
191 for (size_t i = 0; i < full_vars.size(); ++i) {
192 if (full_vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
193 }
194
195 MultiPoly content_in_full_vars = content;
196 if (var_idx >= 0 && content.variables().size() < full_vars.size()) {
197 std::vector<MultiPoly::Term> new_terms;
198 for (const auto& term : content.terms()) {
200 term.first, full_vars.size(), var_idx, 0);
201 new_terms.emplace_back(std::move(full_mono), term.second);
202 }
203 content_in_full_vars = MultiPoly(std::move(new_terms), full_vars);
204 }
205
206 return poly.exact_div(content_in_full_vars);
207}
208static std::string active_univariate_variable(const MultiPoly& poly) {
209 for (const auto& variable : poly.variables()) {
210 if (poly.degree(variable) > 0) { return variable; }
211 }
212 return {};
213}
214
215static MultiPoly embed_univariate_gcd(const MultiPoly& result,
216 const std::string& a_var, const std::vector<std::string>& vars) {
217 int avi = -1;
218 for (size_t i = 0; i < vars.size(); ++i) {
219 if (vars[i] == a_var) { avi = static_cast<int>(i); break; }
220 }
221 std::vector<MultiPoly::Term> nt;
222 for (const auto& term : result.terms()) {
223 Monomial fm(vars.size(), 0);
224 if (avi >= 0 && !term.first.empty()) { fm[static_cast<size_t>(avi)] = term.first[0]; }
225 nt.emplace_back(std::move(fm), term.second);
226 }
227 return MultiPoly(std::move(nt), vars);
228}
229
230static MultiPoly univariate_gcd(const MultiPoly& a, const MultiPoly& b,
231 const std::vector<std::string>& vars) {
232 std::string a_var = active_univariate_variable(a);
233 std::string b_var = active_univariate_variable(b);
234 if (a_var.empty() && b_var.empty()) {
235 return MultiPoly(rational_gcd(a.numeric_content(), b.numeric_content()), vars);
236 }
237 if (a_var.empty() || b_var.empty()) {
238 return MultiPoly(rational_gcd(a.numeric_content(), b.numeric_content()), vars);
239 }
240 if (a_var == b_var) {
241 Rational nc_gcd = rational_gcd(a.numeric_content(), b.numeric_content());
242 Polynomial<Rational> pa = a.to_univariate();
243 Polynomial<Rational> pb = b.to_univariate();
245 if (g.is_zero()) { return MultiPoly(nc_gcd, vars); }
246 MultiPoly result = MultiPoly::from_univariate(g, a_var);
247 result = result * nc_gcd;
248 if (vars.size() > 1) {
249 result = embed_univariate_gcd(result, a_var, vars);
250 }
251 if (!result.terms().empty() && result.terms()[0].second < Rational(0)) { result = result * Rational(-1); }
252 return result;
253 }
254 return MultiPoly(rational_gcd(a.numeric_content(), b.numeric_content()), vars);
255}
256
258 std::vector<Rational> points;
259 std::vector<MultiPoly> values;
261};
262
263static std::vector<Rational> gcd_evaluation_points(int bound) {
264 std::vector<Rational> points;
265 points.push_back(Rational(0));
266 for (int k = 1; static_cast<int>(points.size()) < bound; ++k) {
267 points.push_back(Rational(k));
268 points.push_back(Rational(-k));
269 }
270 return points;
271}
272
273static void collect_gcd_samples(const MultiPoly& a_prim,
274 const MultiPoly& b_prim, const std::string& main_var,
275 const std::vector<Rational>& eval_pts, int num_points, GcdSamples& samples) {
276 auto& used_pts = samples.points;
277 auto& gcd_vals = samples.values;
278 auto& target_deg = samples.target_degree;
279 for (size_t pi = 0; pi < eval_pts.size() &&
280 static_cast<int>(used_pts.size()) < num_points; ++pi) {
281 Rational pt = eval_pts[pi];
282 MultiPoly lc_a = a_prim.leading_coeff(main_var);
283 MultiPoly lc_b = b_prim.leading_coeff(main_var);
284 MultiPoly lca_ev = lc_a.eval(main_var, pt);
285 MultiPoly lcb_ev = lc_b.eval(main_var, pt);
286 if (lca_ev.is_zero() || lcb_ev.is_zero()) { continue; }
287 MultiPoly a_ev = a_prim.eval(main_var, pt);
288 MultiPoly b_ev = b_prim.eval(main_var, pt);
289 MultiPoly g_ev = multivariate_gcd(a_ev, b_ev);
290 int gd = g_ev.is_zero() ? -1 : g_ev.total_degree();
291 if (target_deg < 0) { target_deg = gd; }
292 else if (gd < target_deg) { used_pts.clear(); gcd_vals.clear(); target_deg = gd; }
293 else if (gd > target_deg) { continue; }
294 if (!g_ev.is_zero()) { g_ev = g_ev.make_primitive(); }
295 used_pts.push_back(pt);
296 gcd_vals.push_back(g_ev);
297 }
298}
299
300
301static MultiPoly normalize_gcd_candidate(MultiPoly candidate,
302 const Rational& content) {
303 if (content != Rational(1)) { candidate = candidate * content; }
304 if (!candidate.terms().empty() && candidate.terms()[0].second < Rational(0)) {
305 candidate = candidate * Rational(-1);
306 }
307 return candidate;
308}
309
310static MultiPoly extended_gcd_interpolation(const MultiPoly& a_prim,
311 const MultiPoly& b_prim, const std::string& main_var,
312 const std::vector<std::string>& vars, int degree_bound,
313 const Rational& nc_gcd) {
314 int ext_bound = degree_bound + 5;
315 auto all_pts = gcd_evaluation_points(ext_bound + 10);
316 GcdSamples samples;
317 collect_gcd_samples(a_prim, b_prim, main_var, all_pts, ext_bound + 1, samples);
318 if (samples.target_degree <= 0 || samples.points.empty()) {
319 return MultiPoly(nc_gcd, vars);
320 }
321 auto cand = lagrange_interpolate(samples.points, samples.values, main_var, vars);
322 if (cand.is_zero()) { return MultiPoly(nc_gcd, vars); }
323 cand = cand.make_primitive();
324 if (divides_poly(a_prim, cand) && divides_poly(b_prim, cand)) {
325 return normalize_gcd_candidate(std::move(cand), nc_gcd);
326 }
327 return MultiPoly(nc_gcd, vars);
328}
330 const MultiPoly& a, const MultiPoly& b,
331 const std::vector<std::string>& vars) {
332 std::string main_var = choose_main_variable(a, b);
333 Rational nc_a = a.numeric_content();
334 Rational nc_b = b.numeric_content();
335 Rational nc_gcd = rational_gcd(nc_a, nc_b);
336 MultiPoly a_prim = a.make_primitive();
337 MultiPoly b_prim = b.make_primitive();
338 int deg_a = a_prim.degree(main_var);
339 int deg_b = b_prim.degree(main_var);
340 int degree_bound = std::min(deg_a, deg_b);
341 int num_points = degree_bound + 1;
342 auto eval_pts = gcd_evaluation_points(num_points + 10);
343 GcdSamples samples;
344 collect_gcd_samples(a_prim, b_prim, main_var, eval_pts, num_points, samples);
345 const auto& used_pts = samples.points;
346 const auto& gcd_vals = samples.values;
347 const int target_deg = samples.target_degree;
348 if (target_deg <= 0 || used_pts.empty()) { return MultiPoly(nc_gcd, vars); }
349 if (used_pts.size() == 1 && degree_bound == 0) {
350 MultiPoly r = lagrange_interpolate(used_pts, gcd_vals, main_var, vars);
351 if (nc_gcd != Rational(1)) { r = r * nc_gcd; }
352 return r;
353 }
354 MultiPoly cand = lagrange_interpolate(used_pts, gcd_vals, main_var, vars);
355 if (cand.is_zero()) { return MultiPoly(nc_gcd, vars); }
356 cand = cand.make_primitive();
357 if (divides_poly(a_prim, cand) && divides_poly(b_prim, cand)) {
358 return normalize_gcd_candidate(std::move(cand), nc_gcd);
359 }
360 return extended_gcd_interpolation(a_prim, b_prim, main_var, vars,
361 degree_bound, nc_gcd);
362}
363
364MultiPoly multivariate_gcd(const MultiPoly& a, const MultiPoly& b)
365{
366 if (a.is_zero()) { return b.is_zero() ? MultiPoly() : b.make_primitive(); }
367 if (b.is_zero()) { return a.make_primitive(); }
368 const auto& vars = a.variables().empty() ? b.variables() : a.variables();
369 if (a.is_constant() && b.is_constant()) {
370 Rational g = rational_gcd(a.numeric_content(), b.numeric_content());
371 return MultiPoly(g, vars);
372 }
373 if (a.is_univariate() && b.is_univariate()) {
374 return univariate_gcd(a, b, vars);
375 }
377}
378/**
379 * @internal
380 * @brief 计算多元多项式关于指定变量的形式偏导数
381 *
382 * 对每个含 main_var 的项,新系数 = 原系数 x 指数,新指数 = 原指数 - 1.
383 * 指数为 0 的项被丢弃.
384 *
385 * @param[in] poly 输入多元多项式
386 * @param[in] main_var 求导变量名
387 * @return partialpoly/partialmain_var
388 */
389static MultiPoly formal_derivative(const MultiPoly& poly, const std::string& main_var)
390{
391 if (poly.is_zero()) { return poly; }
392
393 const auto& vars = poly.variables();
394 int var_idx = -1;
395 for (size_t i = 0; i < vars.size(); ++i) {
396 if (vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
397 }
398 if (var_idx < 0) {
399 /// main_var 不在变量列表中,导数为零
400 return MultiPoly(Rational(0), vars);
401 }
402
403 std::vector<MultiPoly::Term> result_terms;
404 for (const auto& term : poly.terms()) {
405 const Monomial& mono = term.first;
406 int exp = (static_cast<size_t>(var_idx) < mono.size()) ? mono[var_idx] : 0;
407 if (exp == 0) { continue; } /**< 常数项关于该变量的导数为零。 */
408
409 Rational new_coeff = term.second * Rational(exp);
410 Monomial new_mono = mono;
411 new_mono[var_idx] = exp - 1;
412 result_terms.emplace_back(std::move(new_mono), std::move(new_coeff));
413 }
414
415 if (result_terms.empty()) { return MultiPoly(Rational(0), vars); }
416 return MultiPoly(std::move(result_terms), vars);
417}
418
419/**
420 * @brief 多元无平方因子分解(Yun 算法的多元推广)
421 *
422 * 通过计算 gcd(f, partialf/partialx_main) 检测重因子,将多项式分解为
423 * f = f_1 * f_2^2 * f₃^3 * ... 的形式,其中每个 fᵢ 无平方.
424 *
425 * @param[in] poly 输入多元多项式
426 * @param[in] main_var 主变量名
427 * @return 无平方因子分解结果,components[i] 的重数为 i+1
428 */
429SquareFreeDecomp square_free_decompose(const MultiPoly& poly, const std::string& main_var)
430{
431 /// 零多项式或常数多项式:直接返回
432 if (poly.is_zero() || poly.is_constant()) {
433 return SquareFreeDecomp{{poly}};
434 }
435
436 /// 若 main_var 不在变量列表中或次数为 0,多项式无重因子
437 const auto& vars = poly.variables();
438 int var_idx = -1;
439 for (size_t i = 0; i < vars.size(); ++i) {
440 if (vars[i] == main_var) { var_idx = static_cast<int>(i); break; }
441 }
442 if (var_idx < 0 || poly.degree(main_var) <= 0) {
443 return SquareFreeDecomp{{poly}};
444 }
445
446 /// 步骤 1:计算 f' = partialf/partialmain_var
447 MultiPoly f_prime = formal_derivative(poly, main_var);
448
449 /// 步骤 2:计算 g = gcd(f, f');特征 0 下 f' 为零时,f 直接作为单个无平方因子.
450 if (f_prime.is_zero()) {
451 return SquareFreeDecomp{{poly}};
452 }
453
454 MultiPoly g = multivariate_gcd(poly, f_prime);
455
456 /// 步骤 3:若 g 为常数,f 已无平方
457 if (g.is_constant()) {
458 return SquareFreeDecomp{{poly}};
459 }
460
461 /// 步骤 4:Yun 算法迭代提取无平方分量
462 /// w = f / g, y = f' / g, z = y - w'
463 MultiPoly w = poly.exact_div(g);
464 MultiPoly y = f_prime.exact_div(g);
465 MultiPoly w_prime = formal_derivative(w, main_var);
466 MultiPoly z = y - w_prime;
467
468 std::vector<MultiPoly> components;
469
470 while (!z.is_zero()) {
471 MultiPoly component_i = multivariate_gcd(w, z);
472 w = w.exact_div(component_i);
473 y = z.exact_div(component_i);
474 w_prime = formal_derivative(w, main_var);
475 z = y - w_prime;
476 components.push_back(std::move(component_i));
477 }
478
479 /// w 是最后一个分量
480 components.push_back(std::move(w));
481
482 /// 过滤掉常数为 1 的平凡分量(保留结构但不影响语义)
483 /// 注意:components[i] 的重数为 i+1
484 return SquareFreeDecomp{std::move(components)};
485}
486
487} // namespace LMCAS
一元多项式模板类
static Polynomial gcd(Polynomial a, Polynomial b)
计算两个多项式的最大公因式
bool is_zero() const
判断是否为零多项式
多元多项式因式分解器公共 API。
const std::string & variable
static std::vector< Rational > gcd_evaluation_points(int bound)
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
static MultiPoly recursive_multivariate_gcd(const MultiPoly &a, const MultiPoly &b, const std::vector< std::string > &vars)
std::vector< MultiPoly > values
__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
static void collect_gcd_samples(const MultiPoly &a_prim, const MultiPoly &b_prim, const std::string &main_var, const std::vector< Rational > &eval_pts, int num_points, GcdSamples &samples)
__attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorField gradient(const std const std::vector< std::string > & vars
static std::string active_univariate_variable(const MultiPoly &poly)
static MultiPoly lagrange_interpolate(const std::vector< Rational > &points, const std::vector< MultiPoly > &values, const std::string &main_var, const std::vector< std::string > &all_vars)
const VectorField const VectorField & c
const MultiPoly & b
SquareFreeDecomp square_free_decompose(const MultiPoly &poly, const std::string &main_var)
多元无平方因子分解(Yun 算法的多元推广)
MultiPoly multivariate_primitive_part(const MultiPoly &poly, const std::string &main_var)
const ExprPtr & exponent
__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
static MultiPoly normalize_gcd_candidate(MultiPoly candidate, const Rational &content)
static std::vector< Rational > lagrange_basis_coefficients(const std::vector< Rational > &points, size_t i, const Rational &denom)
static void add_lagrange_value(MultiPoly &result, const MultiPoly &value, const std::vector< Rational > &basis_coeffs, const std::vector< std::string > &all_vars, int var_idx)
static std::map< int, MultiPoly > extract_coefficients(const MultiPoly &poly, const std::string &main_var)
ExprResult pi()
static MultiPoly embed_univariate_gcd(const MultiPoly &result, const std::string &a_var, const std::vector< std::string > &vars)
const std::string const ExprPtr & value
MultiPoly multivariate_gcd(const MultiPoly &a, const MultiPoly &b)
static std::string choose_main_variable(const MultiPoly &a, const MultiPoly &b)
static bool divides_poly(const MultiPoly &dividend, const MultiPoly &divisor)
__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 & t
const std::string & main_var
static Rational rational_gcd(const Rational &a, const Rational &b)
std::vector< Rational > points
static MultiPoly extended_gcd_interpolation(const MultiPoly &a_prim, const MultiPoly &b_prim, const std::string &main_var, const std::vector< std::string > &vars, int degree_bound, const Rational &nc_gcd)
static MultiPoly formal_derivative(const MultiPoly &poly, const std::string &main_var)
计算多元多项式关于指定变量的形式偏导数
static Monomial restore_main_exponent(const Monomial &reduced, size_t variable_count, int variable_index, int exponent)
MultiPoly multivariate_content(const MultiPoly &poly, const std::string &main_var)
static MultiPoly univariate_gcd(const MultiPoly &a, const MultiPoly &b, const std::vector< std::string > &vars)
无平方因子分解结果
混合超越方程不可约因式分解器公共 API.