14 for (
const int current : signs) {
15 if (current == 0)
continue;
16 if (previous != 0 && current != previous) ++changes;
24 const Rational&
point) {
25 if (polynomial.
is_zero())
return 0;
26 const int degree = polynomial.
degree();
27 const BigInt numerator =
point.get_numerator();
29 BigInt coefficient_denominator(1);
30 for (
const auto& coefficient : polynomial.
coeffs) {
31 coefficient_denominator *= coefficient.get_denominator();
33 std::vector<BigInt> numerator_powers(
34 static_cast<std::size_t
>(degree) + 1, BigInt(1));
35 std::vector<BigInt> denominator_powers(
36 static_cast<std::size_t
>(degree) + 1, BigInt(1));
38 numerator_powers[
static_cast<std::size_t
>(
exponent)] =
39 numerator_powers[
static_cast<std::size_t
>(
exponent - 1)] *
41 denominator_powers[
static_cast<std::size_t
>(
exponent)] =
42 denominator_powers[
static_cast<std::size_t
>(
exponent - 1)] *
47 const auto& coefficient =
49 if (coefficient == Rational(0))
continue;
50 value += coefficient.get_numerator() *
51 (coefficient_denominator / coefficient.get_denominator()) *
52 numerator_powers[
static_cast<std::size_t
>(
exponent)] *
54 static_cast<std::size_t
>(degree -
exponent)];
56 if (
value == BigInt(0))
return 0;
57 return value < BigInt(0) ? -1 : 1;
68 if (polynomial.
degree() <= 0) {
74 sequence.push_back(polynomial);
76 while (!sequence.back().is_zero()) {
79 const auto& dividend = sequence[sequence.size() - 2];
80 const auto& divisor = sequence.back();
81 auto division = dividend.div_mod(divisor);
82 auto remainder = std::move(division.second);
83 if (remainder.is_zero())
break;
84 for (
auto& coefficient : remainder.coeffs) coefficient = -coefficient;
86 sequence.push_back(std::move(remainder));
88 if (!sequence.empty() && sequence.back().is_zero()) sequence.pop_back();
94 const Rational&
point,
99 std::vector<int> signs;
100 signs.reserve(sequence.size());
101 for (
const auto&
member : sequence) {
110 const Rational&
lower,
111 const Rational&
upper,
118 if (!lower_variations) {
122 if (!upper_variations) {
125 int count = lower_variations.value() - upper_variations.value();
130 "Sturm variation produced a negative open-interval count",
156 auto half = lower_is_root
162 if (lower_is_root == (half.value() == 1)) {
176 const Rational midpoint = (current.
lower + current.
upper) / Rational(2);
184 const std::size_t accounted = left.value() +
right.value() +
185 (midpoint_is_root ? 1U : 0U);
186 if (accounted != current.
count) {
189 "Sturm subdivision did not preserve the root count",
operation);
191 if (
right.value() != 0) {
192 pending.push_back({midpoint, current.
upper,
right.value()});
194 if (midpoint_is_root) isolated.emplace_back(midpoint, midpoint);
195 if (left.value() != 0) {
196 pending.push_back({current.
lower, midpoint, left.value()});
207 std::vector<PendingInterval> pending;
208 std::vector<RationalInterval> isolated;
209 if (total.value() != 0) pending.push_back({-bound, bound, total.value()});
210 isolated.reserve(total.value());
211 while (!pending.empty()) {
216 if (current.
count == 1) {
220 isolated.emplace_back(current.
lower, current.
upper);
227 std::sort(isolated.begin(), isolated.end(),
229 if (left.first != right.first) return left.first < right.first;
230 return left.second < right.second;
232 if (isolated.size() != total.value()) {
235 "Sturm isolation lost a distinct real root",
operation);
244 const Rational&
lower,
245 const Rational&
upper,
251 "real-root interval bounds must be ordered",
257 if (polynomial.
degree() <= 0) {
263 polynomial_sign_at(square_free,
lower) == 0 ? 1U : 0U);
267 auto interior = count_open_roots(
269 if (!interior)
return interior;
270 std::size_t count = interior.value();
271 if (polynomial_sign_at(square_free,
lower) == 0) ++count;
272 if (polynomial_sign_at(square_free,
upper) == 0) ++count;
274 }
catch (
const std::bad_alloc&) {
277 "Sturm root counting allocation failed",
279 }
catch (
const std::exception& error) {
291 if (polynomial.
degree() <= 0) {
294 if (polynomial.
degree() == 1) {
295 const Rational root = -polynomial.
coeffs[0] / polynomial.
coeffs[1];
303 return isolate_sturm_sequence(square_free, sequence.value(),
context,
operation);
304 }
catch (
const std::bad_alloc&) {
307 "Sturm root isolation allocation failed",
operation);
308 }
catch (
const std::exception& error) {
Polynomial differentiate() const
求导
bool is_zero() const
判断是否为零多项式
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< void > clear_isolation_endpoints(const Polynomial< Rational > &square_free, const SturmSequence &sequence, PendingInterval &interval, ComputationContext &context, const std::string &operation)
Result< std::size_t > count_open_roots(const Polynomial< Rational > &square_free, const SturmSequence &sequence, const Rational &lower, const Rational &upper, ComputationContext &context, const std::string &operation)
Result< SturmSequence > make_sturm_sequence(Polynomial< Rational > polynomial, ComputationContext &context, const std::string &operation)
int sign_changes(const std::vector< int > &signs)
std::vector< Polynomial< Rational > > SturmSequence
Result< int > variations_at(const SturmSequence &sequence, const Rational &point, ComputationContext &context, const std::string &operation)
Result< std::vector< RationalInterval > > isolate_sturm_sequence(const Polynomial< Rational > &square_free, const SturmSequence &sequence, ComputationContext &context, const std::string &operation)
Result< void > subdivide_isolation(const Polynomial< Rational > &square_free, const SturmSequence &sequence, const PendingInterval ¤t, std::vector< PendingInterval > &pending, std::vector< RationalInterval > &isolated, ComputationContext &context, const std::string &operation)
int polynomial_sign_at(const Polynomial< Rational > &polynomial, const Rational &point)
Result< std::vector< RationalInterval > > isolate_real_roots_exact(const Polynomial< Rational > &polynomial, ComputationContext &context, const std::string &operation)
Result< std::size_t > count_real_roots_exact(const Polynomial< Rational > &polynomial, const Rational &lower, const Rational &upper, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
std::pair< Rational, Rational > RationalInterval
std::size_t std::size_t ComputationContext & context
Rational strict_cauchy_root_bound(const Polynomial< Rational > &polynomial)
const std::string const LimitExprPtr & point
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
ExprResult member(const ExprPtr &element, const ExprPtr &set, ComputationContext &context)
const std::string const ExprPtr & value
const ExprPtr & denominator