19static std::map<int, MultiPoly>
22 const auto&
vars = poly.variables();
24 for (
size_t i = 0; i <
vars.size(); ++i) {
25 if (
vars[i] ==
main_var) { var_idx =
static_cast<int>(i);
break; }
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]); }
31 std::map<int, MultiPoly> coeffs;
32 if (var_idx < 0) { coeffs[0] = poly;
return coeffs; }
33 for (
const auto& term : poly.terms()) {
35 int exp = (
static_cast<size_t>(var_idx) < mono.size()) ? mono[var_idx] : 0;
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]); }
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;
46 coeffs[
exp] = coeffs[
exp] + term_poly;
51static bool divides_poly(
const MultiPoly& dividend,
const MultiPoly& divisor)
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; }
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]; }
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);
80 size_t variable_count,
int variable_index,
int exponent) {
82 size_t reduced_index = 0;
83 for (
size_t i = 0; i < variable_count; ++i) {
84 if (
static_cast<int>(i) == variable_index) {
87 if (reduced_index < reduced.size()) { full[i] = reduced[reduced_index]; }
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];
105 basis_coeffs = std::move(nc);
107 for (
auto&
c : basis_coeffs)
c =
c / denom;
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);
127 const std::vector<MultiPoly>& values,
const std::string&
main_var,
128 const std::vector<std::string>& all_vars)
130 size_t n = points.size();
131 if (n == 0) {
return MultiPoly(Rational(0), all_vars); }
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; }
136 MultiPoly result(Rational(0), all_vars);
137 for (
size_t i = 0; i < n; ++i) {
138 if (values[i].is_zero()) {
continue; }
140 for (
size_t j = 0; j < n; ++j) {
141 if (j == i) {
continue; }
142 denom = denom * (points[i] - points[j]);
144 if (denom.is_zero()) {
continue; }
153 if (poly.is_zero()) {
return MultiPoly(); }
155 const auto&
vars = poly.variables();
157 for (
size_t i = 0; i <
vars.size(); ++i) {
158 if (
vars[i] ==
main_var) { var_idx =
static_cast<int>(i);
break; }
160 if (var_idx < 0) {
return poly; }
161 if (poly.degree(
main_var) <= 0) {
return poly; }
163 if (coeffs.empty()) {
return MultiPoly(); }
164 auto it = coeffs.begin();
165 MultiPoly content_gcd = it->second;
167 for (; it != coeffs.end(); ++it) {
168 if (it->second.is_zero()) {
continue; }
170 if (content_gcd.is_constant()) {
171 Rational nc = content_gcd.numeric_content();
172 if (nc == Rational(1)) {
return content_gcd; }
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); }
182 if (poly.is_zero()) {
return poly; }
184 if (content.is_zero()) {
return MultiPoly(); }
185 if (content.is_constant() && content.numeric_content() == Rational(1)) {
return poly; }
189 const auto& full_vars = poly.variables();
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; }
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);
203 content_in_full_vars = MultiPoly(std::move(new_terms), full_vars);
206 return poly.exact_div(content_in_full_vars);
209 for (
const auto&
variable : poly.variables()) {
216 const std::string& a_var,
const std::vector<std::string>&
vars) {
218 for (
size_t i = 0; i <
vars.size(); ++i) {
219 if (
vars[i] == a_var) { avi =
static_cast<int>(i);
break; }
221 std::vector<MultiPoly::Term> nt;
222 for (
const auto& term : result.terms()) {
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);
227 return MultiPoly(std::move(nt),
vars);
231 const std::vector<std::string>&
vars) {
234 if (a_var.empty() && b_var.empty()) {
237 if (a_var.empty() || b_var.empty()) {
240 if (a_var == b_var) {
241 Rational nc_gcd =
rational_gcd(
a.numeric_content(),
b.numeric_content());
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) {
251 if (!result.terms().empty() && result.terms()[0].second < Rational(0)) { result = result * Rational(-1); }
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));
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;
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);
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);
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);
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;
319 return MultiPoly(nc_gcd,
vars);
322 if (cand.is_zero()) {
return MultiPoly(nc_gcd,
vars); }
323 cand = cand.make_primitive();
327 return MultiPoly(nc_gcd,
vars);
330 const MultiPoly&
a,
const MultiPoly&
b,
331 const std::vector<std::string>&
vars) {
333 Rational nc_a =
a.numeric_content();
334 Rational nc_b =
b.numeric_content();
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;
345 const auto& used_pts = samples.
points;
346 const auto& gcd_vals = samples.
values;
348 if (target_deg <= 0 || used_pts.empty()) {
return MultiPoly(nc_gcd,
vars); }
349 if (used_pts.size() == 1 && degree_bound == 0) {
351 if (nc_gcd != Rational(1)) {
r =
r * nc_gcd; }
355 if (cand.is_zero()) {
return MultiPoly(nc_gcd,
vars); }
356 cand = cand.make_primitive();
361 degree_bound, nc_gcd);
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);
373 if (
a.is_univariate() &&
b.is_univariate()) {
391 if (poly.is_zero()) {
return poly; }
393 const auto&
vars = poly.variables();
395 for (
size_t i = 0; i <
vars.size(); ++i) {
396 if (
vars[i] ==
main_var) { var_idx =
static_cast<int>(i);
break; }
400 return MultiPoly(Rational(0),
vars);
403 std::vector<MultiPoly::Term> result_terms;
404 for (
const auto& term : poly.terms()) {
406 int exp = (
static_cast<size_t>(var_idx) < mono.size()) ? mono[var_idx] : 0;
407 if (
exp == 0) {
continue; }
409 Rational new_coeff = term.second * Rational(
exp);
411 new_mono[var_idx] =
exp - 1;
412 result_terms.emplace_back(std::move(new_mono), std::move(new_coeff));
415 if (result_terms.empty()) {
return MultiPoly(Rational(0),
vars); }
416 return MultiPoly(std::move(result_terms),
vars);
432 if (poly.is_zero() || poly.is_constant()) {
437 const auto&
vars = poly.variables();
439 for (
size_t i = 0; i <
vars.size(); ++i) {
440 if (
vars[i] ==
main_var) { var_idx =
static_cast<int>(i);
break; }
442 if (var_idx < 0 || poly.degree(
main_var) <= 0) {
450 if (f_prime.is_zero()) {
457 if (g.is_constant()) {
463 MultiPoly w = poly.exact_div(g);
464 MultiPoly y = f_prime.exact_div(g);
466 MultiPoly z = y - w_prime;
468 std::vector<MultiPoly> components;
470 while (!z.is_zero()) {
472 w = w.exact_div(component_i);
473 y = z.exact_div(component_i);
476 components.push_back(std::move(component_i));
480 components.push_back(std::move(w));
static Polynomial gcd(Polynomial a, Polynomial b)
计算两个多项式的最大公因式
bool is_zero() const
判断是否为零多项式
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
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)
__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)
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 ÷nd, 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)