LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
ode_polynomial_utils.hpp
浏览该文件的文档.
1
#pragma once
2
3
#include <algorithm>
4
#include <cmath>
5
#include <utility>
6
#include <vector>
7
8
namespace
LMCAS::ode_root_detail
{
9
10
using
RealPolynomial
= std::vector<double>;
11
12
struct
CharRoot
{
13
double
real_part
;
14
double
imag_part
;
15
int
multiplicity
;
16
bool
is_complex
;
17
};
18
19
struct
Complex
{
20
double
re
;
21
double
im
;
22
23
Complex
(
double
real
= 0.0,
double
imaginary = 0.0)
24
:
re
(
real
),
im
(imaginary) {}
25
Complex
operator*
(
const
Complex
& other)
const
{
26
return
{
re
* other.
re
-
im
* other.
im
,
27
re
* other.
im
+
im
* other.
re
};
28
}
29
Complex
operator+
(
const
Complex
& other)
const
{
30
return
{
re
+ other.
re
,
im
+ other.
im
};
31
}
32
Complex
operator-
(
const
Complex
& other)
const
{
33
return
{
re
- other.
re
,
im
- other.
im
};
34
}
35
Complex
operator/
(
const
Complex
& other)
const
{
36
const
double
denominator
=
37
other.
re
* other.
re
+ other.
im
* other.
im
;
38
if
(
denominator
< 1
e
-300) {
39
return
{INFINITY, INFINITY};
40
}
41
return
{(
re
* other.
re
+
im
* other.
im
) /
denominator
,
42
(
im
* other.
re
-
re
* other.
im
) /
denominator
};
43
}
44
double
magnitude
()
const
{
45
return
std::hypot(
re
,
im
);
46
}
47
};
48
49
inline
bool
is_exact_zero_polynomial_root
(
50
const
RealPolynomial
& coefficients,
const
Complex
& root) {
51
return
root.
re
== 0.0 && root.
im
== 0.0 && coefficients.back() == 0.0;
52
}
53
54
inline
double
polynomial_root_backward_error
(
55
const
RealPolynomial
& coefficients,
const
Complex
& root) {
56
Complex
value
{coefficients.front(), 0.0};
57
double
scale = std::abs(coefficients.front());
58
const
double
root_magnitude = root.
magnitude
();
59
for
(
size_t
i = 1; i < coefficients.size(); ++i) {
60
value
=
value
* root +
Complex
{coefficients[i], 0.0};
61
scale = scale * root_magnitude + std::abs(coefficients[i]);
62
}
63
if
(!std::isfinite(
value
.re) || !std::isfinite(
value
.im) ||
64
!std::isfinite(scale)) {
65
return
INFINITY;
66
}
67
if
(scale == 0.0) {
68
// At an exact zero root with zero constant term, both the residual
69
// and its coefficientwise bound vanish: no perturbation is needed.
70
// A nonzero root can instead underflow the bound, which is not proof.
71
return
is_exact_zero_polynomial_root
(coefficients, root)
72
? 0.0 : INFINITY;
73
}
74
return
value
.magnitude() / scale;
75
}
76
77
inline
double
polynomial_scale
(
const
RealPolynomial
& polynomial) {
78
double
scale = 0.0;
79
for
(
double
coefficient : polynomial) {
80
scale = std::max(scale, std::abs(coefficient));
81
}
82
return
scale;
83
}
84
85
inline
void
trim_polynomial
(
RealPolynomial
& polynomial) {
86
const
double
scale =
polynomial_scale
(polynomial);
87
const
double
tolerance = std::max(1.0, scale) * 1
e
-10;
88
auto
first = polynomial.begin();
89
while
(first + 1 != polynomial.end() && std::abs(*first) <= tolerance) {
90
++first;
91
}
92
polynomial.erase(polynomial.begin(), first);
93
if
(polynomial.empty()) {
94
polynomial.push_back(0.0);
95
}
96
}
97
98
inline
std::pair<RealPolynomial, RealPolynomial>
divide_polynomials
(
99
const
RealPolynomial
& dividend,
const
RealPolynomial
& divisor) {
100
if
(divisor.empty() || divisor.front() == 0.0 ||
101
dividend.size() < divisor.size()) {
102
return
{{0.0}, dividend};
103
}
104
105
RealPolynomial
remainder = dividend;
106
RealPolynomial
quotient(
107
dividend.size() - divisor.size() + 1, 0.0);
108
for
(
size_t
i = 0; i < quotient.size(); ++i) {
109
const
double
factor = remainder[i] / divisor.front();
110
quotient[i] = factor;
111
for
(
size_t
j = 0; j < divisor.size(); ++j) {
112
remainder[i + j] -= factor * divisor[j];
113
}
114
}
115
remainder.erase(
116
remainder.begin(), remainder.begin() + quotient.size());
117
if
(remainder.empty()) {
118
remainder.push_back(0.0);
119
}
120
trim_polynomial
(quotient);
121
trim_polynomial
(remainder);
122
return
{std::move(quotient), std::move(remainder)};
123
}
124
125
inline
RealPolynomial
monic_polynomial
(
RealPolynomial
polynomial) {
126
trim_polynomial
(polynomial);
127
if
(polynomial.empty() || polynomial.front() == 0.0) {
128
return
{0.0};
129
}
130
const
double
leading = polynomial.front();
131
for
(
double
& coefficient : polynomial) coefficient /= leading;
132
return
polynomial;
133
}
134
135
inline
RealPolynomial
polynomial_derivative
(
136
const
RealPolynomial
& polynomial) {
137
if
(polynomial.size() <= 1) {
138
return
{0.0};
139
}
140
RealPolynomial
derivative;
141
derivative.reserve(polynomial.size() - 1);
142
const
size_t
degree = polynomial.size() - 1;
143
for
(
size_t
i = 0; i < degree; ++i) {
144
derivative.push_back(
145
polynomial[i] *
static_cast<
double
>
(degree - i));
146
}
147
return
derivative;
148
}
149
150
inline
RealPolynomial
approximate_polynomial_gcd
(
151
RealPolynomial
lhs,
RealPolynomial
rhs
) {
152
lhs =
monic_polynomial
(std::move(lhs));
153
rhs
=
monic_polynomial
(std::move(
rhs
));
154
for
(
int
iteration = 0; iteration < 8 &&
rhs
.size() > 1; ++iteration) {
155
auto
division =
divide_polynomials
(lhs,
rhs
);
156
RealPolynomial
remainder = std::move(division.second);
157
if
(remainder.size() == 1 && remainder.front() == 0.0) {
158
return
rhs
;
159
}
160
lhs = std::move(
rhs
);
161
rhs
=
monic_polynomial
(std::move(remainder));
162
}
163
return
{1.0};
164
}
165
166
inline
bool
polynomial_remainder_is_small
(
167
const
RealPolynomial
& remainder,
const
RealPolynomial
& dividend) {
168
return
polynomial_scale
(remainder) <=
169
std::max(1.0,
polynomial_scale
(dividend)) * 1
e
-7;
170
}
171
172
}
LMCAS::ode_root_detail
定义
ode_characteristic_roots.hpp:9
LMCAS::ode_root_detail::divide_polynomials
std::pair< RealPolynomial, RealPolynomial > divide_polynomials(const RealPolynomial ÷nd, const RealPolynomial &divisor)
定义
ode_polynomial_utils.hpp:98
LMCAS::ode_root_detail::polynomial_derivative
RealPolynomial polynomial_derivative(const RealPolynomial &polynomial)
定义
ode_polynomial_utils.hpp:135
LMCAS::ode_root_detail::polynomial_root_backward_error
double polynomial_root_backward_error(const RealPolynomial &coefficients, const Complex &root)
定义
ode_polynomial_utils.hpp:54
LMCAS::ode_root_detail::CharRoot::real_part
double real_part
定义
ode_polynomial_utils.hpp:13
LMCAS::ode_root_detail::trim_polynomial
void trim_polynomial(RealPolynomial &polynomial)
定义
ode_polynomial_utils.hpp:85
LMCAS::ode_root_detail::monic_polynomial
RealPolynomial monic_polynomial(RealPolynomial polynomial)
定义
ode_polynomial_utils.hpp:125
LMCAS::ode_root_detail::is_exact_zero_polynomial_root
bool is_exact_zero_polynomial_root(const RealPolynomial &coefficients, const Complex &root)
定义
ode_polynomial_utils.hpp:49
LMCAS::ode_root_detail::approximate_polynomial_gcd
RealPolynomial approximate_polynomial_gcd(RealPolynomial lhs, RealPolynomial rhs)
定义
ode_polynomial_utils.hpp:150
LMCAS::ode_root_detail::polynomial_scale
double polynomial_scale(const RealPolynomial &polynomial)
定义
ode_polynomial_utils.hpp:77
LMCAS::ode_root_detail::RealPolynomial
std::vector< double > RealPolynomial
定义
ode_polynomial_utils.hpp:10
LMCAS::ode_root_detail::polynomial_remainder_is_small
bool polynomial_remainder_is_small(const RealPolynomial &remainder, const RealPolynomial ÷nd)
定义
ode_polynomial_utils.hpp:166
LMCAS::ode_root_detail::CharRoot::imag_part
double imag_part
定义
ode_polynomial_utils.hpp:14
LMCAS::ode_root_detail::CharRoot::multiplicity
int multiplicity
定义
ode_polynomial_utils.hpp:15
LMCAS::ode_root_detail::CharRoot::is_complex
bool is_complex
定义
ode_polynomial_utils.hpp:16
LMCAS::ode_root_detail::CharRoot
定义
ode_polynomial_utils.hpp:12
LMCAS::e
ExprResult e()
定义
expr_values.cpp:112
LMCAS::real
ExprResult real(const ExprPtr &expression, ComputationContext &context)
定义
expr_arithmetic.cpp:98
LMCAS::value
const std::string const ExprPtr & value
定义
expr.hpp:293
LMCAS::rhs
const ExprPtr & rhs
定义
expr.hpp:150
LMCAS::denominator
const ExprPtr & denominator
定义
expr.hpp:200
LMCAS::ode_root_detail::Complex
定义
ode_polynomial_utils.hpp:19
LMCAS::ode_root_detail::Complex::operator-
Complex operator-(const Complex &other) const
定义
ode_polynomial_utils.hpp:32
LMCAS::ode_root_detail::Complex::operator*
Complex operator*(const Complex &other) const
定义
ode_polynomial_utils.hpp:25
LMCAS::ode_root_detail::Complex::magnitude
double magnitude() const
定义
ode_polynomial_utils.hpp:44
LMCAS::ode_root_detail::Complex::operator/
Complex operator/(const Complex &other) const
定义
ode_polynomial_utils.hpp:35
LMCAS::ode_root_detail::Complex::re
double re
定义
ode_polynomial_utils.hpp:20
LMCAS::ode_root_detail::Complex::im
double im
定义
ode_polynomial_utils.hpp:21
LMCAS::ode_root_detail::Complex::Complex
Complex(double real=0.0, double imaginary=0.0)
定义
ode_polynomial_utils.hpp:23
LMCAS::ode_root_detail::Complex::operator+
Complex operator+(const Complex &other) const
定义
ode_polynomial_utils.hpp:29
src
internal
ode_polynomial_utils.hpp
生成于
, 为 LMCAS使用
1.18.0