LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
integration_rational_collection.cpp
浏览该文件的文档.
2
3namespace LMCAS {
4namespace {
5Result<bool> rd_collect_rational(const std::shared_ptr<const SymbolicNode>& node,
6 const std::string& var,
7 std::vector<Polynomial<Rational>>& num,
8 std::vector<Polynomial<Rational>>& den);
9
10Result<bool> rd_collect_sum(const AddNode& add, const std::string& var,
11 std::vector<Polynomial<Rational>>& num, std::vector<Polynomial<Rational>>& den) {
12 std::vector<std::pair<std::vector<Polynomial<Rational>>,
13 std::vector<Polynomial<Rational>>>> parts;
14 parts.reserve(add.operands().size());
15 for (const auto& op : add.operands()) {
16 std::vector<Polynomial<Rational>> sub_num, sub_den;
17 auto collected = rd_collect_rational(op, var, sub_num, sub_den);
18 if (!collected || !collected.value()) { return collected; }
19 parts.push_back({std::move(sub_num), std::move(sub_den)});
20 }
21
22 Polynomial<Rational> total_num(var);
23 Polynomial<Rational> total_den({Rational(1)}, var);
24
25 std::vector<Polynomial<Rational>> Q_per_term;
26 Q_per_term.reserve(parts.size());
27 for (const auto& [pn, pd] : parts) {
28 Polynomial<Rational> q({Rational(1)}, var);
29 for (const auto& d : pd) q = q * d;
30 Q_per_term.push_back(q);
31 total_den = total_den * q;
32 }
33
34 for (size_t i = 0; i < parts.size(); ++i) {
35 Polynomial<Rational> p({Rational(1)}, var);
36 for (const auto& nn : parts[i].first) p = p * nn;
37 for (size_t j = 0; j < parts.size(); ++j) {
38 if (j == i) { continue; }
39 p = p * Q_per_term[j];
40 }
41 total_num = total_num + p;
42 }
43
44 num.push_back(total_num);
45 den.push_back(total_den);
46 return true;
47}
48
49Result<bool> rd_collect_power(const PowerNode& pw, const std::string& var,
50 std::vector<Polynomial<Rational>>& num, std::vector<Polynomial<Rational>>& den) {
51 auto en = std::dynamic_pointer_cast<const NumberNode>(pw.exponent());
52 if (!en) { return false; }
53
54 const auto bounded_exponent = integration_bounded_exponent(*en, -64, 64);
55 if (!bounded_exponent) { return false; }
56
57 std::vector<Polynomial<Rational>> bn, bd;
58 auto collected = rd_collect_rational(pw.base(), var, bn, bd);
59 if (!collected || !collected.value()) { return collected; }
60
61 Polynomial<Rational> base_num({Rational(1)}, var);
62 for (const auto& p : bn) base_num = base_num * p;
63 Polynomial<Rational> base_den({Rational(1)}, var);
64 for (const auto& p : bd) base_den = base_den * p;
65
66 if (*bounded_exponent == 0) {
67 num.push_back(Polynomial<Rational>({Rational(1)}, var));
68 return true;
69 }
70 const int power_count = *bounded_exponent < 0 ? -*bounded_exponent : *bounded_exponent;
71 Polynomial<Rational> n_pow({Rational(1)}, var);
72 Polynomial<Rational> d_pow({Rational(1)}, var);
73 for (int i = 0; i < power_count; ++i) {
74 n_pow = n_pow * base_num;
75 d_pow = d_pow * base_den;
76 }
77 if (*bounded_exponent > 0) {
78 num.push_back(n_pow);
79 den.push_back(d_pow);
80 } else {
81 num.push_back(d_pow);
82 den.push_back(n_pow);
83 }
84 return true;
85}
86
87Result<bool> rd_collect_rational(const std::shared_ptr<const SymbolicNode>& node,
88 const std::string& var,
89 std::vector<Polynomial<Rational>>& num,
90 std::vector<Polynomial<Rational>>& den) {
91 if (!node) { return false; }
92
93 if (auto n = std::dynamic_pointer_cast<const NumberNode>(node)) {
94 auto p = symbolic_to_poly<Rational>(LMCAS::detail::make_expression_ptr(n), var);
95 if (!p) {
96 if (p.error().code == CasErrc::UnsupportedExpression) { return false; }
97 return Result<bool>::failure(p.error());
98 }
99 num.push_back(std::move(p.value()));
100 return true;
101 }
102 if (auto v = std::dynamic_pointer_cast<const VariableNode>(node)) {
103 if (!v->is_constant() && v->name() == var) {
104 num.push_back(Polynomial<Rational>({Rational(0), Rational(1)}, var));
105 return true;
106 }
107 return false;
108 }
109
110 if (auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
111 return rd_collect_sum(*add, var, num, den);
112 }
113 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
114 for (const auto& op : mul->operands()) {
115 auto collected = rd_collect_rational(op, var, num, den);
116 if (!collected || !collected.value()) { return collected; }
117 }
118 return true;
119 }
120
121 if (auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
122 return rd_collect_power(*power, var, num, den);
123 }
124 return false;
125}
126
128 const std::string& var) {
129 if (!P.is_zero()) {
131 if (!g.is_zero() && g.degree() >= 1) {
132 auto pq = P.div_mod(g);
133 auto qq = Q.div_mod(g);
134 if (pq.second.is_zero() && qq.second.is_zero()) {
135 P = pq.first;
136 Q = qq.first;
137 }
138 }
139 }
140
141 if (Q.degree() >= 0) {
142 Rational lc = Q.lead_coeff();
143 if (!(lc == Rational(1)) && !(lc == Rational(0))) {
144 Polynomial<Rational> P_scaled(var);
145 P_scaled.coeffs.reserve(P.coeffs.size());
146 for (const auto& c : P.coeffs) { P_scaled.coeffs.push_back(c / lc); }
147 Polynomial<Rational> Q_scaled(var);
148 Q_scaled.coeffs.reserve(Q.coeffs.size());
149 for (const auto& c : Q.coeffs) { Q_scaled.coeffs.push_back(c / lc); }
150 P_scaled.trim();
151 Q_scaled.trim();
152 P = P_scaled;
153 Q = Q_scaled;
154 }
155 }
156}
157
158}
159
161 const SymbolicExpr& expr, const std::string& var,
163
164 std::vector<Polynomial<Rational>> nums, dens;
165 auto collected = rd_collect_rational(LMCAS::detail::node(expr), var, nums, dens);
166 if (!collected || !collected.value()) { return collected; }
167
168 Polynomial<Rational> P({Rational(1)}, var);
169 for (const auto& p : nums) { P = P * p; }
170 Polynomial<Rational> Q({Rational(1)}, var);
171 for (const auto& p : dens) { Q = Q * p; }
172
173 if (Q.is_zero()) { return false; } /** @brief 分母为零时返回 false。 */
174
175 rd_normalize_fraction(P, Q, var);
176
177 P_out = P;
178 Q_out = Q;
179 return true;
180}
181
182}
加法节点,表示多个操作数的求和。
一元多项式模板类
static Polynomial gcd(Polynomial a, Polynomial b)
计算两个多项式的最大公因式
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
bool is_zero() const
判断是否为零多项式
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
CoeffType lead_coeff() const
获取首项系数
int degree() const
获取多项式的次数
void trim()
去除高次零系数
幂运算节点,表示 base^exponent。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
Result< bool > rd_collect_power(const PowerNode &pw, const std::string &var, std::vector< Polynomial< Rational > > &num, std::vector< Polynomial< Rational > > &den)
Result< bool > rd_collect_rational(const std::shared_ptr< const SymbolicNode > &node, const std::string &var, std::vector< Polynomial< Rational > > &num, std::vector< Polynomial< Rational > > &den)
void rd_normalize_fraction(Polynomial< Rational > &P, Polynomial< Rational > &Q, const std::string &var)
Result< bool > rd_collect_sum(const AddNode &add, const std::string &var, std::vector< Polynomial< Rational > > &num, std::vector< Polynomial< Rational > > &den)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< bool > extract_rational(const SymbolicExpr &expr, const std::string &var, Polynomial< Rational > &numerator, Polynomial< Rational > &denominator)
std::shared_ptr< SymbolicExpr > num(int value)
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const VectorField const VectorField & c
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const ExprPtr RelationOp op
std::optional< int > integration_bounded_exponent(const NumberNode &number, int minimum_exponent, int maximum_exponent)