15 const Rational&
value) {
16 if (
value < Rational(0))
return std::nullopt;
17 const BigInt numerator =
value.get_numerator();
19 const BigInt numerator_root = numerator.sqrt();
21 if (numerator_root * numerator_root != numerator ||
22 denominator_root * denominator_root !=
denominator) {
25 return Rational(numerator_root, denominator_root);
29 if (polynomial.
degree() != 4 ||
30 polynomial.
coeffs[1] != Rational(0) ||
31 polynomial.
coeffs[3] != Rational(0)) {
34 const Rational&
c = polynomial.
coeffs[0];
35 const Rational&
b = polynomial.
coeffs[2];
36 const Rational&
a = polynomial.
coeffs[4];
37 const Rational discriminant =
b *
b - Rational(4) *
a *
c;
39 if (!square_root)
return {};
40 const Rational first =
41 (-
b - *square_root) / (Rational(2) *
a);
42 const Rational second =
43 (-
b + *square_root) / (Rational(2) *
a);
44 if (first == second)
return {};
54 const auto* left_real = std::get_if<RealIsolation>(&left);
55 const auto* right_real = std::get_if<RealIsolation>(&
right);
56 if (left_real && !right_real) {
59 if (!left_real && right_real) {
62 if (left_real && right_real) {
64 left_real->value, right_real->value,
context);
66 const auto& left_complex = std::get<ComplexIsolation>(left);
67 const auto& right_complex = std::get<ComplexIsolation>(
right);
69 left_complex.real_projection,
70 right_complex.real_projection,
72 if (!real_comparison || real_comparison.value() != 0) {
73 return real_comparison;
76 left_complex.imaginary_projection,
77 right_complex.imaginary_projection,
83 std::vector<RootIsolation>
roots;
95 for (std::size_t index = 1; index <
roots.size(); ++index) {
97 std::size_t position = index;
98 while (position > 0) {
101 if (comparison.value() <= 0)
break;
102 roots[position] = std::move(
roots[position - 1]);
105 roots[position] = std::move(current);
113 if (factors.empty() && polynomial.
degree() >= 6) {
116 factors = std::move(factor_result.value().value);
118 if (factors.empty()) factors = {polynomial};
119 std::size_t factored_degree = 0;
120 bool strict_factorization = factors.size() > 1;
121 for (
auto& factor : factors) {
122 factor = factor.square_free_part().make_monic();
123 factor.variable_name =
"_root";
124 if (factor.degree() <= 0 || factor.degree() >= polynomial.
degree()) {
125 strict_factorization =
false;
128 factored_degree +=
static_cast<std::size_t
>(factor.degree());
130 if (!strict_factorization ||
131 factored_degree !=
static_cast<std::size_t
>(polynomial.
degree())) factors.clear();
136 const std::vector<Poly>& factors, std::size_t degree,
138 std::vector<RootIsolation> combined;
139 combined.reserve(degree);
140 for (
const auto& factor : factors) {
143 combined.insert(combined.end(),
144 std::make_move_iterator(factor_roots.value().begin()),
145 std::make_move_iterator(factor_roots.value().end()));
157 const std::size_t real_count = real_roots.value().size();
158 const std::size_t degree =
static_cast<std::size_t
>(polynomial.
degree());
159 if (real_count > degree) {
163 std::vector<RootIsolation> result;
164 result.reserve(degree);
165 for (std::size_t index = 0; index < real_count; ++index) {
167 polynomial, real_roots.value()[index].first,
168 real_roots.value()[index].second, index, 1}});
170 if (real_count == degree) {
177 for (
auto& isolation : complex_roots.value()) result.push_back(std::move(isolation));
178 if (result.size() != degree) {
181 "certified root isolation did not cover the polynomial degree",
operation);
187 const Poly& polynomial, std::vector<RootIsolation>
roots, std::size_t step_cost) {
200 const std::size_t starting_steps =
context.steps_used();
204 if (input.
degree() <= 0) {
207 "exact root isolation requires a nonconstant polynomial",
operation);
211 for (
const auto& entry : root_isolation_cache) {
212 if (!same_polynomial(entry.polynomial, polynomial))
continue;
213 const std::size_t remaining_cost = entry.step_cost > 0 ? entry.step_cost - 1 : 0;
214 auto cached_step =
context.consume_steps(remaining_cost,
operation +
".cache");
218 auto factors = strict_factors(polynomial,
context);
222 : isolate_factors(factors.value(),
static_cast<std::size_t
>(polynomial.degree()),
225 return remember_isolations(polynomial, std::move(
roots.
value()),
226 context.steps_used() - starting_steps);
227 }
catch (
const std::bad_alloc&) {
230 }
catch (
const std::exception& error) {
245 "RootOf index exceeds the number of distinct roots",
std::string variable_name
变量名
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
Polynomial square_free_part() const
计算无平方因子部分
int degree() const
获取多项式的次数
Polynomial make_monic() const
首一化(使首项系数为 1)
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< std::vector< Poly > > strict_factors(const Poly &polynomial, ComputationContext &context)
bool same_polynomial(const Poly &left, const Poly &right)
Result< std::vector< RootIsolation > > isolate_unfactored(const Poly &polynomial, ComputationContext &context, const std::string &operation)
std::vector< Poly > factor_biquadratic(const Poly &polynomial)
Result< std::vector< RootIsolation > > isolate_factors(const std::vector< Poly > &factors, std::size_t degree, ComputationContext &context, const std::string &operation)
std::vector< RootIsolationCacheEntry > root_isolation_cache
std::optional< Rational > exact_rational_square_root(const Rational &value)
Result< int > compare_isolations(const RootIsolation &left, const RootIsolation &right, ComputationContext &context)
std::vector< RootIsolation > roots
Result< std::vector< RootIsolation > > remember_isolations(const Poly &polynomial, std::vector< RootIsolation > roots, std::size_t step_cost)
Result< void > order_isolations(std::vector< RootIsolation > &roots, ComputationContext &context)
Poly clear_denominators(Poly polynomial)
Polynomial< Rational > Poly
Result< std::vector< ComplexIsolation > > isolate_nonreal_roots(const Poly &polynomial, std::size_t complex_count, ComputationContext &context, const std::string &operation)
std::variant< RealIsolation, ComplexIsolation > RootIsolation
Result< std::vector< RationalInterval > > isolate_real_roots_exact(const Polynomial< Rational > &polynomial, ComputationContext &context, const std::string &operation)
Result< RootIsolation > isolate_exact_root(const ExactRootId &root, ComputationContext &context, const std::string &operation)
Result< int > compare_exact_real_algebraic(ExactRealAlgebraic lhs, ExactRealAlgebraic rhs, ComputationContext &context)
Result< std::vector< RootIsolation > > isolate_exact_roots(const Polynomial< Rational > &input, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
std::size_t std::size_t ComputationContext & context
const VectorField const VectorField & c
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
ExprSetResult roots(const ExprPtr &expression, const std::string &variable, ComputationContext &context, const SolveOptions &options)
const std::string const ExprPtr & value
const ExprPtr & denominator
Polynomial< Rational > polynomial