LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
integration_rational_coefficients.cpp
浏览该文件的文档.
3
4namespace LMCAS {
5
6namespace {
7using RationalFactors = std::vector<std::pair<Polynomial<Rational>, int>>;
8
10 std::vector<size_t>& unknown_offset_per_term, size_t& num_unknowns) {
11 for (size_t i = 0; i < factors.size(); ++i) {
12 unknown_offset_per_term.push_back(num_unknowns);
13 const auto& [fpoly, mult] = factors[i];
14 if (fpoly.degree() == 1) {
15 num_unknowns += static_cast<size_t>(mult);
16 } else if (fpoly.degree() == 2) {
17 num_unknowns += static_cast<size_t>(2 * mult);
18 } else {
19 return false;
20 }
21 }
22 return num_unknowns != 0;
23}
24
26 const Polynomial<Rational>& fpoly, int mult,
27 std::vector<Polynomial<Rational>>& q_over_fpow_l) {
28 const auto& var = Q.variable_name;
29 Polynomial<Rational> remaining = Q;
30 for (int t = 0; t < mult; ++t) {
31 auto qr = remaining.div_mod(fpoly);
32 if (!qr.second.is_zero()) {
33 return false;
34 }
35 remaining = qr.first;
36 }
37 Polynomial<Rational> cur({Rational(1)}, var);
38 for (int l = mult; l >= 1; --l) {
39 Polynomial<Rational> factor_poly = remaining * cur;
40 q_over_fpow_l[l] = factor_poly;
41 cur = cur * fpoly;
42 }
43 return true;
44}
45
46void rd_fill_factor_columns(const Polynomial<Rational>& fpoly, int mult,
47 const std::vector<Polynomial<Rational>>& q_over_fpow_l,
48 size_t col_off, std::vector<std::vector<Rational>>& M) {
49 const size_t rows = M.size();
50 if (fpoly.degree() == 1) {
51 for (int l = 1; l <= mult; ++l) {
52 const auto& qpl = q_over_fpow_l[l];
53 size_t this_col = col_off + static_cast<size_t>(l - 1);
54 for (size_t k = 0; k < rows; ++k) {
55 Rational c = (k < qpl.coeffs.size()) ? qpl.coeffs[k] : Rational(0);
56 M[k][this_col] = c;
57 }
58 }
59 } else if (fpoly.degree() == 2) {
60 for (int l = 1; l <= mult; ++l) {
61 const auto& qpl = q_over_fpow_l[l];
62 size_t base_col = col_off + static_cast<size_t>(2 * (l - 1));
63 size_t b_col = base_col;
64 size_t c_col = base_col + 1;
65 for (size_t k = 0; k < rows; ++k) {
66 Rational c = (k < qpl.coeffs.size()) ? qpl.coeffs[k] : Rational(0);
67 M[k][c_col] = c;
68 }
69 for (size_t k = 0; k < rows; ++k) {
70 if (k == 0) {
71 M[k][b_col] = Rational(0);
72 } else {
73 size_t src = k - 1;
74 Rational c = (src < qpl.coeffs.size()) ? qpl.coeffs[src] : Rational(0);
75 M[k][b_col] = c;
76 }
77 }
78 }
79 }
80}
81
83 const RationalFactors& factors, const std::vector<size_t>& unknown_offset_per_term,
84 std::vector<std::vector<Rational>>& M) {
85 for (size_t i = 0; i < factors.size(); ++i) {
86 const auto& [fpoly, mult] = factors[i];
87 std::vector<Polynomial<Rational>> complements(mult + 1, Polynomial<Rational>(Q.variable_name));
88 if (!rd_factor_complements(Q, fpoly, mult, complements)) { return false; }
89 rd_fill_factor_columns(fpoly, mult, complements, unknown_offset_per_term[i], M);
90 }
91 return true;
92}
93
95 const std::vector<size_t>& unknown_offset_per_term, const std::vector<Rational>& sol,
96 const std::string& var, std::vector<Polynomial<Rational>>& numerators_out) {
97 for (size_t i = 0; i < factors.size(); ++i) {
98 const auto& [fpoly, mult] = factors[i];
99 size_t col_off = unknown_offset_per_term[i];
100 if (fpoly.degree() == 1) {
101 for (int l = 1; l <= mult; ++l) {
102 Rational A = sol[col_off + static_cast<size_t>(l - 1)];
103 numerators_out.push_back(Polynomial<Rational>({A}, var));
104 }
105 } else { /** @brief 二次因子。 */
106 for (int l = 1; l <= mult; ++l) {
107 size_t base_col = col_off + static_cast<size_t>(2 * (l - 1));
108 Rational B = sol[base_col];
109 Rational C = sol[base_col + 1];
110 numerators_out.push_back(
111 Polynomial<Rational>({C, B}, var));
112 }
113 }
114 }
115}
116}
117
119 const Polynomial<Rational>& P,
120 const Polynomial<Rational>& Q,
121 const std::vector<std::pair<Polynomial<Rational>, int>>& factors,
122 std::vector<Polynomial<Rational>>& numerators_out,
124
125 numerators_out.clear();
126
127 size_t num_unknowns = 0;
128 std::vector<size_t> unknown_offset_per_term;
129 unknown_offset_per_term.reserve(factors.size());
130 if (!rd_unknown_offsets(factors, unknown_offset_per_term, num_unknowns)) { return false; }
131 int N = Q.degree();
132 if (N < 0) { return false; }
133 size_t rows = static_cast<size_t>(N);
134 size_t cols = num_unknowns + 1; /**< P 的增广列。 */
135
136 std::vector<std::vector<Rational>> M(rows, std::vector<Rational>(cols, Rational(0)));
137 if (P.degree() >= N) { return false; }
138 for (size_t k = 0; k < rows; ++k) {
139 Rational c = (k < P.coeffs.size()) ? P.coeffs[k] : Rational(0);
140 M[k][num_unknowns] = c;
141 }
142
143 if (!rd_fill_coefficient_matrix(Q, factors, unknown_offset_per_term, M)) { return false; }
144 std::vector<Rational> augmented;
145 augmented.reserve(rows * cols);
146 for (const auto& row : M) {
147 augmented.insert(augmented.end(), row.begin(), row.end());
148 }
149 auto solved = detail::solve_rational_unique(
150 rows, num_unknowns, std::move(augmented), context,
151 "integrate.rational.coefficients");
152 if (!solved) {
153 if (solved.error().code == CasErrc::Inconclusive ||
154 solved.error().code == CasErrc::DomainError) {
155 return false;
156 }
157 return Result<bool>::failure(solved.error());
158 }
159 auto sol = std::move(solved.value());
160 numerators_out.reserve(num_unknowns);
161 rd_unpack_numerators(factors, unknown_offset_per_term, sol, Q.variable_name, numerators_out);
162 return true;
163}
164
165}
一元多项式模板类
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::string variable_name
变量名
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
static Result failure(CasErrc code, std::string message, std::string operation={})
void rd_fill_factor_columns(const Polynomial< Rational > &fpoly, int mult, const std::vector< Polynomial< Rational > > &q_over_fpow_l, size_t col_off, std::vector< std::vector< Rational > > &M)
bool rd_fill_coefficient_matrix(const Polynomial< Rational > &Q, const RationalFactors &factors, const std::vector< size_t > &unknown_offset_per_term, std::vector< std::vector< Rational > > &M)
void rd_unpack_numerators(const RationalFactors &factors, const std::vector< size_t > &unknown_offset_per_term, const std::vector< Rational > &sol, const std::string &var, std::vector< Polynomial< Rational > > &numerators_out)
bool rd_unknown_offsets(const RationalFactors &factors, std::vector< size_t > &unknown_offset_per_term, size_t &num_unknowns)
bool rd_factor_complements(const Polynomial< Rational > &Q, const Polynomial< Rational > &fpoly, int mult, std::vector< Polynomial< Rational > > &q_over_fpow_l)
Result< std::vector< Rational > > solve_rational_unique(std::size_t rows, std::size_t coefficient_columns, std::vector< Rational > matrix, ComputationContext &context, const std::string &operation)
std::size_t std::size_t ComputationContext & context
Result< bool > solve_coefficients(const Polynomial< Rational > &numerator, const Polynomial< Rational > &denominator, const std::vector< std::pair< Polynomial< Rational >, int > > &factors, std::vector< Polynomial< Rational > > &numerators, ComputationContext &context)
const VectorField const VectorField & c
__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