13int& LimitVisitor::active_limit_depth() {
14 static thread_local int depth = 0;
18std::shared_ptr<const SymbolicNode> LimitVisitor::make_product_or_one(
19 const std::vector<std::shared_ptr<const SymbolicNode>>& factors) {
20 if (factors.empty()) {
23 if (factors.size() == 1) {
29LimitVisitor::EvaluationScope::EvaluationScope() {
30 if (LimitVisitor::active_limit_depth() < LimitVisitor::max_active_limit_depth) {
31 ++LimitVisitor::active_limit_depth();
36LimitVisitor::EvaluationScope::~EvaluationScope() {
37 if (entered) --LimitVisitor::active_limit_depth();
40std::shared_ptr<const SymbolicNode> LimitVisitor::get_result()
const {
return result; }
42void LimitVisitor::visit(
const NumberNode& node) { result =
node.clone(); }
45 result = !
node.is_constant() &&
node.name() == var ?
point->clone() :
node.clone();
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) {
55 entries.push_back(result);
58 node.rows(),
node.cols(), std::move(entries));
62 for (
const auto& [index, entry] :
63 std::get<MatrixNode::SparseStorage>(
node.storage())) {
65 entries.emplace(index, result);
68 node.rows(),
node.cols(), std::move(entries));
81 std::shared_ptr<const SymbolicNode>
right;
94 auto body =
node.body();
95 if (
node.index_var() != var) {
107 auto body =
node.body();
108 if (
node.index_var() != var) {
118 auto body =
node.body();
119 if (
node.source_var() != var) {
129 auto predicate =
node.predicate();
130 if (
node.bound_var() != var) {
131 predicate->accept(*
this);
140 auto predicate =
node.predicate();
141 if (
node.element_var() != var) {
142 predicate->accept(*
this);
149 std::vector<std::shared_ptr<const SymbolicNode>> elements;
150 elements.reserve(
node.elements().size());
153 elements.push_back(result);
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);
178 node.name(), std::move(arguments));
181 std::shared_ptr<const SymbolicNode>
lower;
182 std::shared_ptr<const SymbolicNode>
upper;
189 auto body =
node.body();
190 if (
node.variable() != var) {
197void LimitVisitor::visit(
const LimitNode& node) {
199 auto nested_point = result;
200 auto body =
node.body();
201 if (
node.variable() != var) {
206 body,
node.variable(), nested_point,
node.direction());
208void LimitVisitor::visit(
const RootOfNode& node) {
209 result =
node.clone();
214 result,
node.dimension(),
node.scale_to_base(),
node.display_unit());
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
极限访问器,通过代入和 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
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
ExprResult real(const ExprPtr &expression, ComputationContext &context)
std::size_t std::size_t depth
const NumberDomainSet & domain