LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
limit_visitor_core.cpp
浏览该文件的文档.
4
5#include <cmath>
6#include <iostream>
7#include <limits>
8#include <optional>
9#include <utility>
10
11namespace LMCAS {
12
13int& LimitVisitor::active_limit_depth() {
14 static thread_local int depth = 0;
15 return depth;
16}
17
18std::shared_ptr<const SymbolicNode> LimitVisitor::make_product_or_one(
19 const std::vector<std::shared_ptr<const SymbolicNode>>& factors) {
20 if (factors.empty()) {
22 }
23 if (factors.size() == 1) {
24 return factors[0];
25 }
27}
28
29LimitVisitor::EvaluationScope::EvaluationScope() {
30 if (LimitVisitor::active_limit_depth() < LimitVisitor::max_active_limit_depth) {
31 ++LimitVisitor::active_limit_depth();
32 entered = true;
33 }
34}
35
36LimitVisitor::EvaluationScope::~EvaluationScope() {
37 if (entered) --LimitVisitor::active_limit_depth();
38}
39
40std::shared_ptr<const SymbolicNode> LimitVisitor::get_result() const { return result; }
41
42void LimitVisitor::visit(const NumberNode& node) { result = node.clone(); }
43
44void LimitVisitor::visit(const VariableNode& node) {
45 result = !node.is_constant() && node.name() == var ? point->clone() : node.clone();
46}
47
48void LimitVisitor::visit(const MatrixNode& node) {
49 if (const auto* dense =
50 std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
52 entries.reserve(dense->size());
53 for (const auto& entry : *dense) {
54 entry->accept(*this);
55 entries.push_back(result);
56 }
58 node.rows(), node.cols(), std::move(entries));
59 return;
60 }
62 for (const auto& [index, entry] :
63 std::get<MatrixNode::SparseStorage>(node.storage())) {
64 entry->accept(*this);
65 entries.emplace(index, result);
66 }
68 node.rows(), node.cols(), std::move(entries));
69}
70
71void LimitVisitor::visit(const RelationalNode& node) {
72 node.left()->accept(*this);
73 auto left = result;
74 node.right()->accept(*this);
75 result = LMCAS::detail::make_node<RelationalNode>(left, result, node.op());
76}
77
78void LimitVisitor::visit(const LogicalNode& node) {
79 node.left()->accept(*this);
80 auto left = result;
81 std::shared_ptr<const SymbolicNode> right;
82 if (node.right()) {
83 node.right()->accept(*this);
84 right = result;
85 }
87}
88
89void LimitVisitor::visit(const SummationNode& node) {
90 node.lower_bound()->accept(*this);
91 auto lower = result;
92 node.upper_bound()->accept(*this);
93 auto upper = result;
94 auto body = node.body();
95 if (node.index_var() != var) {
96 body->accept(*this);
97 body = result;
98 }
100 body, node.index_var(), lower, upper);
101}
102void LimitVisitor::visit(const ProductNode& node) {
103 node.lower_bound()->accept(*this);
104 auto lower = result;
105 node.upper_bound()->accept(*this);
106 auto upper = result;
107 auto body = node.body();
108 if (node.index_var() != var) {
109 body->accept(*this);
110 body = result;
111 }
113 body, node.index_var(), lower, upper);
114}
115void LimitVisitor::visit(const TransformNode& node) {
116 node.target()->accept(*this);
117 auto target = result;
118 auto body = node.body();
119 if (node.source_var() != var) {
120 body->accept(*this);
121 body = result;
122 }
124 node.transform_type(), body, node.source_var(), target);
125}
126void LimitVisitor::visit(const QuantifierNode& node) {
127 node.domain()->accept(*this);
128 auto domain = result;
129 auto predicate = node.predicate();
130 if (node.bound_var() != var) {
131 predicate->accept(*this);
132 predicate = result;
133 }
135 node.quantifier_type(), node.bound_var(), domain, predicate);
136}
137void LimitVisitor::visit(const SetBuilderNode& node) {
138 node.domain()->accept(*this);
139 auto domain = result;
140 auto predicate = node.predicate();
141 if (node.element_var() != var) {
142 predicate->accept(*this);
143 predicate = result;
144 }
146 node.element_var(), domain, predicate);
147}
148void LimitVisitor::visit(const FiniteSetNode& node) {
149 std::vector<std::shared_ptr<const SymbolicNode>> elements;
150 elements.reserve(node.elements().size());
151 for (const auto& element : node.elements()) {
152 element->accept(*this);
153 elements.push_back(result);
154 }
155 result = LMCAS::detail::make_node<FiniteSetNode>(std::move(elements));
156}
157void LimitVisitor::visit(const IntervalNode& node) {
158 node.lower()->accept(*this);
159 auto lower = result;
160 node.upper()->accept(*this);
162 lower, result, node.lower_closed(), node.upper_closed());
163}
164void LimitVisitor::visit(const MembershipNode& node) {
165 node.element()->accept(*this);
166 auto element = result;
167 node.set()->accept(*this);
169}
170void LimitVisitor::visit(const UninterpretedFunctionNode& node) {
171 std::vector<std::shared_ptr<const SymbolicNode>> arguments;
172 arguments.reserve(node.arguments().size());
173 for (const auto& argument : node.arguments()) {
174 argument->accept(*this);
175 arguments.push_back(result);
176 }
178 node.name(), std::move(arguments));
179}
180void LimitVisitor::visit(const IntegralNode& node) {
181 std::shared_ptr<const SymbolicNode> lower;
182 std::shared_ptr<const SymbolicNode> upper;
183 if (node.lower()) {
184 node.lower()->accept(*this);
185 lower = result;
186 node.upper()->accept(*this);
187 upper = result;
188 }
189 auto body = node.body();
190 if (node.variable() != var) {
191 body->accept(*this);
192 body = result;
193 }
195 body, node.variable(), lower, upper);
196}
197void LimitVisitor::visit(const LimitNode& node) {
198 node.point()->accept(*this);
199 auto nested_point = result;
200 auto body = node.body();
201 if (node.variable() != var) {
202 body->accept(*this);
203 body = result;
204 }
206 body, node.variable(), nested_point, node.direction());
207}
208void LimitVisitor::visit(const RootOfNode& node) {
209 result = node.clone();
210}
211void LimitVisitor::visit(const QuantityNode& node) {
212 node.value()->accept(*this);
214 result, node.dimension(), node.scale_to_base(), node.display_unit());
215}
216
217void LimitVisitor::visit(const ComplexNode& node) {
218 node.real()->accept(*this);
219 auto real = result;
220 node.imag()->accept(*this);
221 result = SymbolicFactory::create_complex(real, result);
222}
223
224} // namespace LMCAS
复数节点,表示 real + imag * i。
矩阵节点,支持稠密和稀疏两种存储方式。
std::map< size_t, std::shared_ptr< const SymbolicNode > > SparseStorage
稀疏存储,索引映射到节点。
std::vector< std::shared_ptr< const SymbolicNode > > DenseStorage
稠密存储,按行优先展开。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
static std::shared_ptr< const SymbolicNode > create_complex(std::shared_ptr< const SymbolicNode > real, std::shared_ptr< const SymbolicNode > imag)
创建复数节点,自动简化(若虚部为 0,则返回实部).
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
变量节点,表示一个符号变量。
微分访问器,对 AST 执行符号求导。
极限访问器,通过代入和 L'Hôpital 法则计算极限。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
const std::string const LimitExprPtr & point
const ExprPtr & element
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const ExprPtr & lower
std::size_t std::size_t depth
const NumberDomainSet & domain
const ExprPtr & target
const ExprPtr & right
符号规范化访问器接口。