17 const BigInt& numerator = coefficient.get_numerator();
18 const BigInt&
denominator = coefficient.get_denominator();
19 if (numerator.is_negative()) {
return std::nullopt; }
20 BigInt numerator_root = numerator.sqrt();
21 if (numerator_root * numerator_root != numerator) {
return std::nullopt; }
23 if (denominator_root * denominator_root !=
denominator) {
return std::nullopt; }
24 return Rational(numerator_root, denominator_root);
28 const std::vector<std::string>&
vars) {
31 std::vector<MultiPoly::Term> homo_terms;
32 for (
int k = 0; k <= d; ++k) {
33 Rational coeff = (k < static_cast<int>(uf.
coeffs.size())) ? uf.
coeffs[k] : Rational(0);
34 if (coeff.is_zero()) {
continue; }
38 homo_terms.emplace_back(std::move(mono), coeff);
40 MultiPoly homo_factor(std::move(homo_terms),
vars);
41 homo_factor = homo_factor.make_primitive();
47 const auto&
vars = poly.variables();
48 MultiPoly product(Rational(1),
vars);
49 for (
const auto& f : result.
factors) {
50 product = product * f;
52 if (!product.is_zero() && !poly.is_zero()) {
54 MultiPoly ratio = poly.exact_div(product);
55 if (ratio.is_constant()) {
56 result.
constant = ratio.numeric_content();
57 if (!ratio.terms().empty() && ratio.terms()[0].second < Rational(0)) {
61 }
catch (
const std::runtime_error&) {
62 if (!product.terms().empty() && !poly.terms().empty()) {
63 result.
constant = poly.terms()[0].second / product.terms()[0].second;
86std::optional<std::pair<MultiPoly, MultiPoly>>
89 if (poly.num_terms() != 2) {
return std::nullopt; }
91 const auto& terms = poly.terms();
92 const auto&
vars = poly.variables();
95 int pos_idx = -1, neg_idx = -1;
96 if (terms[0].second > Rational(0) && terms[1].second < Rational(0)) {
97 pos_idx = 0; neg_idx = 1;
98 }
else if (terms[1].second > Rational(0) && terms[0].second < Rational(0)) {
99 pos_idx = 1; neg_idx = 0;
107 Rational pos_coeff = terms[pos_idx].second;
108 Rational neg_coeff = -terms[neg_idx].second;
113 if (!positive_root) {
return std::nullopt; }
115 if (!negative_root) {
return std::nullopt; }
118 const Monomial& pos_mono = terms[pos_idx].first;
119 const Monomial& neg_mono = terms[neg_idx].first;
121 for (
size_t i = 0; i < pos_mono.size(); ++i) {
122 if (pos_mono[i] % 2 != 0) {
return std::nullopt; }
124 for (
size_t i = 0; i < neg_mono.size(); ++i) {
125 if (neg_mono[i] % 2 != 0) {
return std::nullopt; }
130 for (
size_t i = 0; i < pos_mono.size(); ++i) {
131 a_mono[i] = pos_mono[i] / 2;
133 const Rational& a_coeff = *positive_root;
134 std::vector<MultiPoly::Term> a_terms = {{a_mono, a_coeff}};
135 MultiPoly
a(std::move(a_terms),
vars);
139 for (
size_t i = 0; i < neg_mono.size(); ++i) {
140 b_mono[i] = neg_mono[i] / 2;
142 const Rational& b_coeff = *negative_root;
143 std::vector<MultiPoly::Term> b_terms = {{b_mono, b_coeff}};
144 MultiPoly
b(std::move(b_terms),
vars);
146 return std::make_pair(
a,
b);
158std::optional<std::tuple<std::string, std::string, int>>
161 if (poly.num_terms() != 2) {
return std::nullopt; }
163 const auto& terms = poly.terms();
164 const auto&
vars = poly.variables();
167 int pos_idx = -1, neg_idx = -1;
168 if (terms[0].second == Rational(1) && terms[1].second == Rational(-1)) {
169 pos_idx = 0; neg_idx = 1;
170 }
else if (terms[1].second == Rational(1) && terms[0].second == Rational(-1)) {
171 pos_idx = 1; neg_idx = 0;
177 auto get_single_var_power = [&](
const Monomial& mono)
178 -> std::optional<std::pair<int, int>> {
179 int nonzero_count = 0;
182 for (
size_t i = 0; i < mono.size(); ++i) {
185 var_index =
static_cast<int>(i);
189 if (nonzero_count != 1 ||
exponent <= 1) {
return std::nullopt; }
190 return std::make_pair(var_index,
exponent);
193 auto pos_info = get_single_var_power(terms[pos_idx].first);
194 if (!pos_info) {
return std::nullopt; }
195 auto neg_info = get_single_var_power(terms[neg_idx].first);
196 if (!neg_info) {
return std::nullopt; }
198 auto [pos_var_idx, pos_exp] = *pos_info;
199 auto [neg_var_idx, neg_exp] = *neg_info;
202 if (pos_exp != neg_exp) {
return std::nullopt; }
203 if (pos_var_idx == neg_var_idx) {
return std::nullopt; }
205 return std::make_tuple(
vars[pos_var_idx],
vars[neg_var_idx], pos_exp);
216std::pair<Monomial, MultiPoly>
219 const auto&
vars = poly.variables();
222 if (poly.is_zero() || poly.num_terms() == 0) {
223 return {identity, poly};
226 const auto& terms = poly.terms();
230 for (
size_t t = 1;
t < terms.size(); ++
t) {
232 for (
size_t i = 0; i < gcd_mono.size(); ++i) {
233 int val = (i < mono.size()) ? mono[i] : 0;
234 if (val < gcd_mono[i]) { gcd_mono[i] = val; }
239 bool is_trivial =
true;
240 for (
size_t i = 0; i < gcd_mono.size(); ++i) {
241 if (gcd_mono[i] != 0) { is_trivial =
false;
break; }
243 if (is_trivial) {
return {identity, poly}; }
246 std::vector<MultiPoly::Term> quotient_terms;
247 quotient_terms.reserve(terms.size());
248 for (
const auto& term : terms) {
250 for (
size_t i = 0; i <
vars.size(); ++i) {
251 int orig = (i < term.first.size()) ? term.first[i] : 0;
252 new_mono[i] = orig - gcd_mono[i];
254 quotient_terms.emplace_back(std::move(new_mono), term.second);
257 MultiPoly quotient(std::move(quotient_terms),
vars);
258 return {gcd_mono, quotient};
273 const MultiPoly& poly,
276 if (!poly.is_homogeneous() || poly.num_vars() != 2) {
277 return std::optional<MultiFactorResult>{};
280 const auto&
vars = poly.variables();
281 std::string var_x =
vars[0];
282 std::string var_y =
vars[1];
285 MultiPoly dehomogenized = poly.eval(var_y, Rational(1));
290 uni_poly = dehomogenized.to_univariate();
291 }
catch (
const std::invalid_argument&) {
292 return std::optional<MultiFactorResult>{};
296 auto checked_factors =
298 if (!checked_factors) {
300 checked_factors.error());
303 return std::optional<MultiFactorResult>{};
305 std::vector<Polynomial<Rational>> uni_factors =
306 std::move(checked_factors.value().value);
307 if (uni_factors.size() <= 1) {
308 return std::optional<MultiFactorResult>{};
313 result.
constant = poly.numeric_content();
315 for (
const auto& uf : uni_factors) {
317 result.
factors.push_back(std::move(homo_factor));
323 return std::optional<MultiFactorResult>(std::move(result));
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
std::pair< Monomial, MultiPoly > extract_common_monomial(const MultiPoly &poly)
提取公因子单项式
bool is_linear(const MultiPoly &poly, const std::string &main_var)
检测是否为线性多项式(主变量次数 <= 1)
static void adjust_homogeneous_constant(const MultiPoly &poly, MultiFactorResult &result)
Result< std::optional< MultiFactorResult > > factor_homogeneous_bivariate(const MultiPoly &poly, ComputationContext &context)
齐次二元多项式分解
static std::optional< Rational > rational_square_root(const Rational &coefficient)
const std::string & main_var
static MultiPoly homogenize_factor(const Polynomial< Rational > &uf, const std::vector< std::string > &vars)
std::optional< std::tuple< std::string, std::string, int > > detect_binomial_power(const MultiPoly &poly)
检测二项式幂模式 xⁿ - yⁿ
std::size_t std::size_t ComputationContext & context
std::optional< std::pair< MultiPoly, MultiPoly > > detect_difference_of_squares(const MultiPoly &poly)
检测差平方模式 a^2 - b^2
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
__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
std::vector< MultiPoly > factors
精确因子列表(各因子本原)
UnivariateFactorResult factor_univariate_bridge_checked(const Polynomial< Rational > &polynomial, ComputationContext &context)
__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 ExprPtr & denominator
__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
std::vector< int > multiplicities
各因子的重数