LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
limit_visitor_product.cpp
浏览该文件的文档.
3
4namespace LMCAS {
5
6std::optional<std::shared_ptr<const SymbolicNode>> LimitVisitor::exact_ratio_at_point(
7 const std::shared_ptr<const SymbolicNode>& num,
8 const std::shared_ptr<const SymbolicNode>& den) {
9 auto nl = exact_leading_at_point(num);
10 auto dl = exact_leading_at_point(den);
11 if (nl && dl && dl->first != Rational(0)) {
12 if (nl->first == Rational(0) || nl->second > dl->second)
13 { return detail::make_node<NumberNode>(BigInt(0)); }
14 Rational coefficient = nl->first / dl->first;
15 if (nl->second == dl->second) { return detail::make_node<NumberNode>(coefficient); }
16 if (direction.empty() && (dl->second - nl->second) % 2) { return std::shared_ptr<const SymbolicNode>{}; }
17 int sign = coefficient > Rational(0) ? 1 : -1;
18 if (direction == "-" && (dl->second - nl->second) % 2) { sign = -sign; }
19 return signed_infinity(sign);
20 }
21 return std::nullopt;
22}
23
24std::shared_ptr<const SymbolicNode> LimitVisitor::evaluated_product_ratio(
25 const std::shared_ptr<const SymbolicNode>& num,
26 const std::shared_ptr<const SymbolicNode>& den, bool at_infinity) {
27 auto numerator = eval_limit(num);
28 auto denominator = eval_limit(den);
29 bool numerator_zero = is_zero_limit(numerator);
30 bool denominator_zero = is_zero_limit(denominator);
31 const bool both_infinite = is_inf(numerator) && is_inf(denominator);
32 if (both_infinite && at_infinity) {
33 auto growth = limit_by_growth_comparison(num, den);
34 if (growth) {
35 return growth;
36 }
37 }
38 if ((numerator_zero && denominator_zero) || both_infinite) {
39 auto value = apply_lhopital(num, den);
40 if (value) {
41 return value;
42 }
43 }
44 if (!numerator_zero && denominator_zero) {
45 return singular_ratio_limit(num, den);
46 }
47 return nullptr;
48}
49
50bool LimitVisitor::positive_tail_product_limit(const MultiplyNode& node) {
51 std::vector<std::shared_ptr<const SymbolicNode>> rewritten;
52 bool changed = false;
53 for (const auto& operand : node.operands()) {
54 auto function = std::dynamic_pointer_cast<const FunctionNode>(operand);
55 auto replacement = function ? positive_tail_log_power(*function) : nullptr;
56 changed = changed || replacement != nullptr;
57 rewritten.push_back(replacement ? replacement : operand);
58 }
59 if (changed) {
60 result = eval_limit(detail::make_node<MultiplyNode>(std::move(rewritten)));
61 return true;
62 }
63 return false;
64}
65
66std::shared_ptr<const SymbolicNode> LimitVisitor::resolve_product_factors(
67 const MultiplyNode& node, const std::vector<std::shared_ptr<const SymbolicNode>>& values) {
68 std::vector<std::shared_ptr<const SymbolicNode>> numerator, denominator;
69 for (const auto& operand : node.operands()) {
70 auto factor = denominator_factor(operand);
71 if (factor) { denominator.push_back(factor); }
72 else { numerator.push_back(operand); }
73 }
74 std::shared_ptr<const SymbolicNode> resolved;
75 if (denominator.empty()) {
76 if (classify_product_form(values) == IndeterminateForm::ZeroTimesInf) {
77 resolved = resolve_zero_times_inf(node.operands(), values);
78 }
79 } else {
80 auto num = make_product_or_one(numerator);
81 auto den = make_product_or_one(denominator);
82 resolved = product_ratio_limit(num, den);
83 }
84 return resolved;
85}
86
87
88
89std::shared_ptr<const SymbolicNode> LimitVisitor::product_ratio_limit(
90 const std::shared_ptr<const SymbolicNode>& num,
91 const std::shared_ptr<const SymbolicNode>& den) {
92 const bool at_infinity = is_limit_at_infinity() || is_limit_at_neg_infinity();
93 if (!at_infinity) {
94 auto exact = exact_ratio_at_point(num, den);
95 if (exact) { return std::move(*exact); }
96 }
97 if (at_infinity) {
98 auto rational = limit_rational_at_infinity(num, den);
99 if (rational) {
100 return rational;
101 }
102 }
103 return evaluated_product_ratio(num, den, at_infinity);
104}
105
106void LimitVisitor::visit(const MultiplyNode& node) {
107 if (is_limit_at_neg_infinity()) {
108 auto value = handle_neg_infinity_limit(LMCAS::detail::make_node<MultiplyNode>(node.operands()));
109 if (value) {
110 result = value;
111 return;
112 }
113 }
114 if (is_limit_at_infinity()) {
115 if (positive_tail_product_limit(node)) { return; }
116 }
117 if (logarithmic_zero_product(node)) {
118 result = LMCAS::detail::make_node<NumberNode>(BigInt(0));
119 return;
120 }
121 if (is_limit_at_infinity()) {
122 if (logarithmic_product_limit(node)) {
123 return;
124 }
125 if (decaying_exponential_product(node)) {
126 result = LMCAS::detail::make_node<NumberNode>(BigInt(0));
127 return;
128 }
129 }
130 if (trigonometric_product_limit(node)) {
131 return;
132 }
133 auto squeezed = try_squeeze(LMCAS::detail::make_node<MultiplyNode>(node.operands()));
134 if (squeezed) {
135 result = squeezed;
136 return;
137 }
138 std::vector<std::shared_ptr<const SymbolicNode>> values;
139 for (const auto& operand : node.operands()) {
140 operand->accept(*this);
141 values.push_back(result);
142 }
143 std::shared_ptr<const SymbolicNode> substituted;
144 if (std::all_of(values.begin(), values.end(), [](const auto& value) { return value != nullptr; })) {
145 NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real);
146 LMCAS::detail::make_node<MultiplyNode>(values)->accept(norm);
147 substituted = norm.get_result();
148 }
149 auto resolved = resolve_product_factors(node, values);
150 result = resolved ? resolved : substituted;
151}
152
153}
乘法节点,表示多个操作数的乘积。
统一规范化数值幂。 精确操作数保留整数和有理数运算;近似求根要求指数精确等于 1/2。 有限浮点幂直接折叠,省去倒数中间值;非有限结果保留幂表达式。
极限访问器,通过代入和 L'Hôpital 法则计算极限。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const std::string const SymbolicNodePtr & replacement
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
std::shared_ptr< SymbolicExpr > num(int value)
@ Rational
Rational numbers
@ Real
Real numbers
std::size_t std::size_t std::size_t growth
const std::string const LimitExprPtr LimitDirection direction
const std::string const ExprPtr & value
const ExprPtr & denominator
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExprResult rational(const Rational &value)